[
  {
    "path": ".clang-format",
    "content": "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-\nLanguage                                  : Cpp\nBasedOnStyle                              : Google \nStandard                                  : Auto\n#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-\nAccessModifierOffset                      : -4\nAlignTrailingComments                     : true\nAllowAllParametersOfDeclarationOnNextLine : false\nAllowShortBlocksOnASingleLine             : true\nAllowShortFunctionsOnASingleLine          : true\nAllowShortIfStatementsOnASingleLine       : false\nAllowShortLoopsOnASingleLine              : false\nBinPackParameters                         : false\nBreakBeforeBraces                         : Allman\nBreakBeforeTernaryOperators               : false\nBreakConstructorInitializersBeforeComma   : true\nColumnLimit                               : 120 \nCpp11BracedListStyle                      : true\nDerivePointerAlignment                    : true\nDerivePointerBinding                      : false\nIndentWidth                               : 4\nKeepEmptyLinesAtTheStartOfBlocks          : true\nMaxEmptyLinesToKeep                       : 2\nNamespaceIndentation                      : All \nPointerBindsToType                        : true\nSpacesBeforeTrailingComments              : 1\nSpacesInAngles                            : false\nSpacesInSquareBrackets                    : false\nTabWidth                                  : 4\nUseTab                                    : ForIndentation\n#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-\n#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n# http://git-scm.com/docs/gitattributes\n* text=auto\n.appveyor.yml -text eol=crlf\n.appveyor-mingw.yml -text eol=crlf\nci-*.cmd -text eol=crlf"
  },
  {
    "path": ".github/workflows/c-cpp.yml",
    "content": "name: EASTL Build & Test Pipeline\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  checkout:\n    name: Checkout EASTL\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          path: EASTL/\n      - name: Upload checked out code\n        uses: actions/upload-artifact@v4\n        with:\n          name: Code\n          path: EASTL/\n          \n  build:\n    needs: checkout\n    \n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ windows-latest, ubuntu-latest ]\n        compiler: [ clang, gcc, msvc ]\n        configuration: [ Debug, Release ]\n        std_iter_compatibility: [ std_iter_category_disabled, std_iter_category_enabled ]\n        exclude:\n          - os: windows-latest\n            compiler: gcc\n          - os: windows-latest\n            compiler: clang\n          - os: ubuntu-latest\n            compiler: msvc\n        include:  \n          - os: windows-latest\n            compiler: msvc\n            cxxflags: '/std:c++20 /Zc:char8_t'\n          - os: ubuntu-latest\n            compiler: clang\n            cc: 'clang-18'\n            cxx: 'clang++-18'\n            cxxflags: '-std=c++20'\n          - os: ubuntu-latest\n            compiler: gcc\n            cc: 'gcc-14'\n            cxx: 'g++-14'\n            cxxflags: '-std=c++2a'\n\n    name: Build EASTL\n    runs-on: ${{ matrix.os }}\n    \n    steps:\n      - name: Download a Build Artifact\n        uses: actions/download-artifact@v4\n        with:\n          name: Code\n          path: Code/\n\n      - run: mkdir build\n      - run: cd build && cmake ../Code -DEASTL_BUILD_BENCHMARK:BOOL=ON -DEASTL_BUILD_TESTS:BOOL=ON -DEASTL_STD_ITERATOR_CATEGORY_ENABLED:BOOL=${{ contains(matrix.std_iter_compatibility, 'enabled') && 'ON' || 'OFF' }}\n        env:\n          CXXFLAGS: ${{ matrix.cxxflags }}\n          CXX: ${{ matrix.cxx }}\n          CC: ${{ matrix.cc }}\n      - run: cd build && cmake --build . --config ${{ matrix.configuration }}\n      - name: Upload binaries\n        uses: actions/upload-artifact@v4\n        with:\n          name: Binaries-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.configuration }}-${{ matrix.std_iter_compatibility }}\n          path: build/\n    \n  test:\n    needs: build\n    name: Run EASTL tests\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ windows-latest, ubuntu-latest ]\n        compiler: [ clang, msvc, gcc ]\n        configuration: [ Debug, Release ]\n        std_iter_compatibility: [ std_iter_category_disabled, std_iter_category_enabled ]\n        exclude:\n        - os: windows-latest\n          compiler: gcc\n        - os: windows-latest\n          compiler: clang\n        - os: ubuntu-latest\n          compiler: msvc\n    runs-on: ${{ matrix.os }}\n    \n    steps:\n      - name: Download a Build Artifact\n        uses: actions/download-artifact@v4\n        with:\n          name: Binaries-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.configuration }}-${{ matrix.std_iter_compatibility }}\n          path: Binaries/\n      - if: matrix.os == 'ubuntu-latest'\n        run: chmod 755 ./Binaries/test/EASTLTest\n      - run: cd Binaries/test && ctest -C ${{ matrix.configuration }} -V\n        \n  benchmark:\n    needs: build\n    name: Run EASTL benchmarks\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ windows-latest, ubuntu-latest ]\n        compiler: [ clang, msvc, gcc ]\n        configuration: [ Release ]\n        exclude:\n        - os: windows-latest\n          compiler: gcc\n        - os: windows-latest\n          compiler: clang\n        - os: ubuntu-latest\n          compiler: msvc\n    runs-on: ${{ matrix.os }}\n\n    steps:\n      - name: Download a Build Artifact\n        uses: actions/download-artifact@v4\n        with:\n          name: Binaries-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.configuration }}-std_iter_category_disabled\n          path: Binaries/\n      - if: matrix.os == 'ubuntu-latest'\n        run: chmod 755 ./Binaries/benchmark/EASTLBenchmarks\n      - run: cd Binaries/benchmark && ctest -C ${{ matrix.configuration }} -V\n"
  },
  {
    "path": ".gitignore",
    "content": "tags\ncscope.out\n**/*.swp\n**/*.swo\n.swp\n*.swp\n.swo\n.TMP\n-.d\neastl_build_out\nbuild_bench\nbench.bat\nbuild.bat\n.p4config\n\n## CMake generated files\nCMakeCache.txt\ncmake_install.cmake\n\n## Patch files\n*.patch\n\n## For Visual Studio Generated projects\n*.sln\n**/*.vcxproj\n**/*.vcxproj.filters\n*.VC.opendb\n*.sdf\n**/*.suo\n**/*.user\n.vs/*\n**/Debug/*\nCMakeFiles/*\nEASTL.dir/**\nRelWithDebInfo/*\nRelease/*\nWin32/*\nx64/*\nMinSizeRel/*\nbuild*/*\nTesting/*\n%ALLUSERSPROFILE%/*\n\n# Buck\n/buck-out/\n/.buckd/\n/buckaroo/\n.buckconfig.local\nBUCKAROO_DEPS\n.vscode/settings.json\n"
  },
  {
    "path": ".p4ignore",
    "content": "/.git/\ntags\n.gitignore\ncscope.out\n"
  },
  {
    "path": "3RDPARTYLICENSES.TXT",
    "content": "Additional licenses also apply to this software package as detailed below.\n\n\n\nHP STL comes with the following license:\n\n///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) 1994\n// Hewlett-Packard Company\n// \n// Permission to use, copy, modify, distribute and sell this software\n// and its documentation for any purpose is hereby granted without fee,\n// provided that the above copyright notice appear in all copies and\n// that both that copyright notice and this permission notice appear\n// in supporting documentation. Hewlett-Packard Company makes no\n// representations about the suitability of this software for any\n// purpose. It is provided \"as is\" without express or implied warranty.\n///////////////////////////////////////////////////////////////////////////////\n\n\n\nlibc++ comes with the following license:\n\n==============================================================================\nlibc++ License\n==============================================================================\n\nThe libc++ library is dual licensed under both the University of Illinois\n\"BSD-Like\" license and the MIT license.  As a user of this code you may choose\nto use it under either license.  As a contributor, you agree to allow your code\nto be used under both.\n\nFull text of the relevant licenses is included below.\n\n==============================================================================\n\nUniversity of Illinois/NCSA\nOpen Source License\n\nCopyright (c) 2009-2015 by the contributors listed at \nhttp://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT\n\nAll rights reserved.\n\nDeveloped by:\n\n    LLVM Team\n\n    University of Illinois at Urbana-Champaign\n\n    http://llvm.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal with\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\n    * Redistributions of source code must retain the above copyright notice,\n      this list of conditions and the following disclaimers.\n\n    * Redistributions in binary form must reproduce the above copyright notice,\n      this list of conditions and the following disclaimers in the\n      documentation and/or other materials provided with the distribution.\n\n    * Neither the names of the LLVM Team, University of Illinois at\n      Urbana-Champaign, nor the names of its contributors may be used to\n      endorse or promote products derived from this Software without specific\n      prior written permission.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nCONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE\nSOFTWARE.\n\n==============================================================================\n\nCopyright (c) 2009-2014 by the contributors listed at \nhttp://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n==============================================================================\n  \n*No express or implied license to use PlayStation®4 libraries included.\nPlayStation®4 development tools and libraries are subject to separate license\nwith Sony Interactive Entertainment LLC.\n\n==============================================================================\n\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "#-------------------------------------------------------------------------------------------\n# Copyright (C) Electronic Arts Inc.  All rights reserved.\n#-------------------------------------------------------------------------------------------\ncmake_minimum_required(VERSION 3.11)\ninclude(FetchContent)\nproject(EASTL CXX)\n\n#-------------------------------------------------------------------------------------------\n# Options\n#-------------------------------------------------------------------------------------------\noption(EASTL_BUILD_BENCHMARK \"Enable generation of build files for benchmark\" OFF)\noption(EASTL_BUILD_TESTS \"Enable generation of build files for tests\" OFF)\noption(EASTL_STD_ITERATOR_CATEGORY_ENABLED \"Enable compatibility with std:: iterator categories\" OFF)\n\n\noption(EASTL_DISABLE_APRIL_2024_DEPRECATIONS \"Enable use of API marked for removal in April 2024.\" OFF)\noption(EASTL_DISABLE_SEPT_2024_DEPRECATIONS \"Enable use of API marked for removal in September 2024.\" OFF)\noption(EASTL_DISABLE_APRIL_2025_DEPRECATIONS \"Enable use of API marked for removal in April 2025.\" OFF)\n\n#-------------------------------------------------------------------------------------------\n# Compiler Flags\n#-------------------------------------------------------------------------------------------\nset (CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/scripts/CMake\")\ninclude(CommonCppFlags)\n\n#-------------------------------------------------------------------------------------------\n# Library definition\n#-------------------------------------------------------------------------------------------\nfile(GLOB EASTL_SOURCES \"source/*.cpp\")\nfile(GLOB_RECURSE EASTL_HEADERS \"include/EASTL/**.h\")\nadd_library(EASTL ${EASTL_SOURCES} ${EASTL_HEADERS})\ntarget_compile_features(EASTL PUBLIC cxx_std_14)\n\n# include both source and headers in the files tab in Visual Studio\nsource_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX \"Header Files\" FILES ${EASTL_HEADERS})\n\nif (MSVC)\n    set(EASTL_NATVIS_DIR \"doc\")\n    set(EASTL_NATVIS_FILE \"${EASTL_NATVIS_DIR}/EASTL.natvis\")\n    target_sources(EASTL INTERFACE\n        $<INSTALL_INTERFACE:${EASTL_NATVIS_FILE}>\n        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${EASTL_NATVIS_FILE}>\n    )\nendif()\n\nif(EASTL_BUILD_BENCHMARK)\n    add_subdirectory(benchmark)\nendif()\n\nif(EASTL_BUILD_TESTS)\n    add_subdirectory(test)\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Defines\n#-------------------------------------------------------------------------------------------\nadd_definitions(-D_CHAR16T)\nadd_definitions(-D_CRT_SECURE_NO_WARNINGS)\nadd_definitions(-D_SCL_SECURE_NO_WARNINGS)\nadd_definitions(-DEASTL_OPENSOURCE=1)\nif (EASTL_STD_ITERATOR_CATEGORY_ENABLED)\n  add_definitions(-DEASTL_STD_ITERATOR_CATEGORY_ENABLED=1)\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Include dirs\n#-------------------------------------------------------------------------------------------\ntarget_include_directories(EASTL PUBLIC include)\n\n#-------------------------------------------------------------------------------------------\n# Dependencies\n#-------------------------------------------------------------------------------------------\nFetchContent_Declare(\n  EABase\n  GIT_REPOSITORY https://github.com/electronicarts/EABase.git\n  GIT_TAG        0699a15efdfd20b6cecf02153bfa5663decb653c\n  GIT_SUBMODULES \"\" # This should be temporary until we update the cyclic submodule dependencies in EABase.\n)\n\nFetchContent_MakeAvailable(EABase)\n\ntarget_link_libraries(EASTL EABase)\n\n#-------------------------------------------------------------------------------------------\n# Deprecations\n#-------------------------------------------------------------------------------------------\nif(EASTL_DISABLE_APRIL_2024_DEPRECATIONS)\n  target_compile_definitions(EASTL PUBLIC EA_DEPRECATIONS_FOR_2024_APRIL=EA_DISABLED)\nendif()\nif(EASTL_DISABLE_SEPT_2024_DEPRECATIONS)\n  target_compile_definitions(EASTL PUBLIC EA_DEPRECATIONS_FOR_2024_SEPT=EA_DISABLED)\nendif()\nif(EASTL_DISABLE_APRIL_2025_DEPRECATIONS)\n  target_compile_definitions(EASTL PUBLIC EA_DEPRECATIONS_FOR_2025_APRIL=EA_DISABLED)\nendif()\n\n\n#-------------------------------------------------------------------------------------------\n# Installation\n#-------------------------------------------------------------------------------------------\ninstall(TARGETS EASTL DESTINATION lib)\ninstall(DIRECTORY include/EASTL DESTINATION include)\n\nif (MSVC)\n    install(FILES ${EASTL_NATVIS_FILE} DESTINATION ${EASTL_NATVIS_DIR})\nendif()\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Contributing\n\nBefore you can contribute, EA must have a Contributor License Agreement (CLA) on file that has been signed by each contributor.\nYou can sign here: [Go to CLA](https://electronicarts.na1.echosign.com/public/esignWidget?wid=CBFCIBAA3AAABLblqZhByHRvZqmltGtliuExmuV-WNzlaJGPhbSRg2ufuPsM3P0QmILZjLpkGslg24-UJtek*)\n\nIf you want to be recognized for your contributions to EASTL or have a project using EASTL be recognized; you can submit a pull request to the appropriate sections in [README.md](README.md).\nSome examples of what the format and information will look like is as follows.\n* John Smith - jsmith@domain.com\n* John Smith\n* Frostbite - Electronic Arts\n* My Project - [link to said project]\n\n### Pull Request Policy\n\nAll code contributions to EASTL are submitted as [Github pull requests](https://help.github.com/articles/using-pull-requests/).  All pull requests will be reviewed by an EASTL maintainer according to the guidelines found in the next section.\n\nYour pull request should:\n\n* merge cleanly\n* come with tests\n\t* tests should be minimal and stable\n\t* fail before your fix is applied\n* pass the test suite\n* code formatting is encoded in clang format\n\t* limit using clang format on new code\n\t* do not deviate from style already established in the files\n\n### Getting the Repository\n\n```bash\ngit clone https://github.com/electronicarts/EASTL\n```\n\n### Running the Unit Tests\n\nEASTL uses CMake as its build system. \n\n* Create and navigate to \"your_build_folder\":\n\t* mkdir your_build_folder && cd your_build_folder\n* Generate build scripts:\n\t* cmake eastl_source_folder -DEASTL_BUILD_TESTS:BOOL=ON\n* Build unit tests for \"your_config\":\n\t* cmake --build . --config your_config\n* Run the unit tests for \"your_config\" from the test folder:\n\t* cd test && ctest -C your_config\n\nHere is an example batch file.\n```batch\nset build_folder=out\nmkdir %build_folder%\npushd %build_folder%\ncall cmake .. -DEASTL_BUILD_TESTS:BOOL=ON -DEASTL_BUILD_BENCHMARK:BOOL=OFF\ncall cmake --build . --config Release\ncall cmake --build . --config Debug\ncall cmake --build . --config RelWithDebInfo\ncall cmake --build . --config MinSizeRel\npushd test\ncall ctest -C Release\ncall ctest -C Debug\ncall ctest -C RelWithDebInfo\ncall ctest -C MinSizeRel\npopd\npopd\n```\n\nHere is an example bash file\n```bash\nbuild_folder=out\nmkdir $build_folder\npushd $build_folder\ncmake .. -DEASTL_BUILD_TESTS:BOOL=ON -DEASTL_BUILD_BENCHMARK:BOOL=OFF\ncmake --build . --config Release\ncmake --build . --config Debug\ncmake --build . --config RelWithDebInfo\ncmake --build . --config MinSizeRel\npushd test\nctest -C Release\nctest -C Debug\nctest -C RelWithDebInfo\nctest -C MinSizeRel\npopd\npopd\n```\n\nThe value of EASTL_BUILD_BENCHMARK can be toggled to `ON` in order to build projects that include the benchmark program.\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2019, Electronic Arts\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its\n   contributors may be used to endorse or promote products derived from\n   this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# EA Standard Template Library\n\n[![Build Status](https://travis-ci.org/electronicarts/EASTL.svg?branch=master)](https://travis-ci.org/electronicarts/EASTL)  \n\nEASTL stands for Electronic Arts Standard Template Library. It is a C++ template library of containers, algorithms, and iterators useful for runtime and tool development across multiple platforms. It is a fairly extensive and robust implementation of such a library and has an emphasis on high performance above all other considerations.\n\n\n## Usage\n\nIf you are familiar with the C++ STL or have worked with other templated container/algorithm libraries, you probably don't need to read this. If you have no familiarity with C++ templates at all, then you probably will need more than this document to get you up to speed. In this case, you need to understand that templates, when used properly, are powerful vehicles for the ease of creation of optimized C++ code. A description of C++ templates is outside the scope of this documentation, but there is plenty of such documentation on the Internet.\n\nEASTL is suitable for any tools and shipping applications where the functionality of EASTL is useful. Modern compilers are capable of producing good code with templates and many people are using them in both current generation and future generation applications on multiple platforms from embedded systems to servers and mainframes.\n\n## Package Managers\n\nYou can download and install EASTL using the [Conan](https://github.com/conan-io/conan) package manager:\n\n    conan install eastl/3.15.00@\n\nThe EASTL package in conan is kept up to date by Conan team members and community contributors. If the version is out-of-date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the Conan Center Index repository.\n\n\nYou can download and install EASTL using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:\n\n    git clone https://github.com/Microsoft/vcpkg.git\n    cd vcpkg\n    ./bootstrap-vcpkg.sh\n    ./vcpkg integrate install\n    vcpkg install eastl\n\nThe EASTL port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.\n\n\n## Documentation\n\nPlease see [EASTL Introduction](doc/Introduction.md).\n\n\n## Compiling sources\n\nPlease see [CONTRIBUTING.md](CONTRIBUTING.md) for details on compiling and testing the source.\n\n## Credits And Maintainers\n\nEASTL was created by Paul Pedriana and he maintained the project for roughly 10 years.\n\nEASTL was subsequently maintained by Roberto Parolin for more than 8 years.\nHe was the driver and proponent for getting EASTL opensourced.\nRob was a mentor to all members of the team and taught us everything we ever wanted to know about C++ spookyness.\n\nAfter Rob, maintenance of EASTL passed to Max Winkler for roughly a year, then to Liam Mitchell for about another year. \n\nThe current maintainers (since circa 2022) are Galo Rojo and Jonathan Hopkins.\n\nSignificant EASTL contributions were made by (in alphabetical order):\n\n* Avery Lee\n* Claire Andrews\n* Galo Rojo\n* Jonathan Hopkins\n* JP Flouret\n* Liam Mitchell\n* Matt Newport\n* Max Winkler\n* Paul Pedriana\n* Roberto Parolin\n* Simon Everett\n\n## Contributors\n\n## Projects And Products Using EASTL\n\n* Frostbite - Electronic Arts - [https://www.ea.com/frostbite]\n\n## License\n\nModified BSD License (3-Clause BSD license) see the file LICENSE in the project root.\n"
  },
  {
    "path": "_config.yml",
    "content": "theme: jekyll-theme-minimal"
  },
  {
    "path": "benchmark/CMakeLists.txt",
    "content": "#-------------------------------------------------------------------------------------------\n# Copyright (C) Electronic Arts Inc.  All rights reserved.\n#-------------------------------------------------------------------------------------------\n\n#-------------------------------------------------------------------------------------------\n# CMake info\n#-------------------------------------------------------------------------------------------\ncmake_minimum_required(VERSION 3.1)\nproject(EASTLBenchmarks CXX)\ninclude(CTest)\n\n#-------------------------------------------------------------------------------------------\n# Defines\n#-------------------------------------------------------------------------------------------\nadd_definitions(-D_CHAR16T)\n\n#-------------------------------------------------------------------------------------------\n# Include directories\n#-------------------------------------------------------------------------------------------\ninclude_directories(source)\ninclude_directories(../test/source)\n\n#-------------------------------------------------------------------------------------------\n# Compiler Flags\n#-------------------------------------------------------------------------------------------\nset (CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/../scripts/CMake\")\ninclude(CommonCppFlags)\n\n# Libstdc++ calls new internally, since DLLs have no weak symbols, runtime symbol resolution fails and EASTL's new is not called.\n# Linking against static libstdc++ fixes this.\n# See https://github.com/electronicarts/EASTL/issues/40 for more info.\nif (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_CXX_COMPILER_ID MATCHES \"GNU\" AND MINGW)\n    set(CMAKE_EXE_LINKER_FLAGS_RELEASE \"${CMAKE_EXE_LINKER_FLAGS_RELEASE} -static-libstdc++\")\n    set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO \"${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -static-libstdc++\")\n    set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL \"${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -static-libstdc++\")\nendif()\n\nif (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND CMAKE_BUILD_TYPE MATCHES \"MinSizeRel\" AND MINGW)\n    message(FATAL_ERROR \"FIXME: MinSizeRel on MingW-w64's Clang fails to link.\")\nendif()\n\n# The benchmark suite fails to compile if char8_t is enabled, so disable it.\nif (EASTL_NO_CHAR8T_FLAG)\n    add_compile_options(${EASTL_NO_CHAR8T_FLAG})\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Source files\n#-------------------------------------------------------------------------------------------\nfile(GLOB EASTLBENCHMARK_SOURCES \"source/*.cpp\")\nfile(GLOB EASTLTEST_SOURCES \"../test/source/EASTLTestAllocator.cpp\" \"../test/source/EASTLTest.cpp\")\nfile(GLOB EASTLBENCHMARK_HEADERS \"source/*.h\")\nset(SOURCES ${EASTLBENCHMARK_SOURCES} ${EASTLTEST_SOURCES} ${EASTLBENCHMARK_HEADERS})\n\n# include both source and headers in the files view in Visual Studio\nsource_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX \"Header Files\" FILES ${EASTLBENCHMARK_HEADERS})\n\n#-------------------------------------------------------------------------------------------\n# Defines\n#-------------------------------------------------------------------------------------------\nadd_definitions(-D_CRT_SECURE_NO_WARNINGS)\nadd_definitions(-D_SCL_SECURE_NO_WARNINGS)\nadd_definitions(-DEASTL_THREAD_SUPPORT_AVAILABLE=0)\nadd_definitions(-DEASTL_OPENSOURCE=1)\nadd_definitions(-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS)  # silence std::hash_map deprecation warnings\nif (EASTL_STD_ITERATOR_CATEGORY_ENABLED)\n  add_definitions(-DEASTL_STD_ITERATOR_CATEGORY_ENABLED=1)\nendif()\n\nif(NOT EASTL_BUILD_TESTS)\n    add_subdirectory(../test/packages/EAStdC ../test/EAStdC)\n    add_subdirectory(../test/packages/EAAssert ../test/EAAssert)\n    add_subdirectory(../test/packages/EAThread ../test/EAThread)\n    add_subdirectory(../test/packages/EATest ../test/EATest)\n    add_subdirectory(../test/packages/EAMain ../test/EAMain)\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Executable definition\n#-------------------------------------------------------------------------------------------\nadd_executable(EASTLBenchmarks ${SOURCES})\n\nset(THREADS_PREFER_PTHREAD_FLAG ON)\nfind_package(Threads REQUIRED)\n\nset(EASTLBenchmark_Libraries\n    EABase\n    EAAssert\n    EAMain\n    EAThread\n    EAStdC\n    EASTL\n    EATest)\ntarget_link_libraries(EASTLBenchmarks ${EASTLBenchmark_Libraries} Threads::Threads)\n\n#-------------------------------------------------------------------------------------------\n# Run Unit tests and verify the results.\n#-------------------------------------------------------------------------------------------\nadd_test(EASTLBenchmarkRuns EASTLBenchmarks)\nset_tests_properties (EASTLBenchmarkRuns PROPERTIES PASS_REGULAR_EXPRESSION \"RETURNCODE=0\")\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkAlgorithm.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// BenchmarkAlgorithm.cpp\n//\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EAStdC/EAMemory.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/sort.h>\n#include <EASTL/vector.h>\n#include <EASTL/slist.h>\n#include <EASTL/list.h>\n#include <EASTL/string.h>\n#include <EASTL/random.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdio.h>\n#include <stdlib.h>\n#include <string>\n#include <vector>\n#include <list>\n#include <algorithm>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n#ifdef _MSC_VER\n\t#pragma warning(disable: 4996) // Function call with parameters that may be unsafe\n#endif\n\n\nusing namespace EA;\n\n\ntypedef std::vector<unsigned char>   StdVectorUChar;\ntypedef eastl::vector<unsigned char> EaVectorUChar;\n\ntypedef std::vector<signed char>     StdVectorSChar;\ntypedef eastl::vector<signed char>   EaVectorSChar;\n\ntypedef std::vector<uint32_t>        StdVectorUint32;\ntypedef eastl::vector<uint32_t>      EaVectorUint32;\n\ntypedef std::vector<uint64_t>        StdVectorUint64;\ntypedef eastl::vector<uint64_t>      EaVectorUint64;\n\ntypedef std::vector<TestObject>      StdVectorTO;\ntypedef eastl::vector<TestObject>    EaVectorTO;\n\n\n// We make a fake version of C++11 std::next, as some C++ compilers don't currently \n// provide the C++11 next algorithm in their standard libraries.\nnamespace std__\n{\n\ttemplate<typename InputIterator>\n\tinline InputIterator \n\tnext(InputIterator it, typename std::iterator_traits<InputIterator>::difference_type n = 1)\n\t{\n\t\tstd::advance(it, n);\n\t\treturn it;\n\t}\n}\n\n\nnamespace\n{\n\t// Exists for the purpose testing PODs that are larger than built-in types.\n\ttemplate <size_t kSize>\n\tstruct SizedPOD\n\t{\n\t\tchar memory[kSize];\n\t};\n\n\tvoid TestFindEndStd(EA::StdC::Stopwatch& stopwatch, const std::string& sTest, const char* pSearchStringBegin, const char* pSearchStringEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::string::const_iterator it = std::find_end(sTest.begin(), sTest.end(), pSearchStringBegin, pSearchStringEnd);\n\t\tstopwatch.Stop();\n\t\tif(it != sTest.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%c\", *it);\n\t}\n\n\tvoid TestFindEndEa(EA::StdC::Stopwatch& stopwatch, const eastl::string& sTest, const char* pSearchStringBegin, const char* pSearchStringEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::string::const_iterator it = eastl::find_end(sTest.begin(), sTest.end(), pSearchStringBegin, pSearchStringEnd);\n\t\tstopwatch.Stop();\n\t\tif(it != sTest.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%c\", *it);\n\t}\n\n\n\n\tvoid TestSearchStd(EA::StdC::Stopwatch& stopwatch, const std::string& sTest, const char* pSearchStringBegin, const char* pSearchStringEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::string::const_iterator it = std::search(sTest.begin(), sTest.end(), pSearchStringBegin, pSearchStringEnd);\n\t\tstopwatch.Stop();\n\t\tif(it != sTest.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%c\", *it);\n\t}\n\n\tvoid TestSearchEa(EA::StdC::Stopwatch& stopwatch, const eastl::string& sTest, const char* pSearchStringBegin, const char* pSearchStringEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::string::const_iterator it = eastl::search(sTest.begin(), sTest.end(), pSearchStringBegin, pSearchStringEnd);\n\t\tstopwatch.Stop();\n\t\tif(it != sTest.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%c\", *it);\n\t}\n\n\n\n\tvoid TestSearchNStd(EA::StdC::Stopwatch& stopwatch, const std::string& sTest, int n, char c)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::string::const_iterator it = std::search_n(sTest.begin(), sTest.end(), n, c);\n\t\tstopwatch.Stop();\n\t\tif(it != sTest.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%c\", *it);\n\t}\n\n\tvoid TestSearchNEa(EA::StdC::Stopwatch& stopwatch, const eastl::string& sTest, int n, char c)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::string::const_iterator it = eastl::search_n(sTest.begin(), sTest.end(), n, c);\n\t\tstopwatch.Stop();\n\t\tif(it != sTest.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%c\", *it);\n\t}\n\n\n\n\ttemplate <typename Container>\n\tvoid TestUniqueStd(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypename Container::iterator it = std::unique(c.begin(), c.end());\n\t\tstopwatch.Stop();\n\t\tc.erase(it, c.end());\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestUniqueEa(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypename Container::iterator it = eastl::unique(c.begin(), c.end());\n\t\tstopwatch.Stop();        \n\t\tc.erase(it, c.end());\n\t}\n\n\n\n\ttemplate <typename Container>\n\tvoid TestMinElementStd(EA::StdC::Stopwatch& stopwatch, const Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst typename Container::const_iterator it = std::min_element(c.begin(), c.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &it);\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestMinElementEa(EA::StdC::Stopwatch& stopwatch, const Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst typename Container::const_iterator it = eastl::min_element(c.begin(), c.end());\n\t\tstopwatch.Stop();        \n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &it);\n\t}\n\n\n\n\ttemplate <typename Container>\n\tvoid TestCountStd(EA::StdC::Stopwatch& stopwatch, const Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst typename Container::difference_type n = std::count(c.begin(), c.end(), (typename Container::value_type)999999);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", (int)n);\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestCountEa(EA::StdC::Stopwatch& stopwatch, const Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst typename Container::difference_type n = eastl::count(c.begin(), c.end(), (typename Container::value_type)999999);\n\t\tstopwatch.Stop();        \n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", (int)n);\n\t}\n\n\n\n\ttemplate <typename Container>\n\tvoid TestAdjacentFindStd(EA::StdC::Stopwatch& stopwatch, const Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst typename Container::const_iterator it = std::adjacent_find(c.begin(), c.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &it);\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestAdjacentFindEa(EA::StdC::Stopwatch& stopwatch, const Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst typename Container::const_iterator it = eastl::adjacent_find(c.begin(), c.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &it);\n\t}\n\n\n\n\ttemplate <typename Container>\n\tvoid TestLowerBoundStd(EA::StdC::Stopwatch& stopwatch, const Container& c, const typename Container::value_type* pBegin,  const typename Container::value_type* pEnd)\n\t{\n\n\t\tstopwatch.Restart();\n\t\twhile(pBegin != pEnd)\n\t\t{\n\t\t\ttypename Container::const_iterator it = std::lower_bound(c.begin(), c.end(), *pBegin++);\n\t\t\tBenchmark::DoNothing(&it);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestLowerBoundEa(EA::StdC::Stopwatch& stopwatch, Container& c, const typename Container::value_type* pBegin,  const typename Container::value_type* pEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pBegin != pEnd)\n\t\t{\n\t\t\ttypename Container::const_iterator it = eastl::lower_bound(c.begin(), c.end(), *pBegin++);\n\t\t\tBenchmark::DoNothing(&it);\n\t\t}\n\t\tstopwatch.Stop();        \n\t}\n\n\n\n\ttemplate <typename Container>\n\tvoid TestUpperBoundStd(EA::StdC::Stopwatch& stopwatch, const Container& c, const typename Container::value_type* pBegin,  const typename Container::value_type* pEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pBegin != pEnd)\n\t\t{\n\t\t\ttypename Container::const_iterator it = std::upper_bound(c.begin(), c.end(), *pBegin++);\n\t\t\tBenchmark::DoNothing(&it);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestUpperBoundEa(EA::StdC::Stopwatch& stopwatch, Container& c, const typename Container::value_type* pBegin,  const typename Container::value_type* pEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pBegin != pEnd)\n\t\t{\n\t\t\ttypename Container::const_iterator it = eastl::upper_bound(c.begin(), c.end(), *pBegin++);\n\t\t\tBenchmark::DoNothing(&it);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\n\ttemplate <typename Container>\n\tvoid TestEqualRangeStd(EA::StdC::Stopwatch& stopwatch, const Container& c, const typename Container::value_type* pBegin,  const typename Container::value_type* pEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pBegin != pEnd)\n\t\t{\n\t\t\tstd::pair<const typename Container::const_iterator, \n\t\t\t\t\t  const typename Container::const_iterator> itPair = std::equal_range(c.begin(), c.end(), *pBegin++);\n\n\t\t\tBenchmark::DoNothing(&itPair);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestEqualRangeEa(EA::StdC::Stopwatch& stopwatch, Container& c, const typename Container::value_type* pBegin,  const typename Container::value_type* pEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pBegin != pEnd)\n\t\t{\n\t\t\teastl::pair<const typename Container::const_iterator, \n\t\t\t\t\t\tconst typename Container::const_iterator> itPair = eastl::equal_range(c.begin(), c.end(), *pBegin++);\n\t\t\tBenchmark::DoNothing(&itPair);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tvoid TestLexicographicalCompareStd(EA::StdC::Stopwatch& stopwatch, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst bool bResult = std::lexicographical_compare(first1, last1, first2, last2);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", bResult ? (int)1 : (int)0);\n\t}\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tvoid TestLexicographicalCompareEa(EA::StdC::Stopwatch& stopwatch, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)\n\t{\n\t\tstopwatch.Restart();\n\t\tconst bool bResult = eastl::lexicographical_compare(first1, last1, first2, last2);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", bResult ? (int)1 : (int)0);\n\t}\n\n\n\n\ttemplate <typename Iterator, typename OutputIterator>\n\tvoid TestCopyStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, OutputIterator result)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::copy(first, last, result);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", (int)*first);\n\t}\n\n\ttemplate <typename Iterator, typename OutputIterator>\n\tvoid TestCopyEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, OutputIterator result)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::copy(first, last, result);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", (int)*first);\n\t}\n\n\n\n\ttemplate <typename Iterator, typename OutputIterator>\n\tvoid TestCopyBackwardStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, OutputIterator result)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::copy_backward(first, last, result);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", (int)*first);\n\t}\n\n\ttemplate <typename Iterator, typename OutputIterator>\n\tvoid TestCopyBackwardEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, OutputIterator result)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::copy_backward(first, last, result);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", (int)*first);\n\t}\n\n\n\n\ttemplate <typename Iterator, typename Value>\n\tvoid TestFillStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, const Value& v)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::fill(first, last, v);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\ttemplate <typename Iterator, typename Value>\n\tvoid TestFillEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, const Value& v)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::fill(first, last, v);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\n\n\ttemplate <typename Iterator, typename Value>\n\tvoid TestFillNStd(EA::StdC::Stopwatch& stopwatch, Iterator first, int n, const Value& v)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::fill_n(first, n, v);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\ttemplate <typename Iterator, typename Value>\n\tvoid TestFillNEa(EA::StdC::Stopwatch& stopwatch, Iterator first, int n, const Value& v)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::fill_n(first, n, v);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\n\n\ttemplate <typename Iterator>\n\tvoid TestReverseStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::reverse(first, last);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\ttemplate <typename Iterator>\n\tvoid TestReverseEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::reverse(first, last);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\n\n\ttemplate <typename Iterator>\n\tvoid TestRotateStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator middle, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::rotate(first, middle, last); // C++11 specifies that rotate has a return value, but not all std implementations return it.\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\ttemplate <typename Iterator>\n\tvoid TestRotateEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator middle, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::rotate(first, middle, last);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*first);\n\t}\n\n\ttemplate <typename Iterator>\n\tvoid TestMergeStd(EA::StdC::Stopwatch& stopwatch, Iterator firstIn1, Iterator lastIn1, Iterator firstIn2, Iterator lastIn2, Iterator out)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::merge(firstIn1, lastIn1, firstIn2, lastIn2, out);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*out);\n\t}\n\n\ttemplate <typename Iterator>\n\tvoid TestMergeEa(EA::StdC::Stopwatch& stopwatch, Iterator firstIn1, Iterator lastIn1, Iterator firstIn2, Iterator lastIn2, Iterator out)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::merge(firstIn1, lastIn1, firstIn2, lastIn2, out);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*out);\n\t}\n} // namespace\n\n\n\n\nvoid BenchmarkAlgorithm1(EASTLTest_Rand& /*rng*/, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\t{\n\t\tstd::string   sTestStd;\n\t\teastl::string sTestEa;\n\t\tconst char*   pSearchString1Begin = \"AAA\";\n\t\tconst char*   pSearchString1End   = pSearchString1Begin + strlen(pSearchString1Begin);\n\t\tconst char*   pSearchString2Begin = \"BBB\"; // This is something that doesn't exist searched string.\n\t\tconst char*   pSearchString2End   = pSearchString2Begin + strlen(pSearchString2Begin);\n\t\tconst char*   pSearchString3Begin = \"CCC\";\n\t\tconst char*   pSearchString3End   = pSearchString3Begin + strlen(pSearchString3Begin);\n\n\t\tfor(int i = 0; i < 10000; i++)\n\t\t\tsTestStd += \"This is a test of the find_end algorithm. \";\n\t\tsTestEa.assign(sTestStd.data(), (eastl_size_t)sTestStd.length());\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test find_end\n\t\t\t///////////////////////////////\n\n\t\t\tsTestStd.insert(sTestStd.size() * 15 / 16, pSearchString1Begin);\n\t\t\tsTestEa.insert (sTestEa.size()  * 15 / 16, pSearchString1Begin);\n\t\t\tTestFindEndStd(stopwatch1, sTestStd, pSearchString1Begin, pSearchString1End);\n\t\t\tTestFindEndEa (stopwatch2, sTestEa,  pSearchString1Begin, pSearchString1End);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/find_end/string/end\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tsTestStd.insert(sTestStd.size() / 2, pSearchString2Begin);\n\t\t\tsTestEa.insert (sTestEa.size()  / 2, pSearchString2Begin);\n\t\t\tTestFindEndStd(stopwatch1, sTestStd, pSearchString2Begin, pSearchString2End);\n\t\t\tTestFindEndEa (stopwatch2, sTestEa,  pSearchString2Begin, pSearchString2End);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/find_end/string/middle\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFindEndStd(stopwatch1, sTestStd, pSearchString3Begin, pSearchString3End);\n\t\t\tTestFindEndEa (stopwatch2, sTestEa,  pSearchString3Begin, pSearchString3End);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/find_end/string/none\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test search\n\t\t\t///////////////////////////////\n\t\t\tTestSearchStd(stopwatch1, sTestStd, pSearchString1Begin, pSearchString1End);\n\t\t\tTestSearchEa (stopwatch2, sTestEa,  pSearchString1Begin, pSearchString1End);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/search/string<char>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test search_n\n\t\t\t///////////////////////////////\n\t\t\tTestSearchNStd(stopwatch1, sTestStd, 3, 'A');\n\t\t\tTestSearchNEa (stopwatch2, sTestEa, 3, 'A');\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/search_n/string<char>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test adjacent_find\n\t\t\t///////////////////////////////\n\n\t\t}\n\t}\n}\n\n\nvoid BenchmarkAlgorithm2(EASTLTest_Rand& rng, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\t{\n\t\tStdVectorUint32 stdVectorUint32;\n\t\tEaVectorUint32  eaVectorUint32;\n\n\t\tStdVectorUint64 stdVectorUint64;\n\t\tEaVectorUint64  eaVectorUint64;\n\n\t\tStdVectorTO     stdVectorTO;\n\t\tEaVectorTO      eaVectorTO;\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tstdVectorUint32.clear();\n\t\t\teaVectorUint32.clear();\n\n\t\t\tfor(int j = 0; j < 100000; j++)\n\t\t\t{\n\t\t\t\tstdVectorUint32.push_back(j);\n\t\t\t\teaVectorUint32.push_back(j);\n\t\t\t\tstdVectorUint64.push_back(j);\n\t\t\t\teaVectorUint64.push_back(j);\n\t\t\t\tstdVectorTO.push_back(TestObject(j));\n\t\t\t\teaVectorTO.push_back(TestObject(j));\n\n\t\t\t\tif((rng() % 16) == 0)\n\t\t\t\t{\n\t\t\t\t\tstdVectorUint32.push_back(i);\n\t\t\t\t\teaVectorUint32.push_back(i);\n\t\t\t\t\tstdVectorUint64.push_back(j);\n\t\t\t\t\teaVectorUint64.push_back(j);\n\t\t\t\t\tstdVectorTO.push_back(TestObject(j));\n\t\t\t\t\teaVectorTO.push_back(TestObject(j));\n\n\t\t\t\t\tif((rng() % 16) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tstdVectorUint32.push_back(i);\n\t\t\t\t\t\teaVectorUint32.push_back(i);\n\t\t\t\t\t\tstdVectorUint64.push_back(j);\n\t\t\t\t\t\teaVectorUint64.push_back(j);\n\t\t\t\t\t\tstdVectorTO.push_back(TestObject(j));\n\t\t\t\t\t\teaVectorTO.push_back(TestObject(j));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test unique\n\t\t\t///////////////////////////////\n\n\t\t\tTestUniqueStd(stopwatch1, stdVectorUint32);\n\t\t\tTestUniqueEa (stopwatch2, eaVectorUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/unique/vector<uint32_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestUniqueStd(stopwatch1, stdVectorUint64);\n\t\t\tTestUniqueEa (stopwatch2, eaVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/unique/vector<uint64_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestUniqueStd(stopwatch1, stdVectorTO);\n\t\t\tTestUniqueEa (stopwatch2, eaVectorTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/unique/vector<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test min_element\n\t\t\t///////////////////////////////\n\n\t\t\tTestMinElementStd(stopwatch1, stdVectorTO);\n\t\t\tTestMinElementEa (stopwatch2, eaVectorTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/min_element/vector<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test count\n\t\t\t///////////////////////////////\n\n\t\t\tTestCountStd(stopwatch1, stdVectorUint64);\n\t\t\tTestCountEa (stopwatch2, eaVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/count/vector<uint64_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t\n\t\t\t///////////////////////////////\n\t\t\t// Test adjacent_find\n\t\t\t///////////////////////////////\n\n\t\t\t// Due to the above unique testing, the container should container unique elements. Let's change that.\n\t\t\tstdVectorTO[stdVectorTO.size() - 2] = stdVectorTO[stdVectorTO.size() - 1];\n\t\t\teaVectorTO[eaVectorTO.size() - 2] = eaVectorTO[eaVectorTO.size() - 1];\n\t\t\tTestAdjacentFindStd(stopwatch1, stdVectorTO);\n\t\t\tTestAdjacentFindEa (stopwatch2, eaVectorTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/adj_find/vector<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test lower_bound\n\t\t\t///////////////////////////////\n\n\t\t\t// Sort the containers for the following tests.\n\t\t\tstd::sort(stdVectorTO.begin(), stdVectorTO.end());\n\t\t\teaVectorTO.assign(&stdVectorTO[0], &stdVectorTO[0] + stdVectorTO.size());\n\n\t\t\tTestLowerBoundStd(stopwatch1, stdVectorTO, &stdVectorTO[0], &stdVectorTO[0] + stdVectorTO.size());\n\t\t\tTestLowerBoundEa (stopwatch2, eaVectorTO,   &eaVectorTO[0],  &eaVectorTO[0] + eaVectorTO.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/lower_bound/vector<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test upper_bound\n\t\t\t///////////////////////////////\n\n\t\t\tstd::sort(stdVectorUint32.begin(), stdVectorUint32.end());\n\t\t\teaVectorUint32.assign(&stdVectorUint32[0], &stdVectorUint32[0] + stdVectorUint32.size());\n\n\t\t\tTestUpperBoundStd(stopwatch1, stdVectorUint32, &stdVectorUint32[0], &stdVectorUint32[0] + stdVectorUint32.size());\n\t\t\tTestUpperBoundEa (stopwatch2,  eaVectorUint32,  &eaVectorUint32[0],  &eaVectorUint32[0] + eaVectorUint32.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/upper_bound/vector<uint32_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test equal_range\n\t\t\t///////////////////////////////\n\n\t\t\t// VS2010 (and later versions?) is extremely slow executing this in debug builds. It can take minutes for a \n\t\t\t// single TestEqualRangeStd call to complete. It's so slow that it's nearly pointless to execute.\n\t\t\t#if !defined(_MSC_VER) || (_MSC_VER < 1600) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2) \n\t\t\t\tstd::sort(stdVectorUint64.begin(), stdVectorUint64.end());\n\t\t\t\teaVectorUint64.assign(&stdVectorUint64[0], &stdVectorUint64[0] + stdVectorUint64.size());\n\n\t\t\t\tTestEqualRangeStd(stopwatch1, stdVectorUint64, &stdVectorUint64[0], &stdVectorUint64[0] + stdVectorUint64.size());\n\t\t\t\tTestEqualRangeEa (stopwatch2,  eaVectorUint64,  &eaVectorUint64[0],  &eaVectorUint64[0] +  eaVectorUint64.size());\n\n\t\t\t\tif(i == 1)\n\t\t\t\t\tBenchmark::AddResult(\"algorithm/equal_range/vector<uint64_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t\t#endif\n\t\t}\n\t}\n}\n\n\nvoid BenchmarkAlgorithm3(EASTLTest_Rand& /*rng*/, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\t{\n\t\tStdVectorUChar  stdVectorUChar1(100000);\n\t\tStdVectorUChar  stdVectorUChar2(100000);\n\t\tEaVectorUChar   eaVectorUChar1(100000);\n\t\tEaVectorUChar   eaVectorUChar2(100000);\n\n\t\tStdVectorSChar  stdVectorSChar1(100000);\n\t\tStdVectorSChar  stdVectorSChar2(100000);\n\t\tEaVectorSChar   eaVectorSChar1(100000);\n\t\tEaVectorSChar   eaVectorSChar2(100000);\n\n\t\tStdVectorTO     stdVectorTO1(100000);\n\t\tStdVectorTO     stdVectorTO2(100000);\n\t\tEaVectorTO      eaVectorTO1(100000);\n\t\tEaVectorTO      eaVectorTO2(100000);\n\n\t\t// All these containers should have values of zero in them.\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test lexicographical_compare\n\t\t\t///////////////////////////////\n\n\t\t\tTestLexicographicalCompareStd(stopwatch1, stdVectorUChar1.begin(), stdVectorUChar1.end(), stdVectorUChar2.begin(), stdVectorUChar2.end());\n\t\t\tTestLexicographicalCompareEa (stopwatch2,  eaVectorUChar1.begin(),  eaVectorUChar2.end(),  eaVectorUChar2.begin(),  eaVectorUChar2.end());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/lex_cmp/vector<uchar>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestLexicographicalCompareStd(stopwatch1, &stdVectorSChar1[0], &stdVectorSChar1[0] + stdVectorSChar1.size(), &stdVectorSChar2[0], &stdVectorSChar2[0] + stdVectorSChar2.size());\n\t\t\tTestLexicographicalCompareEa (stopwatch2,  &eaVectorSChar1[0],  &eaVectorSChar1[0] +  eaVectorSChar1.size(),  &eaVectorSChar2[0],  &eaVectorSChar2[0] +  eaVectorSChar2.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/lex_cmp/schar[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestLexicographicalCompareStd(stopwatch1, stdVectorTO1.begin(), stdVectorTO1.end(), stdVectorTO2.begin(), stdVectorTO2.end());\n\t\t\tTestLexicographicalCompareEa (stopwatch2,  eaVectorTO1.begin(),  eaVectorTO1.end(),  eaVectorTO2.begin(),  eaVectorTO2.end());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/lex_cmp/vector<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n\n}\n\n\nvoid BenchmarkAlgorithm4(EASTLTest_Rand& /*rng*/, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\t{\n\t\tstd::vector<uint32_t>   stdVectorUint321(10000);\n\t\tstd::vector<uint32_t>   stdVectorUint322(10000);\n\t\teastl::vector<uint32_t> eaVectorUint321(10000);\n\t\teastl::vector<uint32_t> eaVectorUint322(10000);\n\n\t\tstd::vector<uint64_t>   stdVectorUint64(100000);\n\t\teastl::vector<uint64_t> eaVectorUint64(100000);\n\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test copy\n\t\t\t///////////////////////////////\n\n\t\t\tTestCopyStd(stopwatch1, stdVectorUint321.begin(), stdVectorUint321.end(), stdVectorUint322.begin());\n\t\t\tTestCopyEa (stopwatch2,  eaVectorUint321.begin(),  eaVectorUint321.end(),  eaVectorUint322.begin());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/copy/vector<uint32_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test copy_backward\n\t\t\t///////////////////////////////\n\n\t\t\tTestCopyBackwardStd(stopwatch1, stdVectorUint321.begin(), stdVectorUint321.end(), stdVectorUint322.end());\n\t\t\tTestCopyBackwardEa (stopwatch2,  eaVectorUint321.begin(),  eaVectorUint321.end(),  eaVectorUint322.end());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/copy_backward/vector<uint32_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test fill\n\t\t\t///////////////////////////////\n\n\t\t\tTestFillStd(stopwatch1, stdVectorUint64.begin(), stdVectorUint64.end(), UINT64_C(37));\n\t\t\tTestFillEa (stopwatch2,  eaVectorUint64.begin(),  eaVectorUint64.end(), UINT64_C(37));\n\t\t\tTestFillStd(stopwatch1, stdVectorUint64.begin(), stdVectorUint64.end(), UINT64_C(37)); // Intentionally do this a second time, as we are finding \n\t\t\tTestFillEa (stopwatch2,  eaVectorUint64.begin(),  eaVectorUint64.end(), UINT64_C(37)); // the results are inconsistent otherwise.\n\t\t\tif(EA::StdC::Memcheck64(&eaVectorUint64[0], UINT64_C(37), eaVectorUint64.size()))\n\t\t\t\tEA::UnitTest::Report(\"eastl algorithm 64 bit fill failure.\");\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill/vector<uint64_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test fill_n\n\t\t\t///////////////////////////////\n\n\t\t\tTestFillNStd(stopwatch1, stdVectorUint64.begin(), (int)stdVectorUint64.size(), UINT64_C(37));\n\t\t\tTestFillNEa (stopwatch2,  eaVectorUint64.begin(), (int) eaVectorUint64.size(), UINT64_C(37));\n\t\t\tTestFillNStd(stopwatch1, stdVectorUint64.begin(), (int)stdVectorUint64.size(), UINT64_C(37)); // Intentionally do this a second time, as we are finding \n\t\t\tTestFillNEa (stopwatch2,  eaVectorUint64.begin(), (int) eaVectorUint64.size(), UINT64_C(37));  // the results are inconsistent otherwise.\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill_n/vector<uint64_t>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\n\nvoid BenchmarkAlgorithm5(EASTLTest_Rand& /*rng*/, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\t{\n\t\tstd::vector<void*>      stdVectorVoid(100000);\n\t\teastl::vector<void*>    eaVectorVoid(100000);\n\n\t\tstd::vector<char>       stdVectorChar(100000);\n\t\teastl::vector<char>     eaVectorChar(100000);\n\n\t\tstd::vector<bool>       stdVectorBool(100000);\n\t\teastl::vector<bool>     eaVectorBool(100000);\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tTestFillStd(stopwatch1, stdVectorVoid.begin(), stdVectorVoid.end(), (void*)NULL);\n\t\t\tTestFillEa (stopwatch2, eaVectorVoid.begin(),  eaVectorVoid.end(),  (void*)NULL);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill/vector<void*>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFillStd(stopwatch1,    &stdVectorChar[0],     &stdVectorChar[0] + stdVectorChar.size(), 'd'); // Intentionally use ' ' and not casted to any type.\n\t\t\tTestFillEa (stopwatch2,  eaVectorChar.data(),   eaVectorChar.data() +  eaVectorChar.size(), 'd');\n\t\t\tTestFillStd(stopwatch1,    &stdVectorChar[0],     &stdVectorChar[0] + stdVectorChar.size(), 'd'); // Intentionally do this a second time, as we are finding \n\t\t\tTestFillEa (stopwatch2,  eaVectorChar.data(),   eaVectorChar.data() +  eaVectorChar.size(), 'd'); // the results are inconsistent otherwise.\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill/char[]/'d'\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFillStd(stopwatch1, stdVectorChar.begin(), stdVectorChar.end(), (char)'d'); \n\t\t\tTestFillEa (stopwatch2,  eaVectorChar.begin(),  eaVectorChar.end(), (char)'d');\n\t\t\tTestFillStd(stopwatch1, stdVectorChar.begin(), stdVectorChar.end(), (char)'d'); // Intentionally do this a second time, as we are finding \n\t\t\tTestFillEa (stopwatch2,  eaVectorChar.begin(),  eaVectorChar.end(), (char)'d'); // the results are inconsistent otherwise.\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill/vector<char>/'d'\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFillStd(stopwatch1, stdVectorChar.begin(), stdVectorChar.end(), (char)0); \n\t\t\tTestFillEa (stopwatch2,  eaVectorChar.begin(),  eaVectorChar.end(), (char)0);\n\t\t\tTestFillStd(stopwatch1, stdVectorChar.begin(), stdVectorChar.end(), (char)0); // Intentionally do this a second time, as we are finding \n\t\t\tTestFillEa (stopwatch2,  eaVectorChar.begin(),  eaVectorChar.end(), (char)0); // the results are inconsistent otherwise.\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill/vector<char>/0\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFillStd(stopwatch1,  eaVectorBool.data(),   eaVectorBool.data() +  eaVectorBool.size(), false); // Intentionally use eaVectorBool for the array. \n\t\t\tTestFillEa (stopwatch2,  eaVectorBool.data(),   eaVectorBool.data() +  eaVectorBool.size(), false);\n\t\t\tTestFillStd(stopwatch1,  eaVectorBool.data(),   eaVectorBool.data() +  eaVectorBool.size(), false);\n\t\t\tTestFillEa (stopwatch2,  eaVectorBool.data(),   eaVectorBool.data() +  eaVectorBool.size(), false);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill/bool[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test fill_n\n\t\t\t///////////////////////////////\n\n\t\t\tTestFillNStd(stopwatch1,  eaVectorChar.data(), (int) eaVectorChar.size(), 'd'); // Intentionally use eaVectorBool for the array.\n\t\t\tTestFillNEa (stopwatch2,  eaVectorChar.data(), (int) eaVectorChar.size(), 'd');\n\t\t\tTestFillNStd(stopwatch1,  eaVectorChar.data(), (int) eaVectorChar.size(), 'd'); // Intentionally do this a second time, as we are finding \n\t\t\tTestFillNEa (stopwatch2,  eaVectorChar.data(), (int) eaVectorChar.size(), 'd'); // the results are inconsistent otherwise.\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill_n/char[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFillNStd(stopwatch1,  eaVectorBool.data(), (int) eaVectorBool.size(), false); // Intentionally use eaVectorBool for the array.\n\t\t\tTestFillNEa (stopwatch2,  eaVectorBool.data(), (int) eaVectorBool.size(), false);\n\t\t\tTestFillNStd(stopwatch1,  eaVectorBool.data(), (int) eaVectorBool.size(), false); // Intentionally do this a second time, as we are finding \n\t\t\tTestFillNEa (stopwatch2,  eaVectorBool.data(), (int) eaVectorBool.size(), false); // the results are inconsistent otherwise.\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/fill_n/bool[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\n\nvoid BenchmarkAlgorithm6(EASTLTest_Rand& /*rng*/, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\t// We allocate this on the heap because some platforms don't always have enough stack space for this.\n\tstd::vector<LargePOD>*   pstdVectorLP1 = new std::vector<LargePOD>(100);\n\tstd::vector<LargePOD>*   pstdVectorLP2 = new std::vector<LargePOD>(100);\n\teastl::vector<LargePOD>* peaVectorLP1  = new eastl::vector<LargePOD>(100);\n\teastl::vector<LargePOD>* peaVectorLP2  = new eastl::vector<LargePOD>(100);\n\n\t// Aliases.\n\tstd::vector<LargePOD>&   stdVectorLP1 = *pstdVectorLP1;\n\tstd::vector<LargePOD>&   stdVectorLP2 = *pstdVectorLP2;\n\teastl::vector<LargePOD>& eaVectorLP1  = *peaVectorLP1;\n\teastl::vector<LargePOD>& eaVectorLP2  = *peaVectorLP2;\n\n\tfor(int i = 0; i < 2; i++)\n\t{\n\t\t///////////////////////////////\n\t\t// Test copy\n\t\t///////////////////////////////\n\n\t\tTestCopyStd(stopwatch1, stdVectorLP1.begin(), stdVectorLP1.end(), stdVectorLP2.begin());\n\t\tTestCopyEa (stopwatch2,  eaVectorLP1.begin(),  eaVectorLP1.end(),  eaVectorLP2.begin());\n\n\t\tif(i == 1)\n\t\t\tBenchmark::AddResult(\"algorithm/copy/vector<LargePOD>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t///////////////////////////////\n\t\t// Test copy_backward\n\t\t///////////////////////////////\n\n\t\tTestCopyBackwardStd(stopwatch1, stdVectorLP1.begin(), stdVectorLP1.end(), stdVectorLP2.end());\n\t\tTestCopyBackwardEa (stopwatch2,  eaVectorLP1.begin(),  eaVectorLP1.end(),  eaVectorLP2.end());\n\n\t\tif(i == 1)\n\t\t\tBenchmark::AddResult(\"algorithm/copy_backward/vector<LargePOD>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t}\n\n\tdelete pstdVectorLP1;\n\tdelete pstdVectorLP2;\n\tdelete peaVectorLP1;\n\tdelete peaVectorLP2;\n}\n\n\nvoid BenchmarkAlgorithm7(EASTLTest_Rand& /*rng*/, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\t{\n\t\tstd::list<TestObject>     stdListTO(10000);\n\t\teastl::list<TestObject>   eaListTO(10000);\n\n\t\tstd::vector<TestObject>   stdVectorTO(10000);\n\t\teastl::vector<TestObject> eaVectorTO(10000);\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test reverse\n\t\t\t///////////////////////////////\n\n\t\t\tTestReverseStd(stopwatch1, stdListTO.begin(), stdListTO.end());\n\t\t\tTestReverseEa (stopwatch2,  eaListTO.begin(),  eaListTO.end());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/reverse/list<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestReverseStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.end());\n\t\t\tTestReverseEa (stopwatch2,  eaVectorTO.begin(),  eaVectorTO.end());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/reverse/vector<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n\n\t{\n\t\t// Create some containers and seed them with incremental values (i.e. 0, 1, 2, 3...).\n\t\teastl::slist<int32_t> eaSlistIntLarge(10000);\n\t\teastl::generate(eaSlistIntLarge.begin(), eaSlistIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\n\t\tstd::vector< SizedPOD<32> > stdVectorLargePod32(10000);\n\t\tfor(std::vector< SizedPOD<32> >::iterator it = stdVectorLargePod32.begin(); it != stdVectorLargePod32.end(); ++it)\n\t\t\tmemset(&*it, 0, sizeof(SizedPOD<32>));\n\t\teastl::vector< SizedPOD<32> > eaVectorLargePod32(10000);\n\t\tfor(eastl::vector< SizedPOD<32> >::iterator it = eaVectorLargePod32.begin(); it != eaVectorLargePod32.end(); ++it)\n\t\t\tmemset(&*it, 0, sizeof(SizedPOD<32>));\n\n\t\tstd::list<int32_t> stdListIntLarge(10000);\n\t\teastl::generate(stdListIntLarge.begin(), stdListIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\t\teastl::list<int32_t> eaListIntLarge(10000);\n\t\teastl::generate(eaListIntLarge.begin(), eaListIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\n\t\tstd::vector<int32_t> stdVectorIntLarge(10000);\n\t\teastl::generate(stdVectorIntLarge.begin(), stdVectorIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\t\teastl::vector<int32_t> eaVectorIntLarge(10000);\n\t\teastl::generate(eaVectorIntLarge.begin(), eaVectorIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\n\t\tstd::list<int32_t> stdListIntSmall(10);\n\t\teastl::generate(stdListIntLarge.begin(), stdListIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\t\teastl::list<int32_t> eaListIntSmall(10);\n\t\teastl::generate(eaListIntLarge.begin(), eaListIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\n\t\tstd::vector<int32_t> stdVectorIntSmall(10);\n\t\teastl::generate(stdVectorIntLarge.begin(), stdVectorIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\t\teastl::vector<int32_t> eaVectorIntSmall(10);\n\t\teastl::generate(eaVectorIntLarge.begin(), eaVectorIntLarge.end(), GenerateIncrementalIntegers<int32_t>());\n\n\n\n\t\tstd::list<TestObject> stdListTOLarge(10000);\n\t\teastl::generate(stdListTOLarge.begin(), stdListTOLarge.end(), GenerateIncrementalIntegers<TestObject>());\n\n\t\teastl::list<TestObject> eaListTOLarge(10000);\n\t\teastl::generate(eaListTOLarge.begin(), eaListTOLarge.end(), GenerateIncrementalIntegers<TestObject>());\n\n\n\t\tstd::vector<TestObject> stdVectorTOLarge(10000);\n\t\teastl::generate(stdVectorTOLarge.begin(), stdVectorTOLarge.end(), GenerateIncrementalIntegers<TestObject>());\n\n\t\teastl::vector<TestObject> eaVectorTOLarge(10000);\n\t\teastl::generate(eaVectorTOLarge.begin(), eaVectorTOLarge.end(), GenerateIncrementalIntegers<TestObject>());\n\n\n\t\tstd::list<TestObject> stdListTOSmall(10);\n\t\teastl::generate(stdListTOSmall.begin(), stdListTOSmall.end(), GenerateIncrementalIntegers<TestObject>());\n\n\t\teastl::list<TestObject> eaListTOSmall(10);\n\t\teastl::generate(eaListTOSmall.begin(), eaListTOSmall.end(), GenerateIncrementalIntegers<TestObject>());\n\n\n\t\tstd::vector<TestObject> stdVectorTOSmall(10);\n\t\teastl::generate(stdVectorTOSmall.begin(), stdVectorTOSmall.end(), GenerateIncrementalIntegers<TestObject>());\n\n\t\teastl::vector<TestObject> eaVectorTOSmall(10);\n\t\teastl::generate(eaVectorTOSmall.begin(), eaVectorTOSmall.end(), GenerateIncrementalIntegers<TestObject>());\n\t\t\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test reverse\n\t\t\t///////////////////////////////\n\n\t\t\t// There is no guaranteed Standard Library forward_list or slist.\n\t\t\tTestRotateEa (stopwatch2,  eaSlistIntLarge.begin(), eastl::next( eaSlistIntLarge.begin(),  (eaSlistIntLarge.size() / 2) - 1),  eaSlistIntLarge.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/slist<int32_t> large\", stopwatch1.GetUnits(), 0 /* untested */, stopwatch2.GetElapsedTime());\n\n\n\n\t\t\tTestRotateStd(stopwatch1, stdVectorLargePod32.begin(), std__::next(stdVectorLargePod32.begin(), (stdVectorLargePod32.size() / 2) - 1), stdVectorLargePod32.end());\n\t\t\tTestRotateEa (stopwatch2,  eaVectorLargePod32.begin(), eastl::next( eaVectorLargePod32.begin(),  (eaVectorLargePod32.size() / 2) - 1),  eaVectorLargePod32.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/vector<SizedPOD<32>> large\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\tTestRotateStd(stopwatch1, stdListIntLarge.begin(), std__::next(stdListIntLarge.begin(), (stdListIntLarge.size() / 2) - 1), stdListIntLarge.end());\n\t\t\tTestRotateEa (stopwatch2,  eaListIntLarge.begin(), eastl::next( eaListIntLarge.begin(),  (eaListIntLarge.size() / 2) - 1),  eaListIntLarge.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/list<int32_t> large\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestRotateStd(stopwatch1, stdVectorIntLarge.begin(), std__::next(stdVectorIntLarge.begin(), (stdVectorIntLarge.size() / 2) - 1), stdVectorIntLarge.end());\n\t\t\tTestRotateEa (stopwatch2,  eaVectorIntLarge.begin(), eastl::next( eaVectorIntLarge.begin(),  (eaVectorIntLarge.size() / 2) - 1),  eaVectorIntLarge.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/vector<int32_t large>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\tTestRotateStd(stopwatch1, stdListIntSmall.begin(), std__::next(stdListIntSmall.begin(), (stdListIntSmall.size() / 2) - 1), stdListIntSmall.end());\n\t\t\tTestRotateEa (stopwatch2,  eaListIntSmall.begin(), eastl::next( eaListIntSmall.begin(),  (eaListIntSmall.size() / 2) - 1),  eaListIntSmall.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/list<int32_t> small\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestRotateStd(stopwatch1, stdVectorIntSmall.begin(), std__::next(stdVectorIntSmall.begin(), (stdVectorIntSmall.size() / 2) - 1), stdVectorIntSmall.end());\n\t\t\tTestRotateEa (stopwatch2,  eaVectorIntSmall.begin(), eastl::next( eaVectorIntSmall.begin(),  (eaVectorIntSmall.size() / 2) - 1),  eaVectorIntSmall.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/vector<int32_t small>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\tTestRotateStd(stopwatch1, stdListTOLarge.begin(), std__::next(stdListTOLarge.begin(), (stdListTOLarge.size() / 2) - 1), stdListTOLarge.end());\n\t\t\tTestRotateEa (stopwatch2,  eaListTOLarge.begin(), eastl::next( eaListTOLarge.begin(),  (eaListTOLarge.size() / 2) - 1),  eaListTOLarge.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/list<TestObject large>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestRotateStd(stopwatch1, stdVectorTOLarge.begin(), std__::next(stdVectorTOLarge.begin(), (stdVectorTOLarge.size() / 2) - 1), stdVectorTOLarge.end());\n\t\t\tTestRotateEa (stopwatch2,  eaVectorTOLarge.begin(), eastl::next( eaVectorTOLarge.begin(),  (eaVectorTOLarge.size() / 2) - 1),  eaVectorTOLarge.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/vector<TestObject large>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\tTestRotateStd(stopwatch1, stdListTOSmall.begin(), std__::next(stdListTOSmall.begin(), (stdListTOSmall.size() / 2) - 1), stdListTOSmall.end());\n\t\t\tTestRotateEa (stopwatch2,  eaListTOSmall.begin(), eastl::next( eaListTOSmall.begin(),  (eaListTOSmall.size() / 2) - 1),  eaListTOSmall.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/list<TestObject small>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestRotateStd(stopwatch1, stdVectorTOSmall.begin(), std__::next(stdVectorTOSmall.begin(), (stdVectorTOSmall.size() / 2) - 1), stdVectorTOSmall.end());\n\t\t\tTestRotateEa (stopwatch2,  eaVectorTOSmall.begin(), eastl::next( eaVectorTOSmall.begin(),  (eaVectorTOSmall.size() / 2) - 1),  eaVectorTOSmall.end());\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"algorithm/rotate/vector<TestObject small>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\nvoid BenchmarkAlgorithm8(EASTLTest_Rand& rng, EA::StdC::Stopwatch& stopwatch1, EA::StdC::Stopwatch& stopwatch2)\n{\n\tconst uint32_t ElementCount = 10000;\n\n\teastl::vector<int> srcVecA(ElementCount);\n\teastl::vector<int> srcVecB(ElementCount);\n\n\tstd::vector<int> stdVecAInt(ElementCount);\n\tstd::vector<int> stdVecBInt(ElementCount);\n\tstd::vector<int> stdVecOutInt(2 * ElementCount);\n\tstd::vector<TestObject> stdVecATestObject(ElementCount);\n\tstd::vector<TestObject> stdVecBTestObject(ElementCount);\n\tstd::vector<TestObject> stdVecOutTestObject(2 * ElementCount);\n\n\teastl::vector<int> eaVecAInt(ElementCount);\n\teastl::vector<int> eaVecBInt(ElementCount);\n\teastl::vector<int> eaVecOutInt(2 * ElementCount);\n\teastl::vector<TestObject> eaVecATestObject(ElementCount);\n\teastl::vector<TestObject> eaVecBTestObject(ElementCount);\n\teastl::vector<TestObject> eaVecOutTestObject(2 * ElementCount);\n\n\t// Note:\n\t//   In some cases the compiler may generate branch free code for the loop body of merge.\n\t//   In this situation the performance of merging data that has a random merge selection (i.e. the chance that the smallest\n\t//   element is taken from the first or second list is essentially random) is the same as merging data where the choice of\n\t//   which list has the smallest element is predictable.\n\t//   However, if the compiler doesn't generate branch free code, then the performance of merge will suffer from branch\n\t//   misprediction when merging random data and will benefit greatly when misprediction is rare.\n\t//   This benchmark is aimed at highlighting what sort of code is being generated, and also showing the impact of\n\t//   predictability of the comparisons performed during merge.  The branch predictablity /can/ have a large impact\n\t//   on merge sort performance.\n\n\t// 'unpred' is the case where the comparison is unpredictable\n\t// 'pred' is the case where the comparison is mostly predictable\n\tconst char* patternDescriptions[][2] =\n\t{\n\t\t{\n\t\t\t\"algorithm/merge/vector<int> (unpred)\",\n\t\t\t\"algorithm/merge/vector<int> (pred)\",\n\t\t},\n\t\t{\n\t\t\t\"algorithm/merge/vector<TestObject> (unpred)\",\n\t\t\t\"algorithm/merge/vector<TestObject> (pred)\",\n\t\t},\n\t};\n\n\tenum Pattern\n\t{\n\t\tP_Random,\n\t\tP_Predictable,\n\t\tP_Count\n\t};\n\n\tfor (int pattern = 0; pattern < P_Count; pattern++)\n\t{\n\t\tif (pattern == P_Random)\n\t\t{\n\t\t\teastl::generate(srcVecA.begin(), srcVecA.end(), [&]{ return int(rng()); });\n\t\t\teastl::sort(srcVecA.begin(), srcVecA.end());\n\t\t\teastl::generate(srcVecB.begin(), srcVecB.end(), [&] { return int(rng()); });\n\t\t\teastl::sort(srcVecB.begin(), srcVecB.end());\n\t\t}\n\t\telse if (pattern == P_Predictable)\n\t\t{\n\t\t\t// The data pattern means that a simple/naive algorithm will select 'runLen' values\n\t\t\t// from one list, and then 'runLen' values from the other list (alternating back and forth).\n\t\t\t// Of course, a merge algorithm that is more complicated might have a different order of\n\t\t\t// comparison.\n\t\t\tconst int runLen = 32;\n\t\t\tfor (int i = 0; i < ElementCount; i++)\n\t\t\t{\n\t\t\t\tint baseValue = ((i / runLen) * 2 * runLen) + (i % (runLen));\n\t\t\t\tsrcVecA[i] = baseValue;\n\t\t\t\tsrcVecB[i] = baseValue + runLen;\n\t\t\t}\n\t\t}\n\n\t\t///////////////////////////////\n\t\t// Test merge\n\t\t///////////////////////////////\n\t\tfor (int i = 0; i < 2; i++)\n\t\t{\n\t\t\teastl::copy(srcVecA.begin(), srcVecA.end(), stdVecAInt.begin());\n\t\t\teastl::copy(srcVecB.begin(), srcVecB.end(), stdVecBInt.begin());\n\t\t\teastl::copy(srcVecA.begin(), srcVecA.end(), eaVecAInt.begin());\n\t\t\teastl::copy(srcVecB.begin(), srcVecB.end(), eaVecBInt.begin());\n\t\t\tTestMergeStd(stopwatch1, stdVecAInt.begin(), stdVecAInt.end(), stdVecBInt.begin(), stdVecBInt.end(), stdVecOutInt.begin());\n\t\t\tTestMergeEa(stopwatch2, eaVecAInt.begin(), eaVecAInt.end(), eaVecBInt.begin(), eaVecBInt.end(), eaVecOutInt.begin());\n\n\t\t\tif (i == 1)\n\t\t\t{\n\t\t\t\tBenchmark::AddResult(patternDescriptions[0][pattern], stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t\t}\n\n\t\t\tfor (int j = 0; j < ElementCount; j++)\n\t\t\t{\n\t\t\t\tstdVecATestObject[j] = TestObject(srcVecA[j]);\n\t\t\t\tstdVecBTestObject[j] = TestObject(srcVecB[j]);\n\t\t\t\teaVecATestObject[j] = TestObject(srcVecA[j]);\n\t\t\t\teaVecBTestObject[j] = TestObject(srcVecB[j]);\n\t\t\t}\n\t\t\tTestMergeStd(stopwatch1, stdVecATestObject.begin(), stdVecATestObject.end(), stdVecBTestObject.begin(), stdVecBTestObject.end(), stdVecOutTestObject.begin());\n\t\t\tTestMergeEa(stopwatch2, eaVecATestObject.begin(), eaVecATestObject.end(), eaVecBTestObject.begin(), eaVecBTestObject.end(), eaVecOutTestObject.begin());\n\n\t\t\tif (i == 1)\n\t\t\t{\n\t\t\t\tBenchmark::AddResult(patternDescriptions[1][pattern], stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\n\nvoid BenchmarkAlgorithm()\n{\n\tEASTLTest_Printf(\"Algorithm\\n\");\n\n\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch  stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch  stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\tBenchmarkAlgorithm1(rng, stopwatch1, stopwatch2);\n\tBenchmarkAlgorithm2(rng, stopwatch1, stopwatch2);\n\tBenchmarkAlgorithm3(rng, stopwatch1, stopwatch2);\n\tBenchmarkAlgorithm4(rng, stopwatch1, stopwatch2);\n\tBenchmarkAlgorithm5(rng, stopwatch1, stopwatch2);\n\tBenchmarkAlgorithm6(rng, stopwatch1, stopwatch2);\n\tBenchmarkAlgorithm7(rng, stopwatch1, stopwatch2);\n\tBenchmarkAlgorithm8(rng, stopwatch1, stopwatch2);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkBitset.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifdef _MSC_VER\n\t// Microsoft STL generates warnings.\n\t#pragma warning(disable: 4267) // 'initializing' : conversion from 'size_t' to 'const int', possible loss of data\n#endif\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/bitset.h>\n\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <bitset>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\nusing namespace EA;\n\n\nnamespace\n{\n\ttemplate <typename Bitset>\n\tvoid TestSet(EA::StdC::Stopwatch& stopwatch, Bitset& b)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t{\n\t\t\tb.set();\n\t\t\tBenchmark::DoNothing(&b);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Bitset>\n\tvoid TestSetIndex(EA::StdC::Stopwatch& stopwatch, Bitset& b, size_t index)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t{\n\t\t\tb.set(index);\n\t\t\tBenchmark::DoNothing(&b);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Bitset>\n\tvoid TestReset(EA::StdC::Stopwatch& stopwatch, Bitset& b)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t{\n\t\t\tb.reset();\n\t\t\tBenchmark::DoNothing(&b);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Bitset>\n\tvoid TestFlip(EA::StdC::Stopwatch& stopwatch, Bitset& b)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t{\n\t\t\tb.flip();\n\t\t\tBenchmark::DoNothing(&b);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Bitset>\n\tvoid TestTest(EA::StdC::Stopwatch& stopwatch, Bitset& b, unsigned nANDValue)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(unsigned i = 0; i < 100000; i++)\n\t\t\tBenchmark::DoNothing(b.test(i & nANDValue)); // We use & instead of % because the former is always fast due to forced power of 2.\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Bitset>\n\tvoid TestCount(EA::StdC::Stopwatch& stopwatch, Bitset& b)\n\t{\n\t\tsize_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t{\n\t\t\ttemp += b.count();\n\t\t\tBenchmark::DoNothing(&temp);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Bitset>\n\tvoid TestRightShift(EA::StdC::Stopwatch& stopwatch, Bitset& b, size_t n)\n\t{\n\t\tsize_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t{\n\t\t\tb >>= n;\n\t\t\tBenchmark::DoNothing(&temp);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n} // namespace\n\n\n\nvoid BenchmarkBitset()\n{\n\tEASTLTest_Printf(\"Bitset\\n\");\n\n\tEA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\tstd::bitset<15>     stdBitset15;\n\t\teastl::bitset<15>   eaBitset15;\n\n\t\tstd::bitset<35>     stdBitset35;\n\t\teastl::bitset<35>   eaBitset35;\n\n\t\tstd::bitset<75>     stdBitset75;\n\t\teastl::bitset<75>   eaBitset75;\n\n\t\tstd::bitset<1500>   stdBitset1500;\n\t\teastl::bitset<1500> eaBitset1500;\n\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test set()\n\t\t\t///////////////////////////////\n\n\t\t\tTestSet(stopwatch1, stdBitset15);\n\t\t\tTestSet(stopwatch2, eaBitset15);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<15>/set()\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSet(stopwatch1, stdBitset35);\n\t\t\tTestSet(stopwatch2, eaBitset35);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<35>/set()\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSet(stopwatch1, stdBitset75);\n\t\t\tTestSet(stopwatch2, eaBitset75);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<75>/set()\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSet(stopwatch1, stdBitset1500);\n\t\t\tTestSet(stopwatch2, eaBitset1500);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<1500>/set()\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test set(index)\n\t\t\t///////////////////////////////\n\n\t\t\tTestSetIndex(stopwatch1, stdBitset15, 13);\n\t\t\tTestSetIndex(stopwatch2, eaBitset15, 13);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<15>/set(i)\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSetIndex(stopwatch1, stdBitset35, 33);\n\t\t\tTestSetIndex(stopwatch2, eaBitset35, 33);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<35>/set(i)\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSetIndex(stopwatch1, stdBitset75, 73);\n\t\t\tTestSetIndex(stopwatch2, eaBitset75, 73);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<75>/set(i)\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSetIndex(stopwatch1, stdBitset1500, 730);\n\t\t\tTestSetIndex(stopwatch2, eaBitset1500, 730);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<1500>/set(i)\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test reset()\n\t\t\t///////////////////////////////\n\n\t\t\tTestReset(stopwatch1, stdBitset15);\n\t\t\tTestReset(stopwatch2, eaBitset15);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<15>/reset\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestReset(stopwatch1, stdBitset35);\n\t\t\tTestReset(stopwatch2, eaBitset35);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<35>/reset\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestReset(stopwatch1, stdBitset75);\n\t\t\tTestReset(stopwatch2, eaBitset75);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<75>/reset\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestReset(stopwatch1, stdBitset1500);\n\t\t\tTestReset(stopwatch2, eaBitset1500);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<1500>/reset\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test flip\n\t\t\t///////////////////////////////\n\n\t\t\tTestFlip(stopwatch1, stdBitset15);\n\t\t\tTestFlip(stopwatch2, eaBitset15);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<15>/flip\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFlip(stopwatch1, stdBitset35);\n\t\t\tTestFlip(stopwatch2, eaBitset35);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<35>/flip\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFlip(stopwatch1, stdBitset75);\n\t\t\tTestFlip(stopwatch2, eaBitset75);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<75>/flip\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFlip(stopwatch1, stdBitset1500);\n\t\t\tTestFlip(stopwatch2, eaBitset1500);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<1500>/flip\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test test\n\t\t\t///////////////////////////////\n\n\t\t\tTestTest(stopwatch1, stdBitset15, 7);\n\t\t\tTestTest(stopwatch2, eaBitset15, 7);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<15>/test\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestTest(stopwatch1, stdBitset35, 31);\n\t\t\tTestTest(stopwatch2, eaBitset35, 31);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<35>/test\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestTest(stopwatch1, stdBitset75, 63);\n\t\t\tTestTest(stopwatch2, eaBitset75, 63);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<75>/test\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestTest(stopwatch1, stdBitset1500, 1023);\n\t\t\tTestTest(stopwatch2, eaBitset1500, 1023);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<1500>/test\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test count\n\t\t\t///////////////////////////////\n\n\t\t\tTestCount(stopwatch1, stdBitset15);\n\t\t\tTestCount(stopwatch2, eaBitset15);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<15>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestCount(stopwatch1, stdBitset35);\n\t\t\tTestCount(stopwatch2, eaBitset35);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<35>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestCount(stopwatch1, stdBitset75);\n\t\t\tTestCount(stopwatch2, eaBitset75);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<75>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestCount(stopwatch1, stdBitset1500);\n\t\t\tTestCount(stopwatch2, eaBitset1500);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<1500>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test >>=\n\t\t\t///////////////////////////////\n\n\t\t\tTestRightShift(stopwatch1, stdBitset15, 1);\n\t\t\tTestRightShift(stopwatch2, eaBitset15, 1);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<15>/>>=/1\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t\tGetStdSTLType() == kSTLPort ? \"STLPort is broken, neglects wraparound check.\" : NULL);\n\n\t\t\tTestRightShift(stopwatch1, stdBitset35, 1);\n\t\t\tTestRightShift(stopwatch2, eaBitset35, 1);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<35>/>>=/1\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t\tGetStdSTLType() == kSTLPort ? \"STLPort is broken, neglects wraparound check.\" : NULL);\n\n\t\t\tTestRightShift(stopwatch1, stdBitset75, 1);\n\t\t\tTestRightShift(stopwatch2, eaBitset75, 1);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<75>/>>=/1\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t\tGetStdSTLType() == kSTLPort ? \"STLPort is broken, neglects wraparound check.\" : NULL);\n\n\t\t\tTestRightShift(stopwatch1, stdBitset1500, 1);\n\t\t\tTestRightShift(stopwatch2, eaBitset1500, 1);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"bitset<1500>/>>=/1\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t\tGetStdSTLType() == kSTLPort ? \"STLPort is broken, neglects wraparound check.\" : NULL);\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkDeque.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/deque.h>\n#include <EASTL/vector.h>\n#include <EASTL/sort.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4350) // behavior change: X called instead of Y\n#endif\n#include <algorithm>\n#include <vector>\n#include <deque>\n#include <stdio.h>\n#include <stdlib.h>\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace EA;\n\n\nnamespace\n{\n\tstruct ValuePair\n\t{\n\t\tuint32_t key;\n\t\tuint32_t v;\n\t};\n\n\tstruct VPCompare\n\t{\n\t\tbool operator()(const ValuePair& vp1, const ValuePair& vp2) const\n\t\t{\n\t\t\treturn (vp1.key == vp2.key) ? (vp1.v < vp2.v) : (vp1.key < vp2.key);\n\t\t}\n\t};\n\n\tbool operator<(const ValuePair& vp1, const ValuePair& vp2)\n\t{\n\t\treturn (vp1.key == vp2.key) ? (vp1.v < vp2.v) : (vp1.key < vp2.key);\n\t}\n\n\tbool operator==(const ValuePair& vp1, const ValuePair& vp2)\n\t{\n\t\treturn (vp1.key == vp2.key) && (vp1.v == vp2.v);\n\t}\n}\n\n\ntypedef std::deque<ValuePair>   StdDeque;\ntypedef eastl::deque<ValuePair, EASTLAllocatorType, 128> EaDeque;  // What value do we pick for the subarray size to make the comparison fair? Using the default isn't ideal because it results in this test measuring speed efficiency and ignoring memory efficiency. \n\n\n\nnamespace\n{\n\ttemplate <typename Container>\n\tvoid TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t{\n\t\t\tconst ValuePair vp = { intVector[j], intVector[j] };\n\t\t\tc.push_back(vp);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestPushFront(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t{\n\t\t\tconst ValuePair vp = { intVector[j], intVector[j] };\n\t\t\tc.push_front(vp);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tuint64_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor(typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)\n\t\t\ttemp += c[j].key;\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(temp & 0xffffffff));\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestIteration(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::iterator it = c.begin(), itEnd = c.end();\n\t\tstopwatch.Restart();\n\t\twhile(it != itEnd)\n\t\t\t++it;\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(*it).key);\n\n\t\t/* Alternative way to measure:\n\t\tconst eastl_size_t n = c.size();\n\t\tstopwatch.Restart();\n\t\tfor(eastl_size_t i = 0; i < n; ++i)\n\t\t\t++it;\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(*it).key);\n\t\t*/\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\t// Intentionally use eastl find in order to measure just  \n\t\t// vector access speed and not be polluted by sort speed.\n\t\tconst ValuePair vp = { 0xffffffff, 0 };\n\t\tstopwatch.Restart();\n\t\ttypename Container::iterator it = eastl::find(c.begin(), c.end(), vp);\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(*it).key);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestSort(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\t// Intentionally use eastl sort in order to measure just  \n\t\t// vector access speed and not be polluted by sort speed.\n\t\tVPCompare vpCompare;\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(c.begin(), c.end(), vpCompare);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c[0].key);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tconst ValuePair               vp = { 0xffffffff, 0 };\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator  it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = 2000, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.insert(it, vp);\n\n\t\t\tif(it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator  it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = 2000, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.erase(it);\n\n\t\t\tif(it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n} // namespace\n\n\n\nvoid BenchmarkDeque()\n{\n\tEASTLTest_Printf(\"Deque\\n\");\n\n\tEA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch              stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch              stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{ // Exercise some declarations\n\t\tint nErrorCount = 0;\n\t\tValuePair vp1 = { 0, 0 }, vp2 = { 0, 0 };\n\t\tVPCompare c1, c2;\n\n\t\tVERIFY(c1.operator()(vp1, vp2) == c2.operator()(vp1, vp2));\n\t\tVERIFY((vp1 < vp2) || (vp1 == vp2) || !(vp1 == vp2));\n\t}\n\n\t{\n\t\teastl::vector<uint32_t> intVector(100000);\n\t\teastl::generate(intVector.begin(), intVector.end(), rng);\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tStdDeque stdDeque;\n\t\t\tEaDeque  eaDeque;\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_back\n\t\t\t///////////////////////////////\n\n\t\t\tTestPushBack(stopwatch1, stdDeque, intVector);\n\t\t\tTestPushBack(stopwatch2,  eaDeque, intVector);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/push_back\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_front\n\t\t\t///////////////////////////////\n\n\t\t\tTestPushFront(stopwatch1, stdDeque, intVector);\n\t\t\tTestPushFront(stopwatch2,  eaDeque, intVector);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/push_front\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test operator[]\n\t\t\t///////////////////////////////\n\n\t\t\tTestBracket(stopwatch1, stdDeque);\n\t\t\tTestBracket(stopwatch2,  eaDeque);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration\n\t\t\t///////////////////////////////\n\n\t\t\tTestIteration(stopwatch1, stdDeque);\n\t\t\tTestIteration(stopwatch2,  eaDeque);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find()\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, stdDeque);\n\t\t\tTestFind(stopwatch2,  eaDeque);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/find\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test sort\n\t\t\t///////////////////////////////\n\n\t\t\t// Currently VC++ complains about our sort function decrementing std::iterator that is already at begin(). In the strictest sense,\n\t\t\t// that's a valid complaint, but we aren't testing std STL here. We will want to revise our sort function eventually.\n\t\t\t#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)\n\t\t\t\tTestSort(stopwatch1, stdDeque);\n\t\t\t\tTestSort(stopwatch2,  eaDeque);\n\n\t\t\t\tif(i == 1)\n\t\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/sort\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t\t#endif\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert\n\t\t\t///////////////////////////////\n\n\t\t\tTestInsert(stopwatch1, stdDeque);\n\t\t\tTestInsert(stopwatch2,  eaDeque);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase\n\t\t\t///////////////////////////////\n\n\t\t\tTestErase(stopwatch1, stdDeque);\n\t\t\tTestErase(stopwatch2,  eaDeque);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"deque<ValuePair>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkHash.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/vector.h>\n#include <EASTL/hash_map.h>\n#include <EASTL/string.h>\n#include <EASTL/algorithm.h>\n\n\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <unordered_map>\n#include <string>\n#include <algorithm>\n#include <stdio.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n\nusing namespace EA;\n\n\n// HashString8\n//\n// We define a string\n//\ntemplate <typename String>\nstruct HashString8\n{\n\t// Defined for EASTL, STLPort, SGI, etc. and Metrowerks-related hash tables:\n\tsize_t operator()(const String& s) const \n\t{ \n\t\tconst uint8_t* p = (const uint8_t*) s.c_str();\n\t\tuint32_t c, stringHash = UINT32_C(2166136261);\n\t\twhile((c = *p++) != 0)\n\t\t\tstringHash = (stringHash * 16777619) ^ c;\n\t\treturn stringHash;\n\t}\n\n\t// Defined for Dinkumware-related (e.g. MS STL) hash tables:\n\tbool operator()(const String& s1, const String& s2) const\n\t{\n\t\treturn s1 < s2;\n\t}\n\n\t// Defined for Dinkumware-related (e.g. MS STL) hash tables:\n\tenum {\n\t\tbucket_size = 7,\n\t\tmin_buckets = 8\n\t};\n};\n\n\nusing StdMapUint32TO = std::unordered_map<uint32_t, TestObject>;\nusing StdMapStrUint32 = std::unordered_map<std::string, uint32_t, HashString8<std::string>>;\n\nusing EaMapUint32TO = eastl::hash_map<uint32_t, TestObject>;\nusing EaMapStrUint32 = eastl::hash_map<eastl::string, uint32_t, HashString8<eastl::string>>;\n\n\nnamespace\n{\n\ttemplate <typename Container, typename Value>\n\tvoid TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\tc.insert(pArrayBegin, pArrayEnd);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestIteration(EA::StdC::Stopwatch& stopwatch, const Container& c, const Value& findValue)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypename Container::const_iterator it = eastl::find(c.begin(), c.end(), findValue); // It shouldn't matter what find implementation we use here, as it merely iterates values.\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*it);\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tBenchmark::DoNothing(&c[pArrayBegin->first]);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\ttypename Container::iterator it = c.find(pArrayBegin->first);\n\t\t\tBenchmark::DoNothing(&it);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestFindAsStd(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\ttypename Container::iterator it = c.find(pArrayBegin->first.c_str());\n\t\t\tBenchmark::DoNothing(&it);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestFindAsEa(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\ttypename Container::iterator it = c.find_as(pArrayBegin->first.c_str());\n\t\t\tBenchmark::DoNothing(&it);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestCount(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\ttypename Container::size_type temp = 0;\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\ttemp += c.count(pArrayBegin->first);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestEraseValue(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tc.erase(pArrayBegin->first);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestErasePosition(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = c.size() / 3, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\t// The erase fucntion is supposed to return an iterator, but the C++ standard was \n\t\t\t// not initially clear about it and some STL implementations don't do it correctly.\n\t\t\t#if (defined(_MSC_VER) || defined(_CPPLIB_VER)) // _CPPLIB_VER is something defined by Dinkumware STL.\n\t\t\t\tit = c.erase(it);\n\t\t\t#else\n\t\t\t\t// This pathway may execute at a slightly different speed than the \n\t\t\t\t// standard behaviour, but that's fine for the benchmark because the\n\t\t\t\t// benchmark is measuring the speed of erasing while iterating, and \n\t\t\t\t// however it needs to get done by the given STL is how it is measured.\n\t\t\t\tconst typename Container::iterator itErase(it++);\n\t\t\t\tc.erase(itErase);\n\t\t\t#endif\n\n\t\t\t++it;\n\t\t\t++it;\n\t\t}\n\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p %p\", &c, &it);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestEraseRange(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator  it1 = c.begin();\n\t\ttypename Container::iterator  it2 = c.begin();\n\n\t\tfor(j = 0, jEnd = c.size() / 3; j < jEnd; ++j)\n\t\t\t++it2;\n\n\t\tstopwatch.Restart();\n\t\tc.erase(it1, it2);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p %p %p\", &c, &it1, &it2);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestClear(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tc.clear();\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t}\n\n\n} // namespace\n\n\n\nvoid BenchmarkHash()\n{\n\tEASTLTest_Printf(\"HashMap\\n\");\n\n\tEA::UnitTest::Rand  rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\teastl::vector<   std::pair<uint32_t, TestObject> > stdVectorUT(10000);\n\t\teastl::vector< eastl::pair<uint32_t, TestObject> >  eaVectorUT(10000);\n\n\t\teastl::vector<   std::pair<  std::string, uint32_t> > stdVectorSU(10000);\n\t\teastl::vector< eastl::pair<eastl::string, uint32_t> >  eaVectorSU(10000);\n\n\t\tfor(eastl_size_t i = 0, iEnd = stdVectorUT.size(); i < iEnd; i++)\n\t\t{\n\t\t\tconst uint32_t n1 = rng.RandLimit((uint32_t)(iEnd / 2));\n\t\t\tconst uint32_t n2 = rng.RandValue();\n\n\t\t\tstdVectorUT[i] =   std::pair<uint32_t, TestObject>(n1, TestObject(n2));\n\t\t\teaVectorUT[i]  = eastl::pair<uint32_t, TestObject>(n1, TestObject(n2));\n\n\t\t\tchar str_n1[32];\n\t\t\tsprintf(str_n1, \"%u\", (unsigned)n1);\n\n\t\t\tstdVectorSU[i] =   std::pair<  std::string, uint32_t>(  std::string(str_n1), n2);\n\t\t\teaVectorSU[i]  = eastl::pair<eastl::string, uint32_t>(eastl::string(str_n1), n2);\n\t\t}\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tStdMapUint32TO  stdMapUint32TO;\n\t\t\tEaMapUint32TO   eaMapUint32TO;\n\n\t\t\tStdMapStrUint32 stdMapStrUint32;\n\t\t\tEaMapStrUint32  eaMapStrUint32;\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert(const value_type&)\n\t\t\t///////////////////////////////\n\n\t\t\tTestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());\n\t\t\tTestInsert(stopwatch2, eaMapUint32TO,   eaVectorUT.data(),  eaVectorUT.data() +  eaVectorUT.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());\n\t\t\tTestInsert(stopwatch2, eaMapStrUint32,    eaVectorSU.data(),  eaVectorSU.data() +  eaVectorSU.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration\n\t\t\t///////////////////////////////\n\n\t\t\tTestIteration(stopwatch1, stdMapUint32TO, StdMapUint32TO::value_type(9999999, TestObject(9999999)));\n\t\t\tTestIteration(stopwatch2,  eaMapUint32TO,  EaMapUint32TO::value_type(9999999, TestObject(9999999)));\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestIteration(stopwatch1, stdMapStrUint32, StdMapStrUint32::value_type(  std::string(\"9999999\"), 9999999));\n\t\t\tTestIteration(stopwatch2,  eaMapStrUint32,  EaMapStrUint32::value_type(eastl::string(\"9999999\"), 9999999));\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test operator[]\n\t\t\t///////////////////////////////\n\n\t\t\tTestBracket(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());\n\t\t\tTestBracket(stopwatch2, eaMapUint32TO,   eaVectorUT.data(),  eaVectorUT.data() +  eaVectorUT.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestBracket(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());\n\t\t\tTestBracket(stopwatch2, eaMapStrUint32,    eaVectorSU.data(),  eaVectorSU.data() +  eaVectorSU.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());\n\t\t\tTestFind(stopwatch2, eaMapUint32TO,   eaVectorUT.data(),  eaVectorUT.data() +  eaVectorUT.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/find\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFind(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());\n\t\t\tTestFind(stopwatch2, eaMapStrUint32,    eaVectorSU.data(),  eaVectorSU.data() +  eaVectorSU.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/find\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find_as\n\t\t\t///////////////////////////////\n\n\t\t\tTestFindAsStd(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());\n\t\t\tTestFindAsEa(stopwatch2, eaMapStrUint32,    eaVectorSU.data(),  eaVectorSU.data() +  eaVectorSU.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/find_as/char*\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test count\n\t\t\t///////////////////////////////\n\n\t\t\tTestCount(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());\n\t\t\tTestCount(stopwatch2, eaMapUint32TO,   eaVectorUT.data(),  eaVectorUT.data() +  eaVectorUT.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestCount(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());\n\t\t\tTestCount(stopwatch2, eaMapStrUint32,   eaVectorSU.data(),  eaVectorSU.data() +  eaVectorSU.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(const key_type& key)\n\t\t\t///////////////////////////////\n\n\t\t\tTestEraseValue(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + (stdVectorUT.size() / 2));\n\t\t\tTestEraseValue(stopwatch2, eaMapUint32TO,   eaVectorUT.data(),  eaVectorUT.data() +  (eaVectorUT.size() / 2));\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/erase val\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestEraseValue(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + (stdVectorSU.size() / 2));\n\t\t\tTestEraseValue(stopwatch2, eaMapStrUint32,   eaVectorSU.data(),  eaVectorSU.data() +  (eaVectorSU.size() / 2));\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/erase val\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(iterator position)\n\t\t\t///////////////////////////////\n\n\t\t\tTestErasePosition(stopwatch1, stdMapUint32TO);\n\t\t\tTestErasePosition(stopwatch2, eaMapUint32TO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/erase pos\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestErasePosition(stopwatch1, stdMapStrUint32);\n\t\t\tTestErasePosition(stopwatch2, eaMapStrUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/erase pos\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(iterator first, iterator last)\n\t\t\t///////////////////////////////\n\n\t\t\tTestEraseRange(stopwatch1, stdMapUint32TO);\n\t\t\tTestEraseRange(stopwatch2, eaMapUint32TO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/erase range\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestEraseRange(stopwatch1, stdMapStrUint32);\n\t\t\tTestEraseRange(stopwatch2, eaMapStrUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/erase range\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test clear()\n\t\t\t///////////////////////////////\n\n\t\t\t// Clear the containers of whatever they happen to have. We want the containers to have full data.\n\t\t\tTestClear(stopwatch1, stdMapUint32TO);\n\t\t\tTestClear(stopwatch2, eaMapUint32TO);\n\t\t\tTestClear(stopwatch1, stdMapStrUint32);\n\t\t\tTestClear(stopwatch2, eaMapStrUint32);\n\n\t\t\t// Re-set the containers with full data.\n\t\t\tTestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());\n\t\t\tTestInsert(stopwatch2, eaMapUint32TO,   eaVectorUT.data(),  eaVectorUT.data() +  eaVectorUT.size());\n\t\t\tTestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());\n\t\t\tTestInsert(stopwatch2, eaMapStrUint32,   eaVectorSU.data(),  eaVectorSU.data() +  eaVectorSU.size());\n\n\t\t\t// Now clear the data again, this time measuring it.\n\t\t\tTestClear(stopwatch1, stdMapUint32TO);\n\t\t\tTestClear(stopwatch2, eaMapUint32TO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<uint32_t, TestObject>/clear\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestClear(stopwatch1, stdMapStrUint32);\n\t\t\tTestClear(stopwatch2, eaMapStrUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"hash_map<string, uint32_t>/clear\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkHeap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/heap.h>\n#include <EASTL/vector.h>\n#include <EASTL/algorithm.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4350) // behavior change: X called instead of Y\n#endif\n#include <algorithm>\n#include <vector>\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace EA;\n\n\nnamespace\n{\n\ttemplate <typename Iterator>\n\tvoid TestMakeHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::make_heap(first, last);\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Iterator>\n\tvoid TestMakeHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::make_heap(first, last);\n\t\tstopwatch.Stop();\n\t}\n\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tvoid TestPushHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(first2 != last2)\n\t\t{\n\t\t\t*last1++ = *first2++;\n\t\t\tstd::push_heap(first1, last1);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tvoid TestPushHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(first2 != last2)\n\t\t{\n\t\t\t*last1++ = *first2++;\n\t\t\teastl::push_heap(first1, last1);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\n\ttemplate <typename Iterator>\n\tvoid TestPopHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, Iterator popEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(last != popEnd)\n\t\t\tstd::pop_heap(first, last--);\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Iterator>\n\tvoid TestPopHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, Iterator popEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(last != popEnd)\n\t\t\teastl::pop_heap(first, last--);\n\t\tstopwatch.Stop();\n\t}\n\n\n\n\ttemplate <typename Iterator>\n\tvoid TestSortHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::sort_heap(first, last);\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Iterator>\n\tvoid TestSortHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::sort_heap(first, last);\n\t\tstopwatch.Stop();\n\t}\n\n} // namespace\n\n\n\nvoid BenchmarkHeap()\n{\n\tEASTLTest_Printf(\"Heap (Priority Queue)\\n\");\n\n\tEA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch              stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch              stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\tconst int kArraySize = 100000;\n\n\t\t// uint32[]\n\t\tuint32_t* const pIntArrayS = new uint32_t[kArraySize * 2];  // * 2 because we will be adding more items via push_heap.\n\t\tuint32_t* const pIntArrayE = new uint32_t[kArraySize * 2];  // S means Std; E means EA.\n\t\tuint32_t* const pIntArray2 = new uint32_t[kArraySize];      // This will be used for pop_heap.\n\n\t\teastl::generate(pIntArrayS, pIntArrayS + kArraySize, rng);\n\t\teastl::copy(pIntArrayS, pIntArrayS + kArraySize, pIntArrayE);\n\t\teastl::copy(pIntArrayS, pIntArrayS + kArraySize, pIntArray2);\n\n\n\t\t// vector<TestObject>\n\t\tstd::vector<TestObject>   stdVectorTO(kArraySize * 2);\n\t\tstd::vector<TestObject>   stdVectorTO2(kArraySize);\n\t\teastl::vector<TestObject> eaVectorTO(kArraySize * 2);\n\t\teastl::vector<TestObject> eaVectorTO2(kArraySize);\n\n\t\tfor(int k = 0; k < kArraySize; k++)\n\t\t{\n\t\t\tstdVectorTO[k]  = TestObject(pIntArrayS[k]);\n\t\t\tstdVectorTO2[k] = TestObject(pIntArrayS[k]);\n\t\t\teaVectorTO[k]   = TestObject(pIntArrayS[k]);\n\t\t\teaVectorTO2[k]  = TestObject(pIntArrayS[k]);\n\t\t}\n\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test make_heap\n\t\t\t///////////////////////////////\n\n\t\t\tTestMakeHeapStd(stopwatch1, pIntArrayS, pIntArrayS + kArraySize);\n\t\t\tTestMakeHeapEa (stopwatch2, pIntArrayE, pIntArrayE + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (uint32_t[])/make_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestMakeHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + kArraySize);\n\t\t\tTestMakeHeapEa (stopwatch2, eaVectorTO.begin(),  eaVectorTO.begin()  + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (vector<TestObject>)/make_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_heap\n\t\t\t///////////////////////////////\n\n\t\t\tTestPushHeapStd(stopwatch1, pIntArrayS, pIntArrayS + kArraySize, pIntArray2, pIntArray2 + kArraySize);\n\t\t\tTestPushHeapEa (stopwatch2, pIntArrayE, pIntArrayE + kArraySize, pIntArray2, pIntArray2 + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (uint32_t[])/push_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestPushHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + kArraySize, stdVectorTO2.begin(), stdVectorTO2.begin() + kArraySize);\n\t\t\tTestPushHeapEa (stopwatch2, eaVectorTO.begin(),  eaVectorTO.begin()  + kArraySize, eaVectorTO2.begin(),  eaVectorTO2.begin()  + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (vector<TestObject>)/push_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test pop_heap\n\t\t\t///////////////////////////////\n\n\t\t\tTestPopHeapStd(stopwatch1, pIntArrayS, pIntArrayS + (kArraySize * 2), pIntArrayS + kArraySize); // * 2 because we used push_heap above to add more items.\n\t\t\tTestPopHeapEa (stopwatch2, pIntArrayE, pIntArrayE + (kArraySize * 2), pIntArrayE + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (uint32_t[])/pop_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestPopHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + (kArraySize * 2), stdVectorTO.begin() + kArraySize); // * 2 because we used push_heap above to add more items.\n\t\t\tTestPopHeapEa (stopwatch2, eaVectorTO.begin(),  eaVectorTO.begin()  + (kArraySize * 2), eaVectorTO.begin()  + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (vector<TestObject>)/pop_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test sort_heap\n\t\t\t///////////////////////////////\n\n\t\t\tTestSortHeapStd(stopwatch1, pIntArrayS, pIntArrayS + kArraySize);\n\t\t\tTestSortHeapEa (stopwatch2, pIntArrayE, pIntArrayE + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (uint32_t[])/sort_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSortHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + kArraySize);\n\t\t\tTestSortHeapEa (stopwatch2, eaVectorTO.begin(),  eaVectorTO.begin()  + kArraySize);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"heap (vector<TestObject>)/sort_heap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\n\t\tdelete[] pIntArrayS;\n\t\tdelete[] pIntArrayE;\n\t\tdelete[] pIntArray2;\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/list.h>\n#include <EASTL/vector.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/random.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4555) // expression has no effect; expected expression with side-effect\n\t#pragma warning(disable: 4350) // behavior change: X called instead of Y\n#endif\n#include <list>\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace EA;\nusing namespace eastl;\n\n\n\ntypedef std::list<TestObject>   StdListTO;\ntypedef eastl::list<TestObject> EaListTO;\n\n\n\nnamespace\n{\n\tvoid DoNothing(void*)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename ContainerSource, typename Container>\n\tvoid TestCtorIterator(EA::StdC::Stopwatch& stopwatch, const ContainerSource& cs, Container*) // Dummy Container argument because of GCC 2.X limitations.\n\t{\n\t\tstopwatch.Restart();\n\t\tContainer c(cs.begin(), cs.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestCtorN(EA::StdC::Stopwatch& stopwatch, Container*) // Dummy Container argument because of GCC 2.X limitations.\n\t{\n\t\tstopwatch.Restart();\n\t\tContainer c(10000);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject* pTOBegin, const TestObject* const pTOEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pTOBegin != pTOEnd)\n\t\t\tc.push_back(*pTOBegin++);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject* pTOBegin, const TestObject* const pTOEnd)\n\t{\n\t\ttypename Container::iterator it = c.begin();\n\t\tstopwatch.Restart();\n\t\twhile(pTOBegin != pTOEnd)\n\t\t{\n\t\t\tit = c.insert(it, *pTOBegin++);\n\n\t\t\tif(++it == c.end()) // Try to safely increment the iterator a couple times\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestSize(EA::StdC::Stopwatch& stopwatch, Container& c, void (*pFunction)(...))\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; (i < 10000) && c.size(); i++)\n\t\t\t(*pFunction)(&c);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject& to)\n\t{\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t\tstopwatch.Restart();\n\t\ttypename Container::iterator it = eastl::find(c.begin(), c.end(), to);\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%d\", (*it).mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestReverse(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t\tstopwatch.Restart();\n\t\tc.reverse();\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestRemove(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject* pTOBegin, const TestObject* const pTOEnd)\n\t{\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t\tstopwatch.Restart();\n\t\twhile(pTOBegin != pTOEnd)\n\t\t\tc.remove(*pTOBegin++);\n\t\tstopwatch.Stop();\n\t\tif(!c.empty())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestSplice(EA::StdC::Stopwatch& stopwatch, Container& c, Container& cSource)\n\t{\n\t\ttypename Container::iterator it = c.begin();\n\t\tint i = 0, iEnd = (int)cSource.size() - 5;\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t\tstopwatch.Restart();\n\t\twhile(i++ != iEnd)\n\t\t\tc.splice(it, cSource, cSource.begin());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::iterator it = c.begin();\n\t\tint i = 0, iEnd = (int)c.size() - 5;\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t\tstopwatch.Restart();\n\t\twhile(i++ != iEnd)\n\t\t{\n\t\t\tit = c.erase(it);\n\n\t\t\tif(it == c.end()) // Try to safely increment the iterator a couple times\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.back().mX);\n\t}\n\n} // namespace\n\n\n\n\nvoid BenchmarkList()\n{\n\tEASTLTest_Printf(\"List\\n\");\n\n\tEASTLTest_Rand      rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\tEaListTO  eaListTO_1(1);\n\tEaListTO  eaListTO_10(10);\n\tEaListTO  eaListTO_100(100);\n\tStdListTO stdListTO_1(1);\n\tStdListTO stdListTO_10(10);\n\tStdListTO stdListTO_100(100);\n\n\t{\n\t\tchar buffer[32];\n\t\tsprintf(buffer, \"%p\", &DoNothing);\n\t}\n\n\t{\n\t\teastl::vector<TestObject> toVector(100000);\n\t\tfor(eastl_size_t i = 0, iEnd = toVector.size(); i < iEnd; ++i)\n\t\t\ttoVector[i] = TestObject((int)i);\n\t\trandom_shuffle(toVector.begin(), toVector.end(), rng);\n\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tStdListTO stdListTO;\n\t\t\tEaListTO  eaListTO;\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test list(InputIterator first, InputIterator last)\n\t\t\t///////////////////////////////\n\n\t\t\tTestCtorIterator(stopwatch1, toVector, &stdListTO);\n\t\t\tTestCtorIterator(stopwatch2, toVector, &eaListTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/ctor(it)\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test list(size_type n)\n\t\t\t///////////////////////////////\n\n\t\t\tTestCtorN(stopwatch1, &stdListTO);\n\t\t\tTestCtorN(stopwatch2, &eaListTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/ctor(n)\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_back()\n\t\t\t///////////////////////////////\n\n\t\t\tTestPushBack(stopwatch1, stdListTO, toVector.data(), toVector.data() + toVector.size());\n\t\t\tTestPushBack(stopwatch2,  eaListTO, toVector.data(), toVector.data() + toVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/push_back\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert()\n\t\t\t///////////////////////////////\n\n\t\t\tTestInsert(stopwatch1, stdListTO, toVector.data(), toVector.data() + toVector.size());\n\t\t\tTestInsert(stopwatch2,  eaListTO, toVector.data(), toVector.data() + toVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test size()\n\t\t\t///////////////////////////////\n\n\t\t\tTestSize(stopwatch1, stdListTO_1, Benchmark::DoNothing);\n\t\t\tTestSize(stopwatch2,  eaListTO_1, Benchmark::DoNothing);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/size/1\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSize(stopwatch1, stdListTO_10, Benchmark::DoNothing);\n\t\t\tTestSize(stopwatch2,  eaListTO_10, Benchmark::DoNothing);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/size/10\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()\n\t\t\t\t\t\t\t\t\t#if !EASTL_LIST_SIZE_CACHE\n\t\t\t\t\t\t\t\t\t\t, \"EASTL is configured to not cache the list size.\"\n\t\t\t\t\t\t\t\t\t#endif\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\tTestSize(stopwatch1, stdListTO_100, Benchmark::DoNothing);\n\t\t\tTestSize(stopwatch2,  eaListTO_100, Benchmark::DoNothing);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/size/100\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()\n\t\t\t\t\t\t\t\t\t#if !EASTL_LIST_SIZE_CACHE\n\t\t\t\t\t\t\t\t\t\t, \"EASTL is configured to not cache the list size.\"\n\t\t\t\t\t\t\t\t\t#endif\n\t\t\t\t\t\t\t\t\t);\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find()\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, stdListTO, TestObject(99999999));\n\t\t\tTestFind(stopwatch2,  eaListTO, TestObject(99999999));\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/find\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test reverse()\n\t\t\t///////////////////////////////\n\n\t\t\tTestReverse(stopwatch1, stdListTO);\n\t\t\tTestReverse(stopwatch2,  eaListTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/reverse\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test remove()\n\t\t\t///////////////////////////////\n\n\t\t\trandom_shuffle(toVector.begin(), toVector.end(), rng);\n\t\t\tTestRemove(stopwatch1, stdListTO, &toVector[0], &toVector[20]);\n\t\t\tTestRemove(stopwatch2,  eaListTO, &toVector[0], &toVector[20]);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/remove\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test splice()\n\t\t\t///////////////////////////////\n\t\t\tStdListTO listCopyStd(stdListTO);\n\t\t\tEaListTO  listCopyEa(eaListTO);\n\n\t\t\tTestSplice(stopwatch1, stdListTO, listCopyStd);\n\t\t\tTestSplice(stopwatch2,  eaListTO, listCopyEa);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/splice\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase()\n\t\t\t///////////////////////////////\n\n\t\t\tTestErase(stopwatch1, stdListTO);\n\t\t\tTestErase(stopwatch2,  eaListTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"list<TestObject>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkMap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/map.h>\n#include <EASTL/vector.h>\n#include <EASTL/algorithm.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <map>\n#include <algorithm>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\nusing namespace EA;\n\n\ntypedef std::map<TestObject, uint32_t>     StdMapTOUint32;\ntypedef eastl::map<TestObject, uint32_t>   EaMapTOUint32;\n\n\nnamespace\n{\n\ttemplate <typename Container, typename Value>\n\tvoid TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd, const Value& highValue)\n\t{\n\t\tstopwatch.Restart();\n\t\tc.insert(pArrayBegin, pArrayEnd);\n\t\tstopwatch.Stop();\n\t\tc.insert(highValue);\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestIteration(EA::StdC::Stopwatch& stopwatch, const Container& c, const Value& findValue)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypename Container::const_iterator it = eastl::find(c.begin(), c.end(), findValue); // It shouldn't matter what find implementation we use here, as it merely iterates values.\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p\", &*it);\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tBenchmark::DoNothing(c[pArrayBegin->first]);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tBenchmark::DoNothing(c.find(pArrayBegin->first)->second);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestCount(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\ttypename Container::size_type temp = 0;\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\ttemp += c.count(pArrayBegin->first);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestLowerBound(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tBenchmark::DoNothing(c.lower_bound(pArrayBegin->first)->second);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestUpperBound(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tBenchmark::DoNothing(c.upper_bound(pArrayBegin->first)->second);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestEqualRange(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tBenchmark::DoNothing(c.equal_range(pArrayBegin->first).second->second);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename Value>\n\tvoid TestEraseValue(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tc.erase(pArrayBegin->first);\n\t\t\t++pArrayBegin;\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestErasePosition(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = c.size() / 3, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\t// The erase fucntion is supposed to return an iterator, but the C++ standard was \n\t\t\t// not initially clear about it and some STL implementations don't do it correctly.\n\t\t\t#if (((defined(_MSC_VER) || defined(_CPPLIB_VER)) && !defined(_HAS_STRICT_CONFORMANCE))) // _CPPLIB_VER is something defined by Dinkumware STL.\n\t\t\t\tit = c.erase(it);  // Standard behavior.\n\t\t\t#else\n\t\t\t\t// This pathway may execute at a slightly different speed than the \n\t\t\t\t// standard behaviour, but that's fine for the benchmark because the\n\t\t\t\t// benchmark is measuring the speed of erasing while iterating, and \n\t\t\t\t// however it needs to get done by the given STL is how it is measured.\n\t\t\t\tconst typename Container::iterator itErase(it++);\n\t\t\t\tc.erase(itErase);\n\t\t\t#endif\n\n\t\t\t++it;\n\t\t\t++it;\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p %p\", &c, &it);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestEraseRange(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator  it1 = c.begin();\n\t\ttypename Container::iterator  it2 = c.begin();\n\n\t\tfor(j = 0, jEnd = c.size() / 3; j < jEnd; ++j)\n\t\t\t++it2;\n\n\t\tstopwatch.Restart();\n\t\tc.erase(it1, it2);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%p %p %p\", &c, &it1, &it2);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestClear(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tc.clear();\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t}\n\n\n} // namespace\n\n\n\nvoid BenchmarkMap()\n{\n\tEASTLTest_Printf(\"Map\\n\");\n\n\tEA::UnitTest::Rand  rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\teastl::vector< std::pair<TestObject, uint32_t> >   stdVector(10000);\n\t\teastl::vector< eastl::pair<TestObject, uint32_t> > eaVector(10000);\n\n\t\tfor(eastl_size_t i = 0, iEnd = stdVector.size(); i < iEnd; i++)\n\t\t{\n\t\t\tconst uint32_t n1 = rng.RandLimit(((uint32_t)iEnd / 2));\n\t\t\tconst uint32_t n2 = rng.RandValue();\n\n\t\t\tstdVector[i] = std::pair<TestObject, uint32_t>(TestObject(n1), n2);\n\t\t\teaVector[i]  = eastl::pair<TestObject, uint32_t>(TestObject(n1), n2);\n\t\t}\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tStdMapTOUint32 stdMapTOUint32;\n\t\t\tEaMapTOUint32  eaMapTOUint32;\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert(const value_type&)\n\t\t\t///////////////////////////////\n\t\t\tconst std::pair<TestObject, uint32_t>   stdHighValue(TestObject(0x7fffffff), 0x7fffffff);\n\t\t\tconst eastl::pair<TestObject, uint32_t> eaHighValue(TestObject(0x7fffffff), 0x7fffffff);\n\n\t\t\tTestInsert(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size(), stdHighValue);\n\t\t\tTestInsert(stopwatch2,  eaMapTOUint32,  eaVector.data(),  eaVector.data() +  eaVector.size(),  eaHighValue);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration\n\t\t\t///////////////////////////////\n\n\t\t\tTestIteration(stopwatch1, stdMapTOUint32, StdMapTOUint32::value_type(TestObject(9999999), 9999999));\n\t\t\tTestIteration(stopwatch2,  eaMapTOUint32,  EaMapTOUint32::value_type(TestObject(9999999), 9999999));\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test operator[]\n\t\t\t///////////////////////////////\n\n\t\t\tTestBracket(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());\n\t\t\tTestBracket(stopwatch2,  eaMapTOUint32,  eaVector.data(),  eaVector.data() +  eaVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());\n\t\t\tTestFind(stopwatch2,  eaMapTOUint32,  eaVector.data(),  eaVector.data() +  eaVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/find\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test count\n\t\t\t///////////////////////////////\n\n\t\t\tTestCount(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());\n\t\t\tTestCount(stopwatch2,  eaMapTOUint32,  eaVector.data(),  eaVector.data() +  eaVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test lower_bound\n\t\t\t///////////////////////////////\n\n\t\t\tTestLowerBound(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());\n\t\t\tTestLowerBound(stopwatch2,  eaMapTOUint32,  eaVector.data(),  eaVector.data() +  eaVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/lower_bound\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test upper_bound\n\t\t\t///////////////////////////////\n\n\t\t\tTestUpperBound(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());\n\t\t\tTestUpperBound(stopwatch2,  eaMapTOUint32,  eaVector.data(),  eaVector.data() +  eaVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/upper_bound\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test equal_range\n\t\t\t///////////////////////////////\n\n\t\t\tTestEqualRange(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());\n\t\t\tTestEqualRange(stopwatch2, eaMapTOUint32,   eaVector.data(),  eaVector.data() +  eaVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/equal_range\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(const key_type& key)\n\t\t\t///////////////////////////////\n\n\t\t\tTestEraseValue(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + (stdVector.size() / 2));\n\t\t\tTestEraseValue(stopwatch2,  eaMapTOUint32,  eaVector.data(),  eaVector.data() +  (eaVector.size() / 2));\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/erase/key\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(iterator position)\n\t\t\t///////////////////////////////\n\n\t\t\tTestErasePosition(stopwatch1, stdMapTOUint32);\n\t\t\tTestErasePosition(stopwatch2, eaMapTOUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/erase/pos\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t\tGetStdSTLType() == kSTLMS ? \"MS uses a code bloating implementation of erase.\" : NULL);\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(iterator first, iterator last)\n\t\t\t///////////////////////////////\n\n\t\t\tTestEraseRange(stopwatch1, stdMapTOUint32);\n\t\t\tTestEraseRange(stopwatch2, eaMapTOUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/erase/range\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test clear()\n\t\t\t///////////////////////////////\n\n\t\t\tTestClear(stopwatch1, stdMapTOUint32);\n\t\t\tTestClear(stopwatch2, eaMapTOUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"map<TestObject, uint32_t>/clear\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkSet.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/set.h>\n#include <EASTL/vector.h>\n#include <EASTL/algorithm.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <set>\n#include <algorithm>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\nusing namespace EA;\n\n\ntypedef std::set<uint32_t>     StdSetUint32;\ntypedef eastl::set<uint32_t>   EaSetUint32;\n\n\nnamespace\n{\n\ttemplate <typename Container>\n\tvoid TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\tc.insert(pArrayBegin, pArrayEnd);\n\t\tstopwatch.Stop();\n\n\t\t// Intentionally push back a high uint32_t value. We do this so that \n\t\t// later upper_bound, lower_bound and equal_range never return end().\n\t\tc.insert(0xffffffff);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestIteration(EA::StdC::Stopwatch& stopwatch, const Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypename Container::const_iterator it = eastl::find(c.begin(), c.end(), uint32_t(9999999));\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)*it);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)\n\t{\n\t\tuint32_t temp = 0;\n\t\ttypename Container::iterator it;\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tit = c.find(*pArrayBegin++);\n\t\t\ttemp += *it;\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestCount(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)\n\t{\n\t\ttypename Container::size_type temp = 0;\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t\ttemp += c.count(*pArrayBegin++);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestLowerBound(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)\n\t{\n\t\tuint32_t temp = 0;\n\t\ttypename Container::iterator it;\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tit = c.lower_bound(*pArrayBegin++);\n\t\t\ttemp += *it; // We know that it != end because earlier we inserted 0xffffffff.\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestUpperBound(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)\n\t{\n\t\tuint32_t temp = 0;\n\t\ttypename Container::iterator it;\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\tit = c.upper_bound(*pArrayBegin++);\n\t\t\ttemp += *it; // We know that it != end because earlier we inserted 0xffffffff.\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestEqualRange(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)\n\t{\n\t\tuint32_t temp = 0;\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t{\n\t\t\ttemp += *(c.equal_range(*pArrayBegin++).first); // We know that it != end because earlier we inserted 0xffffffff.\n\t\t}\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestEraseValue(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(pArrayBegin != pArrayEnd)\n\t\t\tc.erase(*pArrayBegin++);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestErasePosition(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = c.size() / 3, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\t// The erase fucntion is supposed to return an iterator, but the C++ standard was \n\t\t\t// not initially clear about it and some STL implementations don't do it correctly.\n\t\t\t#if (((defined(_MSC_VER) || defined(_CPPLIB_VER)) && !defined(_HAS_STRICT_CONFORMANCE))) // _CPPLIB_VER is something defined by Dinkumware STL.\n\t\t\t\tit = c.erase(it);\n\t\t\t#else\n\t\t\t\t// This pathway may execute at a slightly different speed than the \n\t\t\t\t// standard behaviour, but that's fine for the benchmark because the\n\t\t\t\t// benchmark is measuring the speed of erasing while iterating, and \n\t\t\t\t// however it needs to get done by the given STL is how it is measured.\n\t\t\t\tconst typename Container::iterator itErase(it++);\n\t\t\t\tc.erase(itErase);\n\t\t\t#endif\n\n\t\t\t++it;\n\t\t\t++it;\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestEraseRange(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator  it1 = c.begin();\n\t\ttypename Container::iterator  it2 = c.begin();\n\n\t\tfor(j = 0, jEnd = c.size() / 3; j < jEnd; ++j)\n\t\t\t++it2;\n\n\t\tstopwatch.Restart();\n\t\tc.erase(it1, it2);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestClear(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tc.clear();\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)c.size());\n\t}\n\n\n} // namespace\n\n\n\nvoid BenchmarkSet()\n{\n\tEASTLTest_Printf(\"Set\\n\");\n\n\tEA::UnitTest::Rand  rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\teastl::vector<uint32_t> intVector(10000);\n\t\tfor(eastl_size_t i = 0, iEnd = intVector.size(); i < iEnd; i++)\n\t\t\tintVector[i] = (uint32_t)rng.RandLimit(((uint32_t)iEnd / 2));  // This will result in duplicates and even a few triplicates.\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tStdSetUint32 stdSetUint32;\n\t\t\tEaSetUint32  eaSetUint32;\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert(const value_type&)\n\t\t\t///////////////////////////////\n\n\t\t\tTestInsert(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());\n\t\t\tTestInsert(stopwatch2, eaSetUint32,  intVector.data(), intVector.data() + intVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration\n\t\t\t///////////////////////////////\n\n\t\t\tTestIteration(stopwatch1, stdSetUint32);\n\t\t\tTestIteration(stopwatch2, eaSetUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());\n\t\t\tTestFind(stopwatch2, eaSetUint32,  intVector.data(), intVector.data() + intVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/find\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test count\n\t\t\t///////////////////////////////\n\n\t\t\tTestCount(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());\n\t\t\tTestCount(stopwatch2, eaSetUint32,  intVector.data(), intVector.data() + intVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/count\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test lower_bound\n\t\t\t///////////////////////////////\n\n\t\t\tTestLowerBound(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());\n\t\t\tTestLowerBound(stopwatch2, eaSetUint32,  intVector.data(), intVector.data() + intVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/lower_bound\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test upper_bound\n\t\t\t///////////////////////////////\n\n\t\t\tTestUpperBound(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());\n\t\t\tTestUpperBound(stopwatch2, eaSetUint32,  intVector.data(), intVector.data() + intVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/upper_bound\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test equal_range\n\t\t\t///////////////////////////////\n\n\t\t\tTestEqualRange(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());\n\t\t\tTestEqualRange(stopwatch2, eaSetUint32,  intVector.data(), intVector.data() + intVector.size());\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/equal_range\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(const key_type& key)\n\t\t\t///////////////////////////////\n\n\t\t\tTestEraseValue(stopwatch1, stdSetUint32, &intVector[0], &intVector[intVector.size() / 2]);\n\t\t\tTestEraseValue(stopwatch2, eaSetUint32,  &intVector[0], &intVector[intVector.size() / 2]);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/erase/val\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(iterator position)\n\t\t\t///////////////////////////////\n\n\t\t\tTestErasePosition(stopwatch1, stdSetUint32);\n\t\t\tTestErasePosition(stopwatch2, eaSetUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/erase/pos\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t\tGetStdSTLType() == kSTLMS ? \"MS uses a code bloating implementation of erase.\" : NULL);\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(iterator first, iterator last)\n\t\t\t///////////////////////////////\n\n\t\t\tTestEraseRange(stopwatch1, stdSetUint32);\n\t\t\tTestEraseRange(stopwatch2, eaSetUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/erase range\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test clear()\n\t\t\t///////////////////////////////\n\n\t\t\tTestClear(stopwatch1, stdSetUint32);\n\t\t\tTestClear(stopwatch2, eaSetUint32);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"set<uint32_t>/clear\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkSort.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/bonus/sort_extra.h>\n#include <EASTL/sort.h>\n#include <EASTL/vector.h>\n#include <EAStdC/EAStopwatch.h>\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdlib.h>\n#include <algorithm>\n#include <functional>\n#include <vector>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\nusing namespace EA;\n\n\nnamespace\n{\n\tstruct ValuePair\n\t{\n\t\tuint32_t key;\n\t\tuint32_t v;\n\t};\n\n\tstruct VPCompare\n\t{\n\t\tbool operator()(const ValuePair& vp1, const ValuePair& vp2) const\n\t\t{\n\t\t\t// return *(const uint64_t*)&vp1 < *(const uint64_t*)&vp2;\n\t\t\treturn (vp1.key == vp2.key) ? (vp1.v < vp2.v) : (vp1.key < vp2.key);\n\t\t}\n\t};\n\n\tbool operator<(const ValuePair& vp1, const ValuePair& vp2)\n\t{\n\t\t// return *(const uint64_t*)&vp1 < *(const uint64_t*)&vp2;\n\t\treturn (vp1.key == vp2.key) ? (vp1.v < vp2.v) : (vp1.key < vp2.key);\n\t}\n\n\tbool operator==(const ValuePair& vp1, const ValuePair& vp2)\n\t{\n\t\t// return *(const uint64_t*)&vp1 == *(const uint64_t*)&vp2;\n\t\treturn (vp1.key == vp2.key) && (vp1.v == vp2.v);\n\t}\n}\n\n// VPCompareC\n// Useful for testing the the C qsort function.\nint VPCompareC(const void* elem1, const void* elem2)\n{\n\treturn (int)(*(const uint64_t*)elem1 - *(const uint64_t*)elem2);\n}\n\n\ntypedef std::vector<ValuePair>    StdVectorVP;\ntypedef eastl::vector<ValuePair>  EaVectorVP;\n\ntypedef std::vector<uint32_t>     StdVectorInt;\ntypedef eastl::vector<uint32_t>   EaVectorInt;\n\ntypedef std::vector<TestObject>   StdVectorTO;\ntypedef eastl::vector<TestObject> EaVectorTO;\n\n\nnamespace\n{\n\t#ifndef EA_PREFIX_NO_INLINE\n\t\t#ifdef _MSC_VER\n\t\t\t#define EA_PREFIX_NO_INLINE EA_NO_INLINE\n\t\t\t#define EA_POSTFIX_NO_INLINE\n\t\t#else\n\t\t\t#define EA_PREFIX_NO_INLINE\n\t\t\t#define EA_POSTFIX_NO_INLINE EA_NO_INLINE\n\t\t#endif\n\t#endif\n\n\tEA_PREFIX_NO_INLINE void TestQuickSortStdVP (EA::StdC::Stopwatch& stopwatch, StdVectorVP&  stdVectorVP)  EA_POSTFIX_NO_INLINE;\n\tEA_PREFIX_NO_INLINE void TestQuickSortEaVP  (EA::StdC::Stopwatch& stopwatch, EaVectorVP&   eaVectorVP)   EA_POSTFIX_NO_INLINE;\n\tEA_PREFIX_NO_INLINE void TestQuickSortStdInt(EA::StdC::Stopwatch& stopwatch, StdVectorInt& stdVectorInt) EA_POSTFIX_NO_INLINE;\n\tEA_PREFIX_NO_INLINE void TestQuickSortEaInt (EA::StdC::Stopwatch& stopwatch, EaVectorInt&  eaVectorInt)  EA_POSTFIX_NO_INLINE;\n\tEA_PREFIX_NO_INLINE void TestQuickSortStdTO (EA::StdC::Stopwatch& stopwatch, StdVectorTO&  stdVectorTO)  EA_POSTFIX_NO_INLINE;\n\tEA_PREFIX_NO_INLINE void TestQuickSortEaTO  (EA::StdC::Stopwatch& stopwatch, EaVectorTO&   eaVectorTO)   EA_POSTFIX_NO_INLINE;\n\n\n\n\tvoid TestQuickSortStdVP(EA::StdC::Stopwatch& stopwatch, StdVectorVP& stdVectorVP)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::sort(stdVectorVP.begin(), stdVectorVP.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)stdVectorVP[0].key);\n\t}\n\n\n\tvoid TestQuickSortEaVP(EA::StdC::Stopwatch& stopwatch, EaVectorVP& eaVectorVP)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(eaVectorVP.begin(), eaVectorVP.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)eaVectorVP[0].key);\n\t}\n\n\n\tvoid TestQuickSortStdInt(EA::StdC::Stopwatch& stopwatch, StdVectorInt& stdVectorInt)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::sort(stdVectorInt.begin(), stdVectorInt.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)stdVectorInt[0]);\n\t}\n\n\n\tvoid TestQuickSortEaInt(EA::StdC::Stopwatch& stopwatch, EaVectorInt& eaVectorInt)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(eaVectorInt.begin(), eaVectorInt.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)eaVectorInt[0]);\n\t}\n\n\n\tvoid TestQuickSortStdTO(EA::StdC::Stopwatch& stopwatch, StdVectorTO& stdVectorTO)\n\t{\n\t\tstopwatch.Restart();\n\t\tstd::sort(stdVectorTO.begin(), stdVectorTO.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)stdVectorTO[0].mX);\n\t}\n\n\n\tvoid TestQuickSortEaTO(EA::StdC::Stopwatch& stopwatch, EaVectorTO& eaVectorTO)\n\t{\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(eaVectorTO.begin(), eaVectorTO.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)eaVectorTO[0].mX);\n\t}\n\n} // namespace\n\n\nnamespace\n{\n\tenum SortFunctionType\n\t{\n\t\tsf_qsort,             // C qsort\n\t\tsf_shell_sort,        // eastl::shell_sort.\n\t\tsf_heap_sort,         // eastl::heap_sort\n\t\tsf_merge_sort,        // eastl::merge_sort\n\t\tsf_merge_sort_buffer, // eastl::merge_sort_buffer\n\t\tsf_comb_sort,         // eastl::comb_sort\n\t\tsf_bubble_sort,       // eastl::bubble_sort\n\t\tsf_selection_sort,    // eastl::selection_sort\n\t\tsf_shaker_sort,       // eastl::shaker_sort\n\t\tsf_quick_sort,        // eastl::quick_sort\n\t\tsf_tim_sort,          // eastl::tim_sort\n\t\tsf_insertion_sort,    // eastl::insertion_sort\n\t\tsf_std_sort,          // std::sort\n\t\tsf_std_stable_sort,   // std::stable_sort\n\t\tsf_radix_sort,        // eastl::radix_sort (unconventional sort)\n\t\tsf_count              //\n\t};\n\n\tconst char* GetSortFunctionName(int sortFunctionType)\n\t{\n\t\tswitch (sortFunctionType)\n\t\t{\n\t\t\tcase sf_quick_sort:\n\t\t\t\treturn \"eastl::sort\";\n\n\t\t\tcase sf_tim_sort:\n\t\t\t\treturn \"eastl::tim_sort\";\n\n\t\t\tcase sf_insertion_sort:\n\t\t\t\treturn \"eastl::insertion_sort\";\n\n\t\t\tcase sf_shell_sort:\n\t\t\t\treturn \"eastl::shell_sort\";\n\n\t\t\tcase sf_heap_sort:\n\t\t\t\treturn \"eastl::heap_sort\";\n\n\t\t\tcase sf_merge_sort:\n\t\t\t\treturn \"eastl::merge_sort\";\n\n\t\t\tcase sf_merge_sort_buffer:\n\t\t\t\treturn \"eastl::merge_sort_buffer\";\n\n\t\t\tcase sf_comb_sort:\n\t\t\t\treturn \"eastl::comb_sort\";\n\n\t\t\tcase sf_bubble_sort:\n\t\t\t\treturn \"eastl::bubble_sort\";\n\n\t\t\tcase sf_selection_sort:\n\t\t\t\treturn \"eastl::selection_sort\";\n\n\t\t\tcase sf_shaker_sort:\n\t\t\t\treturn \"eastl::shaker_sort\";\n\n\t\t\tcase sf_radix_sort:\n\t\t\t\treturn \"eastl::radix_sort\";\n\n\t\t\tcase sf_qsort:\n\t\t\t\treturn \"qsort\";\n\n\t\t\tcase sf_std_sort:\n\t\t\t\treturn \"std::sort\";\n\n\t\t\tcase sf_std_stable_sort:\n\t\t\t\treturn \"std::stable_sort\";\n\n\t\t\tdefault:\n\t\t\t\treturn \"unknown\";\n\t\t}\n\t}\n\n\n\tenum RandomizationType\n\t{\n\t\tkRandom,                    // Completely random data.\n\t\tkRandomSorted,  // Random values already sorted.\n\t\tkOrdered,                   // Already sorted.\n\t\tkMostlyOrdered,             // Partly sorted already.\n\t\tkRandomizationTypeCount\n\t};\n\n\tconst char* GetRandomizationTypeName(int randomizationType)\n\t{\n\t\tswitch (randomizationType)\n\t\t{\n\t\t\tcase kRandom:\n\t\t\t\treturn \"random\";\n\n\t\t\tcase kRandomSorted:\n\t\t\t\treturn \"random sorted\";\n\n\t\t\tcase kOrdered:\n\t\t\t\treturn \"ordered\";\n\n\t\t\tcase kMostlyOrdered:\n\t\t\t\treturn \"mostly ordered\";\n\n\t\t\tdefault:\n\t\t\t\treturn \"unknown\";\n\t\t}\n\t}\n\n\ttemplate <typename ElementType, typename RandomType>\n\tvoid Randomize(eastl::vector<ElementType>& v, EA::UnitTest::RandGenT<RandomType>& rng, RandomizationType type)\n\t{\n\t\ttypedef RandomType value_type;\n\n\t\tswitch (type)\n\t\t{\n\t\t\tdefault:\n\t\t\tcase kRandomizationTypeCount: // We specify this only to avoid a compiler warning about not testing for it.\n\t\t\tcase kRandom:\n\t\t\t{\n\t\t\t\teastl::generate(v.begin(), v.end(), rng);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase kRandomSorted:\n\t\t\t{\n\t\t\t\t// This randomization type differs from kOrdered because the set of values is random (but sorted), in the kOrdered\n\t\t\t\t// case the set of values is contiguous (i.e. 0, 1, ..., n) which can have different performance characteristics.\n\t\t\t\t// For example, radix_sort performs poorly for kOrdered.\n\t\t\t\teastl::generate(v.begin(), v.end(), rng);\n\t\t\t\teastl::sort(v.begin(), v.end());\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase kOrdered:\n\t\t\t{\n\t\t\t\tfor(eastl_size_t i = 0; i < v.size(); ++i)\n\t\t\t\t\tv[i] = value_type((value_type)i);   // Note that value_type may be a struct and not an integer. Thus the casting and construction here.\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase kMostlyOrdered:\n\t\t\t{\n\t\t\t\tfor(eastl_size_t i = 0; i < v.size(); ++i)\n\t\t\t\t\tv[i] = value_type((value_type)i);   // Note that value_type may be a struct and not an integer. Thus the casting and construction here.\n\n\t\t\t\t// We order random segments.\n\t\t\t\t// The algorithm below in practice will make slightly more than kPercentOrdered be ordered.\n\t\t\t\tconst eastl_size_t kPercentOrdered = 80; // In actuality, due to statistics, the actual ordered percent will be about 82-85%.\n\n\t\t\t\tfor(eastl_size_t n = 0, s = v.size(), nEnd = ((s < (100 - kPercentOrdered)) ? 1 : (s / (100 - kPercentOrdered))); n < nEnd; n++)\n\t\t\t\t{\n\t\t\t\t\teastl_size_t i = rng.mRand.RandLimit((uint32_t)s);\n\t\t\t\t\teastl_size_t j = rng.mRand.RandLimit((uint32_t)s);\n\n\t\t\t\t\teastl::swap(v[i], v[j]);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\n\tchar gSlowAssignBuffer1[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* ... */};\n\tchar gSlowAssignBuffer2[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* ... */};\n\n\n\t// SlowAssign\n\t// Implements an object which has slow assign performance.\n\ttemplate <typename T>\n\tstruct SlowAssign\n\t{\n\t\ttypedef T key_type;\n\t\tT x;\n\n\t\tstatic int nAssignCount;\n\n\t\tSlowAssign()\n\t\t\t{ x = 0; memcpy(gSlowAssignBuffer1, gSlowAssignBuffer2, sizeof(gSlowAssignBuffer1)); }\n\n\t\tSlowAssign(const SlowAssign& sa)\n\t\t\t{ ++nAssignCount; x = sa.x; memcpy(gSlowAssignBuffer1, gSlowAssignBuffer2, sizeof(gSlowAssignBuffer1)); }\n\n\t\tSlowAssign& operator=(const SlowAssign& sa)\n\t\t\t{ ++nAssignCount; x = sa.x; memcpy(gSlowAssignBuffer1, gSlowAssignBuffer2, sizeof(gSlowAssignBuffer1)); return *this; }\n\n\t\tSlowAssign& operator=(int a)\n\t\t\t{ x = (T)a; return *this; }\n\n\t\tstatic void Reset()\n\t\t\t{ nAssignCount = 0; }\n\t};\n\n\ttemplate<> int SlowAssign<uint32_t>::nAssignCount = 0;\n\n\ttemplate <typename T>\n\tbool operator <(const SlowAssign<T>& a, const SlowAssign<T>& b)\n\t\t{ return a.x < b.x; }\n\n\n\t// SlowCompare\n\t// Implements a compare which is N time slower than a simple integer compare.\n\ttemplate <typename T>\n\tstruct SlowCompare\n\t{\n\t\tstatic int nCompareCount;\n\n\t\tbool operator()(T a, T b)\n\t\t{\n\t\t\t++nCompareCount;\n\n\t\t\treturn (a < b) && // It happens that gSlowAssignBuffer1 is always zeroed.\n\t\t\t       (gSlowAssignBuffer1[0] == 0) && (gSlowAssignBuffer1[1] == 0) && (gSlowAssignBuffer1[1] == 0) &&\n\t\t\t       (gSlowAssignBuffer1[2] == 0) && (gSlowAssignBuffer1[4] == 0) && (gSlowAssignBuffer1[5] == 0);\n\t\t}\n\n\t\tstatic void Reset() { nCompareCount = 0; }\n\t};\n\n\ttemplate <>\n\tint SlowCompare<int32_t>::nCompareCount = 0;\n\n\n\t// qsort callback functions\n\t// qsort compare function returns negative if b > a and positive if a > b.\n\ttemplate <typename T>\n\tint CompareInteger(const void* a, const void* b)\n\t{\n\t\t// Even though you see the following in Internet example code, it doesn't work!\n\t\t// The reason is that it works only if a and b are both >= 0, otherwise large\n\t\t// values can cause integer register wraparound. A similar kind of problem happens\n\t\t// if you try to do the same thing with floating point value compares.\n\t\t// See http://www.akalin.cx/2006/06/23/on-the-qsort-comparison-function/\n\t\t// Internet exmaple code:\n\t\t//     return *(const int32_t*)a - *(const int32_t*)b;\n\n\t\t// This double comparison might seem like it's crippling qsort against the\n\t\t// STL-based sorts which do a single compare. But consider that the returning\n\t\t// of -1, 0, +1 gives qsort more information, and its logic takes advantage\n\t\t// of that.\n\t\tif (*(const T*)a < *(const T*)b)\n\t\t\treturn -1;\n\t\tif (*(const T*)a > *(const T*)b)\n\t\t\treturn +1;\n\t\treturn 0;\n\t}\n\n\n\tint SlowCompareInt32(const void* a, const void* b)\n\t{\n\t\t++SlowCompare<int32_t>::nCompareCount;\n\n\t\t// This code is similar in performance to the C++ SlowCompare template functor above.\n\t\tif((gSlowAssignBuffer1[0] == 0) && (gSlowAssignBuffer1[1] == 0) &&\n\t\t   (gSlowAssignBuffer1[1] == 0) && (gSlowAssignBuffer1[2] == 0) &&\n\t\t   (gSlowAssignBuffer1[4] == 0) && (gSlowAssignBuffer1[5] == 0))\n\t\t{\n\t\t\tif (*(const int32_t*)a < *(const int32_t*)b)\n\t\t\t\treturn -1;\n\t\t\tif (*(const int32_t*)a > *(const int32_t*)b)\n\t\t\t\treturn +1;\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\ttemplate <typename slow_assign_type>\n\tstruct slow_assign_extract_radix_key\n\t{\n\t\ttypedef typename slow_assign_type::key_type radix_type;\n\n\t\tconst radix_type operator()(const slow_assign_type& obj) const\n\t\t{\n\t\t\treturn obj.x;\n\t\t}\n\t};\n\t\n\ttemplate <typename integer_type>\n\tstruct identity_extract_radix_key\n\t{\n\t\ttypedef integer_type radix_type;\n\n\t\tconst radix_type operator()(const integer_type& x) const\n\t\t{\n\t\t\treturn x;\n\t\t}\n\t};\n} // namespace\n\n\nstruct BenchmarkResult\n{\n\tuint64_t mTime;\n\tuint64_t mCompareCount;\n\tuint64_t mAssignCount;\n\n\tBenchmarkResult() : mTime(0), mCompareCount(0), mAssignCount(0) {}\n};\n\n\nint CompareSortPerformance()\n{\n\t// Sizes of arrays to be sorted.\n\tconst eastl_size_t kSizes[] = { 10, 100, 1000, 10000 };\n\tconst eastl_size_t kSizesCount = EAArrayCount(kSizes);\n\tstatic BenchmarkResult sResults[kRandomizationTypeCount][kSizesCount][sf_count];\n\tint nErrorCount = 0;\n\n\tEA::UnitTest::ReportVerbosity(2, \"Sort comparison\\n\");\n\tEA::UnitTest::ReportVerbosity(2, \"Random seed = %u\\n\", (unsigned)EA::UnitTest::GetRandSeed());\n\n\tEA::UnitTest::RandGenT<int32_t> rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch             stopwatch(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch             stopwatchGlobal(EA::StdC::Stopwatch::kUnitsSeconds);\n\tconst eastl_size_t kArraySizeMax = *eastl::max_element(eastl::begin(kSizes), eastl::end(kSizes));\n\tconst int                       kRunCount = 4;\n\n\t#if !defined(EA_DEBUG)\n\t\tEA::UnitTest::SetHighThreadPriority();\n\t#endif\n\n\teastl::vector<SortFunctionType> allSortFunctions;\n\tfor (int i = 0; i < sf_count; i++)\n\t{\n\t\tallSortFunctions.push_back(SortFunctionType(i));\n\t}\n\n\t{\n\t\tauto& sortFunctions = allSortFunctions;\n\n\t\t// Regular speed test.\n\t\t// In this case we test the sorting of integral values.\n\t\t// This is probably the most common type of comparison.\n\t\tEA::UnitTest::ReportVerbosity(2, \"Sort comparison: Regular speed test\\n\");\n\n\t\ttypedef uint32_t                      ElementType;\n\t\ttypedef eastl::less<ElementType>      CompareFunction;\n\n\t\teastl::string sOutput;\n\t\tsOutput.set_capacity(100000);\n\t\tElementType* pBuffer = new ElementType[kArraySizeMax];\n\n\t\tmemset(sResults, 0, sizeof(sResults));\n\n\t\tstopwatchGlobal.Restart();\n\n\t\tfor (int c = 0; c < kRunCount; c++)\n\t\t{\n\t\t\tfor (int i = 0; i < kRandomizationTypeCount; i++)\n\t\t\t{\n\t\t\t\tfor (size_t sizeType = 0; sizeType < EAArrayCount(kSizes); sizeType++)\n\t\t\t\t{\n\t\t\t\t\tconst eastl_size_t size = kSizes[sizeType];\n\n\t\t\t\t\tfor (SortFunctionType sortFunction : sortFunctions)\n\t\t\t\t\t{\n\t\t\t\t\t\teastl::vector<ElementType> v(size);\n\n\t\t\t\t\t\trng.SetSeed(EA::UnitTest::GetRandSeed());\n\t\t\t\t\t\tRandomize(v, rng, (RandomizationType)i);\n\n\t\t\t\t\t\tswitch (sortFunction)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase sf_quick_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::quick_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_tim_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::tim_sort_buffer(v.begin(), v.end(), pBuffer, CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_insertion_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::insertion_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_shell_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::shell_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_heap_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::heap_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_merge_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::merge_sort(v.begin(), v.end(), *get_default_allocator((EASTLAllocatorType*)NULL), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_merge_sort_buffer:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::merge_sort_buffer(v.begin(), v.end(), pBuffer, CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_comb_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::comb_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_bubble_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::bubble_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_selection_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::selection_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_shaker_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::shaker_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_radix_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::radix_sort<ElementType*, identity_extract_radix_key<ElementType>>(v.begin(), v.end(), pBuffer);\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_qsort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tqsort(&v[0], (size_t)v.size(), sizeof(ElementType), CompareInteger<ElementType>);\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_std_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tstd::sort(v.data(), v.data() + v.size(), std::less<ElementType>());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_std_stable_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tstd::stable_sort(v.data(), v.data() + v.size(), std::less<ElementType>());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_count:\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t// unsupported\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst uint64_t elapsedTime = (uint64_t)stopwatch.GetElapsedTime();\n\n\t\t\t\t\t\t// If this result was faster than a previously fastest result, record this one instead.\n\t\t\t\t\t\tif ((c == 0) || (elapsedTime < sResults[i][sizeType][sortFunction].mTime))\n\t\t\t\t\t\t\tsResults[i][sizeType][sortFunction].mTime = elapsedTime;\n\n\t\t\t\t\t\tVERIFY(eastl::is_sorted(v.begin(), v.end()));\n\n\t\t\t\t\t} // for each sort function...\n\n\t\t\t\t} // for each size type...\n\n\t\t\t} // for each randomization type...\n\n\t\t} // for each run\n\n\t\tEA::UnitTest::ReportVerbosity(2, \"Total time: %.2f s\\n\", stopwatchGlobal.GetElapsedTimeFloat());\n\n\t\tdelete[] pBuffer;\n\n\t\t// Now print the results.\n\t\tfor (int i = 0; i < kRandomizationTypeCount; i++)\n\t\t{\n\t\t\tfor (size_t sizeType = 0; sizeType < EAArrayCount(kSizes); sizeType++)\n\t\t\t{\n\t\t\t\tconst eastl_size_t size = kSizes[sizeType];\n\n\t\t\t\tfor (SortFunctionType sortFunction : sortFunctions)\n\t\t\t\t{\n\t\t\t\t\tsOutput.append_sprintf(\"%25s, %14s, Size: %8u, Time: %14\" PRIu64 \" ticks %0.2f ticks/elem\\n\",\n\t\t\t\t\t                       GetSortFunctionName(sortFunction), GetRandomizationTypeName(i),\n\t\t\t\t\t                       (unsigned)size, sResults[i][sizeType][sortFunction].mTime,\n\t\t\t\t\t                       float(sResults[i][sizeType][sortFunction].mTime)/float(size));\n\t\t\t\t}\n\t\t\t\tsOutput.append(\"\\n\");\n\t\t\t}\n\t\t}\n\n\t\tEA::UnitTest::ReportVerbosity(2, \"%s\\n\\n\", sOutput.c_str());\n\t}\n\n\t{\n\t\t// Do a speed test for the case of slow compares.\n\t\t// By this we mean to compare sorting speeds when the comparison of elements is slow.\n\t\t// Sort functions use element comparison to tell where elements go and use element\n\t\t// movement to get them there. But some sorting functions accomplish sorting performance by\n\t\t// minimizing the amount of movement, some minimize the amount of comparisons, and the\n\t\t// best do a good job of minimizing both.\n\t\tauto sortFunctions = allSortFunctions;\n\t\t// We can't test this radix_sort because what we need isn't exposed.\n\t\tsortFunctions.erase(eastl::remove(sortFunctions.begin(), sortFunctions.end(), sf_radix_sort), sortFunctions.end());\n\t\tEA::UnitTest::ReportVerbosity(2, \"Sort comparison: Slow compare speed test\\n\");\n\n\t\ttypedef int32_t ElementType;\n\t\ttypedef SlowCompare<ElementType> CompareFunction;\n\n\t\teastl::string sOutput;\n\t\tsOutput.set_capacity(100000);\n\t\tElementType* pBuffer = new ElementType[kArraySizeMax];\n\n\t\tmemset(sResults, 0, sizeof(sResults));\n\n\t\tstopwatchGlobal.Restart();\n\n\t\tfor (int c = 0; c < kRunCount; c++)\n\t\t{\n\t\t\tfor (int i = 0; i < kRandomizationTypeCount; i++)\n\t\t\t{\n\t\t\t\tfor (size_t sizeType = 0; sizeType < EAArrayCount(kSizes); sizeType++)\n\t\t\t\t{\n\t\t\t\t\tconst eastl_size_t size = kSizes[sizeType];\n\n\t\t\t\t\tfor (SortFunctionType sortFunction : sortFunctions)\n\t\t\t\t\t{\n\t\t\t\t\t\teastl::vector<ElementType> v(size);\n\n\t\t\t\t\t\trng.SetSeed(EA::UnitTest::GetRandSeed());\n\t\t\t\t\t\tRandomize(v, rng, (RandomizationType)i);\n\t\t\t\t\t\tCompareFunction::Reset();\n\n\t\t\t\t\t\tswitch (sortFunction)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase sf_quick_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::quick_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_tim_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::tim_sort_buffer(v.begin(), v.end(), pBuffer, CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_insertion_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::insertion_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_shell_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::shell_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_heap_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::heap_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_merge_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::merge_sort(v.begin(), v.end(), *get_default_allocator((EASTLAllocatorType*)NULL), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_merge_sort_buffer:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::merge_sort_buffer(v.begin(), v.end(), pBuffer, CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_comb_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::comb_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_bubble_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::bubble_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_selection_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::selection_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_shaker_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::shaker_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_qsort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tqsort(&v[0], (size_t)v.size(), sizeof(ElementType), SlowCompareInt32);\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_std_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tstd::sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_std_stable_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tstd::stable_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_radix_sort:\n\t\t\t\t\t\t\tcase sf_count:\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t// unsupported\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst uint64_t elapsedTime = (uint64_t)stopwatch.GetElapsedTime();\n\n\t\t\t\t\t\t// If this result was faster than a previously fastest result, record this one instead.\n\t\t\t\t\t\tif ((c == 0) || (elapsedTime < sResults[i][sizeType][sortFunction].mTime))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsResults[i][sizeType][sortFunction].mTime = elapsedTime;\n\t\t\t\t\t\t\tsResults[i][sizeType][sortFunction].mCompareCount = (uint64_t)CompareFunction::nCompareCount;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tVERIFY(eastl::is_sorted(v.begin(), v.end()));\n\t\t\t\t\t} // for each sort function...\n\n\t\t\t\t} // for each size type...\n\n\t\t\t} // for each randomization type...\n\n\t\t} // for each run\n\n\t\tEA::UnitTest::ReportVerbosity(2, \"Total time: %.2f s\\n\", stopwatchGlobal.GetElapsedTimeFloat());\n\n\t\tdelete[] pBuffer;\n\n\t\t// Now print the results.\n\t\tfor (int i = 0; i < kRandomizationTypeCount; i++)\n\t\t{\n\t\t\tfor (size_t sizeType = 0; sizeType < EAArrayCount(kSizes); sizeType++)\n\t\t\t{\n\t\t\t\tconst eastl_size_t size = kSizes[sizeType];\n\n\t\t\t\tfor (SortFunctionType sortFunction : sortFunctions)\n\t\t\t\t{\n\t\t\t\t\tsOutput.append_sprintf(\"%25s, %14s, Size: %6u, Time: %11\" PRIu64 \" ticks, Compares: %11\" PRIu64 \"\\n\",\n\t\t\t\t\t                       GetSortFunctionName(sortFunction), GetRandomizationTypeName(i),\n\t\t\t\t\t                       (unsigned)size, sResults[i][sizeType][sortFunction].mTime,\n\t\t\t\t\t                       sResults[i][sizeType][sortFunction].mCompareCount);\n\t\t\t\t}\n\n\t\t\t\tsOutput.append(\"\\n\");\n\t\t\t}\n\t\t}\n\n\t\tEA::UnitTest::ReportVerbosity(2, \"%s\\n\\n\", sOutput.c_str());\n\t}\n\n\t{\n\t\t// Do a speed test for the case of slow assignment.\n\t\t// By this we mean to compare sorting speeds when the movement of elements is slow.\n\t\t// Sort functions use element comparison to tell where elements go and use element\n\t\t// movement to get them there. But some sorting functions accomplish sorting performance by\n\t\t// minimizing the amount of movement, some minimize the amount of comparisons, and the\n\t\t// best do a good job of minimizing both.\n\t\tauto sortFunctions = allSortFunctions;\n\t\t// Can't implement this for qsort because the C standard library doesn't expose it.\n\t\t// We could implement it by copying and modifying the source code.\n\t\tsortFunctions.erase(eastl::remove(sortFunctions.begin(), sortFunctions.end(), sf_qsort), sortFunctions.end());\n\n\t\tEA::UnitTest::ReportVerbosity(2, \"Sort comparison: Slow assignment speed test\\n\");\n\n\t\ttypedef SlowAssign<uint32_t> ElementType;\n\t\ttypedef eastl::less<ElementType> CompareFunction;\n\n\t\teastl::string sOutput;\n\t\tsOutput.set_capacity(100000);\n\t\tElementType* pBuffer = new ElementType[kArraySizeMax];\n\n\t\tmemset(sResults, 0, sizeof(sResults));\n\n\t\tstopwatchGlobal.Restart();\n\n\t\tfor (int c = 0; c < kRunCount; c++)\n\t\t{\n\t\t\tfor (int i = 0; i < kRandomizationTypeCount; i++)\n\t\t\t{\n\t\t\t\tfor (size_t sizeType = 0; sizeType < EAArrayCount(kSizes); sizeType++)\n\t\t\t\t{\n\t\t\t\t\tconst eastl_size_t size = kSizes[sizeType];\n\n\t\t\t\t\tfor (SortFunctionType sortFunction : sortFunctions)\n\t\t\t\t\t{\n\t\t\t\t\t\teastl::vector<ElementType> v(size);\n\n\t\t\t\t\t\tRandomize<ElementType>(v, rng, (RandomizationType)i);\n\t\t\t\t\t\tElementType::Reset();\n\n\t\t\t\t\t\tswitch (sortFunction)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase sf_quick_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::quick_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_tim_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::tim_sort_buffer(v.begin(), v.end(), pBuffer, CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_insertion_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::insertion_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_shell_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::shell_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_heap_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::heap_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_merge_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::merge_sort(v.begin(), v.end(), *get_default_allocator((EASTLAllocatorType*)NULL), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_merge_sort_buffer:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::merge_sort_buffer(v.begin(), v.end(), pBuffer, CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_comb_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::comb_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_bubble_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::bubble_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_selection_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::selection_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_shaker_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::shaker_sort(v.begin(), v.end(), CompareFunction());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_radix_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\teastl::radix_sort<ElementType*, slow_assign_extract_radix_key<ElementType>>(v.begin(), v.end(), pBuffer);\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_std_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tstd::sort(v.begin(), v.end(), std::less<ElementType>());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_std_stable_sort:\n\t\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\t\tstd::stable_sort(v.begin(), v.end(), std::less<ElementType>());\n\t\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase sf_qsort:\n\t\t\t\t\t\t\tcase sf_count:\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t// unsupported\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst uint64_t elapsedTime = (uint64_t)stopwatch.GetElapsedTime();\n\n\t\t\t\t\t\t// If this result was faster than a previously fastest result, record this one instead.\n\t\t\t\t\t\tif ((c == 0) || (elapsedTime < sResults[i][sizeType][sortFunction].mTime))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsResults[i][sizeType][sortFunction].mTime = elapsedTime;\n\t\t\t\t\t\t\tsResults[i][sizeType][sortFunction].mAssignCount = (uint64_t)ElementType::nAssignCount;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tVERIFY(eastl::is_sorted(v.begin(), v.end()));\n\n\t\t\t\t\t} // for each sort function...\n\n\t\t\t\t} // for each size type...\n\n\t\t\t} // for each randomization type...\n\n\t\t} // for each run\n\n\t\tEA::UnitTest::ReportVerbosity(2, \"Total time: %.2f s\\n\", stopwatchGlobal.GetElapsedTimeFloat());\n\n\t\tdelete[] pBuffer;\n\n\t\t// Now print the results.\n\t\tfor (int i = 0; i < kRandomizationTypeCount; i++)\n\t\t{\n\t\t\tfor (size_t sizeType = 0; sizeType < EAArrayCount(kSizes); sizeType++)\n\t\t\t{\n\t\t\t\tconst eastl_size_t size = kSizes[sizeType];\n\n\t\t\t\tfor (SortFunctionType sortFunction : sortFunctions)\n\t\t\t\t{\n\t\t\t\t\tsOutput.append_sprintf(\"%25s, %14s, Size: %6u, Time: %11\" PRIu64 \" ticks, Assignments: %11\" PRIu64 \"\\n\",\n\t\t\t\t\t                       GetSortFunctionName(sortFunction), GetRandomizationTypeName(i),\n\t\t\t\t\t                       (unsigned)size, sResults[i][sizeType][sortFunction].mTime,\n\t\t\t\t\t                       sResults[i][sizeType][sortFunction].mAssignCount);\n\t\t\t\t}\n\n\t\t\t\tsOutput.append(\"\\n\");\n\t\t\t}\n\t\t}\n\t\tEA::UnitTest::ReportVerbosity(2, \"%s\\n\", sOutput.c_str());\n\t}\n\n\t#if !defined(EA_DEBUG)\n\t\tEA::UnitTest::SetNormalThreadPriority();\n\t#endif\n\n\treturn nErrorCount;\n}\n\ntypedef eastl::function<void(eastl::string &output, const char* sortFunction, const char* randomizationType, size_t size, size_t numSubArrays, const BenchmarkResult &result)> OutputResultCallback;\ntypedef eastl::function<void(BenchmarkResult &result)> PostExecuteCallback;\ntypedef eastl::function<void()> PreExecuteCallback;\n\n\ntemplate<class ElementType, class CompareFunction>\nstatic int CompareSmallInputSortPerformanceHelper(eastl::vector<eastl_size_t> &arraySizes, eastl::vector<SortFunctionType> &sortFunctions, const PreExecuteCallback &preExecuteCallback, const PostExecuteCallback &postExecuteCallback, const OutputResultCallback &outputResultCallback)\n{\n\tint nErrorCount = 0;\n\n\tEA::UnitTest::RandGenT<int32_t> rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch stopwatch(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch stopwatchGlobal(EA::StdC::Stopwatch::kUnitsSeconds);\n\tconst eastl_size_t kArraySizeMax = *eastl::max_element(eastl::begin(arraySizes), eastl::end(arraySizes));\n\tconst int kRunCount = 4;\n\tconst int numSubArrays = 128;\n\n\teastl::string sOutput;\n\tsOutput.set_capacity(100000);\n\tElementType* pBuffer = new ElementType[kArraySizeMax];\n\n\tstopwatchGlobal.Restart();\n\n\tfor (int i = 0; i < kRandomizationTypeCount; i++)\n\t{\n\t\tfor (size_t size : arraySizes)\n\t\t{\n\t\t\tfor (SortFunctionType sortFunction : sortFunctions)\n\t\t\t{\n\t\t\t\tBenchmarkResult bestResult{};\n\n\t\t\t\tfor (int c = 0; c < kRunCount; c++)\n\t\t\t\t{\n\t\t\t\t\teastl::vector<ElementType> v(size * numSubArrays);\n\n\t\t\t\t\trng.SetSeed(EA::UnitTest::GetRandSeed());\n\t\t\t\t\tRandomize(v, rng, (RandomizationType)i);\n\t\t\t\t\tpreExecuteCallback();\n\n\t\t\t\t\tswitch (sortFunction)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase sf_quick_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::quick_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_tim_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::tim_sort_buffer(begin, begin + size, pBuffer, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_insertion_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::insertion_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_shell_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::shell_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_heap_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::heap_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_merge_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::merge_sort(begin, begin + size, *get_default_allocator((EASTLAllocatorType*)NULL), CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_merge_sort_buffer:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::merge_sort_buffer(begin, begin + size, pBuffer, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_comb_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::comb_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_bubble_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::bubble_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_selection_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::selection_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_shaker_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teastl::shaker_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_std_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstd::sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_std_stable_sort:\n\t\t\t\t\t\t\tstopwatch.Restart();\n\t\t\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstd::stable_sort(begin, begin + size, CompareFunction());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstopwatch.Stop();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase sf_qsort:\n\t\t\t\t\t\tcase sf_radix_sort:\n\t\t\t\t\t\tcase sf_count:\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tEATEST_VERIFY_F(false, \"Missing case statement for sort function %s.\", GetSortFunctionName(sortFunction));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tBenchmarkResult result {};\n\t\t\t\t\tresult.mTime = (uint64_t)stopwatch.GetElapsedTime();\n\t\t\t\t\tpostExecuteCallback(result);\n\n\t\t\t\t\t// If this result was faster than a previously fastest result, record this one instead.\n\t\t\t\t\tif ((c == 0) || (result.mTime < bestResult.mTime))\n\t\t\t\t\t\tbestResult = result;\n\n\t\t\t\t\tfor (auto begin = v.begin(); begin != v.end(); begin += size)\n\t\t\t\t\t{\n\t\t\t\t\t\tVERIFY(eastl::is_sorted(begin, begin + size));\n\t\t\t\t\t}\n\t\t\t\t} // for each run\n\n\t\t\t\toutputResultCallback(sOutput, GetSortFunctionName(sortFunction), GetRandomizationTypeName(i), size, numSubArrays, bestResult);\n\n\t\t\t} // for each sort function...\n\t\t\tsOutput.append(\"\\n\");\n\n\t\t} // for each size type...\n\n\t} // for each randomization type...\n\n\tEA::UnitTest::ReportVerbosity(2, \"Total time: %.2f s\\n\", stopwatchGlobal.GetElapsedTimeFloat());\n\tEA::UnitTest::ReportVerbosity(2, \"%s\\n\", sOutput.c_str());\n\n\tdelete[] pBuffer;\n\treturn nErrorCount;\n}\n\nstatic int CompareSmallInputSortPerformance()\n{\n\tint nErrorCount = 0;\n\teastl::vector<eastl_size_t> arraySizes{1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 64, 128, 256};\n\t// Test quick sort and merge sort to provide a \"base line\" for performance.  The other sort algorithms are mostly\n\t// O(n^2) and they are benchmarked to determine what sorts are ideal for sorting small arrays or sub-arrays.  (i.e.\n\t// this is useful to determine good algorithms to choose as a base case for some of the recursive sorts).\n\teastl::vector<SortFunctionType> sortFunctions{sf_quick_sort,     sf_merge_sort_buffer,     sf_bubble_sort, sf_comb_sort,\n\t                                              sf_insertion_sort, sf_selection_sort, sf_shell_sort,  sf_shaker_sort};\n\n\tEA::UnitTest::ReportVerbosity(2, \"Small Sub-array Sort comparison: Regular speed test\\n\");\n\tnErrorCount += CompareSmallInputSortPerformanceHelper<uint32_t, eastl::less<uint32_t>>(\n\t    arraySizes, sortFunctions, PreExecuteCallback([]() {}), PostExecuteCallback([](BenchmarkResult&) {}),\n\t    OutputResultCallback([](eastl::string& output, const char* sortFunction, const char* randomizationType,\n\t                            size_t size, size_t numSubArrays, const BenchmarkResult& result) {\n\t\t    output.append_sprintf(\"%25s, %14s, Size: %8u, Time: %0.1f ticks %0.2f ticks/elem\\n\", sortFunction,\n\t\t                          randomizationType, (unsigned)size, float(result.mTime) / float(numSubArrays),\n\t\t                          float(result.mTime) / float(size * numSubArrays));\n\t    }));\n\n\tEA::UnitTest::ReportVerbosity(2, \"Small Sub-array Sort comparison: Slow compare speed test\\n\");\n\tnErrorCount += CompareSmallInputSortPerformanceHelper<int32_t, SlowCompare<int32_t>>(\n\t    arraySizes, sortFunctions, PreExecuteCallback([]() { SlowCompare<int32_t>::Reset(); }),\n\t    PostExecuteCallback(\n\t        [](BenchmarkResult& result) { result.mCompareCount = (uint64_t)SlowCompare<int32_t>::nCompareCount; }),\n\t    OutputResultCallback([](eastl::string& output, const char* sortFunction, const char* randomizationType,\n\t                            size_t size, size_t numSubArrays, const BenchmarkResult& result) {\n\t\t    output.append_sprintf(\"%25s, %14s, Size: %6u, Time: %0.2f ticks, Compares: %0.2f\\n\", sortFunction,\n\t\t                          randomizationType, (unsigned)size, float(result.mTime) / float(numSubArrays),\n\t\t                          float(result.mCompareCount) / float(numSubArrays));\n\t    }));\n\n\tEA::UnitTest::ReportVerbosity(2, \"Small Sub-array Sort comparison: Slow assignment speed test\\n\");\n\tnErrorCount += CompareSmallInputSortPerformanceHelper<SlowAssign<uint32_t>, eastl::less<SlowAssign<uint32_t>>>(\n\t    arraySizes, sortFunctions, PreExecuteCallback([]() { SlowAssign<uint32_t>::Reset(); }),\n\t    PostExecuteCallback([](BenchmarkResult& result) {\n\t\t    result.mCompareCount = (uint64_t)SlowCompare<int32_t>::nCompareCount;\n\t\t    result.mAssignCount = (uint64_t)SlowAssign<uint32_t>::nAssignCount;\n\t    }),\n\t    OutputResultCallback([](eastl::string& output, const char* sortFunction, const char* randomizationType,\n\t                            size_t size, size_t numSubArrays, const BenchmarkResult& result) {\n\t\t    output.append_sprintf(\"%25s, %14s, Size: %6u, Time: %0.2f ticks, Assignments: %0.2f\\n\", sortFunction,\n\t\t                          randomizationType, (unsigned)size, float(result.mTime) / float(numSubArrays),\n\t\t                          float(result.mAssignCount) / float(numSubArrays));\n\t    }));\n\n\treturn nErrorCount;\n}\n\n\nvoid BenchmarkSort()\n{\n\tEASTLTest_Printf(\"Sort\\n\");\n\n\tEA::UnitTest::RandGenT<uint32_t> rng(12345678); // For debugging sort code we should use 12345678, for normal testing use EA::UnitTest::GetRandSeed().\n\tEA::StdC::Stopwatch              stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch              stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\tif (EA::UnitTest::GetVerbosity() >= 3)\n\t{\n\t\tCompareSortPerformance();\n\t\tCompareSmallInputSortPerformance();\n\t}\n\n\t{ // Exercise some declarations\n\t\tint nErrorCount = 0;\n\n\t\tValuePair vp1 = {0, 0}, vp2 = {0, 0};\n\t\tVPCompare c1, c2;\n\n\t\tVERIFY(c1.operator()(vp1, vp2) == c2.operator()(vp1, vp2));\n\t\tVERIFY((vp1 < vp2) || (vp1 == vp2) || !(vp1 == vp2));\n\t}\n\n\t{\n\t\teastl::vector<uint32_t> intVector(10000);\n\t\teastl::generate(intVector.begin(), intVector.end(), rng);\n\n\t\tfor (int i = 0; i < 2; i++)\n\t\t{\n\t\t\t///////////////////////////////\n\t\t\t// Test quick_sort/vector/ValuePair\n\t\t\t///////////////////////////////\n\n\t\t\tStdVectorVP stdVectorVP(intVector.size());\n\t\t\tEaVectorVP eaVectorVP(intVector.size());\n\n\t\t\tfor (eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t\t{\n\t\t\t\tconst ValuePair vp = {intVector[j], intVector[j]};\n\t\t\t\tstdVectorVP[j] = vp;\n\t\t\t\teaVectorVP[j] = vp;\n\t\t\t}\n\n\t\t\tTestQuickSortStdVP(stopwatch1, stdVectorVP);\n\t\t\tTestQuickSortEaVP (stopwatch2,  eaVectorVP);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/vector<ValuePair>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\t// Benchmark the sorting of something that is already sorted.\n\t\t\tTestQuickSortStdVP(stopwatch1, stdVectorVP);\n\t\t\tTestQuickSortEaVP (stopwatch2,  eaVectorVP);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/vector<ValuePair>/sorted\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test quick_sort/vector/Int\n\t\t\t///////////////////////////////\n\n\t\t\tStdVectorInt stdVectorInt(intVector.size());\n\t\t\tEaVectorInt  eaVectorInt (intVector.size());\n\n\t\t\tfor(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t\t{\n\t\t\t\tstdVectorInt[j] = intVector[j];\n\t\t\t\teaVectorInt[j]  = intVector[j];\n\t\t\t}\n\n\t\t\tTestQuickSortStdInt(stopwatch1, stdVectorInt);\n\t\t\tTestQuickSortEaInt (stopwatch2,  eaVectorInt);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/vector<uint32>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\t// Benchmark the sorting of something that is already sorted.\n\t\t\tTestQuickSortStdInt(stopwatch1, stdVectorInt);\n\t\t\tTestQuickSortEaInt (stopwatch2,  eaVectorInt);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/vector<uint32>/sorted\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test quick_sort/vector/TestObject\n\t\t\t///////////////////////////////\n\n\t\t\tStdVectorTO stdVectorTO(intVector.size());\n\t\t\tEaVectorTO eaVectorTO(intVector.size());\n\n\t\t\tfor (eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t\t{\n\t\t\t\tstdVectorTO[j] = TestObject(intVector[j]);\n\t\t\t\teaVectorTO[j] = TestObject(intVector[j]);\n\t\t\t}\n\n\t\t\tTestQuickSortStdTO(stopwatch1, stdVectorTO);\n\t\t\tTestQuickSortEaTO(stopwatch2, eaVectorTO);\n\n\t\t\tif (i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/vector<TestObject>\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\t// Benchmark the sorting of something that is already sorted.\n\t\t\tTestQuickSortStdTO(stopwatch1, stdVectorTO);\n\t\t\tTestQuickSortEaTO(stopwatch2, eaVectorTO);\n\n\t\t\tif (i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/vector<TestObject>/sorted\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test quick_sort/TestObject[]\n\t\t\t///////////////////////////////\n\n\t\t\t// Reset the values back to the unsorted state.\n\t\t\tfor(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t\t{\n\t\t\t\tstdVectorTO[j] = TestObject(intVector[j]);\n\t\t\t\teaVectorTO[j]  = TestObject(intVector[j]);\n\t\t\t}\n\n\t\t\tTestQuickSortStdTO(stopwatch1, stdVectorTO);\n\t\t\tTestQuickSortEaTO (stopwatch2,  eaVectorTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/TestObject[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\t// Benchmark the sorting of something that is already sorted.\n\t\t\tTestQuickSortStdTO(stopwatch1, stdVectorTO);\n\t\t\tTestQuickSortEaTO (stopwatch2,  eaVectorTO);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"sort/q_sort/TestObject[]/sorted\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkString.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/string.h>\n#include <EASTL/sort.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <algorithm>\n#include <string>\n#include <stdio.h>\n#include <stdlib.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\nusing namespace EA;\n\n\nnamespace\n{\n\ttemplate <typename Container> \n\tvoid TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t\tc.push_back((typename Container::value_type)(i & ((typename Container::value_type)~0)));\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename T> \n\tvoid TestInsert1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p)\n\t{\n\t\tconst typename Container::size_type s = c.size();\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100; i++)\n\t\t\tc.insert(s - (typename Container::size_type)(i * 317), p);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container> \n\tvoid TestErase1(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tconst typename Container::size_type s = c.size();\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 100; i++)\n\t\t\tc.erase(s - (typename Container::size_type)(i * 339), 7);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename T> \n\tvoid TestReplace1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int n)\n\t{\n\t\tconst typename Container::size_type s = c.size();\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tc.replace(s - (typename Container::size_type)(i * 5), ((n - 2) + (i & 3)), p, n); // The second argument rotates through n-2, n-1, n, n+1, n-2, etc.\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container> \n\tvoid TestReserve(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tconst typename Container::size_type s = c.capacity();\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tc.reserve((s - 2) + (i & 3)); // The second argument rotates through n-2, n-1, n, n+1, n-2, etc.\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container> \n\tvoid TestSize(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, c.size()); \n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tint32_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor(typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)\n\t\t\ttemp += c[j];\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)temp);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, *eastl::find(c.begin(), c.end(), (typename Container::value_type)~0));\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename T> \n\tvoid TestFind1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, c.find(p, (typename Container::size_type)pos, (typename Container::size_type)n));\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container, typename T> \n\tvoid TestRfind1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, c.rfind(p, (typename Container::size_type)pos, (typename Container::size_type)n));\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container, typename T> \n\tvoid TestFirstOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, c.find_first_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container, typename T> \n\tvoid TestLastOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, c.find_last_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container, typename T> \n\tvoid TestFirstNotOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, c.find_first_not_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container, typename T> \n\tvoid TestLastNotOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tBenchmark::DoNothing(&c, c.find_last_not_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container> \n\tvoid TestCompare(EA::StdC::Stopwatch& stopwatch, Container& c1, Container& c2) // size()\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 500; i++)\n\t\t\tBenchmark::DoNothing(&c1, c1.compare(c2));\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container> \n\tvoid TestSwap(EA::StdC::Stopwatch& stopwatch, Container& c1, Container& c2) // size()\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(int i = 0; i < 10000; i++) // Make sure this is an even count so that when done things haven't changed.\n\t\t{\n\t\t\tc1.swap(c2);\n\t\t\tBenchmark::DoNothing(&c1);\n\t\t} \n\t\tstopwatch.Stop();\n\t}\n\n} // namespace\n\n\n\n\nvoid BenchmarkString()\n{\n\tEASTLTest_Printf(\"String\\n\");\n\n\tEA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tstd::basic_string<char8_t>    ss8(16, 0);   // We initialize to size of 16 because different implementations may make\n\t\t\teastl::basic_string<char8_t>  es8(16, 0);   // different tradeoffs related to startup size. Initial operations are faster\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// when strings start with a higher reserve, but they use more memory. \n\t\t\tstd::basic_string<char16_t>   ss16(16, 0);  // We try to nullify this tradeoff for the tests below by starting all at \n\t\t\teastl::basic_string<char16_t> es16(16, 0);  // the same baseline allocation.\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_back\n\t\t\t///////////////////////////////\n\n\t\t\tTestPushBack(stopwatch1, ss8);\n\t\t\tTestPushBack(stopwatch2, es8);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/push_back\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestPushBack(stopwatch1, ss16);\n\t\t\tTestPushBack(stopwatch2, es16);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/push_back\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert(size_type position, const value_type* p)\n\t\t\t///////////////////////////////\n\n\t\t\tconst char8_t pInsert1_8[] = { 'a', 0 };\n\t\t\tTestInsert1(stopwatch1, ss8, pInsert1_8);\n\t\t\tTestInsert1(stopwatch2, es8, pInsert1_8);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/insert/pos,p\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tconst char16_t pInsert1_16[] = { 'a', 0 };\n\t\t\tTestInsert1(stopwatch1, ss16, pInsert1_16);\n\t\t\tTestInsert1(stopwatch2, es16, pInsert1_16);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/insert/pos,p\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase(size_type position, size_type n)\n\t\t\t///////////////////////////////\n\n\t\t\tTestErase1(stopwatch1, ss8);\n\t\t\tTestErase1(stopwatch2, es8);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/erase/pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestErase1(stopwatch1, ss16);\n\t\t\tTestErase1(stopwatch2, es16);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/erase/pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////            \n\t\t\t// Test replace(size_type position, size_type n1, const value_type* p, size_type n2)\n\t\t\t///////////////////////////////\n\n\t\t\tconst int kReplace1Size = 8;\n\t\t\tconst char8_t pReplace1_8[kReplace1Size] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };\n\n\t\t\tTestReplace1(stopwatch1, ss8, pReplace1_8, kReplace1Size);\n\t\t\tTestReplace1(stopwatch2, es8, pReplace1_8, kReplace1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/replace/pos,n,p,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tconst char16_t pReplace1_16[kReplace1Size] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };\n\n\t\t\tTestReplace1(stopwatch1, ss16, pReplace1_16, kReplace1Size);\n\t\t\tTestReplace1(stopwatch2, es16, pReplace1_16, kReplace1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/replace/pos,n,p,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test reserve(size_type)\n\t\t\t///////////////////////////////\n\n\t\t\tTestReserve(stopwatch1, ss8);\n\t\t\tTestReserve(stopwatch2, es8);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/reserve\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestReserve(stopwatch1, ss16);\n\t\t\tTestReserve(stopwatch2, es16);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/reserve\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test size()\n\t\t\t///////////////////////////////\n\n\t\t\tTestSize(stopwatch1, ss8);\n\t\t\tTestSize(stopwatch2, es8);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/size\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSize(stopwatch1, ss16);\n\t\t\tTestSize(stopwatch2, es16);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/size\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test operator[].\n\t\t\t///////////////////////////////\n\n\t\t\tTestBracket(stopwatch1, ss8);\n\t\t\tTestBracket(stopwatch2, es8);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestBracket(stopwatch1, ss16);\n\t\t\tTestBracket(stopwatch2, es16);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration via find().\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, ss8);\n\t\t\tTestFind(stopwatch2, es8);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFind(stopwatch1, ss16);\n\t\t\tTestFind(stopwatch2, es16);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find(const value_type* p, size_type position, size_type n)\n\t\t\t///////////////////////////////\n\n\t\t\tconst int kFind1Size = 7;\n\t\t\tconst char8_t pFind1_8[kFind1Size] = { 'p', 'a', 't', 't', 'e', 'r', 'n' };\n\n\t\t\tss8.insert(ss8.size() / 2, pFind1_8);\n\t\t\tes8.insert(es8.size() / 2, pFind1_8);\n\n\t\t\tTestFind1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);\n\t\t\tTestFind1(stopwatch2, es8, pFind1_8, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/find/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tconst char16_t pFind1_16[kFind1Size] = { 'p', 'a', 't', 't', 'e', 'r', 'n' };\n\n\t\t\t#if !defined(EA_PLATFORM_IPHONE) && (!defined(EA_COMPILER_CLANG) && defined(EA_PLATFORM_MINGW)) // Crashes on iPhone.\n\t\t\t  ss16.insert(ss8.size() / 2, pFind1_16);\n\t\t\t#endif\n\t\t\tes16.insert(es8.size() / 2, pFind1_16);\n\n\t\t\tTestFind1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);\n\t\t\tTestFind1(stopwatch2, es16, pFind1_16, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/find/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test rfind(const value_type* p, size_type position, size_type n)\n\t\t\t///////////////////////////////\n\n\t\t\tTestRfind1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);\n\t\t\tTestRfind1(stopwatch2, es8, pFind1_8, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/rfind/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestRfind1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);\n\t\t\tTestRfind1(stopwatch2, es16, pFind1_16, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/rfind/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t//NOTICE (RASHIN):\n\t\t\t//FindFirstOf variants are incredibly slow on palm pixi debug builds.\n\t\t\t//Disabling for now...\n\t\t#if !defined(EA_DEBUG)\n\t\t\t///////////////////////////////\n\t\t\t// Test find_first_of(const value_type* p, size_type position, size_type n\n\t\t\t///////////////////////////////\n\n\t\t\tconst int kFindOf1Size = 7;\n\t\t\tconst char8_t pFindOf1_8[kFindOf1Size] = { '~', '~', '~', '~', '~', '~', '~' };\n\n\t\t\tTestFirstOf1(stopwatch1, ss8, pFindOf1_8, 15, kFindOf1Size);\n\t\t\tTestFirstOf1(stopwatch2, es8, pFindOf1_8, 15, kFindOf1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/find_first_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tconst char16_t pFindOf1_16[kFindOf1Size] = { '~', '~', '~', '~', '~', '~', '~' };\n\n\t\t\tTestFirstOf1(stopwatch1, ss16, pFindOf1_16, 15, kFindOf1Size);\n\t\t\tTestFirstOf1(stopwatch2, es16, pFindOf1_16, 15, kFindOf1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/find_first_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find_last_of(const value_type* p, size_type position, size_type n\n\t\t\t///////////////////////////////\n\n\t\t\tTestLastOf1(stopwatch1, ss8, pFindOf1_8, 15, kFindOf1Size);\n\t\t\tTestLastOf1(stopwatch2, es8, pFindOf1_8, 15, kFindOf1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/find_last_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestLastOf1(stopwatch1, ss16, pFindOf1_16, 15, kFindOf1Size);\n\t\t\tTestLastOf1(stopwatch2, es16, pFindOf1_16, 15, kFindOf1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/find_last_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find_first_not_of(const value_type* p, size_type position, size_type n\n\t\t\t///////////////////////////////\n\n\t\t\tTestFirstNotOf1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);\n\t\t\tTestFirstNotOf1(stopwatch2, es8, pFind1_8, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/find_first_not_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestFirstNotOf1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);\n\t\t\tTestFirstNotOf1(stopwatch2, es16, pFind1_16, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/find_first_not_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test find_last_of(const value_type* p, size_type position, size_type n\n\t\t\t///////////////////////////////\n\n\t\t\tTestLastNotOf1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);\n\t\t\tTestLastNotOf1(stopwatch2, es8, pFind1_8, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/find_last_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestLastNotOf1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);\n\t\t\tTestLastNotOf1(stopwatch2, es16, pFind1_16, 15, kFind1Size);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/find_last_of/p,pos,n\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t#endif\n\n\t\t\t///////////////////////////////\n\t\t\t// Test compare()\n\t\t\t///////////////////////////////\n\n\t\t\tstd::basic_string<char8_t>    ss8X(ss8);\n\t\t\teastl::basic_string<char8_t>  es8X(es8);\n\t\t\tstd::basic_string<char16_t>   ss16X(ss16);\n\t\t\teastl::basic_string<char16_t> es16X(es16);\n\n\t\t\tTestCompare(stopwatch1, ss8, ss8X);\n\t\t\tTestCompare(stopwatch2, es8, es8X);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/compare\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestCompare(stopwatch1, ss16, ss16X);\n\t\t\tTestCompare(stopwatch2, es16, es16X);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/compare\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test swap()\n\t\t\t///////////////////////////////\n\n\t\t\tTestSwap(stopwatch1, ss8, ss8X);\n\t\t\tTestSwap(stopwatch2, es8, es8X);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char8_t>/swap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\tTestSwap(stopwatch1, ss16, ss16X);\n\t\t\tTestSwap(stopwatch2, es16, es16X);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"string<char16_t>/swap\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t}\n\t}\n\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkTupleVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/bonus/tuple_vector.h>\n#include <EASTL/sort.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4350)\n#endif\n#include <algorithm>\n#include <vector>\n#include <stdio.h>\n#include <stdlib.h>\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace EA;\n\n\ntypedef std::vector<uint64_t>     StdVectorUint64;\ntypedef eastl::tuple_vector<uint64_t>   EaTupleVectorUint64;\n\n struct PaddingStruct\n{\n\tchar padding[56] = { 0 };\n};\nstatic const PaddingStruct DefaultPadding;\ntypedef eastl::tuple<uint64_t, PaddingStruct> PaddedTuple;\ntypedef std::vector<PaddedTuple> StdVectorUint64Padded;\ntypedef eastl::tuple_vector<uint64_t, PaddingStruct> EaTupleVectorUint64Padded;\n\nnamespace\n{\n\n\n\t//////////////////////////////////////////////////////////////////////////////\n\t// MovableType\n\t// \n\tstruct MovableType\n\t{\n\t\tint8_t* mpData;\n\t\tenum { kDataSize = 128 };\n\n\t\tMovableType() : mpData(new int8_t[kDataSize])\n\t\t\t{ memset(mpData, 0, kDataSize); }\n\n\t\tMovableType(const MovableType& x) : mpData(new int8_t[kDataSize])\n\t\t\t{ memcpy(mpData, x.mpData, kDataSize); }\n\n\t\tMovableType& operator=(const MovableType& x)\n\t\t{\n\t\t\tif(!mpData)\n\t\t\t\tmpData = new int8_t[kDataSize];\n\t\t\tmemcpy(mpData, x.mpData, kDataSize);\n\t\t\treturn *this;\n\t\t}\n\n\t\t#if EASTL_MOVE_SEMANTICS_ENABLED\n\t\t\tMovableType(MovableType&& x) EA_NOEXCEPT : mpData(x.mpData)\n\t\t\t\t{ x.mpData = NULL; }\n\n\t\t\tMovableType& operator=(MovableType&& x)\n\t\t\t{\n\t\t\t\teastl::swap(mpData, x.mpData); // In practice it may not be right to do a swap, depending on the case.\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t#endif\n\n\t   ~MovableType()\n\t\t\t{ delete[] mpData; }\n\t};\n\n\n\t//////////////////////////////////////////////////////////////////////////////\n\t// AutoRefCount\n\t// \n\t// Basic ref-counted object.\n\t//\n\ttemplate <typename T>\n\tclass AutoRefCount\n\t{\n\tpublic:\n\t\tT* mpObject;\n\n\tpublic:\n\t\tAutoRefCount() EA_NOEXCEPT : mpObject(NULL) \n\t\t\t{}\n\n\t\tAutoRefCount(T* pObject) EA_NOEXCEPT : mpObject(pObject) \n\t\t{ \n\t\t\tif(mpObject)\n\t\t\t\tmpObject->AddRef();\n\t\t} \n\n\t\tAutoRefCount(T* pObject, int) EA_NOEXCEPT : mpObject(pObject) \n\t\t{\n\t\t\t// Inherit the existing refcount.\n\t\t} \n\n\t\tAutoRefCount(const AutoRefCount& x) EA_NOEXCEPT : mpObject(x.mpObject) \n\t\t{ \n\t\t\tif(mpObject)\n\t\t\t\tmpObject->AddRef();\n\t\t}\n\n\t\tAutoRefCount& operator=(const AutoRefCount& x)     \n\t\t{         \n\t\t\treturn operator=(x.mpObject);\n\t\t}\n\n\t\tAutoRefCount& operator=(T* pObject)\n\t\t{         \n\t\t\tif(pObject != mpObject)\n\t\t\t{\n\t\t\t\tT* const pTemp = mpObject; // Create temporary to prevent possible problems with re-entrancy.\n\t\t\t\tif(pObject)\n\t\t\t\t\tpObject->AddRef();\n\t\t\t\tmpObject = pObject;\n\t\t\t\tif(pTemp)\n\t\t\t\t\tpTemp->Release();\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\t#if EASTL_MOVE_SEMANTICS_ENABLED\n\t\t\tAutoRefCount(AutoRefCount&& x) EA_NOEXCEPT : mpObject(x.mpObject) \n\t\t\t{ \n\t\t\t\tx.mpObject = NULL;\n\t\t\t}\n\n\t\t\tAutoRefCount& operator=(AutoRefCount&& x)\n\t\t\t{\n\t\t\t\tif(mpObject)\n\t\t\t\t\tmpObject->Release();\n\t\t\t\tmpObject = x.mpObject;\n\t\t\t\tx.mpObject = NULL;\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t#endif\n\n\t\t~AutoRefCount() \n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\tmpObject->Release();\n\t\t}\n\n\t\tT& operator *() const EA_NOEXCEPT\n\t\t\t{ return *mpObject; }\n\n\t\tT* operator ->() const EA_NOEXCEPT\n\t\t\t{ return  mpObject; }\n\n\t\toperator T*() const EA_NOEXCEPT\n\t\t\t{ return  mpObject; }\n\n\t}; // class AutoRefCount\n\n\n\tstruct RefCounted\n\t{\n\t\tint        mRefCount;\n\t\tstatic int msAddRefCount;\n\t\tstatic int msReleaseCount;\n\n\t\tRefCounted() : mRefCount(1) {}\n\n\t\tint AddRef()\n\t\t\t{ ++msAddRefCount; return ++mRefCount; }\n\n\t\tint Release()\n\t\t{\n\t\t\t++msReleaseCount;\n\t\t\tif(mRefCount > 1)\n\t\t\t\treturn --mRefCount;\n\t\t\tdelete this;\n\t\t\treturn 0;\n\t\t}\n\t};\n\n\tint RefCounted::msAddRefCount  = 0;\n\tint RefCounted::msReleaseCount = 0;\n\n} // namespace \n\n\nnamespace \n{\n\ttemplate <typename Container> \n\tvoid TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t\tc.push_back((uint64_t)intVector[j]);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tuint64_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor(typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)\n\t\t\ttemp += c[j];\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(temp & 0xffffffff));\n\t}\n\n\tvoid TestBracket(EA::StdC::Stopwatch& stopwatch, EaTupleVectorUint64& c)\n\t{\n\t\tuint64_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor (typename EaTupleVectorUint64::size_type j = 0, jEnd = c.size(); j < jEnd; j++)\n\t\t\ttemp += eastl::get<0>(c[j]);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(temp & 0xffffffff));\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypedef typename Container::iterator iterator_t;  // This typedef is required to get this code to compile on RVCT\n\t\titerator_t it = eastl::find(c.begin(), c.end(), UINT64_C(0xffffffffffff));\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)*it);\n\t}\n\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, EaTupleVectorUint64& c)\n\t{\n\t\teastl::tuple<uint64_t> val(0xffffffffffff);\n\t\tstopwatch.Restart();\n\t\tEaTupleVectorUint64::iterator it = eastl::find(c.begin(), c.end(), val);\n\t\tstopwatch.Stop();\n\t\tif (it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)eastl::get<0>(*it));\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestSort(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\t// Intentionally use eastl sort in order to measure just  \n\t\t// vector access speed and not be polluted by sort speed.\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(c.begin(), c.end()); \n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(c[0] & 0xffffffff));\n\t}\n\n\tvoid TestSort(EA::StdC::Stopwatch& stopwatch, EaTupleVectorUint64& c)\n\t{\n\t\t// Intentionally use eastl sort in order to measure just\n\t\t// vector access speed and not be polluted by sort speed.\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(c.begin(), c.end());\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(eastl::get<0>(c[0]) & 0xffffffff));\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.insert(it, UINT64_C(0xffffffffffff));\n\n\t\t\tif(it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.erase(it);\n\n\t\t\tif(it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestMoveReallocate(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(c.size() < 8192)\n\t\t\tc.resize(c.capacity() + 1);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestMoveErase(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(!c.empty())\n\t\t\tc.erase(c.begin());\n\t\tstopwatch.Stop();\n\t}\n\n\t//////////////////////////////////////////////////////////////////////////\n\t// Variations of test functions for the Padded structures\n\ttemplate <typename Container>\n\tvoid TestTuplePushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor (eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t{\n\t\t\tPaddedTuple tup((uint64_t)intVector[j], DefaultPadding);\n\t\t\tc.push_back(tup);\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\t\n\ttemplate <typename Container>\n\tvoid TestTupleBracket(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tuint64_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor (typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)\n\t\t\ttemp += eastl::get<0>(c[j]);\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(temp & 0xffffffff));\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestTupleFind(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypedef typename Container::iterator iterator_t; // This typedef is required to get this code to compile on RVCT\n\t\titerator_t it = eastl::find_if(c.begin(), c.end(), [](auto tup) { return eastl::get<0>(tup) == 0xFFFFFFFF; });\n\t\tstopwatch.Stop();\n\t\tif (it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)eastl::get<0>(*it));\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestTupleSort(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\t// Intentionally use eastl sort in order to measure just\n\t\t// vector access speed and not be polluted by sort speed.\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(c.begin(), c.end(), [](auto a, auto b) { return eastl::get<0>(a) < eastl::get<0>(b); });\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(eastl::get<0>(c[0]) & 0xffffffff));\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestTupleInsert(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\t\tPaddedTuple tup(0xFFFFFFFF, DefaultPadding);\n\n\t\tstopwatch.Restart();\n\t\tfor (j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.insert(it, tup);\n\n\t\t\tif (it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif (++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif (++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\ttemplate <typename Container>\n\tvoid TestTupleErase(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor (j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.erase(it);\n\n\t\t\tif (it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif (++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif (++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n} // namespace\n\n\n\n\n\nvoid BenchmarkTupleVector()\n{\n\tEASTLTest_Printf(\"TupleVector\\n\");\n\n\tEA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch              stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch              stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\teastl::vector<uint32_t> intVector(100000);\n\t\teastl::generate(intVector.begin(), intVector.end(), rng);\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tStdVectorUint64 stdVectorUint64;\n\t\t\tEaTupleVectorUint64  eaTupleVectorUint64;\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_back\n\t\t\t///////////////////////////////\n\n\t\t\tTestPushBack(stopwatch1, stdVectorUint64, intVector);\n\t\t\tTestPushBack(stopwatch2, eaTupleVectorUint64, intVector);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64>/push_back\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test operator[].\n\t\t\t///////////////////////////////\n\n\t\t\tTestBracket(stopwatch1, stdVectorUint64);\n\t\t\tTestBracket(stopwatch2, eaTupleVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration via find().\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, stdVectorUint64);\n\t\t\tTestFind(stopwatch2, eaTupleVectorUint64);\n\t\t\tTestFind(stopwatch1, stdVectorUint64);\n\t\t\tTestFind(stopwatch2, eaTupleVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test sort\n\t\t\t///////////////////////////////\n\n\t\t\t// Currently VC++ complains about our sort function decrementing std::iterator that is already at begin(). In the strictest sense,\n\t\t\t// that's a valid complaint, but we aren't testing std STL here. We will want to revise our sort function eventually.\n\t\t\t#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)\n\t\t\tTestSort(stopwatch1, stdVectorUint64);\n\t\t\tTestSort(stopwatch2, eaTupleVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64>/sort\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t\t#endif\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert\n\t\t\t///////////////////////////////\n\n\t\t\tTestInsert(stopwatch1, stdVectorUint64);\n\t\t\tTestInsert(stopwatch2, eaTupleVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase\n\t\t\t///////////////////////////////\n\n\t\t\tTestErase(stopwatch1, stdVectorUint64);\n\t\t\tTestErase(stopwatch2, eaTupleVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////////////////\n\t\t\t// Test move of MovableType\n\t\t\t// Should be much faster with C++11 move.\n\t\t\t///////////////////////////////////////////\n\n\t\t\tstd::vector<MovableType>   stdVectorMovableType;\n\t\t\teastl::tuple_vector<MovableType> eaTupleVectorMovableType;\n\n\t\t\tTestMoveReallocate(stopwatch1, stdVectorMovableType);\n\t\t\tTestMoveReallocate(stopwatch2, eaTupleVectorMovableType);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<MovableType>/reallocate\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\tTestMoveErase(stopwatch1, stdVectorMovableType);\n\t\t\tTestMoveErase(stopwatch2, eaTupleVectorMovableType);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<MovableType>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////////////////\n\t\t\t// Test move of AutoRefCount\n\t\t\t// Should be much faster with C++11 move.\n\t\t\t///////////////////////////////////////////\n\n\t\t\tstd::vector<AutoRefCount<RefCounted> >   stdVectorAutoRefCount;\n\t\t\teastl::tuple_vector<AutoRefCount<RefCounted> > eaTupleVectorAutoRefCount;\n\n\t\t\tfor(size_t a = 0; a < 2048; a++)\n\t\t\t{\n\t\t\t\tstdVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));\n\t\t\t\teaTupleVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));\n\t\t\t}\n\n\t\t\tRefCounted::msAddRefCount  = 0;\n\t\t\tRefCounted::msReleaseCount = 0;\n\t\t\tTestMoveErase(stopwatch1, stdVectorAutoRefCount);\n\t\t\t//EASTLTest_Printf(\"tuple_vector<AutoRefCount>/erase std counts: %d %d\\n\", RefCounted::msAddRefCount, RefCounted::msReleaseCount);\n\n\t\t\tRefCounted::msAddRefCount  = 0;\n\t\t\tRefCounted::msReleaseCount = 0;\n\t\t\tTestMoveErase(stopwatch2, eaTupleVectorAutoRefCount);\n\t\t\t//EASTLTest_Printf(\"tuple_vector<AutoRefCount>/erase EA counts: %d %d\\n\", RefCounted::msAddRefCount, RefCounted::msReleaseCount);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<AutoRefCount>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\t\t\t\n\t\t\t//////////////////////////////////////////////////////////////////////////\n\t\t\t// Test various operations with \"padded\" data, to demonstrate access/modification of sparse data\n\n\t\t\tStdVectorUint64Padded stdVectorUint64Padded;\n\t\t\tEaTupleVectorUint64Padded eaTupleVectorUint64Padded;\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_back\n\t\t\t///////////////////////////////\n\n\t\t\tTestTuplePushBack(stopwatch1, stdVectorUint64Padded, intVector);\n\t\t\tTestTuplePushBack(stopwatch2, eaTupleVectorUint64Padded, intVector);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64,Padding>/push_back\", stopwatch1.GetUnits(),\n\t\t\t\t\t\t\t\t\t stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test operator[].\n\t\t\t///////////////////////////////\n\n\t\t\tTestTupleBracket(stopwatch1, stdVectorUint64Padded);\n\t\t\tTestTupleBracket(stopwatch2, eaTupleVectorUint64Padded);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64,Padding>/operator[]\", stopwatch1.GetUnits(),\n\t\t\t\t\t\t\t\t\t stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t\t\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration via find().\n\t\t\t///////////////////////////////\n\n\t\t\tTestTupleFind(stopwatch1, stdVectorUint64Padded);\n\t\t\tTestTupleFind(stopwatch2, eaTupleVectorUint64Padded);\n\t\t\tTestTupleFind(stopwatch1, stdVectorUint64Padded);\n\t\t\tTestTupleFind(stopwatch2, eaTupleVectorUint64Padded);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64,Padding>/iteration\", stopwatch1.GetUnits(),\n\t\t\t\t\t\t\t\t\t stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test sort\n\t\t\t///////////////////////////////\n\n\t\t\t// Currently VC++ complains about our sort function decrementing std::iterator that is already at\n\t\t\t// begin(). In the strictest sense, that's a valid complaint, but we aren't testing std STL here. We\n\t\t\t// will want to revise our sort function eventually.\n\t\t\t#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)\n\t\t\tTestTupleSort(stopwatch1, stdVectorUint64Padded);\n\t\t\tTestTupleSort(stopwatch2, eaTupleVectorUint64Padded);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64,Padding>/sort\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t stopwatch2.GetElapsedTime());\n\t\t\t#endif\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert\n\t\t\t///////////////////////////////\n\n\t\t\tTestTupleInsert(stopwatch1, stdVectorUint64Padded);\n\t\t\tTestTupleInsert(stopwatch2, eaTupleVectorUint64Padded);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64,Padding>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase\n\t\t\t///////////////////////////////\n\n\t\t\tTestTupleErase(stopwatch1, stdVectorUint64Padded);\n\t\t\tTestTupleErase(stopwatch2, eaTupleVectorUint64Padded);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"tuple_vector<uint64,Padding>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(),\n\t\t\t\t\t\t\t\t\t stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/BenchmarkVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/vector.h>\n#include <EASTL/sort.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n\t#pragma warning(disable: 4350)\n#endif\n#include <algorithm>\n#include <vector>\n#include <stdio.h>\n#include <stdlib.h>\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace EA;\n\n\ntypedef std::vector<uint64_t>     StdVectorUint64;\ntypedef eastl::vector<uint64_t>   EaVectorUint64;\n\n\nnamespace\n{\n\n\n\t//////////////////////////////////////////////////////////////////////////////\n\t// MovableType\n\t// \n\tstruct MovableType\n\t{\n\t\tint8_t* mpData;\n\t\tenum { kDataSize = 128 };\n\n\t\tMovableType() : mpData(new int8_t[kDataSize])\n\t\t\t{ memset(mpData, 0, kDataSize); }\n\n\t\tMovableType(const MovableType& x) : mpData(new int8_t[kDataSize])\n\t\t\t{ memcpy(mpData, x.mpData, kDataSize); }\n\n\t\tMovableType& operator=(const MovableType& x)\n\t\t{\n\t\t\tif(!mpData)\n\t\t\t\tmpData = new int8_t[kDataSize];\n\t\t\tmemcpy(mpData, x.mpData, kDataSize);\n\t\t\treturn *this;\n\t\t}\n\n\t\tMovableType(MovableType&& x) EA_NOEXCEPT : mpData(x.mpData)\n\t\t\t{ x.mpData = NULL; }\n\n\t\tMovableType& operator=(MovableType&& x)\n\t\t{\n\t\t\teastl::swap(mpData, x.mpData); // In practice it may not be right to do a swap, depending on the case.\n\t\t\treturn *this;\n\t\t}\n\n\t   ~MovableType()\n\t\t\t{ delete[] mpData; }\n\t};\n\n\n\t//////////////////////////////////////////////////////////////////////////////\n\t// AutoRefCount\n\t// \n\t// Basic ref-counted object.\n\t//\n\ttemplate <typename T>\n\tclass AutoRefCount\n\t{\n\tpublic:\n\t\tT* mpObject;\n\n\tpublic:\n\t\tAutoRefCount() EA_NOEXCEPT : mpObject(NULL) \n\t\t\t{}\n\n\t\tAutoRefCount(T* pObject) EA_NOEXCEPT : mpObject(pObject) \n\t\t{ \n\t\t\tif(mpObject)\n\t\t\t\tmpObject->AddRef();\n\t\t} \n\n\t\tAutoRefCount(T* pObject, int) EA_NOEXCEPT : mpObject(pObject) \n\t\t{\n\t\t\t// Inherit the existing refcount.\n\t\t} \n\n\t\tAutoRefCount(const AutoRefCount& x) EA_NOEXCEPT : mpObject(x.mpObject) \n\t\t{ \n\t\t\tif(mpObject)\n\t\t\t\tmpObject->AddRef();\n\t\t}\n\n\t\tAutoRefCount& operator=(const AutoRefCount& x)     \n\t\t{         \n\t\t\treturn operator=(x.mpObject);\n\t\t}\n\n\t\tAutoRefCount& operator=(T* pObject)\n\t\t{         \n\t\t\tif(pObject != mpObject)\n\t\t\t{\n\t\t\t\tT* const pTemp = mpObject; // Create temporary to prevent possible problems with re-entrancy.\n\t\t\t\tif(pObject)\n\t\t\t\t\tpObject->AddRef();\n\t\t\t\tmpObject = pObject;\n\t\t\t\tif(pTemp)\n\t\t\t\t\tpTemp->Release();\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\tAutoRefCount(AutoRefCount&& x) EA_NOEXCEPT : mpObject(x.mpObject) \n\t\t{ \n\t\t\tx.mpObject = NULL;\n\t\t}\n\n\t\tAutoRefCount& operator=(AutoRefCount&& x)\n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\tmpObject->Release();\n\t\t\tmpObject = x.mpObject;\n\t\t\tx.mpObject = NULL;\n\t\t\treturn *this;\n\t\t}\n\n\t\t~AutoRefCount() \n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\tmpObject->Release();\n\t\t}\n\n\t\tT& operator *() const EA_NOEXCEPT\n\t\t\t{ return *mpObject; }\n\n\t\tT* operator ->() const EA_NOEXCEPT\n\t\t\t{ return  mpObject; }\n\n\t\toperator T*() const EA_NOEXCEPT\n\t\t\t{ return  mpObject; }\n\n\t}; // class AutoRefCount\n\n\n\tstruct RefCounted\n\t{\n\t\tint        mRefCount;\n\t\tstatic int msAddRefCount;\n\t\tstatic int msReleaseCount;\n\n\t\tRefCounted() : mRefCount(1) {}\n\n\t\tint AddRef()\n\t\t\t{ ++msAddRefCount; return ++mRefCount; }\n\n\t\tint Release()\n\t\t{\n\t\t\t++msReleaseCount;\n\t\t\tif(mRefCount > 1)\n\t\t\t\treturn --mRefCount;\n\t\t\tdelete this;\n\t\t\treturn 0;\n\t\t}\n\t};\n\n\tint RefCounted::msAddRefCount  = 0;\n\tint RefCounted::msReleaseCount = 0;\n\n} // namespace \n\n\nnamespace \n{\n\ttemplate <typename Container> \n\tvoid TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)\n\t{\n\t\tstopwatch.Restart();\n\t\tfor(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)\n\t\t\tc.push_back((uint64_t)intVector[j]);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tuint64_t temp = 0;\n\t\tstopwatch.Restart();\n\t\tfor(typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)\n\t\t\ttemp += c[j];\n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(temp & 0xffffffff));\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\ttypedef typename Container::iterator iterator_t;  // This typedef is required to get this code to compile on RVCT\n\t\titerator_t it = eastl::find(c.begin(), c.end(), UINT64_C(0xffffffffffff));\n\t\tstopwatch.Stop();\n\t\tif(it != c.end())\n\t\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)*it);\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestSort(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\t// Intentionally use eastl sort in order to measure just  \n\t\t// vector access speed and not be polluted by sort speed.\n\t\tstopwatch.Restart();\n\t\teastl::quick_sort(c.begin(), c.end()); \n\t\tstopwatch.Stop();\n\t\tEA::StdC::Snprintf(Benchmark::gScratchBuffer, Benchmark::kScratchBufferSize, \"%u\", (unsigned)(c[0] & 0xffffffff));\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.insert(it, UINT64_C(0xffffffffffff));\n\n\t\t\tif(it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\ttypename Container::size_type j, jEnd;\n\t\ttypename Container::iterator it;\n\n\t\tstopwatch.Restart();\n\t\tfor(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)\n\t\t{\n\t\t\tit = c.erase(it);\n\n\t\t\tif(it == c.end()) // Try to safely increment the iterator three times.\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t\tif(++it == c.end())\n\t\t\t\tit = c.begin();\n\t\t}\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestMoveReallocate(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(c.size() < 8192)\n\t\t\tc.resize(c.capacity() + 1);\n\t\tstopwatch.Stop();\n\t}\n\n\n\ttemplate <typename Container>\n\tvoid TestMoveErase(EA::StdC::Stopwatch& stopwatch, Container& c)\n\t{\n\t\tstopwatch.Restart();\n\t\twhile(!c.empty())\n\t\t\tc.erase(c.begin());\n\t\tstopwatch.Stop();\n\t}\n\n\n} // namespace\n\n\n\n\n\nvoid BenchmarkVector()\n{\n\tEASTLTest_Printf(\"Vector\\n\");\n\n\tEA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());\n\tEA::StdC::Stopwatch              stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\tEA::StdC::Stopwatch              stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);\n\n\t{\n\t\teastl::vector<uint32_t> intVector(100000);\n\t\teastl::generate(intVector.begin(), intVector.end(), rng);\n\n\t\tfor(int i = 0; i < 2; i++)\n\t\t{\n\t\t\tStdVectorUint64 stdVectorUint64;\n\t\t\tEaVectorUint64  eaVectorUint64;\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test push_back\n\t\t\t///////////////////////////////\n\n\t\t\tTestPushBack(stopwatch1, stdVectorUint64, intVector);\n\t\t\tTestPushBack(stopwatch2, eaVectorUint64,  intVector);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<uint64>/push_back\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test operator[].\n\t\t\t///////////////////////////////\n\n\t\t\tTestBracket(stopwatch1, stdVectorUint64);\n\t\t\tTestBracket(stopwatch2, eaVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<uint64>/operator[]\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test iteration via find().\n\t\t\t///////////////////////////////\n\n\t\t\tTestFind(stopwatch1, stdVectorUint64);\n\t\t\tTestFind(stopwatch2, eaVectorUint64);\n\t\t\tTestFind(stopwatch1, stdVectorUint64);\n\t\t\tTestFind(stopwatch2, eaVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<uint64>/iteration\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test sort\n\t\t\t///////////////////////////////\n\n\t\t\t// Currently VC++ complains about our sort function decrementing std::iterator that is already at begin(). In the strictest sense,\n\t\t\t// that's a valid complaint, but we aren't testing std STL here. We will want to revise our sort function eventually.\n\t\t\t#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)\n\t\t\t\tTestSort(stopwatch1, stdVectorUint64);\n\t\t\t\tTestSort(stopwatch2, eaVectorUint64);\n\n\t\t\t\tif(i == 1)\n\t\t\t\t\tBenchmark::AddResult(\"vector<uint64>/sort\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t\t#endif\n\n\t\t\t///////////////////////////////\n\t\t\t// Test insert\n\t\t\t///////////////////////////////\n\n\t\t\tTestInsert(stopwatch1, stdVectorUint64);\n\t\t\tTestInsert(stopwatch2, eaVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<uint64>/insert\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////\n\t\t\t// Test erase\n\t\t\t///////////////////////////////\n\n\t\t\tTestErase(stopwatch1, stdVectorUint64);\n\t\t\tTestErase(stopwatch2, eaVectorUint64);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<uint64>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////////////////\n\t\t\t// Test move of MovableType\n\t\t\t// Should be much faster with C++11 move.\n\t\t\t///////////////////////////////////////////\n\n\t\t\tstd::vector<MovableType>   stdVectorMovableType;\n\t\t\teastl::vector<MovableType> eaVectorMovableType;\n\n\t\t\tTestMoveReallocate(stopwatch1, stdVectorMovableType);\n\t\t\tTestMoveReallocate(stopwatch2, eaVectorMovableType);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<MovableType>/reallocate\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\tTestMoveErase(stopwatch1, stdVectorMovableType);\n\t\t\tTestMoveErase(stopwatch2, eaVectorMovableType);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<MovableType>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\n\n\t\t\t///////////////////////////////////////////\n\t\t\t// Test move of AutoRefCount\n\t\t\t// Should be much faster with C++11 move.\n\t\t\t///////////////////////////////////////////\n\n\t\t\tstd::vector<AutoRefCount<RefCounted> >   stdVectorAutoRefCount;\n\t\t\teastl::vector<AutoRefCount<RefCounted> > eaVectorAutoRefCount;\n\n\t\t\tfor(size_t a = 0; a < 2048; a++)\n\t\t\t{\n\t\t\t\tstdVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));\n\t\t\t\teaVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));\n\t\t\t}\n\n\t\t\tRefCounted::msAddRefCount  = 0;\n\t\t\tRefCounted::msReleaseCount = 0;\n\t\t\tTestMoveErase(stopwatch1, stdVectorAutoRefCount);\n\t\t\tEASTLTest_Printf(\"vector<AutoRefCount>/erase std counts: %d %d\\n\", RefCounted::msAddRefCount, RefCounted::msReleaseCount);\n\n\t\t\tRefCounted::msAddRefCount  = 0;\n\t\t\tRefCounted::msReleaseCount = 0;\n\t\t\tTestMoveErase(stopwatch2, eaVectorAutoRefCount);\n\t\t\tEASTLTest_Printf(\"vector<AutoRefCount>/erase EA counts: %d %d\\n\", RefCounted::msAddRefCount, RefCounted::msReleaseCount);\n\n\t\t\tif(i == 1)\n\t\t\t\tBenchmark::AddResult(\"vector<AutoRefCount>/erase\", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());\n\t\t}\n\t}\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/EASTLBenchmark.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#include <EASTL/string.h>\n#include <EAMain/EAMain.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n#include <stdio.h>\n#include <math.h>\n#include <float.h>\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\n\nnamespace Benchmark\n{\n\tstatic int64_t ConvertStopwatchUnits(EA::StdC::Stopwatch::Units unitsSource, int64_t valueSource, EA::StdC::Stopwatch::Units unitsDest)\n\t{\n\t\tusing namespace EA::StdC;\n\n\t\tint64_t valueDest = valueSource;\n\n\t\tif(unitsSource != unitsDest)\n\t\t{\n\t\t\tdouble sourceMultiplier;\n\n\t\t\tswitch (unitsSource)\n\t\t\t{\n\t\t\t\tcase Stopwatch::kUnitsCPUCycles:\n\t\t\t\t\tsourceMultiplier = Stopwatch::GetUnitsPerCPUCycle(unitsDest); // This will typically be a number less than 1.\n\t\t\t\t\tvalueDest = (int64_t)(valueSource * sourceMultiplier);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase Stopwatch::kUnitsCycles:\n\t\t\t\t\tsourceMultiplier = Stopwatch::GetUnitsPerStopwatchCycle(unitsDest); // This will typically be a number less than 1.\n\t\t\t\t\tvalueDest = (int64_t)(valueSource * sourceMultiplier);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase Stopwatch::kUnitsNanoseconds:\n\t\t\t\tcase Stopwatch::kUnitsMicroseconds:\n\t\t\t\tcase Stopwatch::kUnitsMilliseconds:\n\t\t\t\tcase Stopwatch::kUnitsSeconds:\n\t\t\t\tcase Stopwatch::kUnitsMinutes:\n\t\t\t\tcase Stopwatch::kUnitsUserDefined:\n\t\t\t\t\t// To do. Also, handle the case of unitsDest being Cycles or CPUCycles and unitsSource being a time.\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn valueDest;\n\t}\n\n\tvoid WriteTime(int64_t timeNS, eastl::string& sTime)\n\t{\n\t\tif(timeNS > 1000000000)\n\t\t\tsTime.sprintf(\" %6.2f s\",  (double)timeNS / 1000000000);\n\t\telse if(timeNS > 1000000)\n\t\t\tsTime.sprintf(\"%6.1f ms\", (double)timeNS / 1000000);\n\t\telse if(timeNS > 1000)\n\t\t\tsTime.sprintf(\"%6.1f us\", (double)timeNS / 1000);\n\t\telse\n\t\t\tsTime.sprintf(\"%6.1f ns\", (double)timeNS / 1);\n\t}\n\n\n\n\tEnvironment gEnvironment;\n\n\tEnvironment& GetEnvironment()\n\t{\n\t\treturn gEnvironment;\n\t}\n\n\n\n\tResultSet gResultSet;\n\n\tResultSet& GetResultSet()\n\t{\n\t\treturn gResultSet;\n\t}\n\n\n\n\t// Scratch sprintf buffer\n\tchar gScratchBuffer[kScratchBufferSize];\n\n\n\tvoid DoNothing(...)\n\t{\n\t\t// Intentionally nothing.\n\t}\n\n\n\tvoid AddResult(const char* pName, int units, int64_t nTime1, int64_t nTime2, const char* pNotes)\n\t{\n\t\tResult result;\n\n\t\tresult.msName   = pName;\n\t\tresult.mUnits   = units;\n\t\tresult.mTime1   = nTime1;\n\t\tresult.mTime1NS = ConvertStopwatchUnits((EA::StdC::Stopwatch::Units)units, nTime1, EA::StdC::Stopwatch::kUnitsNanoseconds);\n\t\tresult.mTime2   = nTime2;\n\t\tresult.mTime2NS = ConvertStopwatchUnits((EA::StdC::Stopwatch::Units)units, nTime2, EA::StdC::Stopwatch::kUnitsNanoseconds);\n\n\t\tif(pNotes)\n\t\t\tresult.msNotes = pNotes;\n\n\t\tgResultSet.insert(result);\n\t}\n\n\n\tvoid PrintResultLine(const Result& result)\n\t{\n\t\tconst double fRatio         = (double)result.mTime1 / (double)result.mTime2;\n\t\tconst double fRatioPrinted  = (fRatio > 100) ? 100 : fRatio;\n\t\tconst double fPercentChange = fabs(((double)result.mTime1 - (double)result.mTime2) / (((double)result.mTime1 + (double)result.mTime2) / 2));\n\t\tconst bool   bDifference    = (result.mTime1 > 10) && (result.mTime2 > 10) && (fPercentChange > 0.25);\n\t\tconst char*  pDifference    = (bDifference ? (result.mTime1 < result.mTime2 ? \"-\" : \"+\") : \"\");\n\n\t\teastl::string sClockTime1, sClockTime2;\n\n\t\tWriteTime(result.mTime1NS, sClockTime1);  // This converts an integer in nanoseconds (e.g. 23400000) to a string (e.g. \"23.4 ms\")\n\t\tWriteTime(result.mTime2NS, sClockTime2);\n\n\t\tEA::UnitTest::Report(\"%-43s | %13\" PRIu64 \" %s | %13\" PRIu64 \" %s | %10.2f%10s\", result.msName.c_str(), result.mTime1, sClockTime1.c_str(), result.mTime2, sClockTime2.c_str(), fRatioPrinted, pDifference);\n\n\t\tif(result.msNotes.length()) // If there are any notes...\n\t\t\tEA::UnitTest::Report(\"   %s\", result.msNotes.c_str());\n\t\tEA::UnitTest::Report(\"\\n\");\n\t}\n\n\n\t#if defined(EASTL_BENCHMARK_WRITE_FILE) && EASTL_BENCHMARK_WRITE_FILE\n\n\t\t#if !defined(EASTL_BENCHMARK_WRITE_FILE_PATH)\n\t\t\t#define EASTL_BENCHMARK_WRITE_FILE_PATH \"BenchmarkResults.txt\"\n\t\t#endif\n\n\t\tstruct FileWriter\n\t\t{\n\t\t\tFILE* mpReportFile;\n\t\t\tEA::EAMain::ReportFunction mpSavedReportFunction;\n\t\t\tstatic FileWriter* gpFileWriter;\n\n\t\t\tstatic void StaticPrintfReportFunction(const char8_t* pText)\n\t\t\t{\n\t\t\t\tif(gpFileWriter)\n\t\t\t\t\tgpFileWriter->PrintfReportFunction(pText);\n\t\t\t}\n\n\t\t\tvoid PrintfReportFunction(const char8_t* pText)\n\t\t\t{\n\t\t\t\tfwrite(pText, strlen(pText), 1, mpReportFile);\n\t\t\t\tEA::EAMain::ReportFunction gpReportFunction = EA::EAMain::GetDefaultReportFunction();\n\t\t\t\tgpReportFunction(pText);\n\t\t\t}\n\n\t\t\tFileWriter() : mpReportFile(NULL), mpSavedReportFunction(NULL)\n\t\t\t{\n\t\t\t\tmpReportFile = fopen(EASTL_BENCHMARK_WRITE_FILE_PATH, \"w+\");\n\n\t\t\t\tif(mpReportFile)\n\t\t\t\t{\n\t\t\t\t\tgpFileWriter = this;\n\t\t\t\t\tmpSavedReportFunction = EA::EAMain::GetDefaultReportFunction();\n\t\t\t\t\tEA::EAMain::SetReportFunction(StaticPrintfReportFunction);\n\t\t\t\t}\n\t\t\t}\n\n\t\t   ~FileWriter()\n\t\t\t{\n\t\t\t\tif(mpReportFile)\n\t\t\t\t{\n\t\t\t\t\tgpFileWriter = NULL;\n\t\t\t\t\tEA::EAMain::SetReportFunction(mpSavedReportFunction);\n\t\t\t\t\tfclose(mpReportFile);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tFileWriter* FileWriter::gpFileWriter = NULL;\n\t#endif\n\n\n\tvoid PrintResults()\n\t{\n\t\t#if defined(EASTL_BENCHMARK_WRITE_FILE) && EASTL_BENCHMARK_WRITE_FILE\n\t\t\tFileWriter fileWriter; // This will auto-execute.\n\t\t#endif\n\n\t\t// Print the results\n\t\tEA::UnitTest::Report(\"\\n\");\n\t\tEA::UnitTest::Report(\"****************************************************************************************\\n\");\n\t\tEA::UnitTest::Report(\"EASTL Benchmark test results\\n\");\n\t\tEA::UnitTest::Report(\"****************************************************************************************\\n\");\n\t\tEA::UnitTest::Report(\"\\n\");\n\t\tEA::UnitTest::Report(\"EASTL version: %s\\n\", EASTL_VERSION);\n\t\tEA::UnitTest::Report(\"Platform: %s\\n\", gEnvironment.msPlatform.c_str());\n\t\tEA::UnitTest::Report(\"Compiler: %s\\n\", EA_COMPILER_STRING);\n\t\t#if defined(EA_DEBUG) || defined(_DEBUG)\n\t\tEA::UnitTest::Report(\"Allocator: PPMalloc::GeneralAllocatorDebug. Thread safety enabled.\\n\");\n\t\tEA::UnitTest::Report(\"Build: Debug. Inlining disabled. STL debug features disabled.\\n\");\n\t\t#else\n\t\tEA::UnitTest::Report(\"Allocator: PPMalloc::GeneralAllocator. Thread safety enabled.\\n\");\n\t\tEA::UnitTest::Report(\"Build: Full optimization. Inlining enabled.\\n\");\n\t\t#endif\n\t\tEA::UnitTest::Report(\"\\n\");\n\t\tEA::UnitTest::Report(\"Values are ticks and time to complete tests; smaller values are better.\\n\");\n\t\tEA::UnitTest::Report(\"\\n\");\n\t\tEA::UnitTest::Report(\"%-43s%26s%26s%13s%13s\\n\", \"Test\", gEnvironment.msSTLName1.c_str(), gEnvironment.msSTLName2.c_str(), \"Ratio\", \"Difference?\");\n\t\tEA::UnitTest::Report(\"---------------------------------------------------------------------------------------------------------------------\\n\");\n\n\t\teastl::string sTestTypeLast;\n\t\teastl::string sTestTypeTemp;\n\n\t\tfor(ResultSet::iterator it = gResultSet.begin(); it != gResultSet.end(); ++it)\n\t\t{\n\t\t\tconst Result& result = *it;\n\n\t\t\teastl_size_t n = result.msName.find('/');\n\t\t\tif(n == eastl::string::npos)\n\t\t\t\tn = result.msName.length();\n\t\t\tsTestTypeTemp.assign(result.msName, 0, n);\n\n\t\t\tif(sTestTypeTemp != sTestTypeLast) // If it looks like we are changing to a new test type... add an empty line to help readability.\n\t\t\t{\n\t\t\t\tif(it != gResultSet.begin())\n\t\t\t\t\tEA::UnitTest::Report(\"\\n\");\n\t\t\t\tsTestTypeLast = sTestTypeTemp;\n\t\t\t}\n\n\t\t\tPrintResultLine(result);\n\t\t}\n\n\t\t// We will print out a final line that has the sum of the rows printed above.\n\t\tResult resultSum;\n\t\tresultSum.msName = \"sum\";\n\n\t\tfor(ResultSet::iterator its = gResultSet.begin(); its != gResultSet.end(); ++its)\n\t\t{\n\t\t\tconst Result& resultTemp = *its;\n\n\t\t\tEASTL_ASSERT(resultTemp.mUnits == EA::StdC::Stopwatch::kUnitsCPUCycles); // Our ConvertStopwatchUnits call below assumes that every measured time is CPUCycles.\n\t\t\tresultSum.mTime1 += resultTemp.mTime1;\n\t\t\tresultSum.mTime2 += resultTemp.mTime2;\n\t\t}\n\n\t\t// We do this convert as a final step instead of the loop in order to avoid loss of precision.\n\t\tresultSum.mTime1NS = ConvertStopwatchUnits(EA::StdC::Stopwatch::kUnitsCPUCycles, resultSum.mTime1, EA::StdC::Stopwatch::kUnitsNanoseconds);\n\t\tresultSum.mTime2NS = ConvertStopwatchUnits(EA::StdC::Stopwatch::kUnitsCPUCycles, resultSum.mTime2, EA::StdC::Stopwatch::kUnitsNanoseconds);\n\t\tEA::UnitTest::Report(\"\\n\");\n\t\tPrintResultLine(resultSum);\n\n\t\tEA::UnitTest::Report(\"\\n\");\n\t\tEA::UnitTest::Report(\"****************************************************************************************\\n\");\n\t\tEA::UnitTest::Report(\"\\n\");\n\n\t\t// Clear the results\n\t\tgResultSet.clear();\n\t\tgEnvironment.clear();\n\t}\n\n} // namespace Benchmark\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/EASTLBenchmark.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTLBENCHMARK_H\n#define EASTLBENCHMARK_H\n\n\n// Intrinsic control\n//\n// Our benchmark results are being skewed by inconsistent decisions by the \n// VC++ compiler to use intrinsic functions. Additionally, many of our \n// benchmarks work on large blocks of elements, whereas intrinsics often\n// are an improvement only over small blocks of elements. As a result, \n// enabling of intrinsics is often resulting in poor benchmark results for\n// code that gets an intrinsic enabled for it, even though it will often\n// happen in real code to be the opposite case. The disabling of intrinsics\n// here often results in EASTL performance being lower than it would be in\n// real-world situations.\n//\n#include <string.h>\n#ifdef _MSC_VER\n\t#pragma function(strlen, strcmp, strcpy, strcat, memcpy, memcmp, memset)\n#endif\n\n\n#include <EASTL/set.h>\n#include <EASTL/string.h>\n#include <EAStdC/EASprintf.h>\n#include <EAStdC/EAStopwatch.h>\n#include <stdlib.h>\n#include <string.h>\n\n\nvoid BenchmarkSort();\nvoid BenchmarkList();\nvoid BenchmarkString();\nvoid BenchmarkVector();\nvoid BenchmarkDeque();\nvoid BenchmarkSet();\nvoid BenchmarkMap();\nvoid BenchmarkHash();\nvoid BenchmarkAlgorithm();\nvoid BenchmarkHeap();\nvoid BenchmarkBitset();\nvoid BenchmarkTupleVector();\n\n\nnamespace Benchmark\n{\n\n\t// Environment\n\t//\n\t// The environment for this benchmark test.\n\t//\n\tstruct Environment\n\t{\n\t\teastl::string8 msPlatform;       // Name of test platform (e.g. \"Windows\")\n\t\teastl::string8 msSTLName1;       // Name of competitor #1 (e.g. \"EASTL\").\n\t\teastl::string8 msSTLName2;       // Name of competitor #2 (e.g. \"MS STL\").\n\n\t\tvoid clear() { msPlatform.set_capacity(0); msSTLName1.set_capacity(0); msSTLName2.set_capacity(0); }\n\t};\n\n\tEnvironment& GetEnvironment();\n\n\n\t// Result\n\t//\n\t// An individual benchmark result.\n\t//\n\tstruct Result\n\t{\n\t\teastl::string8       msName;    // Test name (e.g. \"vector/insert\").\n\t\tint                  mUnits;    // Timing units (e.g. EA::StdC::Stopwatch::kUnitsSeconds).\n\t\tint64_t              mTime1;    // Time of competitor #1.\n\t\tuint64_t             mTime1NS;  // Nanoseconds.\n\t\tint64_t              mTime2;    // Time of competitor #2.\n\t\tint64_t              mTime2NS;  // Nanoseconds.\n\t\teastl::string8       msNotes;   // Any comments to attach to this result.\n\n\t\tResult() : msName(), mUnits(EA::StdC::Stopwatch::kUnitsCPUCycles), \n\t\t\t\t\tmTime1(0), mTime1NS(0), mTime2(0), mTime2NS(0), msNotes() { }\n\t};\n\n\tinline bool operator<(const Result& r1, const Result& r2)\n\t\t{ return r1.msName < r2.msName; } \n\n\ttypedef eastl::set<Result> ResultSet;\n\n\tResultSet& GetResultSet();\n\n\n\t// Scratch sprintf buffer\n\tconst int kScratchBufferSize = 1024;\n\textern char gScratchBuffer[kScratchBufferSize];\n\n\n\n\t// Utility functions\n\t//\n\tvoid DoNothing(...);\n\tvoid AddResult(const char* pName, int units, int64_t nTime1, int64_t nTime2, const char* pNotes = NULL);\n\tvoid PrintResults();\n\tvoid WriteTime(int64_t timeNS, eastl::string& sTime);\n\t\n\n} // namespace Benchmark\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// LargePOD\n///\n/// Implements a structure which is essentially a largish POD. Useful for testing\n/// containers and algorithms for their ability to efficiently work with PODs.\n/// This class isn't strictly a POD by the definition of the C++ standard, \n/// but it suffices for our interests.\n///\nstruct LargeObject\n{\n\tint32_t mData[2048];\n};\n\nstruct LargePOD\n{\n\tLargeObject mLargeObject1;\n\tLargeObject mLargeObject2;\n\tconst char* mpName1;\n\tconst char* mpName2;\n\n\texplicit LargePOD(int32_t x = 0) // A true POD doesn't have a non-trivial constructor.\n\t{\n\t\tmemset(mLargeObject1.mData, 0, sizeof(mLargeObject1.mData));\n\t\tmemset(mLargeObject2.mData, 0, sizeof(mLargeObject2.mData));\n\t\tmLargeObject1.mData[0] = x;\n\n\t\tmpName1 = \"LargePOD1\";\n\t\tmpName2 = \"LargePOD2\";\n\t}\n\n\tLargePOD(const LargePOD& largePOD) // A true POD doesn't have a non-trivial copy-constructor.\n\t\t: mLargeObject1(largePOD.mLargeObject1), \n\t\t  mLargeObject2(largePOD.mLargeObject2), \n\t\t  mpName1(largePOD.mpName1),\n\t\t  mpName2(largePOD.mpName2)\n\t{\n\t}\n\n\tvirtual ~LargePOD() { }\n\n\tLargePOD& operator=(const LargePOD& largePOD) // A true POD doesn't have a non-trivial assignment operator.\n\t{\n\t\tif(&largePOD != this)\n\t\t{\n\t\t\tmLargeObject1 = largePOD.mLargeObject1; \n\t\t\tmLargeObject2 = largePOD.mLargeObject2; \n\t\t\tmpName1       = largePOD.mpName1;\n\t\t\tmpName2       = largePOD.mpName2;\n\t\t}\n\t\treturn *this;\n\t}\n\n\tvirtual void DoSomething() // Note that by declaring this virtual, this class is not truly a POD.\n\t{                          // But it acts like a POD for the purposes of EASTL algorithms.\n\t\tmLargeObject1.mData[1]++;\n\t}\n\n\toperator int()\n\t{\n\t\treturn (int)mLargeObject1.mData[0];\n\t}\n};\n\n//EASTL_DECLARE_POD(LargePOD);\n//EASTL_DECLARE_TRIVIAL_CONSTRUCTOR(LargePOD);\n//EASTL_DECLARE_TRIVIAL_COPY(LargePOD);\n//EASTL_DECLARE_TRIVIAL_ASSIGN(LargePOD);\n//EASTL_DECLARE_TRIVIAL_DESTRUCTOR(LargePOD);\n//EASTL_DECLARE_TRIVIAL_RELOCATE(LargePOD);\n\n// Operators\n// We specifically define only == and <, in order to verify that \n// our containers and algorithms are not mistakenly expecting other \n// operators for the contained and manipulated classes.\ninline bool operator==(const LargePOD& t1, const LargePOD& t2)\n{\n\treturn (memcmp(&t1.mLargeObject1, &t2.mLargeObject1, sizeof(t1.mLargeObject1)) == 0) &&\n\t\t   (memcmp(&t1.mLargeObject2, &t2.mLargeObject2, sizeof(t1.mLargeObject2)) == 0) &&\n\t\t   (strcmp(t1.mpName1, t2.mpName1) == 0)  &&\n\t\t   (strcmp(t1.mpName2, t2.mpName2) == 0);\n}\n\ninline bool operator<(const LargePOD& t1, const LargePOD& t2)\n{\n\treturn (memcmp(&t1.mLargeObject1, &t2.mLargeObject1, sizeof(t1.mLargeObject1)) < 0) &&\n\t\t   (memcmp(&t1.mLargeObject2, &t2.mLargeObject2, sizeof(t1.mLargeObject2)) < 0) &&\n\t\t   (strcmp(t1.mpName1, t2.mpName1) < 0)  &&\n\t\t   (strcmp(t1.mpName2, t2.mpName2) < 0);\n}\n\n\n\n\n\n#endif // Header sentry\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "benchmark/source/main.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLBenchmark.h\"\n#include \"EASTLTest.h\"\n#if !EASTL_OPENSOURCE\n    #include <PPMalloc/EAGeneralAllocatorDebug.h>\n#endif\n#include <EAStdC/EASprintf.h>\n#include <EAStdC/EAStopwatch.h>\n#include <EAStdC/EAString.h>\n#include <EASTL/internal/config.h>\n#include <string.h>\n#include <stdio.h>\nEA_DISABLE_VC_WARNING(4946)\n#include \"EAMain/EAEntryPointMain.inl\"\n#include \"EASTLTestAllocator.h\"\n\n\n///////////////////////////////////////////////////////////////////////////////\n// gpEAGeneralAllocator / gpEAGeneralAllocatorDebug\n//\n#if !EASTL_OPENSOURCE\nnamespace EA\n{\n\tnamespace Allocator\n\t{\n\t\t#ifdef EA_DEBUG\n\t\t\textern         GeneralAllocatorDebug  gGeneralAllocator;\n\t\t\textern PPM_API GeneralAllocatorDebug* gpEAGeneralAllocatorDebug;\n\t\t#else\n\t\t\textern         GeneralAllocator       gGeneralAllocator;\n\t\t\textern PPM_API GeneralAllocator*      gpEAGeneralAllocator;\n\t\t#endif\n\t}\n}\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Required by EASTL.\n//\n#if !defined(EASTL_EASTDC_VSNPRINTF) || !EASTL_EASTDC_VSNPRINTF\n\tint Vsnprintf8(char8_t* pDestination, size_t n, const char8_t*  pFormat, va_list arguments)\n\t{\n\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t}\n\n\tint Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments)\n\t{\n\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t}\n\n\t#if (EASTDC_VERSION_N >= 10600)\n\t\tint Vsnprintf32(char32_t* pDestination, size_t n, const char32_t* pFormat, va_list arguments)\n\t\t{\n\t\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t\t}\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// main\n//\nint EAMain(int argc, char* argv[])\n{\n\tbool bWaitAtEnd   = false;\n\tbool bPrintHelp   = false;\n\tint  nOptionCount = 0;\n\tint  nErrorCount  = 0;\n\n\tEA::EAMain::PlatformStartup();\n\tEA::EAMain::SetVerbosity(2);    // Default value.\n\n\t// Set up debug parameters.\n\t#ifdef EA_DEBUG\n\t  // Only enable this temporarily to help find any problems you might find.\n\t  // EA::Allocator::gpEAGeneralAllocatorDebug->SetAutoHeapValidation(EA::Allocator::GeneralAllocator::kHeapValidationLevelBasic, 16);\n\t#endif\n\n\t// Parse command line arguments\n\tfor(int i = 1; i < argc; i++)\n\t{\n\t\tif(strstr(argv[i], \"-w\") == argv[i])\n\t\t{\n\t\t\tbWaitAtEnd = true;\n\t\t\tnOptionCount++;\n\t\t}\n\t\telse if(strstr(argv[i], \"-v\") == argv[i])\n\t\t{\n\t\t\tuint32_t verbosity = EA::StdC::AtoU32(argv[i] + 3);\n\t\t\tEA::EAMain::SetVerbosity(verbosity);\n\t\t\tnOptionCount++;\n\t\t}\n\t\telse if(strstr(argv[i], \"-l:\") == argv[i])\n\t\t{\n\t\t\tgEASTL_TestLevel = atoi(argv[i] + 3);\n\t\t\tif(gEASTL_TestLevel < kEASTL_TestLevelLow)\n\t\t\t\tgEASTL_TestLevel = kEASTL_TestLevelLow;\n\t\t\telse if(gEASTL_TestLevel > kEASTL_TestLevelHigh)\n\t\t\t\tgEASTL_TestLevel = kEASTL_TestLevelHigh;\n\t\t\tnOptionCount++;\n\t\t}\n\t\telse if(strstr(argv[i], \"-s:\") == argv[i])\n\t\t{\n\t\t\tuint32_t seed = (eastl_size_t)atoi(argv[i] + 3);\n\t\t\tEA::UnitTest::SetRandSeed(seed);\n\t\t\tnOptionCount++;\n\t\t}\n\t\telse if((strstr(argv[i], \"-?\") == argv[i]) || (strstr(argv[i], \"-h\") == argv[i]))\n\t\t{\n\t\t\tbPrintHelp = true;\n\t\t\tnOptionCount++;\n\t\t}\n\t}\n\n\t// Print user help.\n\tif(!bPrintHelp)\n\t\tbPrintHelp = (nOptionCount == 0);\n\n\tif(bPrintHelp)\n\t{\n\t\tEASTLTest_Printf(\"Options\\n\");\n\t\tEASTLTest_Printf(\"   -w     Wait at end.\\n\");\n\t\tEASTLTest_Printf(\"   -l:N   Test level in range of [1, 10]. 10 means maximum testing.\\n\");\n\t\tEASTLTest_Printf(\"   -s:N   Specify a randomization seed. 0 is default and means use clock.\\n\");\n\t\tEASTLTest_Printf(\"   -?     Show help.\\n\");\n\t}\n\n\n\t// Set up test information\n\tBenchmark::Environment& environment = Benchmark::GetEnvironment();\n\tenvironment.msPlatform = EA_PLATFORM_DESCRIPTION;\n\tenvironment.msSTLName1 = GetStdSTLName();\n\tenvironment.msSTLName2 = \"EASTL\";\n\n\n\t// Run tests\n\t#ifndef EA_DEBUG\n\t\tEA::UnitTest::SetHighThreadPriority();\n\t#endif\n\n\tEA::StdC::Stopwatch stopwatch(EA::StdC::Stopwatch::kUnitsSeconds, true);     // Measure seconds, start the counting immediately.\n\n\tBenchmarkAlgorithm();\n\tBenchmarkList();\n\tBenchmarkString();\n\tBenchmarkVector();\n\tBenchmarkDeque();\n\tBenchmarkSet();\n\tBenchmarkMap();\n\tBenchmarkHash();\n\tBenchmarkHeap();\n\tBenchmarkBitset();\n\tBenchmarkSort();\n\tBenchmarkTupleVector();\n\n\tstopwatch.Stop();\n\n\t#ifndef EA_DEBUG\n\t\tEA::UnitTest::SetNormalThreadPriority();\n\t#endif\n\n\tBenchmark::PrintResults();\n\n\teastl::string sClockTime;\n\tBenchmark::WriteTime(stopwatch.GetElapsedTime(), sClockTime);\n\n\tEASTLTest_Printf(\"Time to complete all tests: %s.\\n\", sClockTime.c_str());\n\n\t// Done\n\tif(bWaitAtEnd)\n\t{\n\t\tEASTLTest_Printf(\"\\nPress any key to exit.\\n\");\n\t\tgetchar(); // Wait for the user and shutdown\n\t}\n\n\tEA::EAMain::PlatformShutdown(nErrorCount);\n\n\treturn 0;\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "doc/Benchmarks.md",
    "content": "# EASTL Benchmarks\n\n## Introduction\n\nThis document provides a number of benchmark results of EASTL. Where possible, these benchmarks are implemented as comparisons with equivalent functionality found in other libraries such as compiler STL libraries or other well-known libraries. These comparison benchmarks concentrate on highlighting the differences between implementations rather than the similarities. In many mundane cases -- such as accessing a vector element via operator [] -- virtually all vector/array implementations you are likely to run into will have identical performance.\n\nIt's also important to note that the platform you run on can make a significant difference in the results. On a modern 3+GHz Windows PC many operations are fast due to large memory caches, intelligent branch prediction, and parallel instruction execution. However, on embedded or console systems none of these may be the case.\n\nWhile EASTL generally outperforms std STL, there are some benchmarks here in which EASTL is slower than std STL. There are three primary explanations of this:\n\n1. EASTL is making some kind of speed, memory, or design tradeoff that results in the given speed difference. In may such cases, EASTL goes slower on one benchmark in order to go faster on another benchmark deemed more important. This explanation constitutes about 60% of the cases.\n2. Compiler optimizations and resulting code generation is coincidencally favoring one kind of implementation over another, often when they are visually virtually identical. This explantation constitutes about 30% of the cases.\n3. EASTL is simply not yet as optimized as it could be. This explanation constitutes about 10% of the cases (as of this writing there are about three such functions throughout EASTL).\n\n## Benchmarks\n\nBelow is a table of links to detailed benchmark results derived from the Benchmark test present in the EASTL package. The detailed results are present below the table. Additional platforms will be added as results become available for those platforms. Debug benchmarks are present because (lack of) debug performance can be significant for highly templated libraries. EASTL has specific optimizations to enhance debug performance relative to other standard libraries; in some cases it is 10x or more faster than alternatives (though there are exceptions where EASTL is slower). Feel free to submit results for additional compilers/platforms.\n\n| Platform | Compiler | STL type | Build | Results |\n|------|------|------|------|------|\n| Win32 | VC++ 7.1 | Microsoft (Dinkumware) | Debug | [Detail]() |\n| Win32 | VC++ 7.1 | Microsoft (Dinkumware) | Release | [Detail]() |\n| Win32 | VC++ 7.1 | STLPort | Debug | [Detail]() |\n| Win32 | VC++ 7.1 | STLPort | Release | [Detail]() |\n\n### Win32.VC71.MS.Debug\n\n```\nEASTL version: 0.96.00\nPlatform: Windows on X86\nCompiler: Microsoft Visual C++ compiler, version 1310\nAllocator: PPMalloc::GeneralAllocatorDebug. Thread safety enabled.\nBuild: Debug. Inlining disabled. STL debug features disabled.\n\nValues are times to complete tests; smaller values are better.\nAlarm indicates a greater than 10% difference.\n\nTest                                               VC++        EASTL     Ratio     Alarm\n----------------------------------------------------------------------------------------\nalgorithm/adj_find/vector<TestObject>          33061345      6497757      5.09         *\nalgorithm/copy/vector<LargePOD>                 5844906      4876076      1.20         *\nalgorithm/copy/vector<uint32_t>                 1634346       166065      9.84         *\nalgorithm/copy_backward/vector<LargePOD>        4515974      4638892      0.97\nalgorithm/copy_backward/vector<uint32_t>        1821168       121746     14.96         *\nalgorithm/count/vector<uint64_t>               17048884      2720766      6.27         *\nalgorithm/equal_range/vector<uint64_t>       1111147812    448756888      2.48         *\nalgorithm/fill/bool[]                           1728722        91936     18.80         *\nalgorithm/fill/char[]/'d'                       1299200        33745     38.50         *\nalgorithm/fill/vector<char>/'d'                10205092        33796    100.00         *\nalgorithm/fill/vector<char>/0                  10200748        33805    100.00         *\nalgorithm/fill/vector<uint64_t>                10416538      1399687      7.44         *\nalgorithm/fill/vector<void*>                   10221837      1307700      7.82         *\nalgorithm/fill_n/bool[]                         1399033        34196     40.91         *\nalgorithm/fill_n/char[]                         1299225        33754     38.49         *\nalgorithm/fill_n/vector<uint64_t>               5961637      1371900      4.35         *\nalgorithm/find_end/string/end                  16569373      2657372      6.24         *\nalgorithm/find_end/string/middle               16558638     20242410      0.82         *\nalgorithm/find_end/string/none                 16811207     40480468      0.42         *\nalgorithm/lex_cmp/schar[]                       1749674       194429      9.00         *\nalgorithm/lex_cmp/vector<TestObject>           32824195      5253587      6.25         *\nalgorithm/lex_cmp/vector<uchar>                29852034       202658    100.00         *\nalgorithm/lower_bound/vector<TestObject>      798624462    350027935      2.28         *\nalgorithm/min_element/vector<TestObject>       21675298      5314676      4.08         *\nalgorithm/rand_shuffle/vector<uint64_t>        84236190     43677506      1.93         *\nalgorithm/reverse/list<TestObject>              3007292      2105799      1.43         *\nalgorithm/reverse/vector<TestObject>            2974618      2124796      1.40         *\nalgorithm/search/string<char>                  16228158      3594268      4.52         *\nalgorithm/search_n/string<char>                16926985      1522096     11.12         *\nalgorithm/unique/vector<TestObject>            54206243      9988002      5.43         *\nalgorithm/unique/vector<uint32_t>              26940079      1741991     15.47         *\nalgorithm/unique/vector<uint64_t>              47621344      5213127      9.13         *\nalgorithm/upper_bound/vector<uint32_t>        372381295    137901552      2.70         *\n\nbitset<1500>/>>=/1                             90196544     92539832      0.97\nbitset<1500>/count                             50753832     53742117      0.94\nbitset<1500>/flip                              86935875     85121117      1.02\nbitset<1500>/reset                             78153837     79922611      0.98\nbitset<1500>/set()                             79214968     79360658      1.00\nbitset<1500>/set(i)                            11300589     12199651      0.93\nbitset<1500>/test                              11282679     13186450      0.86         *\n\nbitset<15>/>>=/1                               10500577      6000559      1.75         *\nbitset<15>/count                                4000356      6399753      0.63         *\nbitset<15>/flip                                 7268877      5647944      1.29         *\nbitset<15>/reset                                8564235      5800163      1.48         *\nbitset<15>/set()                                9935523      5914012      1.68         *\nbitset<15>/set(i)                              11199703     12503637      0.90         *\nbitset<15>/test                                10600623     12899592      0.82         *\n\nbitset<35>/>>=/1                               13076052      6599834      1.98         *\nbitset<35>/count                                4800384     11500330      0.42         *\nbitset<35>/flip                                 7915439      5816313      1.36         *\nbitset<35>/reset                                9400049      5803180      1.62         *\nbitset<35>/set()                               10701152      5840316      1.83         *\nbitset<35>/set(i)                              11342936     12271128      0.92\nbitset<35>/test                                10670799     13099682      0.81         *\n\nbitset<75>/>>=/1                               14198834     17151088      0.83         *\nbitset<75>/count                                5795530      8576373      0.68         *\nbitset<75>/flip                                 8516703      8922995      0.95\nbitset<75>/reset                                9999970      8526095      1.17         *\nbitset<75>/set()                               11124877      9009686      1.23         *\nbitset<75>/set(i)                              11300563     12531618      0.90         *\nbitset<75>/test                                11031913     13100523      0.84         *\n\ndeque<ValuePair>/erase                        743801706    335646802      2.22         *\ndeque<ValuePair>/insert                       742331809    341912866      2.17         *\ndeque<ValuePair>/iteration                     29097030     16315827      1.78         *\ndeque<ValuePair>/operator[]                    49859598     24026313      2.08         *\ndeque<ValuePair>/push_back                    424807033     34497608     12.31         *\ndeque<ValuePair>/push_front                   402313373     38006322     10.59         *\ndeque<ValuePair>/sort                         725101017    581796551      1.25         *\n\nhash_map<string, uint32_t>/clear                 559462       961019      0.58         *\nhash_map<string, uint32_t>/count               53377807      8091448      6.60         *\nhash_map<string, uint32_t>/erase pos             613573       858084      0.72         *\nhash_map<string, uint32_t>/erase range          5488748       461134     11.90         *\nhash_map<string, uint32_t>/erase val           35760096     16379858      2.18         *\nhash_map<string, uint32_t>/find                43490335     10324823      4.21         *\nhash_map<string, uint32_t>/find_as/char*       49343818      8617139      5.73         *\nhash_map<string, uint32_t>/insert             107420281    168690439      0.64         *\nhash_map<string, uint32_t>/iteration            2456356      1255153      1.96         *\nhash_map<string, uint32_t>/operator[]          47209502     12581624      3.75         *\n\nhash_map<uint32_t, TestObject>/clear             533172       546449      0.98\nhash_map<uint32_t, TestObject>/count           28667432      2899997      9.89         *\nhash_map<uint32_t, TestObject>/erase pos         683239       538289      1.27         *\nhash_map<uint32_t, TestObject>/erase range      9632676       253037     38.07         *\nhash_map<uint32_t, TestObject>/erase val       25466026      7752188      3.29         *\nhash_map<uint32_t, TestObject>/find            20048253      4678502      4.29         *\nhash_map<uint32_t, TestObject>/insert          71085798     37686187      1.89         *\nhash_map<uint32_t, TestObject>/iteration        1460318      1338317      1.09\nhash_map<uint32_t, TestObject>/operator[]      23226692      7888748      2.94         *\n\nheap (uint32_t[])/make_heap                     5399966      6961305      0.78         *\nheap (uint32_t[])/pop_heap                    108060534    103511318      1.04\nheap (uint32_t[])/push_heap                    22595661     16640688      1.36         *\nheap (uint32_t[])/sort_heap                    93559424     83076731      1.13         *\n\nheap (vector<TestObject>)/make_heap            91770743     21724870      4.22         *\nheap (vector<TestObject>)/pop_heap           1175599317    284007398      4.14         *\nheap (vector<TestObject>)/push_heap           207804541     45918046      4.53         *\nheap (vector<TestObject>)/sort_heap           970394145    208321477      4.66         *\n\nlist<TestObject>/ctor(it)                     805539509    760938607      1.06\nlist<TestObject>/ctor(n)                       80959236     75106995      1.08\nlist<TestObject>/erase                       1052543704   1044976137      1.01\nlist<TestObject>/find                          97785267     75970884      1.29         *\nlist<TestObject>/insert                       873895175    807051107      1.08\nlist<TestObject>/push_back                    812797710    780742425      1.04\nlist<TestObject>/remove                      1850600714   1436980599      1.29         *\nlist<TestObject>/reverse                      180270465     80466636      2.24         *\nlist<TestObject>/size/1                          440148       599642      0.73         *\nlist<TestObject>/size/10                         439433      1329817      0.33         *   EASTL intentionally implements list::size as O(n).\nlist<TestObject>/size/100                        439595     11030060      0.04         *   EASTL intentionally implements list::size as O(n).\nlist<TestObject>/splice                       177106094     69383027      2.55         *\n\nmap<TestObject, uint32_t>/clear                  508283       470807      1.08\nmap<TestObject, uint32_t>/count                43145354     14280357      3.02         *\nmap<TestObject, uint32_t>/equal_range          38594004     16520447      2.34         *\nmap<TestObject, uint32_t>/erase/key            33948082     16123175      2.11         *\nmap<TestObject, uint32_t>/erase/pos              578332       455201      1.27         *   MS uses a code bloating implementation of erase.\nmap<TestObject, uint32_t>/erase/range            387345       284538      1.36         *\nmap<TestObject, uint32_t>/find                 22897224     12766100      1.79         *\nmap<TestObject, uint32_t>/insert               61665800     47286928      1.30         *\nmap<TestObject, uint32_t>/iteration             1977202       745391      2.65         *\nmap<TestObject, uint32_t>/lower_bound          19892941     12260928      1.62         *\nmap<TestObject, uint32_t>/operator[]           24199084     15429634      1.57         *\nmap<TestObject, uint32_t>/upper_bound          19842409     12064441      1.64         *\n\nset<uint32_t>/clear                             1027625      1000901      1.03\nset<uint32_t>/count                            39730182     13329565      2.98         *\nset<uint32_t>/equal_range                      34681649     14768827      2.35         *\nset<uint32_t>/erase range                        841458       602030      1.40         *\nset<uint32_t>/erase/pos                         1380485      1084303      1.27         *   MS uses a code bloating implementation of erase.\nset<uint32_t>/erase/val                        31617425     13344023      2.37         *\nset<uint32_t>/find                             19582428     10788864      1.82         *\nset<uint32_t>/insert                           61434014     48232086      1.27         *\nset<uint32_t>/iteration                         1512057       667820      2.26         *\nset<uint32_t>/lower_bound                      18394885     10402785      1.77         *\nset<uint32_t>/upper_bound                      17189083     10554425      1.63         *\n\nsort/q_sort/TestObject[]                       87088799     15037988      5.79         *\nsort/q_sort/TestObject[]/sorted                21502892      3284299      6.55         *\nsort/q_sort/vector<TestObject>                 87962047     15004677      5.86         *\nsort/q_sort/vector<TestObject>/sorted          21396523      3341163      6.40         *\nsort/q_sort/vector<ValuePair>                  80334589     10429161      7.70         *\nsort/q_sort/vector<ValuePair>/sorted           22133295      3230553      6.85         *\nsort/q_sort/vector<uint32>                     72195388      5940302     12.15         *\nsort/q_sort/vector<uint32>/sorted              19635171       995495     19.72         *\n\nstring<char16_t>/compare                      523013373    534722089      0.98\nstring<char16_t>/erase/pos,n                    3446597      3439492      1.00\nstring<char16_t>/find/p,pos,n                 383873158    441902786      0.87         *\nstring<char16_t>/find_first_not_of/p,pos,n       174157       134131      1.30         *\nstring<char16_t>/find_first_of/p,pos,n         11715423      8520944      1.37         *\nstring<char16_t>/find_last_of/p,pos,n           1871556      1226457      1.53         *\nstring<char16_t>/insert/pos,p                   3624877      3357058      1.08\nstring<char16_t>/iteration                   6766787933    581916665     11.63         *\nstring<char16_t>/operator[]                     4820827      2335579      2.06         *\nstring<char16_t>/push_back                     59812962      6757466      8.85         *\nstring<char16_t>/replace/pos,n,p,n              4371279      4459713      0.98\nstring<char16_t>/reserve                        2307530      1919386      1.20         *\nstring<char16_t>/rfind/p,pos,n                   734826       372615      1.97         *\nstring<char16_t>/size                             41608        28866      1.44         *\nstring<char16_t>/swap                           1033932      1490994      0.69         *\n\nstring<char8_t>/compare                        63086797     64194771      0.98\nstring<char8_t>/erase/pos,n                     2045687      1960270      1.04\nstring<char8_t>/find/p,pos,n                  123872549    471364764      0.26         *\nstring<char8_t>/find_first_not_of/p,pos,n        140013       130271      1.07\nstring<char8_t>/find_first_of/p,pos,n           8051906      8749994      0.92\nstring<char8_t>/find_last_of/p,pos,n            1318835      1230715      1.07\nstring<char8_t>/insert/pos,p                    1770610      1724234      1.03\nstring<char8_t>/iteration                      28112136      2544475     11.05         *\nstring<char8_t>/operator[]                      4810525      2255841      2.13         *\nstring<char8_t>/push_back                      54869634      6127447      8.95         *\nstring<char8_t>/replace/pos,n,p,n               2737578      2847900      0.96\nstring<char8_t>/reserve                         1123395       394902      2.84         *\nstring<char8_t>/rfind/p,pos,n                    737299       368518      2.00         *\nstring<char8_t>/size                              42245        26801      1.58         *\nstring<char8_t>/swap                            1036142      1491028      0.69         *\n\nvector<uint64>/erase                           56417135     55770251      1.01\nvector<uint64>/insert                          56617761     56100468      1.01\nvector<uint64>/iteration                       10413895      1291269      8.06         *\nvector<uint64>/operator[]                      23507193      3479390      6.76         *\nvector<uint64>/push_back                       34687939     13806627      2.51         *\nvector<uint64>/sort                           256886550     84669657      3.03         *\n```\n\n### Win32.VC71.MS.Release\n\n```\nEASTL version: 0.96.00\nPlatform: Windows on X86\nCompiler: Microsoft Visual C++ compiler, version 1310\nAllocator: PPMalloc::GeneralAllocator. Thread safety enabled.\nBuild: Full optimization. Inlining enabled.\n\nValues are times to complete tests; smaller values are better.\nAlarm indicates a greater than 10% difference.\n\nTest                                               VC++        EASTL     Ratio     Alarm\n----------------------------------------------------------------------------------------\nalgorithm/adj_find/vector<TestObject>           2783546      2750660      1.01\nalgorithm/copy/vector<LargePOD>                 6474025      4972738      1.30         *\nalgorithm/copy/vector<uint32_t>                  157267       173162      0.91\nalgorithm/copy_backward/vector<LargePOD>        4836406      4374780      1.11         *\nalgorithm/copy_backward/vector<uint32_t>         104780       120912      0.87         *\nalgorithm/count/vector<uint64_t>                1368440      1368696      1.00\nalgorithm/equal_range/vector<uint64_t>        114199387    102783938      1.11         *\nalgorithm/fill/bool[]                            253215        27353      9.26         *\nalgorithm/fill/char[]/'d'                        253164        27404      9.24         *\nalgorithm/fill/vector<char>/'d'                  253105        27362      9.25         *\nalgorithm/fill/vector<char>/0                    253275        27353      9.26         *\nalgorithm/fill/vector<uint64_t>                  397001       394323      1.01\nalgorithm/fill/vector<void*>                     547196       642362      0.85         *\nalgorithm/fill_n/bool[]                          229177        27361      8.38         *\nalgorithm/fill_n/char[]                          228845        27404      8.35         *\nalgorithm/fill_n/vector<uint64_t>                565233      1376822      0.41         *\nalgorithm/find_end/string/end                   2107116        82356     25.59         *\nalgorithm/find_end/string/middle                2111672       664283      3.18         *\nalgorithm/find_end/string/none                  2110423      1519596      1.39         *\nalgorithm/lex_cmp/schar[]                        741021       176162      4.21         *\nalgorithm/lex_cmp/vector<TestObject>            2610494      2642183      0.99\nalgorithm/lex_cmp/vector<uchar>                  697595       167866      4.16         *\nalgorithm/lower_bound/vector<TestObject>       62462233     58146664      1.07\nalgorithm/min_element/vector<TestObject>        4350385      2671227      1.63         *\nalgorithm/rand_shuffle/vector<uint64_t>        10868261     11300818      0.96\nalgorithm/reverse/list<TestObject>               483718       470024      1.03\nalgorithm/reverse/vector<TestObject>             476739       484322      0.98\nalgorithm/search/string<char>                   2560387      1259496      2.03         *\nalgorithm/search_n/string<char>                 2770991       458524      6.04         *\nalgorithm/unique/vector<TestObject>             4194520      4658910      0.90         *\nalgorithm/unique/vector<uint32_t>                538730       787924      0.68         *\nalgorithm/unique/vector<uint64_t>               3169829      2575636      1.23         *\nalgorithm/upper_bound/vector<uint32_t>         27495562     25321593      1.09\n\nbitset<1500>/>>=/1                             33464228     33469719      1.00\nbitset<1500>/count                             18736116     18814903      1.00\nbitset<1500>/flip                              19299309     18605438      1.04\nbitset<1500>/reset                             22200487     15262847      1.45         *\nbitset<1500>/set()                             14418193     17557319      0.82         *\nbitset<1500>/set(i)                             1599250      1599199      1.00\nbitset<1500>/test                               1599241      1599233      1.00\n\nbitset<15>/>>=/1                                2199222      2264442      0.97\nbitset<15>/count                                1399406      1399193      1.00\nbitset<15>/flip                                 1266712      1199197      1.06\nbitset<15>/reset                                1399364      1399109      1.00\nbitset<15>/set()                                1199197       999201      1.20         *\nbitset<15>/set(i)                               1599258      1462952      1.09\nbitset<15>/test                                 1599275      1599224      1.00\n\nbitset<35>/>>=/1                                2599266      1933376      1.34         *\nbitset<35>/count                                2599240      2592559      1.00\nbitset<35>/flip                                 1693124      1199188      1.41         *\nbitset<35>/reset                                1399406       999201      1.40         *\nbitset<35>/set()                                1599403      1199205      1.33         *\nbitset<35>/set(i)                               1599241      1599190      1.00\nbitset<35>/test                                 1599250      1599232      1.00\n\nbitset<75>/>>=/1                                4199332      4199213      1.00\nbitset<75>/count                                2999497      2199341      1.36         *\nbitset<75>/flip                                 2399499      1830178      1.31         *\nbitset<75>/reset                                2199468      1199197      1.83         *\nbitset<75>/set()                                1999387      1199851      1.67         *\nbitset<75>/set(i)                               1599266      1599198      1.00\nbitset<75>/test                                 1599241      1662651      0.96\n\ndeque<ValuePair>/erase                         90444165     37113253      2.44         *\ndeque<ValuePair>/insert                        93299349     36175167      2.58         *\ndeque<ValuePair>/iteration                      2756414      2122076      1.30         *\ndeque<ValuePair>/operator[]                     5117969      4632075      1.10\ndeque<ValuePair>/push_back                     30300757      3060357      9.90         *\ndeque<ValuePair>/push_front                    25498529      2808392      9.08         *\ndeque<ValuePair>/sort                         142283047    111292464      1.28         *\n\nhash_map<string, uint32_t>/clear                 146769       389699      0.38         *\nhash_map<string, uint32_t>/count               13059434      3460324      3.77         *\nhash_map<string, uint32_t>/erase pos             184246       331925      0.56         *\nhash_map<string, uint32_t>/erase range           382432       167237      2.29         *\nhash_map<string, uint32_t>/erase val            6187898      3302114      1.87         *\nhash_map<string, uint32_t>/find                11289369      3459024      3.26         *\nhash_map<string, uint32_t>/find_as/char*       13559192      3662387      3.70         *\nhash_map<string, uint32_t>/insert              17514012     14095176      1.24         *\nhash_map<string, uint32_t>/iteration             801014       218450      3.67         *\nhash_map<string, uint32_t>/operator[]          11457065      3690385      3.10         *\n\nhash_map<uint32_t, TestObject>/clear             141865       265379      0.53         *\nhash_map<uint32_t, TestObject>/count            1766045       703613      2.51         *\nhash_map<uint32_t, TestObject>/erase pos         172337       218458      0.79         *\nhash_map<uint32_t, TestObject>/erase range       537846       102340      5.26         *\nhash_map<uint32_t, TestObject>/erase val        2220132      1441787      1.54         *\nhash_map<uint32_t, TestObject>/find             1612994      1043953      1.55         *\nhash_map<uint32_t, TestObject>/insert           7141547      4348056      1.64         *\nhash_map<uint32_t, TestObject>/iteration         199512       169328      1.18         *\nhash_map<uint32_t, TestObject>/operator[]       1831733      1519707      1.21         *\n\nheap (uint32_t[])/make_heap                     3366247      1949093      1.73         *\nheap (uint32_t[])/pop_heap                     57280514     53779440      1.07\nheap (uint32_t[])/push_heap                     9700217      7582935      1.28         *\nheap (uint32_t[])/sort_heap                    47227751     46131948      1.02\n\nheap (vector<TestObject>)/make_heap            11458442     11510819      1.00\nheap (vector<TestObject>)/pop_heap            122897267    119061132      1.03\nheap (vector<TestObject>)/push_heap            21688481     21176220      1.02\nheap (vector<TestObject>)/sort_heap            90867380     88869523      1.02\n\nlist<TestObject>/ctor(it)                      74591104     69845817      1.07\nlist<TestObject>/ctor(n)                        6243998      5838582      1.07\nlist<TestObject>/erase                        299509298    206013676      1.45         *\nlist<TestObject>/find                          40927185     14514243      2.82         *\nlist<TestObject>/insert                        71277251     47234534      1.51         *\nlist<TestObject>/push_back                     73780527     44116725      1.67         *\nlist<TestObject>/remove                       786197776    326434612      2.41         *\nlist<TestObject>/reverse                       49283128     25029678      1.97         *\nlist<TestObject>/size/1                          159741       139400      1.15         *\nlist<TestObject>/size/10                         159324       346579      0.46         *   EASTL intentionally implements list::size as O(n).\nlist<TestObject>/size/100                        159188     97235419      0.00         *   EASTL intentionally implements list::size as O(n).\nlist<TestObject>/splice                        63548584     19322931      3.29         *\n\nmap<TestObject, uint32_t>/clear                  167408       170501      0.98\nmap<TestObject, uint32_t>/count                10213685      4748346      2.15         *\nmap<TestObject, uint32_t>/equal_range           9515053      5677558      1.68         *\nmap<TestObject, uint32_t>/erase/key             6646260      4302300      1.54         *\nmap<TestObject, uint32_t>/erase/pos              297135       327938      0.91             MS uses a code bloating implementation of erase.\nmap<TestObject, uint32_t>/erase/range            148614       163702      0.91\nmap<TestObject, uint32_t>/find                  5637531      4767055      1.18         *\nmap<TestObject, uint32_t>/insert                9591128      9030349      1.06\nmap<TestObject, uint32_t>/iteration              323595       325261      0.99\nmap<TestObject, uint32_t>/lower_bound           5398239      4784089      1.13         *\nmap<TestObject, uint32_t>/operator[]            5631250      5141166      1.10\nmap<TestObject, uint32_t>/upper_bound           5436336      4762431      1.14         *\n\nset<uint32_t>/clear                              155983       156026      1.00\nset<uint32_t>/count                             9635965      4392146      2.19         *\nset<uint32_t>/equal_range                       8504157      5247832      1.62         *\nset<uint32_t>/erase range                        140488       119408      1.18         *\nset<uint32_t>/erase/pos                          260678       286697      0.91             MS uses a code bloating implementation of erase.\nset<uint32_t>/erase/val                         6008225      4012825      1.50         *\nset<uint32_t>/find                              5145432      4381945      1.17         *\nset<uint32_t>/insert                            8087129      8697251      0.93\nset<uint32_t>/iteration                          271507       304538      0.89         *\nset<uint32_t>/lower_bound                       4666228      4404250      1.06\nset<uint32_t>/upper_bound                       4623600      4402974      1.05\n\nsort/q_sort/TestObject[]                        9596169      5578652      1.72         *\nsort/q_sort/TestObject[]/sorted                  602463      1016132      0.59         *\nsort/q_sort/vector<TestObject>                  9674828      5430199      1.78         *\nsort/q_sort/vector<TestObject>/sorted            606908      1111647      0.55         *\nsort/q_sort/vector<ValuePair>                   6284194      3423452      1.84         *\nsort/q_sort/vector<ValuePair>/sorted             711629       569364      1.25         *\nsort/q_sort/vector<uint32>                      5453379      2916146      1.87         *\nsort/q_sort/vector<uint32>/sorted                537047       419144      1.28         *\n\nstring<char16_t>/compare                      435083295    251985824      1.73         *\nstring<char16_t>/erase/pos,n                    3454842      3451858      1.00\nstring<char16_t>/find/p,pos,n                 401954723    165298157      2.43         *\nstring<char16_t>/find_first_not_of/p,pos,n       131452        65374      2.01         *\nstring<char16_t>/find_first_of/p,pos,n         11657444      4144515      2.81         *\nstring<char16_t>/find_last_of/p,pos,n           1604248       567571      2.83         *\nstring<char16_t>/insert/pos,p                   3398734      3355460      1.01\nstring<char16_t>/iteration                    218856504    218771844      1.00\nstring<char16_t>/operator[]                      714161       240023      2.98         *\nstring<char16_t>/push_back                     34968235      2444897     14.30         *\nstring<char16_t>/replace/pos,n,p,n              4226693      4198498      1.01\nstring<char16_t>/reserve                        1901765       390805      4.87         *\nstring<char16_t>/rfind/p,pos,n                   195483       150985      1.29         *\nstring<char16_t>/size                             11169        11245      0.99\nstring<char16_t>/swap                           1459280       419807      3.48         *\n\nstring<char8_t>/compare                        63071275     77209580      0.82         *\nstring<char8_t>/erase/pos,n                     2008652      1944494      1.03\nstring<char8_t>/find/p,pos,n                  123201023    167536164      0.74         *\nstring<char8_t>/find_first_not_of/p,pos,n         93372        67864      1.38         *\nstring<char8_t>/find_first_of/p,pos,n           7542492      3375758      2.23         *\nstring<char8_t>/find_last_of/p,pos,n             933972       583576      1.60         *\nstring<char8_t>/insert/pos,p                    1737213      1750847      0.99\nstring<char8_t>/iteration                        893834       899130      0.99\nstring<char8_t>/operator[]                       817879       313437      2.61         *\nstring<char8_t>/push_back                      20857734      2004410     10.41         *\nstring<char8_t>/replace/pos,n,p,n               2578696      2607655      0.99\nstring<char8_t>/reserve                          915127        85289     10.73         *\nstring<char8_t>/rfind/p,pos,n                    196103       148894      1.32         *\nstring<char8_t>/size                              11619        11220      1.04\nstring<char8_t>/swap                            1461056       419874      3.48         *\n\nvector<uint64>/erase                           55235116     55284587      1.00\nvector<uint64>/insert                          55166046     55142755      1.00\nvector<uint64>/iteration                         553954       509719      1.09\nvector<uint64>/operator[]                       1284239       798516      1.61         *\nvector<uint64>/push_back                        5399549      3867959      1.40         *\nvector<uint64>/sort                            43636314     42619952      1.02\n```\n\n### Win32.VC71.STLPort.Debug\n\n```\nEASTL version: 0.96.00\nPlatform: Windows on X86\nCompiler: Microsoft Visual C++ compiler, version 1310\nAllocator: PPMalloc::GeneralAllocatorDebug. Thread safety enabled.\nBuild: Debug. Inlining disabled. STL debug features disabled.\n\nValues are times to complete tests; smaller values are better.\nAlarm indicates a greater than 10% difference.\n\nTest                                            STLPort        EASTL     Ratio     Alarm\n----------------------------------------------------------------------------------------\nalgorithm/adj_find/vector<TestObject>           5661170      5689517      1.00\nalgorithm/copy/vector<LargePOD>                 5573815      5124428      1.09\nalgorithm/copy/vector<uint32_t>                  148273       125782      1.18         *\nalgorithm/copy_backward/vector<LargePOD>        5429791      4834510      1.12         *\nalgorithm/copy_backward/vector<uint32_t>         156765       163038      0.96\nalgorithm/count/vector<uint64_t>                2730922      2730072      1.00\nalgorithm/equal_range/vector<uint64_t>        639366489    452896251      1.41         *\nalgorithm/fill/bool[]                           1299326        27361     47.49         *\nalgorithm/fill/char[]/'d'                         27378        27361      1.00\nalgorithm/fill/vector<char>/'d'                   34459        27361      1.26         *\nalgorithm/fill/vector<char>/0                   1299224        27361     47.48         *\nalgorithm/fill/vector<uint64_t>                 1400647      1400145      1.00\nalgorithm/fill/vector<void*>                    1308779      1309085      1.00\nalgorithm/fill_n/bool[]                         1299156        27352     47.50         *\nalgorithm/fill_n/char[]                         1299258        27369     47.47         *\nalgorithm/fill_n/vector<uint64_t>               1451162      1313632      1.10\nalgorithm/find_end/string/end                  13089999      2526412      5.18         *\nalgorithm/find_end/string/middle               12627412     20190101      0.63         *\nalgorithm/find_end/string/none                 12704185     40728803      0.31         *\nalgorithm/lex_cmp/schar[]                       1749844       195806      8.94         *\nalgorithm/lex_cmp/vector<TestObject>            5060968      4799882      1.05\nalgorithm/lex_cmp/vector<uchar>                 1668354       189490      8.80         *\nalgorithm/lower_bound/vector<TestObject>      450240945    353437573      1.27         *\nalgorithm/min_element/vector<TestObject>        5861744      5326371      1.10\nalgorithm/rand_shuffle/vector<uint64_t>        40780449     45780090      0.89         *\nalgorithm/reverse/list<TestObject>              2657678      2130627      1.25         *\nalgorithm/reverse/vector<TestObject>            2666424      2124889      1.25         *\nalgorithm/search/string<char>                   3110379      3613460      0.86         *\nalgorithm/search_n/string<char>                 3061665      1521261      2.01         *\nalgorithm/unique/vector<TestObject>            12423684      9485439      1.31         *\nalgorithm/unique/vector<uint32_t>               3718699      1726596      2.15         *\nalgorithm/unique/vector<uint64_t>               6205110      4591631      1.35         *\nalgorithm/upper_bound/vector<uint32_t>        185391094    139336317      1.33         *\n\nbitset<1500>/>>=/1                            120666960     92449816      1.31         *   STLPort is broken, neglects wraparound check.\nbitset<1500>/count                            201709793     52874726      3.81         *\nbitset<1500>/flip                              87360297     81737071      1.07\nbitset<1500>/reset                             23950178     77390323      0.31         *\nbitset<1500>/set()                             84608107     76912011      1.10\nbitset<1500>/set(i)                            18023620     12229604      1.47         *\nbitset<1500>/test                              18006553     13276396      1.36         *\n\nbitset<15>/>>=/1                               11935904      6012695      1.99         *   STLPort is broken, neglects wraparound check.\nbitset<15>/count                                9368581      6022742      1.56         *\nbitset<15>/flip                                11600706      6533635      1.78         *\nbitset<15>/reset                                5830957      5874690      0.99\nbitset<15>/set()                               11695328      5701621      2.05         *\nbitset<15>/set(i)                              16363205     12570216      1.30         *\nbitset<15>/test                                16743172     13201452      1.27         *\n\nbitset<35>/>>=/1                               22950918      6774457      3.39         *   STLPort is broken, neglects wraparound check.\nbitset<35>/count                               12655309     11736256      1.08\nbitset<35>/flip                                13738575      5800042      2.37         *\nbitset<35>/reset                               15561434      5800510      2.68         *\nbitset<35>/set()                               13564283      5600709      2.42         *\nbitset<35>/set(i)                              18519689     12199973      1.52         *\nbitset<35>/test                                18000569     13103566      1.37         *\n\nbitset<75>/>>=/1                               25579525     16669664      1.53         *   STLPort is broken, neglects wraparound check.\nbitset<75>/count                               18740698      8480492      2.21         *\nbitset<75>/flip                                13555630      8300335      1.63         *\nbitset<75>/reset                               15200133      8200000      1.85         *\nbitset<75>/set()                               14408112      8001959      1.80         *\nbitset<75>/set(i)                              18137741     12374257      1.47         *\nbitset<75>/test                                18422135     13100038      1.41         *\n\ndeque<ValuePair>/erase                        651933790    326443043      2.00         *\ndeque<ValuePair>/insert                       659786183    333304660      1.98         *\ndeque<ValuePair>/iteration                     23734592     16173706      1.47         *\ndeque<ValuePair>/operator[]                    59126816     23911774      2.47         *\ndeque<ValuePair>/push_back                     58056988     31859266      1.82         *\ndeque<ValuePair>/push_front                    57780891     31743199      1.82         *\ndeque<ValuePair>/sort                         818414195    596568113      1.37         *\n\nhash_map<string, uint32_t>/clear                3422133      2204517      1.55         *\nhash_map<string, uint32_t>/count                9869545      8624924      1.14         *\nhash_map<string, uint32_t>/erase pos            3256350      2069299      1.57         *\nhash_map<string, uint32_t>/erase range          3230203      1151392      2.81         *\nhash_map<string, uint32_t>/erase val           16860362     15939778      1.06\nhash_map<string, uint32_t>/find                10286971      9920910      1.04\nhash_map<string, uint32_t>/find_as/char*      118136025      9458468     12.49         *\nhash_map<string, uint32_t>/insert             188948336    174490082      1.08\nhash_map<string, uint32_t>/iteration            4037049      2021036      2.00         *\nhash_map<string, uint32_t>/operator[]          11472127     12887699      0.89         *\n\nhash_map<uint32_t, TestObject>/clear            2522264      1331848      1.89         *\nhash_map<uint32_t, TestObject>/count            3210739      2897063      1.11         *\nhash_map<uint32_t, TestObject>/erase pos        1862281      1304783      1.43         *\nhash_map<uint32_t, TestObject>/erase range       698079       579606      1.20         *\nhash_map<uint32_t, TestObject>/erase val        8806722      7041298      1.25         *\nhash_map<uint32_t, TestObject>/find             3604875      4709645      0.77         *\nhash_map<uint32_t, TestObject>/insert          40785711     40376342      1.01\nhash_map<uint32_t, TestObject>/iteration        3064088      1508834      2.03         *\nhash_map<uint32_t, TestObject>/operator[]       6053742      8176906      0.74         *\n\nheap (uint32_t[])/make_heap                     5799813      5738596      1.01\nheap (uint32_t[])/pop_heap                    113775168    102076134      1.11         *\nheap (uint32_t[])/push_heap                    21649151     16854845      1.28         *\nheap (uint32_t[])/sort_heap                    97535213     83290735      1.17         *\n\nheap (vector<TestObject>)/make_heap            22215557     22277063      1.00\nheap (vector<TestObject>)/pop_heap            275392171    277340039      0.99\nheap (vector<TestObject>)/push_heap            51479442     47342577      1.09\nheap (vector<TestObject>)/sort_heap           214474736    218497540      0.98\n\nlist<TestObject>/ctor(it)                     767753795    753421427      1.02\nlist<TestObject>/ctor(n)                       74185322     73386245      1.01\nlist<TestObject>/erase                       1021003824   1033873589      0.99\nlist<TestObject>/find                          77666072     74917622      1.04\nlist<TestObject>/insert                       788071150    774188737      1.02\nlist<TestObject>/push_back                    760490154    737327348      1.03\nlist<TestObject>/remove                      1682511938   1434771006      1.17         *\nlist<TestObject>/reverse                       87237327     80394623      1.09\nlist<TestObject>/size/1                         3828111       599530      6.39         *\nlist<TestObject>/size/10                        9600605      1329535      7.22         *   EASTL intentionally implements list::size as O(n).\nlist<TestObject>/size/100                      62952334     15022551      4.19         *   EASTL intentionally implements list::size as O(n).\nlist<TestObject>/splice                        96536412     60804817      1.59         *\n\nmap<TestObject, uint32_t>/clear                 1142127      1099066      1.04\nmap<TestObject, uint32_t>/count                19659726     14647548      1.34         *\nmap<TestObject, uint32_t>/equal_range          36680687     18219086      2.01         *\nmap<TestObject, uint32_t>/erase/key            28892154     16037774      1.80         *\nmap<TestObject, uint32_t>/erase/pos             1209643      1185495      1.02\nmap<TestObject, uint32_t>/erase/range            715402       670539      1.07\nmap<TestObject, uint32_t>/find                 21020992     13429575      1.57         *\nmap<TestObject, uint32_t>/insert               59530871     51120640      1.16         *\nmap<TestObject, uint32_t>/iteration              972825      1191946      0.82         *\nmap<TestObject, uint32_t>/lower_bound          18852651     12495034      1.51         *\nmap<TestObject, uint32_t>/operator[]           22889573     16676736      1.37         *\nmap<TestObject, uint32_t>/upper_bound          18603584     12406922      1.50         *\n\nset<uint32_t>/clear                              919555       882988      1.04\nset<uint32_t>/count                            17561110     12461084      1.41         *\nset<uint32_t>/equal_range                      31522488     15230282      2.07         *\nset<uint32_t>/erase range                        687582       564765      1.22         *\nset<uint32_t>/erase/pos                         1044352      1045355      1.00\nset<uint32_t>/erase/val                        25525304     12940774      1.97         *\nset<uint32_t>/find                             17140751     10704866      1.60         *\nset<uint32_t>/insert                           56035051     45555664      1.23         *\nset<uint32_t>/iteration                          682669       640831      1.07\nset<uint32_t>/lower_bound                      16339932     10475740      1.56         *\nset<uint32_t>/upper_bound                      17779424     10652599      1.67         *\n\nsort/q_sort/TestObject[]                       17000866     14823515      1.15         *\nsort/q_sort/TestObject[]/sorted                 6658559      3263328      2.04         *\nsort/q_sort/vector<TestObject>                 17476629     14953285      1.17         *\nsort/q_sort/vector<TestObject>/sorted           6667034      3327435      2.00         *\nsort/q_sort/vector<ValuePair>                  15391357     10820848      1.42         *\nsort/q_sort/vector<ValuePair>/sorted            6617122      3232949      2.05         *\nsort/q_sort/vector<uint32>                      8343906      6014846      1.39         *\nsort/q_sort/vector<uint32>/sorted               3039430      1003127      3.03         *\n\nstring<char16_t>/compare                     1489709846    532664000      2.80         *\nstring<char16_t>/erase/pos,n                    3528690      3439864      1.03\nstring<char16_t>/find/p,pos,n                2521448321    443752189      5.68         *\nstring<char16_t>/find_first_not_of/p,pos,n       661206       137419      4.81         *\nstring<char16_t>/find_first_of/p,pos,n         54746434      8521335      6.42         *\nstring<char16_t>/find_last_of/p,pos,n          10607778      1212414      8.75         *\nstring<char16_t>/insert/pos,p                   3445016      3360126      1.03\nstring<char16_t>/iteration                    580955636    579452556      1.00\nstring<char16_t>/operator[]                     2206353      1987809      1.11         *\nstring<char16_t>/push_back                     22421368      6007808      3.73         *\nstring<char16_t>/replace/pos,n,p,n              5138454      4464786      1.15         *\nstring<char16_t>/reserve                     4922413418       335622    100.00         *\nstring<char16_t>/rfind/p,pos,n                  1440308       380578      3.78         *\nstring<char16_t>/size                             25355        25398      1.00\nstring<char16_t>/swap                           2122704      1490823      1.42         *\n\nstring<char8_t>/compare                        77222134     77443134      1.00\nstring<char8_t>/erase/pos,n                     1965344      1956521      1.00\nstring<char8_t>/find/p,pos,n                 2468091951    474205522      5.20         *\nstring<char8_t>/find_first_not_of/p,pos,n        660960       130211      5.08         *\nstring<char8_t>/find_first_of/p,pos,n          55020899      9240171      5.95         *\nstring<char8_t>/find_last_of/p,pos,n           10576210      1239053      8.54         *\nstring<char8_t>/insert/pos,p                    1822756      1750880      1.04\nstring<char8_t>/iteration                       2617889      2540148      1.03\nstring<char8_t>/operator[]                      2254794      2256443      1.00\nstring<char8_t>/push_back                      12463022      5210321      2.39         *\nstring<char8_t>/replace/pos,n,p,n               3744862      2855260      1.31         *\nstring<char8_t>/reserve                      1372046888       218815    100.00         *\nstring<char8_t>/rfind/p,pos,n                   1446232       366902      3.94         *\nstring<char8_t>/size                              26859        25431      1.06\nstring<char8_t>/swap                            2123350      1490509      1.42         *\n\nvector<uint64>/erase                           55164013     56417449      0.98\nvector<uint64>/insert                          55872973     56432664      0.99\nvector<uint64>/iteration                        1329102      1324623      1.00\nvector<uint64>/operator[]                       5264738      3136746      1.68         *\nvector<uint64>/push_back                       14903245     13171175      1.13         *\nvector<uint64>/sort                            88429095     88542171      1.00\n```\n\n### Win32.VC71.STLPort.Release\n\n```\nEASTL version: 0.96.00\nPlatform: Windows on X86\nCompiler: Microsoft Visual C++ compiler, version 1310\nAllocator: PPMalloc::GeneralAllocator. Thread safety enabled.\nBuild: Full optimization. Inlining enabled.\n\nValues are times to complete tests; smaller values are better.\nAlarm indicates a greater than 10% difference.\n\nTest                                            STLPort        EASTL     Ratio     Alarm\n----------------------------------------------------------------------------------------\nalgorithm/adj_find/vector<TestObject>           2741046      2731441      1.00\nalgorithm/copy/vector<LargePOD>                 6065923      5085142      1.19         *\nalgorithm/copy/vector<uint32_t>                  158304       165555      0.96\nalgorithm/copy_backward/vector<LargePOD>        4710258      4896476      0.96\nalgorithm/copy_backward/vector<uint32_t>         146030       142630      1.02\nalgorithm/count/vector<uint64_t>                1395921      1406334      0.99\nalgorithm/equal_range/vector<uint64_t>        211692764    118969493      1.78         *\nalgorithm/fill/bool[]                            366078        33737     10.85         *\nalgorithm/fill/char[]/'d'                         33736        33771      1.00\nalgorithm/fill/vector<char>/'d'                   28466        33720      0.84         *\nalgorithm/fill/vector<char>/0                    366086        33728     10.85         *\nalgorithm/fill/vector<uint64_t>                  466250       401591      1.16         *\nalgorithm/fill/vector<void*>                     521603       693481      0.75         *\nalgorithm/fill_n/bool[]                          599709        33762     17.76         *\nalgorithm/fill_n/char[]                          599573        33711     17.79         *\nalgorithm/fill_n/vector<uint64_t>                434971      1374084      0.32         *\nalgorithm/find_end/string/end                   1494742        85349     17.51         *\nalgorithm/find_end/string/middle                1480700       687208      2.15         *\nalgorithm/find_end/string/none                  1540540      1546431      1.00\nalgorithm/lex_cmp/schar[]                        921638       178797      5.15         *\nalgorithm/lex_cmp/vector<TestObject>            2623559      2643551      0.99\nalgorithm/lex_cmp/vector<uchar>                  960899       183608      5.23         *\nalgorithm/lower_bound/vector<TestObject>       60630534     56531528      1.07\nalgorithm/min_element/vector<TestObject>        4209022      2768527      1.52         *\nalgorithm/rand_shuffle/vector<uint64_t>        13762010     15969052      0.86         *\nalgorithm/reverse/list<TestObject>               673387       731825      0.92\nalgorithm/reverse/vector<TestObject>             634576       754511      0.84         *\nalgorithm/search/string<char>                   1262599      1387608      0.91\nalgorithm/search_n/string<char>                 1166242       458592      2.54         *\nalgorithm/unique/vector<TestObject>             4912193      5336317      0.92\nalgorithm/unique/vector<uint32_t>                809387       809081      1.00\nalgorithm/unique/vector<uint64_t>               4371814      2414255      1.81         *\nalgorithm/upper_bound/vector<uint32_t>         31899081     29555596      1.08\n\nbitset<1500>/>>=/1                             63308136     40553560      1.56         *   STLPort is broken, neglects wraparound check.\nbitset<1500>/count                             62523178     22799473      2.74         *\nbitset<1500>/flip                              20302845     19919232      1.02\nbitset<1500>/reset                             18892015     15403148      1.23         *\nbitset<1500>/set()                             15803302     17322192      0.91\nbitset<1500>/set(i)                             2799271      2999310      0.93\nbitset<1500>/test                               2999293      2799262      1.07\n\nbitset<15>/>>=/1                                1199239      3199256      0.37         *   STLPort is broken, neglects wraparound check.\nbitset<15>/count                                3599461      2199231      1.64         *\nbitset<15>/flip                                 1199231      1199188      1.00\nbitset<15>/reset                                1199188      1199180      1.00\nbitset<15>/set()                                1199214      1199180      1.00\nbitset<15>/set(i)                               2599257      1399262      1.86         *\nbitset<15>/test                                 2599274      2599283      1.00\n\nbitset<35>/>>=/1                                6643974      4599239      1.44         *   STLPort is broken, neglects wraparound check.\nbitset<35>/count                                5151331      5399438      0.95\nbitset<35>/flip                                 1999404      1199273      1.67         *\nbitset<35>/reset                                9805285      1399313      7.01         *\nbitset<35>/set()                                2799279      1199248      2.33         *\nbitset<35>/set(i)                               2799246      1599241      1.75         *\nbitset<35>/test                                 2999234      2999251      1.00\n\nbitset<75>/>>=/1                                7002045      6999333      1.00             STLPort is broken, neglects wraparound check.\nbitset<75>/count                                5999351      3002259      2.00         *\nbitset<75>/flip                                 3599334      3599163      1.00\nbitset<75>/reset                                9799344      3399218      2.88         *\nbitset<75>/set()                                3599232      3599062      1.00\nbitset<75>/set(i)                               2799228      1599284      1.75         *\nbitset<75>/test                                 2999250      2799339      1.07\n\ndeque<ValuePair>/erase                        127108651    115258113      1.10\ndeque<ValuePair>/insert                       137727889    116552332      1.18         *\ndeque<ValuePair>/iteration                      7144182      6009899      1.19         *\ndeque<ValuePair>/operator[]                    34241222     20535039      1.67         *\ndeque<ValuePair>/push_back                      6585800      3932126      1.67         *\ndeque<ValuePair>/push_front                     6805865      3993513      1.70         *\ndeque<ValuePair>/sort                         395352323    348778188      1.13         *\n\nhash_map<string, uint32_t>/clear                 426640       447015      0.95\nhash_map<string, uint32_t>/count                4359344      3883089      1.12         *\nhash_map<string, uint32_t>/erase pos             584392       458142      1.28         *\nhash_map<string, uint32_t>/erase range           221034       196078      1.13         *\nhash_map<string, uint32_t>/erase val            3539867      3790813      0.93\nhash_map<string, uint32_t>/find                 3966831      3811910      1.04\nhash_map<string, uint32_t>/find_as/char*       11591612      4243710      2.73         *\nhash_map<string, uint32_t>/insert              16763887     16719194      1.00\nhash_map<string, uint32_t>/iteration             909968       478609      1.90         *\nhash_map<string, uint32_t>/operator[]           4360041      4108313      1.06\n\nhash_map<uint32_t, TestObject>/clear             302634       283722      1.07\nhash_map<uint32_t, TestObject>/count             916487       907426      1.01\nhash_map<uint32_t, TestObject>/erase pos         388042       321385      1.21         *\nhash_map<uint32_t, TestObject>/erase range       122680       116280      1.06\nhash_map<uint32_t, TestObject>/erase val        1710931      1729529      0.99\nhash_map<uint32_t, TestObject>/find             1089462      1346527      0.81         *\nhash_map<uint32_t, TestObject>/insert           4560310      5072350      0.90         *\nhash_map<uint32_t, TestObject>/iteration         960117       495354      1.94         *\nhash_map<uint32_t, TestObject>/operator[]       1872830      1890595      0.99\n\nheap (uint32_t[])/make_heap                     3528418      3327257      1.06\nheap (uint32_t[])/pop_heap                     63243859     61011853      1.04\nheap (uint32_t[])/push_heap                    11602424     10045869      1.15         *\nheap (uint32_t[])/sort_heap                    52965362     48744729      1.09\n\nheap (vector<TestObject>)/make_heap            13191456     13089711      1.01\nheap (vector<TestObject>)/pop_heap            148555656    144787742      1.03\nheap (vector<TestObject>)/push_heap            28696689     26618830      1.08\nheap (vector<TestObject>)/sort_heap           112473989    114018643      0.99\n\nlist<TestObject>/ctor(it)                      80186731     74006287      1.08\nlist<TestObject>/ctor(n)                        6232311      6128007      1.02\nlist<TestObject>/erase                        344556374    212877808      1.62         *\nlist<TestObject>/find                          39859075     14591347      2.73         *\nlist<TestObject>/insert                        86935153     56138233      1.55         *\nlist<TestObject>/push_back                     79569180     46700641      1.70         *\nlist<TestObject>/remove                       785786758    324201016      2.42         *\nlist<TestObject>/reverse                       45248186     24852759      1.82         *\nlist<TestObject>/size/1                          219844       219496      1.00\nlist<TestObject>/size/10                         519563       519579      1.00             EASTL intentionally implements list::size as O(n).\nlist<TestObject>/size/100                       4567194    101230266      0.05         *   EASTL intentionally implements list::size as O(n).\nlist<TestObject>/splice                        68321087     23601687      2.89         *\n\nmap<TestObject, uint32_t>/clear                  168011       180540      0.93\nmap<TestObject, uint32_t>/count                 4830439      5139287      0.94\nmap<TestObject, uint32_t>/equal_range           8700090      6158531      1.41         *\nmap<TestObject, uint32_t>/erase/key             6696776      4617038      1.45         *\nmap<TestObject, uint32_t>/erase/pos              309273       333183      0.93\nmap<TestObject, uint32_t>/erase/range            137419       136068      1.01\nmap<TestObject, uint32_t>/find                  4773498      4931352      0.97\nmap<TestObject, uint32_t>/insert                9651877      9311699      1.04\nmap<TestObject, uint32_t>/iteration              372946       416364      0.90         *\nmap<TestObject, uint32_t>/lower_bound           4784234      4915797      0.97\nmap<TestObject, uint32_t>/operator[]            5040254      5183147      0.97\nmap<TestObject, uint32_t>/upper_bound           4724292      4915984      0.96\n\nset<uint32_t>/clear                              165300       173289      0.95\nset<uint32_t>/count                             4958654      4885086      1.02\nset<uint32_t>/equal_range                       8434134      5698681      1.48         *\nset<uint32_t>/erase range                        145554       133960      1.09\nset<uint32_t>/erase/pos                          299914       324760      0.92\nset<uint32_t>/erase/val                         6506155      4335034      1.50         *\nset<uint32_t>/find                              4866879      4556043      1.07\nset<uint32_t>/insert                            8340523      8957257      0.93\nset<uint32_t>/iteration                          294465       343442      0.86         *\nset<uint32_t>/lower_bound                       4548095      4756498      0.96\nset<uint32_t>/upper_bound                       4559196      4521498      1.01\n\nsort/q_sort/TestObject[]                        7316766      7013894      1.04\nsort/q_sort/TestObject[]/sorted                 1668439      1332885      1.25         *\nsort/q_sort/vector<TestObject>                  7331530      7017260      1.04\nsort/q_sort/vector<TestObject>/sorted           1601629      1247120      1.28         *\nsort/q_sort/vector<ValuePair>                   7071643      7067869      1.00\nsort/q_sort/vector<ValuePair>/sorted            2136390      1703799      1.25         *\nsort/q_sort/vector<uint32>                      3292891      2943627      1.12         *\nsort/q_sort/vector<uint32>/sorted                653693       473612      1.38         *\n\nstring<char16_t>/compare                      356579259    432760228      0.82         *\nstring<char16_t>/erase/pos,n                    3430422      3428645      1.00\nstring<char16_t>/find/p,pos,n                 229263402    225830975      1.02\nstring<char16_t>/find_first_not_of/p,pos,n       187391        81404      2.30         *\nstring<char16_t>/find_first_of/p,pos,n          4411831      4413532      1.00\nstring<char16_t>/find_last_of/p,pos,n            731655       726155      1.01\nstring<char16_t>/insert/pos,p                   3408628      3319726      1.03\nstring<char16_t>/iteration                    309993861    310333547      1.00\nstring<char16_t>/operator[]                      580839       579904      1.00\nstring<char16_t>/push_back                      3983338      2975553      1.34         *\nstring<char16_t>/replace/pos,n,p,n              4361095      4211504      1.04\nstring<char16_t>/reserve                      935141729       247010    100.00         *\nstring<char16_t>/rfind/p,pos,n                   248956       223397      1.11         *\nstring<char16_t>/size                             13311        13107      1.02\nstring<char16_t>/swap                            519129       579445      0.90         *\n\nstring<char8_t>/compare                        76695559     76828015      1.00\nstring<char8_t>/erase/pos,n                     1951566      1947282      1.00\nstring<char8_t>/find/p,pos,n                  185878944    185605039      1.00\nstring<char8_t>/find_first_not_of/p,pos,n        196877        81600      2.41         *\nstring<char8_t>/find_first_of/p,pos,n           4147685      4145356      1.00\nstring<char8_t>/find_last_of/p,pos,n             605897       598222      1.01\nstring<char8_t>/insert/pos,p                    1781592      1768264      1.01\nstring<char8_t>/iteration                        921502       921272      1.00\nstring<char8_t>/operator[]                       361250       359873      1.00\nstring<char8_t>/push_back                       3363288      2530493      1.33         *\nstring<char8_t>/replace/pos,n,p,n               2682600      2633130      1.02\nstring<char8_t>/reserve                       672517501        78387    100.00         *\nstring<char8_t>/rfind/p,pos,n                    226202       200013      1.13         *\nstring<char8_t>/size                              11280        11109      1.02\nstring<char8_t>/swap                             519393       559759      0.93\n\nvector<uint64>/erase                           55184856     55192217      1.00\nvector<uint64>/insert                          56764267     55682726      1.02\nvector<uint64>/iteration                         423122       424039      1.00\nvector<uint64>/operator[]                       1189397       860991      1.38         *\nvector<uint64>/push_back                        5626609      4027317      1.40         *\nvector<uint64>/sort                            49227036     49231362      1.00\n```\n\n----------------------------------------------\nEnd of document\n"
  },
  {
    "path": "doc/BestPractices.md",
    "content": "# EASTL Best Practices\n\nIn this document we discuss best practices for using EASTL. The primary emphasis is on performance with a secondary emphasis on correctness and maintainability. Some best practices apply only to some situations, and these will be pointed out as we go along. In order to be easily digestible, we present these practices as a list of items in the tone of the Effective C++ series of books.\n\n## Summary\n\nThe descriptions here are intentionally terse; this is to make them easier to visually scan.\n\n1. [Consider intrusive containers.](#consider-intrusive-containers)\n2. [Consider fixed-size containers.](#consider-fixed-size-containers)\n3. [Consider custom allocators.](#consider-custom-allocators)\n4. [Consider hash tables instead of maps.](#consider-hash-tables-instead-of-maps)\n5. [Consider a vector_map (a.k.a. sorted vector) for unchanging data.](#consider-a-vector_map-aka-sorted-vector-for-unchanging-data)\n6. [Consider slist instead of list.](#consider-slist-instead-of-list)\n7. [Avoid redundant end() and size() in loops.](#avoid-redundant-end-and-size-in-loops)\n8. [Iterate containers instead of using operator\\[\\].](#iterate-containers-instead-of-using-operator)\n9. [Learn to use the string class appropriately.](#learn-to-use-the-string-class-appropriately)\n10. [Cache list size if you want size() to be O(1).](#cache-list-size-if-you-want-listsize-to-be-o1)\n11. [Use empty() instead of size() when possible.](#use-empty-instead-of-size-when-possible)\n12. [Know your container efficiencies.](#know-your-container-efficiencies)\n13. [Use vector::reserve.](#use-vectorreserve)\n14. [Use vector::set_capacity to trim memory usage.](#use-vectorset_capacity-to-trim-memory-usage)\n15. [Use swap() instead of a manually implemented version.](#use-swap-instead-of-a-manually-implemented-version)\n16. [Consider storing pointers instead of objects.](#consider-storing-pointers-instead-of-objects)\n17. [Consider smart pointers instead of raw pointers.](#consider-smart-pointers-instead-of-raw-pointers)\n18. [Use iterator pre-increment instead of post-increment.](#use-iterator-pre-increment-instead-of-post-increment)\n19. [Make temporary references so the code can be traced/debugged.](#make-temporary-references-so-the-code-can-be-traceddebugged)\n20. [Consider bitvector or bitset instead of vector\\<bool>.](#consider-bitvector-or-bitset-instead-of-vector)\n21. [Vectors can be treated as contiguous memory.](#vectors-can-be-treated-as-contiguous-memory)\n22. [Search hash_map\\<string> using heterogeneous lookup.](#search-hash_mapstring-using-heterogeneous-lookup)\n23. [Take advantage of type_traits.](#take-advantage-of-type_traits)\n24. [Name containers to track memory usage.](#name-containers-to-track-memory-usage)\n25. [Learn the algorithms.](#learn-the-algorithms)\n26. [Pass and return containers by reference instead of value.](#pass-and-return-containers-by-reference-instead-of-value)\n27. [Consider using reset_lose_memory() for fast container teardown.](#consider-using-reset_lose_memory-for-fast-container-teardown)\n28. [Consider using fixed_substring instead of copying strings.](#consider-using-fixed_substring-instead-of-copying-strings)\n29. [Consider using vector::push_back(void).](#consider-using-vectorpush_backvoid)\n\n## Detail\n\n### Consider intrusive containers.\n\nIntrusive containers (such as intrusive_list) differ from regular containers (such as list) in that they use the stored objects to manage the linked list instead of using nodes allocated from a memory heap. The result is better usage of memory. Additionally intrusive_list objects can be removed from their list without knowing what list they belong to. To make an intrusive_list of Widgets, you have Widget inherit from intrusive_list_node or simply have mpPrev/mpNext member variables.\n\nTo create an intrusive_list container, you can use the following code:\n\n```cpp\nclass Widget : public intrusive_list_node\n\n{ };\n\n\n\nintrusive_list<Widget> widgetList;\n\nwidgetList.push_back(someWidget);\n```\n\n### Consider fixed-size containers.\n\nFixed-size containers (such as fixed_list) are variations of regular containers (such as list) in that they allocate from a fixed block of local memory instead of allocating from a generic heap. The result is better usage of memory due to reduced fragmentation, better cache behavior, and faster allocation/deallocation. The presence of fixed-size containers negate the most common complaint that people have about STL: that it fragments the heap or \"allocates all over the place.\"\n\nEASTL fixed containers include:\n\n* fixed_list\n* fixed_slist\n* fixed_vector\n* fixed_string\n* fixed_map\n* fixed_multimap\n* fixed_set\n* fixed_multiset\n* fixed_hash_map\n* fixed_hash_multimap\n* fixed_hash_set\n* fixed_hash_multiset\n\nTo create a fixed_set, you can use the following code:\n\n```cpp\nfixed_set<int, 25> intSet; // Create a set capable of holding 25 elements.\n\nintSet.push_back(37);\n```\n\n### Consider custom allocators.\n\nWhile EASTL provides fixed-size containers in order to control container memory usage, EASTL lets you assign a custom allocator to any container. This lets you define your own memory pool. EASTL has a more flexible and powerful mechanism of doing this that standard STL, as EASTL understands object alignment requirements, allows for debug naming, allows for sharing allocators across containers, and allows dynamic allocator assignment.\n\nTo create a list container that uses your custom allocator and uses block naming, you can use the following code:\n\n```cpp\nlist<int> intList(pSomeAllocator, \"graphics/intList\");\n\nintList.push_back(37);\n```\n\n### Consider hash tables instead of maps.\n\nHash containers (such as hash_map) provide the same interface as associative containers (such as map) but have faster lookup and use less memory. The primary disadvantage relative to associative containers is that hash containers are not sorted.\n\nTo make a hash_map (dictionary) of integers to strings, you can use the following code:\n```cpp\nhash_map<int, const char*> stringTable;\n\nstringTable[37] = \"hello\";\n```\n\n### Consider a vector_map (a.k.a. sorted vector) for unchanging data.\n\nYou can improve speed, memory usage, and cache behavior by using a vector_map instead of a map (or vector_set instead of set, etc.). The primary disadvantage of vector_map is that insertions and removal of elements is O(n) instead of O(1). However, if your associative container is not going to be changing much or at all, you can benefit from using a vector_map. Consider calling reserve on the vector_map in order to set the desired capacity up front.\n\nTo make a vector_set, you can use the following code:\n\n```cpp\nvector_set<int> intSet(16); // Create a vector_set with an initial capacity of 16.\n\nintSet.insert(37);\n```\n\nNote that you can use containers other than vector to implement vector_set. Here's how you do it with deque:\n\n```cpp\nvector_set<int, less<int>, EASTLAllocatorType, deque<int> > intSet;\n\nintSet.insert(37);\n```\n\n### Consider slist instead of list.\n\nAn slist is a singly-linked list; it is much like a list except that it can only be traversed in a forward direction and not a backward direction. The benefit is that each node is 4 bytes instead of 8 bytes. This is a small improvement, but if you don't need reverse iteration then it can be an improvement. There's also intrusive_slist as an option.\n\nTo make an slist, you can use the following code:\n\n```cpp\nslist<int> intSlist;\n\nintSlist.push_front(37);\n```\n\n### Avoid redundant end() and size() in loops.\n\nInstead of writing code like this:\n\n```cpp\nfor(deque<int>::iterator it = d.begin(); it != d.end(); ++it)\n\n    ...\n```\n\nwrite code like this:\n\n```cpp\nfor(deque<int>::iterator it = d.begin(), itEnd = d.end(); it != itEnd; ++it)\n\n    ...\n```\n\nThe latter avoids a function call and return of an object (which in deque's case happens to be more than just a pointer). The above only works when the container is unchanged or for containers that have a constant end value. But \"constant end value\" we mean containers which can be modified but end always remains the same.\n\n| Constant begin | Non-constant begin | Constant end | Non-constant end |\n|------|------|------|------|\n| array<sup>1</sup> | string<br> vector<br> deque<br> intrusive_list<br> intrusive_slist<br> vector_map<br> vector_multimap<br> vector_set<br> vector_multiset<br> bit_vector<br> hash_map<br> hash_multimap<br> hash_set<br> hash_multiset<br> intrusive_hash_map<br> intrusive_hash_multimap<br> intrusive_hash_set<br> intrusive_hash_multiset | array<br> list<br> slist<br> intrusive_list<br> intrusive_slist<br> map<br> multimap<br> set<br> multiset<br> hash_map<sup>2</sup><br> hash_multimap<sup>2</sup><br> hash_set<sup>2</sup><br> hash_multiset<sup>2</sup><br> intrusive_hash_map<br> intrusive_hash_multimap<br> intrusive_hash_set<br> intrusive_hash_multiset | string<br> vector<br> deque<br> vector_map<br> vector_multimap<br> vector_set<br> vector_multiset<br> bit_vector |\n\n* <sup>1</sup> Arrays can be neither resized nor reallocated.\n* <sup>2</sup> Constant end if the hashtable can't/won't re-hash. Non-constant if it can re-hash.\n\n### Iterate containers instead of using operator[].\n\nIt's faster to iterate random access containers via iterators than via operator[], though operator[] usage may look simpler.\n\nInstead of doing this:\n\n```cpp\nfor(unsigned i = 0, iEnd = intVector.size(); i != iEnd; ++i)\n\n    intVector[i] = 37;\n```\n\nyou can execute more efficiently by doing this:\n\n```cpp\nfor(vector<int>::iterator it = intVector.begin(), itEnd = intVector.end(); it != itEnd; ++it)\n\n    *it = 37;\n```\n\n### Learn to use the string class appropriately.\n\nOddly enough, the most mis-used STL container is easily the string class. The tales of string abuse could rival the 1001 Arabian Nights. Most of the abuses involve doing things in a harder way than need be. In examining the historical mis-uses of string, it is clear that many of the problems stem from the user thinking in terms of C-style string operations instead of object-oriented strings. This explains why statements such as strlen(s.c_str()) are so common, whereas the user could just use s.length() instead and be both clearer and more efficient.\n\nHere we provide a table of actual collected examples of things done and how they could have been done instead.\n\n| What was written | What could have been written |\n|------|------|\n| `s = s.Left(i) + '+' + s.Right(s.length() - i - 1);` | `s[i] = '+';` |\n| `string s(\"\"); // This is the most commonly found misuse.` | `string s;` |\n| `s = \"\";` | `s.clear();` |\n| `s.c_str()[0] = 'u';` | `s[0] = 'u';` |\n| `len = strlen(s.c_str());` | `len = s.length();` |\n| `s = string(\"u\");` | `s = \"u\";` |\n| `puts(s + string(\"u\"));` | `puts(s + \"u\");` |\n| `string s(\" \");`<br> `puts(s.c_str());` | `puts(\" \");` |\n| `s.sprintf(\"u\");` | s = \"u\";` |\n| `char array[32];`<br> `sprintf(array, \"%d\", 10);`<br> `s = string(array);` | `s.sprintf(\"%d\", 10);` |\n\nThe chances are that if you want to do something with a string, there is a very basic way to do it. You don't want your code to appear in a future version of the above table.\n\n### Cache list size if you want list::size() to be O(1).\n\nEASTL's list, slist, intrusive_list, and intrusive_slist containers have a size() implementation which is O(n). That is, these containers don't keep a count (cache) of the current list size and when you call the size() function they iterate the list. This is by design and the reasoning behind it has been deeply debated and considered (and is discussed in the FAQ and the list header file). In summary, list doesn't cache its size because the only function that would benefit is the size function while many others would be negatively impacted and the memory footprint would be negatively impacted, yet list::size is not a very frequently called function in well-designed code. At the same time, nothing prevents the user from caching the size himself, though admittedly it adds some tedium and risk to the code writing process.\n\nHere's an example of caching the list size manually:\n\n```cpp\nlist<int> intList;\n\n  size_t    n = 0;\n\n\n\n  intList.push_back(37);\n\n  ++n;\n\n  intList.pop_front();\n\n  --n;\n```\n\n### Use empty() instead of size() when possible.\n\nAll conventional containers have both an empty function and a size function. For all containers empty() executes with O(1) (constant time) efficiency. However, this is not so for size(), as some containers need to calculate the size and others need to do pointer subtraction (which may involve integer division) to find the size.\n\n### Know your container efficiencies.\n\nThe above two practices lead us to this practice, which is a generalization of the above. We present a table of basic information for the conventional EASTL containers. The values are described at the bottom.\n\n| Container | empty() efficiency | size() efficiency | operator[] efficiency | insert() efficiency | erase() efficiency | find() efficiency | sort efficiency |\n|------|------|------|------|------|------|------|------|\n| slist | 1 | O(n) | - | O(1) | O(1) | O(n) | O(n+) |\n| list | 1 | n | - | 1 | 1 | n | n log(n) |\n| intrusive_slist | 1 | n | - | 1 | 1 | 1 | n+ |\n| intrusive_list | 1 | n | - | 1 | 1 | 1 | n log(n) |\n| array | 1 | 1 | 1 | - | - | n | n log(n) |\n| vector | 1 | 1<sup>a</sup> | 1 | \t1 at end, else n | 1 at end, else n | n | n log(n) |\n| vector_set | 1 | 1<sup>a</sup> | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| vector_multiset | 1 | 1<sup>a</sup> | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| vector_map | 1 | 1<sup>a</sup> | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| vector_multimap | 1 | 1<sup>a</sup> | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| deque | 1 | 1<sup>a</sup> | 1 | 1 at begin or end, else n / 2 | 1 at begin or end, else n / 2 | n | n log(n) |\n| bit_vector | 1 | 1<sup>a</sup> | 1 | 1 at end, else n | 1 at end, else n | n | n log(n) |\n| string, cow_string  | 1 | 1<sup>a</sup> | 1 | 1 at end, else n | 1 at end, else n | n | n log(n) |\n| set | 1 | 1 | - | log(n) | log(n) | log(n) | 1 |\n| multiset | 1 | 1 | - | log(n) | log(n) | log(n) | 1 |\n| map | 1 | 1 | log(n) | log(n) | log(n) | log(n) | 1 |\n| multimap | 1 | 1 | - | log(n) | log(n) | log(n) | 1 |\n| hash_set | 1 | 1 | - | 1 | 1 | 1 | - |\n| hash_multiset | 1 | 1 | - | 1 | 1 | 1 | - |\n| hash_map | 1 | 1 | - | 1 | 1 | 1 | - |\n| hash_multimap | 1 | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_set | 1 | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_multiset | 1 | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_map | 1 | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_multimap | 1 | 1 | - | 1 | 1 | 1 | - |\n\nNotes:\n\n* \\- means that the operation does not exist.\n* 1 means amortized constant time. Also known as O(1)\n* n means time proportional to the container size. Also known as O(n)\n* log(n) means time proportional to the natural logarithm of the container size. Also known as O(log(n))\n* n log(n) means time proportional to log(n) times the size of the container. Also known as O(n log(n))\n* n+ means that the time is at least n, and possibly higher.\n* Inserting at the end of a vector may cause the vector to be resized; resizing a vector is O(n). However, the amortized time complexity for vector insertions at the end is constant.\n* Sort assumes the usage of the best possible sort for a large container of random data. Some sort algorithms (e.g. quick_sort) require random access iterators and so the sorting of some containers requires a different sort algorithm. We do not include bucket or radix sorts, as they are always O(n).\n* <sup>a</sup> vector, deque, string size is O(1) but involves pointer subtraction and thus integer division and so is not as efficient as containers that store the size directly.\n\n### Use vector::reserve.\n\nYou can prevent vectors (and strings) from reallocating as you add items by specifying up front how many items you will be requiring. You can do this in the constructor or by calling the reserve function at any time. The capacity function returns the amount of space which is currently reserved.\n\nHere's how you could specify reserved capacity in a vector:\n\n```cpp\nvector<Widget> v(37);   // Reserve space to hold up to 37 items.\n\n    or\n\nvector<Widget> v;       // This empty construction causes to memory to be allocated or reserved.\n\n  v.reserve(37);\n```\n\nThe EASTL vector (and string) implementation looks like this:\n\n```cpp\ntemplate <typename T>\n\n  class vector {\n\n    T* mpBegin;     // Beginning of used element memory.\n\n    T* mpEnd;       // End of used element memory.\n\n    T* mpCapacity;  // End of storage capacity. Is >= mpEnd\n\n   }\n```\n\nAnother approach to being efficient with vector memory usage is to use fixed_vector.\n\n### Use vector::set_capacity to trim memory usage.\n\nA commonly asked question about vectors and strings is, \"How do I reduce the capacity of a vector?\" The conventional solution for std STL is to use the somewhat non-obvious trick of using vector<Widget>(v).swap(v). EASTL provides the same functionality via a member function called set_capacity() which is present in both the vector and string classes.\n\nAn example of reducing a vector is the following:\n\n```cpp\nvector<Widget> v;\n\n...\n\n v.set_capacity();\n```\n\nAn example of resizing to zero and completely freeing the memory of a vector is the following:\n\n```cpp\nvector<Widget> v;\n\n  ...\n\n   v.set_capacity(0);\n```\n\n### Use swap() instead of a manually implemented version.\n\nThe generic swap algorithm provides a basic version for any kind of object. However, each EASTL container provides a specialization of swap which is optimized for that container. For example, the list container implements swap by simply swapping the internal member pointers and not by moving individual elements.\n\n### Consider storing pointers instead of objects.\n\nThere are times when storing pointers to objects is more efficient or useful than storing objects directly in containers. It can be more efficient to store pointers when the objects are big and the container may need to construct, copy, and destruct objects during sorting or resizing. Moving pointers is usually faster than moving objects. It can be useful to store pointers instead of objects when somebody else owns the objects or the objects are in another container. It might be useful for a Widget to be in a list and in a hash table at the same time.\n\n### Consider smart pointers instead of raw pointers.\n\nIf you take the above recommendation and store objects as pointers instead of as objects, you may want to consider storing them as smart pointers instead of as regular pointers. This is particularly useful for when you want to delete the object when it is removed from the container. Smart pointers will automatically delete the pointed-to object when the smart pointer is destroyed. Otherwise, you will have to be careful about how you work with the list so that you don't generate memory leaks. Smart pointers implement a shared reference count on the stored pointer, as so any operation you do on a smart pointer container will do the right thing. Any pointer can be stored in a smart pointer, and custom new/delete mechanisms can work with smart pointers. The primary smart pointer is shared_ptr.\n\nHere is an example of creating and using a shared_ptr:\n\n```cpp\ntypedef shared_ptr<Widget> WPtr;\n\n  list<WPtr> wList;\n\n\n\n  wList.push_back(WPtr(new Widget)); // The user may have operator new/delete overrides.\n\nwList.pop_back();                  // Implicitly deletes the Widget.\n```\n\nHere is an example of creating and using a shared_ptr that uses a custom allocation and deallocation mechanism:\n\n```cpp\ntypedef shared_ptr<Widget, EASTLAllocatorType, WidgetDelete> WPtr; // WidgetDelete is a custom destroyer.\n\n  list<WPtr> wList;\n\n\n\n  wList.push_back(WPtr(WidgetCreate(Widget))); // WidgetCreate is a custom allocator.\n\nwList.pop_back();                            // Implicitly calls WidgetDelete.\n```\n\n### Use iterator pre-increment instead of post-increment.\n\nPre-increment (e.g. ++x) of iterators is better than post-increment (x++) when the latter is not specifically needed. It is common to find code that uses post-incrementing when it could instead use pre-incrementing; presumably this is due to post-increment looking a little better visually. The problem is that the latter constructs a temporary object before doing the increment. With built-in types such as pointers and integers, the compiler will recognize that the object is a trivial built-in type and that the temporary is not needed, but the compiler cannot do this for other types, even if the compiler sees that the temporary is not used; this is because the constructor may have important side effects and the compiler would be broken if it didn't construct the temporary object.\n\nEASTL iterators are usually not trivial types and so it's best not to hope the compiler will do the best thing. Thus you should always play it safe an use pre-increment of iterators whenever post-increment is not required.\n\nHere is an example of using iterator pre-increment; for loops like this should always use pre-increment:\n\n```cpp\nfor(set<int>::iterator it(intSet.begin()), itEnd(intSet.end()); it != itEnd; ++it)\n\n      *it = 37;\n```\n\n### Make temporary references so the code can be traced/debugged.\n\nUsers want to be able to inspect or modify variables which are referenced by iterators. While EASTL containers and iterators are designed to make this easier than other STL implementations, it makes things very easy if the code explicitly declares a reference to the iterated element. In addition to making the variable easier to debug, it also makes code easier to read and makes the debug (and possibly release) version of the application run more efficiently.\n\nInstead of doing this:\n\n```cpp\nfor(list<Widget>::iterator it = wl.begin(), itEnd = wl.end(); it != itEnd; ++it) {\n\n      (*it).x = 37;\n\n      (*it).y = 38;\n\n      (*it).z = 39;\n\n  }\n```\n\nConsider doing this:\n\n```cpp\nfor(list<Widget>::iterator it = wl.begin(), itEnd = wl.end(); it != itEnd; ++it) {\n\n      Widget& w = *it; // The user can easily inspect or modify w here.\n\n      w.x = 37;\n\n      w.y = 38;\n\n      w.z = 39;\n\n  }\n```\n\n### Consider bitvector or bitset instead of vector<bool>.\n\nIn EASTL, a vector of bool is exactly that. It intentionally does not attempt to make a specialization which implements a packed bit array. The bitvector class is specifically designed for this purpose. There are arguments either way, but if vector<bool> were allowed to be something other than an array of bool, it would go against user expectations and prevent users from making a true array of bool. There's a mechanism for specifically getting the bit packing, and it is bitvector.\n\nAdditionally there is bitset, which is not a conventional iterateable container but instead acts like bit flags. bitset may better suit your needs than bitvector if you need to do flag/bit operations instead of array operations. bitset does have an operator[], though.\n\n### Vectors can be treated as contiguous memory.\n\nEASTL vectors (and strings) guarantee that elements are present in a linear contiguous array. This means that you can use a vector as you would a C-style array by using the vector data() member function or by using &v[0].\n\nTo use a vector as a pointer to an array, you can use the following code:\n\n```cpp\nstruct Widget {\n\n      uint32_t x;\n\n      uint32_t y;\n\n  };\n\n\n\n  vector<Widget> v;\n\n\n\n  quick_sort((uint64_t*)v.data(), (uint64_t*)(v.data() + v.size()));\n```\n\n### Search hash_map\\<string> using heterogeneous lookup\n\nWhen using a hash map (or any associative container) of string objects that you want to search for by string literals (e.g. \"hello\") or char pointers, if you search for a string via the `find` function, your string literal will necessarily be converted to a temporary string object, which is inefficient because string allocates.\n\nYou can avoid creating these temporary objects declare the container type with [transparent comparison types](https://en.cppreference.com/w/cpp/utility/functional#Transparent_function_objects) (eg. [`equal_to<void>`](https://en.cppreference.com/w/cpp/utility/functional/less_void)). eg.\n```cpp\neastl::hash_map<string, int, eastl::transparent_string_hash, eastl::equal_to<void>> hashMap;\n  ...\nauto it = hashMap.find(\"hello\"); // No string object created. Uses heterogeneous lookup, which calls transparent_string_hash::operator()(const string&) and equal_to::operator()(const string&, const char*).\n```\nEASTL containers support this optimization for additional member functions that take a `key_type` parameter, ie. heterogeneous lookup, insertion and erasure.\n\nEASTL also has a member function called `find_as` which lets you search a hash table by something other than the container comparison type. Note that the comparison semantics must be equivalent to the container's comparison object, otherwise the behaviour is undefined.\n\nTo use `find_as`, you can use the following code:\n\n```cpp\nhash_map<string, int> hashMap;\n...\nauto it = hashMap.find_as(\"hello\", /* a hash object */, /* an equality comparison object */);\n```\n\nUsing transparent comparison types should be preferred due to the support for additional member functions and additional safety.\n\n### Take advantage of type_traits.\n\nEASTL includes a fairly serious type traits library that is on par with the one found in Boost but offers some additional performance-enhancing help as well. The type_traits library provides information about class *types*, as opposed to class instances. For example, the is_integral type trait tells if a type is one of int, short, long, char, uint64_t, etc.\n\nThere are three primary uses of type traits:\n\n* Allowing for optimized operations on some data types.\n* Allowing for different logic pathways based on data types.\n* Allowing for compile-type assertions about data type expectations.\n\nHere is an example of using type traits to tell if a value is a floating point value or not:\n\n```cpp\ntemplate <typename T>\n\n  DoSomething(T t) {\n\n    assert(is_floating_point<T>::value);\n\n  }\n```\n\nHere is an example of declaring a class that is trivially copyable and using it in a vector.\n\n```cpp\n  class Widget { ... };                   // Anything conforming to the trivially copyable rules: https://en.cppreference.com/w/cpp/language/classes#Trivially_copyable_class\n\n  vector<Widget> wVector{ ... some elements ... };\n\n  wVector.erase(wVector.begin());         // This operation will be optimized to memcpy the elements into place.\n```\n\n### Name containers to track memory usage.\n\nAll EASTL containers which allocate memory have a built-in function called set_name and have a constructor argument that lets you specify the container name. This name is used in memory tracking and allows for the categorization and measurement of memory usage. You merely need to supply a name for your containers to use and it does the rest.\n\nHere is an example of creating a list and naming it \"collision list\":\n\n`list<CollisionData> collisionList(allocator(\"collision list\"));`\n\nor\n\n```cpp\nlist<CollisionData> collisionList;\n\ncollisionList.get_allocator().set_name(\"collision list\");\n```\n\nNote that EASTL containers do not copy the name contents but merely copy the name pointer. This is done for simplicity and efficiency. A user can get around this limitation by creating a persistently present string table. Additionally, the user can get around this by declaring static but non-const strings and modifying them at runtime.\n\n### Learn the algorithms.\n\nEASTL algorithms provide a variety of optimized implementations of fundamental algorithms. Many of the EASTL algorithms are the same as the STL algorithm set, though EASTL adds additional algorithms and additional optimizations not found in STL implementations such as Microsoft's. The copy algorithm, for example, will memcpy data types that have the has_trivial_relocate type trait instead of doing an element-by-element copy.\n\nThe classifications we use here are not exactly the same as found in the C++ standard; they have been modified to be a little more intuitive. Not all the functions listed here may be yet available in EASTL as you read this. If you want some function then send a request to the maintainer. Detailed documentation for each algorithm is found in algorithm.h or the otherwise corresponding header file for the algorithm.\n\n**Search**\n\n* find, find_if\n* find_end\n* find_first_of\n* adjacent_find\n* binary_search\n* search, search_n\n* lower_bound\n* upper_bound\n* equal_range\n\n**Sort**\n\n* is_sorted\n* quick_sort\n* insertion_sort\n* shell_sort\n* heap_sort\n* merge_sort, merge_sort_buffer\n* merge\n* inplace_merge\n* partial_sort\n* stable_sort\n* partial_sort_copy\n* <other sort functions found in the EASTL bonus directories>\n\n**Modifying**\n\n* fill, fill_n\n* generate, generate_n\n* random_shuffle\n* swap\n* iter_swap\n* swap_ranges\n* remove, remove_if\n* remove_copy, remove_copy_if\n* replace, replace_if\n* replace_copy, replace_copy_if\n* reverse\n* reverse_copy\n* rotate\n* rotate_copy\n* partition\n* stable_partition\n* transform\n* next_permutation\n* prev_permutation\n* unique\n* unique_copy\n\n**Non-Modifying**\n\n* for_each\n* copy\n* copy_backward\n* count, count_if\n* equal\n* mismatch\n* min\n* max\n* min_element\n* max_element\n* lexicographical_compare\n* nth_element\n\n**Heap**\n\n* is_heap\n* make_heap\n* push_heap\n* pop_heap\n* change_heap\n* sort_heap\n* remove_heap\n\n**Set**\n\n* includes\n* set_difference\n* set_symmetric_difference\n* set_intersection\n* set_union\n\n### Pass and return containers by reference instead of value.\n\nIf you aren't paying attention you might accidentally write code like this:\n\n```cpp\nvoid DoSomething(list<Widget> widgetList) {\n\n      ...\n\n}\n```\n\nThe problem with the above is that widgetList is passed by value and not by reference. Thus the a copy of the container is made and passed instead of a reference of the container being passed. This may seem obvious to some but this happens periodically and the compiler gives no warning and the code will often execute properly, but inefficiently. Of course there are some occasions where you really do want to pass values instead of references.\n\n### Consider using reset_lose_memory() for fast container teardown.\n\nEASTL containers have a reset_lose_memory function which unilaterally resets the container to a newly constructed state. The contents of the container are forgotten; no destructors are called and no memory is freed. This is a risky but powerful function for the purpose of implementing very fast temporary containers. There are numerous cases in high performance programming when you want to create a temporary container out of a scratch buffer area, use the container, and then just \"vaporize\" it, as it would be waste of time to go through the trouble of clearing the container and destroying and freeing the objects. Such functionality is often used with hash tables or maps and with a stack allocator (a.k.a. linear allocator).\n\nHere's an example of usage of the reset function and a PPMalloc-like StackAllocator:\n\n```cpp\n  pStackAllocator->push_bookmark();\n\n  hash_set<Widget, less<Widget>, StackAllocator> wSet(pStackAllocator);\n\n  <use wSet>\n\n  wSet.reset_lose_memory();\n\n  pStackAllocator->pop_bookmark();\n```\n\n### Consider using fixed_substring instead of copying strings.\n\nEASTL provides a fixed_substring class which uses a reference to a character segment instead of allocating its own string memory. This can be a more efficient way to work with strings under some circumstances.\n\nHere's an example of usage of fixed_substring:\n\n```cpp\nbasic_string<char> str(\"hello world\");\n\n  fixed_substring<char> sub(str, 6, 5); // sub == \"world\"\n\nfixed_substring can refer to any character array and not just one that derives from a string object.\n```\n\n### Consider using vector::push_back(void).\n\nEASTL provides an alternative way to insert elements into containers that avoids copy construction and/or the creation of temporaries. Consider the following code:\n\n```cpp\nvector<Widget> widgetArray;\n\n  widgetArray.push_back(Widget());\n```\n\nThe standard vector push_back function requires you to supply an object to copy from. This incurs the cost of the creation of a temporary and for some types of classes or situations this cost may be undesirable. It additionally requires that your contained class support copy-construction whereas you may not be able to support copy construction. As an alternative, EASTL provides a push_back(void) function which requires nothing to copy from but instead constructs the object in place in the container. So you can do this:\n\n```cpp\nvector<Widget> widgetArray;\n\n  widgetArray.push_back();\n\nwidgetArray.back().x = 0; // Example of how to reference the new object.\n```\n\nOther containers with such copy-less functions include:\n\n```cpp\nvector::push_back()\n\n  deque::push_back()\n\n  deque::push_front()\n\n  list::push_back()\n\n  list::push_front()\n\n  slist::push_front()\n\n  map::insert(const key_type& key)\n\n  multimap::insert(const key_type& key)\n\n  hash_map::insert(const key_type& key)\n\n  hash_multimap::insert(const key_type& key)\n```\n\nNote that the map functions above allow you to insert a default value specified by key alone and not a value_type like with the other map insert functions.\n\n----------------------------------------------\nEnd of document\n"
  },
  {
    "path": "doc/Bonus/tuple_vector_readme.md",
    "content": "## Introduction to tuple_vector\n\n`tuple_vector` is a data container that is designed to abstract and simplify\nthe handling of a \"structure of arrays\" layout of data in memory. In\nparticular, it mimics the interface of `vector`, including functionality to do\ninserts, erases, push_backs, and random-access. It also provides a\n`RandomAccessIterator` and corresponding functionality, making it compatible\nwith most STL (and STL-esque) algorithms such as ranged-for loops, `find_if`,\n`remove_if`, or `sort`.\n\nWhen used or applied properly, this container can improve performance of\nsome algorithms through cache-coherent data accesses or allowing for\nsensible SIMD programming, while keeping the structure of a single\ncontainer, to permit a developer to continue to use existing algorithms in\nSTL and the like.\n\n## Review of \"Structure of arrays\" data layouts\n\nWhen trying to improve the performance of some code, it can sometimes be\ndesirable to transform how some data is stored in memory to be laid out not as\nan \"array of structures\", but as a \"structure of arrays\". That is, instead of\nstoring a series of objects as a single contiguous chunk of memory, one or \nmore data members are instead stored as separate chunks of memory that are \nhandled and accessed in parallel to each other.\n\nThis can be beneficial in two primary respects:\n\n1) To improve the cache coherency of the data accesses, e.g. by utilizing more\ndata that is loaded per cache line loaded from memory, and thereby reducing \nthe amount of time waiting on memory accesses from off-CPU memory.\nThis presentation from Mike Acton touches on this, among other things:\nhttps://www.youtube.com/watch?v=rX0ItVEVjHc\n\n2) To allow the data to be more easily loaded and utilized by SIMD kernels, \nby being able to load memory directly into a SIMD register.\nThis is touched on in this presentation from Andreas Fredriksson for writing\ncode with SIMD intrinsics:\nhttp://www.gdcvault.com/play/1022249/SIMD-at-Insomniac-Games-How\n...and as well in this guide for writing performant ISPC kernels:\nhttps://ispc.github.io/perfguide.html\n\n## How TupleVecImpl works\n\n`tuple_vector` inherits from `TupleVecImpl`, which\nprovides the bulk of the functionality for those data containers. It manages\nthe memory allocated, marshals data members to each array of memory, generates\nthe necessary iterators, and so on. \n\nWhen a `tuple_vector` is declared, it is alongside a list of types, or \"tuple\nelements\", indicating what data to store in the container, similar to how `tuple`\noperates. `TupleVecImpl` uses this list of tuple elements to then inherit from a series of\n`TupleVecLeaf` structures, which each have their own pointer to an array of their\ncorresponding type in memory. When dereferencing the container, either to fetch a\ntuple of references or just fetching pointers to the memory, it is these pointers\nthat are utilized or fetched. \n\nWhile each `TupleVecLeaf` contains a pointer to its own block of memory, they\nare not individual memory allocations. When `TupleVecImpl` needs to grow its\ncapacity, it calculates the total size needed for a single allocation, taking\ninto account the number of objects for the container, the size of each tuple\nelement's type, and the alignment requirements for each type. Pointers into the\nallocation for each tuple element are also determined at the same time, which\nare passed to each `TupleVecLeaf`. From there, many of the interactions with\n`TupleVecImpl`, to modify or access members of the container, then reference\neach `TupleVecLeaf`'s data pointer in series, using parameter packs to repeat\neach operation for each parent `TupleVecLeaf`.\n\n## How tuple_vector's iterator works\n\n`TupleVecImpl` provides a definition to an iterator type, `TupleVecIter`.\nAs mentioned above, `TupleVecIter` provides all of the functionality to operate\nas a `RandomAccessIterator`. When it is dereferenced, it provides a tuple of\nreferences, similar to `at()` or `operator[]` on `TupleVecImpl`, as opposed to\na reference of some other type. As well, a customization of `move_iterator` for\n`TupleVecIter` is provided, which will return a tuple of rvalue-references.\n\nThe way that `TupleVecIter` operates internally is to track an index into the\ncontainer, as well as a copy of all of the `TupleVecImpl`'s `TupleVecLeaf`\npointers at the time of the iterator's construction. As a result, modifying the\niterator involves just changing the index, and dereferencing the iterator into\nthe tuple of references involves dereferencing each pointer with an offset\nspecified by that index.\n\nOf the various ways of handling the multitude of references, this tended to\nprovide the best code-generation. For example, having a tuple of pointers that\nare collectively modified with each iterator modification resulted in the compiler\nnot being able to accurately determine which pointers were relevant to the final\noutput of some function, creating many redundant operations. Similarly, having\nthe iterator refer to the source `TupleVecImpl` for the series of pointers\noften resulted in extra, unnecessary, data hops to the `TupleVecImpl` to repeatedly\nfetch data that was not practically mutable, but theoretically mutable. While this\nsolution is the heaviest in terms of storage, the resulted assembly tends to be\ncompetitive with traditional structure-of-arrays setups.\n\n## How to work with tuple_vector, and where to use it\n\t\nPut simply, `tuple_vector` can be used as a replacement for `vector`. For example,\ninstead of declaring a structure and vector as:\n\n```\nstruct Entity\n{\n\tbool active;\n\tfloat lifetime;\n\tVec3 position;\n}\nvector<Entity> entityVec;\n```\n\n...the `tuple_vector` equivalent of this can be defined as:\n\n```\ntuple_vector<bool, float, Vec3> entityVec;\n```\n\nIn terms of how `tuple_vector` is modified and accessed, it has a similar\nfeatureset as `vector`, except where `vector` would accept or return a single\nvalue, it instead accepts or returns a tuple of values or unstructured series\nof equivalent arguments.\n\nFor example, the following functions can be used to access the data, either by\nfetching a tuple of references to a series of specific values, or the data\npointers to the tuple elements:\n\n```\ntuple<bool&, float&, Vec3&> operator[](size_type)\ntuple<bool&, float&, Vec3&> at(size_type)\ntuple<bool&, float&, Vec3&> iterator::operator*()\ntuple<bool&&, float&&, Vec3&&> move_iterator::operator*()\ntuple<bool*, float*, Vec3*> data()\n\n// extract the Ith tuple element pointer from the tuple_vector\ntemplate<size_type I>\nT* get<I>()\n// e.g. bool* get<0>(), float* get<1>(), and Vec3* get<2>()\n\n// extract the tuple element pointer of type T from the tuple_vector\n// note that this function can only be used if there is one instance\n// of type T in the tuple_vector's elements\ntemplate<typename T>\nT* get<T>()\n// e.g. bool* get<bool>(), float* get<float>(), and Vec3* get<Vec3>()\n```\n\nAnd `push_back(...)` has the following overloads, accepting either values or tuples as needed.\n\n```\ntuple<bool&, float&, Vec3&> push_back()\npush_back(const bool&, const float&, const Vec3&)\npush_back(tuple<const bool&, const float&,const  Vec3&>)\npush_back(bool&&, float&&, Vec3&&)\npush_back(tuple<bool&&, float&&, Vec3&&>)\t\t\n```\n...and so on, and so forth, for others like the constructor, `insert(...)`,\n`emplace(...)`, `emplace_back(...)`, `assign(...)`, and `resize(...)`.\n\nAs well, note that the tuple types that are accepted or returned for \n`tuple_vector<Ts...>` have typedefs available in the case of not wanting to use\nautomatic type deduction:\n```\ntypedef eastl::tuple<Ts...> value_tuple;\ntypedef eastl::tuple<Ts&...> reference_tuple;\ntypedef eastl::tuple<const Ts&...> const_reference_tuple;\ntypedef eastl::tuple<Ts*...> ptr_tuple;\ntypedef eastl::tuple<const Ts*...> const_ptr_tuple;\ntypedef eastl::tuple<Ts&&...> rvalue_tuple;\n```\nWith this, and the fact that the iterator type satisfies\nthe `RandomAccessIterator` requirements, it is possible to use `tuple_vector` in\nmost ways and manners that `vector` was previously used, with few structural\ndifferences.\n\nHowever, even if not using it strictly as a replacement for `vector`, it is\nstill useful as a tool for simplifying management of a traditional structure of\narrays. That is, it is possible to use `tuple_vector` to just perform a single\nlarge memory allocation instead of a series of smaller memory allocations,\nby sizing the `tuple_vector` as needed, fetching the necessary pointers with\n`data()` or `get<...>()`, and carrying on normally.\n\nOne example where this can be utilized is with ISPC integration. Given the\nfollowing ISPC function definition:\n\n\texport void simple(uniform float vin[], uniform float vfactors[], uniform float vout[], uniform int size);\n\n...which generates the following function prototype for C/C++ usage:\n\n\textern void simple(float* vin, float* vfactors, float* vout, int32_t size);\n\t\t\n...this can be utilized with some raw float arrays:\n```\nfloat* vin = new float[NumElements];\nfloat* vfactors = new float[NumElements];\nfloat* vout = new float[NumElements];\n\n// Initialize input buffer\nfor (int i = 0; i < NumElements; ++i)\n{\n\tvin[i] = (float)i;\n\tvfactors[i] = (float)i / 2.0f;\n}\n\n// Call simple() function from simple.ispc file\nsimple(vin, vfactors, vout, NumElements);\n\ndelete vin;\ndelete vfactors;\ndelete vout;\n```\nor, with `tuple_vector`:\n\n```\ntuple_vector<float, float, float> simpleData(NumElements);\nfloat* vin = simpleData.get<0>();\nfloat* vfactors = simpleData.get<1>();\nfloat* vout = simpleData.get<2>();\n\n// Initialize input buffer\nfor (int i = 0; i < NumElements; ++i)\n{\n\tvin[i] = (float)i;\n\tvfactors[i] = (float)i / 2.0f;\n}\n\n// Call simple() function from simple.ispc file\nsimple(vin, vfactors, vout, NumElements);\n```\n\t\t\n`simpleData` here only has a single memory allocation during its construction,\ninstead of the three in the first example, and also automatically releases the\nmemory when it falls out of scope.\n\nIt is possible to also skip a memory allocation entirely, in some circumstances.\nEASTL provides \"fixed\" counterparts of many data containers which allows for a \ndata container to have an inlined buffer of memory. For example, \n`eastl::vector<typename T>` has the following counterpart:\n\n\teastl::fixed_vector<typename T, size_type nodeCount, bool enableOverflow = true>\n\nThis buffer allows for enough space to hold a `nodeCount` number of `T` objects,\nskipping any memory allocation at all, until the requested size becomes\ngreater than `nodeCount` - assuming `enableOverflow` is True.\n\nThere is a similar counterpart to `eastl::tuple_vector<typename... Ts>` available as well:\n\n\teastl::fixed_tuple_vector<size_type nodeCount, bool enableOverflow, typename... Ts>\n\nThis does the similar legwork in creating an inlined buffer, and all of the\nfunctionality of `tuple_vector` otherwise is supported. Note the slight\ndifference in declaration, though: `nodeCount` and `enableOverflow` are defined\nfirst, and `enableOverflow` is not a default parameter. This change arises out\nof restrictions surrounding variadic templates, in that they must be declared\nlast, and cannot be mixed with default template parameters.\n\nLastly, `eastl::vector` and other EASTL data containers support custom Memory Allocator\ntypes, through their template parameters. For example, `eastl::vector`'s full declaration\nis actually:\n\n\teastl::vector<typename T, typename AllocatorType = EASTLAllocatorType>\n\nHowever, because such a default template parameter cannot be used with\nvariadic templates, a separate type for `tuple_vector` is required for such a\ndefinition:\n\n\teastl::tuple_vector_alloc<typename AllocatorType, typename... Ts>\n\nNote that `tuple_vector` uses EASTLAllocatorType as the allocator.\n\n## Performance comparisons/discussion\n\nA small benchmark suite for `tuple_vector` is included when running the\nEASTLBenchmarks project. It provides the following output on a Core i7 3770k\n(Skylake) at 3.5GHz, with DDR3-1600 memory.\n\nThe `tuple_vector` benchmark cases compare total execution time of similar\nalgorithms run against `eastl::tuple_vector` and `std::vector`, such as\nerasing or inserting elements, iterating through the array to find a specific\nelement, sum all of the elements together via operator[] access, or just\nrunning `eastl::sort` on the data containers. More information about the\nEASTLBenchmarks suite can be found in EASTL/doc/EASTL Benchmarks.html\n\t\nBenchmark | STD execution time | EASTL execution time | Ratio\n--------- | -------- | ---------- | -----\n`tuple_vector<AutoRefCount>/erase       ` |   1.7 ms |   1.7 ms | 1.00 \n`tuple_vector<MovableType>/erase        ` | 104.6 ms | 106.3 ms | 0.98 \n`tuple_vector<MovableType>/reallocate   ` |   1.3 ms |   1.7 ms | 0.77  -\n |  |  | \n`tuple_vector<uint64>/erase             ` |   3.4 ms |   3.5 ms | 0.98 \n`tuple_vector<uint64>/insert            ` |   3.4 ms |   3.4 ms | 0.99 \n`tuple_vector<uint64>/iteration         ` |  56.3 us |  81.4 us | 0.69  -\n`tuple_vector<uint64>/operator[]        ` |  67.4 us |  61.8 us | 1.09 \n`tuple_vector<uint64>/push_back         ` |   1.3 ms | 818.3 us | 1.53  +\n`tuple_vector<uint64>/sort              ` |   5.8 ms |   7.3 ms | 0.80 \n |  |  | \n`tuple_vector<uint64,Padding>/erase     ` |  34.7 ms |  32.9 ms | 1.05 \n`tuple_vector<uint64,Padding>/insert    ` |  41.0 ms |  32.6 ms | 1.26 \n`tuple_vector<uint64,Padding>/iteration ` | 247.1 us |  80.5 us | 3.07  +\n`tuple_vector<uint64,Padding>/operator[]` | 695.7 us |  81.1 us | 8.58  +\n`tuple_vector<uint64,Padding>/push_back ` |  10.0 ms |   6.0 ms | 1.67  +\n`tuple_vector<uint64,Padding>/sort      ` |   8.2 ms |  10.1 ms | 0.81 \n |  |  | \n`vector<AutoRefCount>/erase             ` |   1.3 ms |   1.2 ms | 1.05 \n`vector<MovableType>/erase              ` | 104.4 ms | 109.4 ms | 0.95 \n`vector<MovableType>/reallocate         ` |   1.5 ms |   1.5 ms | 0.95 \n |  |  | \n`vector<uint64>/erase                   ` |   4.3 ms |   3.6 ms | 1.20 \n`vector<uint64>/insert                  ` |   4.8 ms |   4.8 ms | 1.01 \n`vector<uint64>/iteration               ` |  71.5 us |  77.3 us | 0.92 \n`vector<uint64>/operator[]              ` |  90.7 us |  87.2 us | 1.04 \n`vector<uint64>/push_back               ` |   1.6 ms |   1.2 ms | 1.38  +\n`vector<uint64>/sort                    ` |   7.7 ms |   8.2 ms | 0.93 \n\t\t\nFirst off, `tuple_vector<uint64>`'s performance versus `std::vector<uint64>` is\ncomparable, as expected, as the `tuple_vector`'s management for one type\nbecomes very similar to just a regular vector. The major notable exception is\nthe iteration case, which runs `eastl::find_if`. This\nperformance differences is a consequence of the iterator design, and how\nit works with indices, not a direct pointer, so the code generation suffers slightly\nin this compute-bound scenario. This is worth noting as a demonstration of a\ncase where falling back to pointer-based iteration by fetching the `begin` and\n`end` pointers of that tuple element may be preferable, instead of using the\niterator constructs.\n\nThe set of `tuple_vector<uint64,Padding>` tests are more interesting. \nThis is a comparison between a single `std::vector` with a\nstructure containing a `uint64` and 56 bytes of padding, and a `tuple_vector` with\ntwo elements: one for `uint64` and one for 56 bytes of padding. The erase,\ninsert, push_back, and sort cases all perform at a similar relative rate as\nthey did in the `tuple_vector<uint64>` tests - demonstrating that operations\nthat have to touch all of elements do not have a significant change in\nperformance.\n\nHowever, iteration and operator[] are very different, because\nthose only access the `uint64` member of both `vector` and `tuple_vector` to run\nsome operation. The iteration test now runs 3x faster whereas before it ran\n0.7x as fast, and operator[] runs 8.5x faster, instead of 1.1x. This\ndemonstrates some of the utility of `tuple_vector`, in that these algorithms end\nup being limited by the CPU's compute capabilities, as opposed to being\nlimited by how fast they can load memory in from DRAM. \n\t\t\nIn a series of other tests, generally speaking, `tuple_vector` tends to perform\non par with manual management of multiple arrays in many algorithms and\noperations, often even generating the same code. It should be noted that\nsignificant degrees of inlining and optimization are required to get the most out\nof `tuple_vector`. Compared to accessing a series of arrays or vectors,\n`tuple_vector` does perform a multitude of extra trivial function calls internally\nin order to manage the various elements, or interact with `eastl::tuple` through\nits interface, so running in debug configurations can run significantly slower\nin some cases, e.g. sometimes running at 0.2x the speed compared to vector.\n\t\t\n## The problem of referencing tuple elements\n\nThis will be experienced shortly after using `tuple_vector` in most capacities,\nbut it should be noted that the most significant drawback is that there is no\nway to **symbolically** reference each tuple element of the `tuple_vector` - much\nin the same way as `tuple`. For example, if translating a struct such as...\n\n```\nstruct Entity\n{\n\tfloat x, y, z;\n\tfloat lifetime;\n};\n```\n...to `tuple_vector`, it will exist as:\n\n```\ntuple_vector<float, float, float, float> entityVec;\n```\n\n...and can only be accessed in a manner like `entityVec.get<3>()` to refer to\nthe `lifetime` member. With existing tools, the only good alternatives are to\nencapsulate each float as a separate struct to give it unique typenames...\n\n```\nstruct entityX { float val; };\nstruct entityY { float val; };\nstruct entityZ { float val; };\nstruct entityLifetime { float val; };\n\ntuple_vector<entityX, entityY, entityZ, entityLifetime> entityVec;\n```\n...and then access each tuple element by typename like\n`entityVec.get<entityLifetime>()`; or, creating an enumerated value to replace\nthe indices...\n\n```\nenum EntityTypeEnum\n{\n\tentityX = 0,\n\tentityY = 1,\n\tentityZ = 2,\n\tentityLifetime = 3\n};\n\ntuple_vector<float, float, float, float> entityVec;\n```\n\n...and then access each tuple element by the enumerated value:\n`entityVec.get<entityLifetime>()`.\n\nEither way, there is a fairly significant maintenance and readability issue\naround this. This is arguably more severe than with `tuple` on its own\nbecause that is generally not intended for structures with long lifetime.\n\nIdeally, if the language could be mutated to accommodate such a thing, it would\nbe good to have some combination of typenames and symbolic names in the\ndeclaration, e.g. something like\n\n```\ntuple_vector<float x, float y, float z, float lifetime> entityVec;\n```\nand be able to reference the tuple elements not just by typename or index, but\nthrough their corresponding symbol, like `entityVec.get<lifetime>()`. Or, it may\nbe interesting if the necessary `get` functions could be even automatically\ngenerated through a reflection system, e.g. `entityVec.get_lifetime()`.\nAll of this remains a pipe dream for now.\n"
  },
  {
    "path": "doc/CMake/EASTL_Project_Integration.md",
    "content": "## Using EASTL in your own projects\n\nThis page describes the steps needed to use EASTL in your own projects\n\n## Setting up your project\n\n### Using CMake\n\nAdd to your CMakeLists.txt:\n\n```cmake\nset(EASTL_ROOT_DIR C:/EASTL)\ninclude_directories (${EASTL_ROOT_DIR}/include)\ninclude_directories (${EASTL_ROOT_DIR}/test/packages/EAAssert/include)\ninclude_directories (${EASTL_ROOT_DIR}/test/packages/EABase/include/Common)\ninclude_directories (${EASTL_ROOT_DIR}/test/packages/EAMain/include)\ninclude_directories (${EASTL_ROOT_DIR}/test/packages/EAStdC/include)\ninclude_directories (${EASTL_ROOT_DIR}/test/packages/EATest/include)\ninclude_directories (${EASTL_ROOT_DIR}/test/packages/EAThread/include)\nset(EASTL_LIBRARY debug ${EASTL_ROOT_DIR}/build/Debug/EASTL.lib optimized ${EASTL_ROOT_DIR}/build/Release/EASTL.lib)\nadd_custom_target(NatVis SOURCES ${EASTL_ROOT_DIR}/doc/EASTL.natvis)\n```\n\nAnd then add the library into the linker \n\n```\ntarget_link_libraries(... ${EASTL_LIBRARY})\n```\n\n### Using Visual Studio\n\nUsing Visual Studio projecs directly you will need do the following steps:\n- Add the include paths\n- Add the library path\n- Add the library dependency\n- Add natvis (optional)\n\n> Note that in the examples below ${EASTL_ROOT_DIR} is the folder in which you stored EASTL. You could create an environment variable for this.\n\n#### Add the include paths\n\nAdd the following paths to your C/C++ -> General -> Additional include directories:\n```\n${EASTL_ROOT_DIR}/include\n${EASTL_ROOT_DIR}/test/packages/EAAssert/include\n${EASTL_ROOT_DIR}/test/packages/EABase/include/Common\n${EASTL_ROOT_DIR}/test/packages/EAMain/include)\n${EASTL_ROOT_DIR}/test/packages/EAStdC/include)\n${EASTL_ROOT_DIR}/test/packages/EATest/include)\n${EASTL_ROOT_DIR}/test/packages/EAThread/include)\n```\n\n#### Add the library path\n\nAdd the following library path to your Linker -> General -> Additional Library Directories:\n```\n${EASTL_ROOT_DIR}/build/$(Configuration)\n```\n\n#### Add the library dependency\n\nEither add the following library to your Linker -> Input -> Additional Dependencies\n```\nEASTL.lib\n```\nOr in code use the following:\n```\n#pragma comment(lib, \"EASTL.lib\")\n```\n\n#### Add natvis (optional)\n\n> Adding the natvis file to your project allows the debugger to use custom visualizers for the eastl data types. This greatly enhances the debugging experience.\n\nAdd the natvis file anywhere in your solution:\n\n```\nRight-click your project: Add -> Existing item and then add the following file:\n${EASTL_ROOT_DIR}/doc/EASTL.natvis\n```\n\n## Setting up your code\n\n### Overloading operator new[]\n\nEASTL requires you to have an overload for the operator new[], here is an example that just forwards to global new[]:\n\n```c\nvoid* __cdecl operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line)\n{\n\treturn new uint8_t[size];\n}\n```\n"
  },
  {
    "path": "doc/Design.md",
    "content": "# EASTL Design\n\n## Introduction\n\nEASTL (EA Standard Template Library) is designed to be a template library which encompasses and extends the functionality of standard C++ STL while improving it in various ways useful to game development. Much of EASTL's design is identical to standard STL, as the large majority of the STL is well-designed for many uses. The primary areas where EASTL deviates from standard STL implementations are essentially the following:\n\n*   EASTL has a simplified and more flexible custom allocation scheme.\n*   EASTL has significantly easier to read code.\n*   EASTL has extension containers and algorithms.\n*   EASTL has optimizations designed for game development.\n\nOf the above items, the only one which is an incompatible difference with STL is the case of memory allocation. The method for defining a custom allocator for EASTL is slightly different than that of standard STL, though they are 90% similar. The 10% difference, however, is what makes EASTL generally easier and more powerful to work with than standard STL. Containers without custom allocators act identically between EASTL and standard STL.\n\n## Motivations\n\nOur motifications for making EASTL drive the design of EASTL. As identified in the EASTL RFC (Request for Comment), the primary reasons for implementing a custom version of the STL are:\n\n*   <span class=\"458151900-03082005\"><font><font>Some STL implementations (especially Microsoft STL) have inferior performance characteristics that make them unsuitable for game development. EASTL is faster than all existing STL implementations.</font></font></span>\n*   The STL is sometimes hard to debug, as most STL implementations use cryptic variable names and unusual data structures.\n*   STL allocators are sometimes painful to work with, as they have many requirements and cannot be modified once bound to a container.\n*   The STL includes excess functionality that can lead to larger code than desirable. It's not very easy to tell programmers they shouldn't use that functionality.\n*   The STL is implemented with very deep function calls. This results is unacceptable performance in non-optimized builds and sometimes in optimized builds as well.\n*   The STL doesn't support alignment of contained objects.\n*   STL containers won't let you insert an entry into a container without supplying an entry to copy from. This can be inefficient.\n*   Useful STL extensions (e.g. slist, hash_map, shared_ptr) found in existing STL implementations such as STLPort are not portable because they don't exist in other versions of STL or aren't consistent between STL versions.  \n\n*   The STL lacks useful extensions that game programmers find useful (e.g. intrusive_list) but which could be best optimized in a portable STL environment.\n*   The STL has specifications that limit our ability to use it efficiently. For example, STL vectors are not guaranteed to use contiguous memory and so cannot be safely used as an array.\n*   The STL puts an emphasis on correctness before performance, whereas sometimes you can get significant performance gains by making things less academcially pure.\n*   STL containers have private implementations that don't allow you to work with their data in a portable way, yet sometimes this is an important thing to be able to do (e.g. node pools).\n*   All existing versions of STL allocate memory in empty versions of at least some of their containers. This is not ideal and prevents optimizations such as container memory resets that can greatly increase performance in some situations.\n*   The STL is slow to compile, as most modern STL implementations are very large.  \n\n*   There are legal issues that make it hard for us to freely use portable STL implementations such as STLPort.\n*   We have no say in the design and implementation of the STL and so are unable to change it to work for our needs.\n\n## Prime Directives\n\nThe implementation of EASTL is guided foremost by the following directives which are listed in order of importance.\n\n1.  Efficiency (speed and memory usage)\n2.  Correctness\n3.  Portability\n4.  Readability\n\nNote that unlike commercial STL implementations which must put correctness above all, we put a higher value on efficiency. As a result, some functionality may have some usage limitation that is not present in other similar systems but which allows for more efficient operation, especially on the platforms of significance to us.\n\nPortability is significant, but not critical. Yes, EASTL must compile and run on all platforms that we will ship games for. But we don't take that to mean under all compilers that could be conceivably used for such platforms. For example, Microsoft VC6 can be used to compile Windows programs, but VC6's C++ support is too weak for EASTL and so you simply cannot use EASTL under VC6.\n\nReadability is something that EASTL achieves better than many other templated libraries, particularly Microsoft STL and STLPort. We make every attempt to make EASTL code clean and sensible. Sometimes our need to provide optimizations (particularly related to type_traits and iterator types) results in less simple code, but efficiency happens to be our prime directive and so it overrides all other considerations.\n\n## Thread Safety\n\nIt's not simple enough to simply say that EASTL is thread-safe or thread-unsafe. However, we can say that with respect to thread safety that EASTL does the right thing.\n\nIndividual EASTL containers are not thread-safe. That is, access to an instance of a container from multiple threads at the same time is unsafe if any of those accesses are modifying operations. A given container can be read from multiple threads simultaneously as well as any other standalone data structure. If a user wants to be able to have modifying access an instance of a container from multiple threads, it is up to the user to ensure that proper thread synchronization occurs. This usually means using a mutex.\n\nEASTL classes other than containers are the same as containers with respect to thread safety. EASTL functions (e.g. algorithms) are inherently thread-safe as they have no instance data and operate entirely on the stack. As of this writing, no EASTL function allocates memory and thus doesn't bring thread safety issues via that means.\n\nThe user may well need to be concerned about thread safety with respect to memory allocation. If the user modifies containers from multiple threads, then allocators are going to be accessed from multiple threads. If an allocator is shared across multiple container instances (of the same type of container or not), then mutexes (as discussed above) the user uses to protect access to indivudual instances will not suffice to provide thread safety for allocators used across multiple instances. The conventional solution here is to use a mutex within the allocator if it is exected to be used by multiple threads.\n\nEASTL uses neither static nor global variables and thus there are no inter-instance dependencies that would make thread safety difficult for the user to implement.\n\n## Container Design\n\nAll EASTL containers follow a set of consistent conventions. Here we define the prototypical container which has the minimal functionality that all (non-adapter) containers must have. Some containers (e.g. stack) are explicitly adapter containers and thus wrap or inherit the properties of the wrapped container in a way that is implementation specific.  \n\n```cpp\ntemplate <class T, class Allocator =\nEASTLAllocator>\n\nclass container\n\n{\n\npublic:\n\n    typedef container<T, Allocator>            this_type;\n\n    typedef\nT                     \n            value_type;\n\n    typedef T*                   \n             pointer;\n\n    typedef const T*                       \n   const_pointer;\n\n    typedef\nT&                                 reference;\n\n\n    typedef const\nT&                           const_reference;\n\n\n    typedef\nptrdiff_t                          difference_type;\n\n\n    typedef\nimpl_defined                       size_type;\n\n\n    typedef impl-defined                  \n    iterator;\n\n    typedef impl-defined                  \n    const_iterator;\n\n    typedef reverse_iterator<iterator>         reverse_iterator;\n\n    typedef reverse_iterator<const_iterator>   reverse_const_iterator;\n\n    typedef Allocator                 \n        allocator_type;\n\n\n\npublic:\n\n    container(const\nallocator_type& allocator = allocator_type());\n\n    container(const this_type&\nx);\n\n\n\n    this_type&\noperator=(this_type& x);\n\n    void swap(this_type& x);\n\n    void reset();\n\n\n\n    allocator_type& get_allocator();\n\n    void            set_allocator(allocator_type& allocator);\n\n\n\n    iterator       begin();\n\n    const_iterator begin() const;\n\n    iterator       end();\n\n    const_iterator end() const;\n\n\n\n    bool validate() const;\n     int  validate_iterator(const_iterator i)\nconst;\n\n\nprotected:\n\n    allocator_type mAllocator;\n\n};\n\n\n\ntemplate <class T, class\nAllocator>\n\nbool operator==(const container<T, Allocator>& a, const container<T, Allocator>& b);\n\n\n\ntemplate <class T, class\nAllocator>\n\nbool operator!=(const container<T, Allocator>& a, const\ncontainer<T, Allocator>&\nb);\n```\n\nNotes:\n\n*   Swapped containers do not swap their allocators.\n*   Newly constructed empty containers do no memory allocation. Some STL and other container libraries allocate an initial node from the class memory allocator. EASTL containers by design never do this. If a container needs an initial node, that node should be made part of the container itself or be a static empty node object.\n*   Empty containers (new or otherwise) contain no constructed objects, including those that might be in an 'end' node. Similarly, no user object (e.g. of type T) should be constructed unless required by the design and unless documented in the cotainer/algorithm contract. \n*   The reset function is a special extension function which unilaterally resets the container to an empty state without freeing the memory of the contained objects. This is useful for very quickly tearing down a container built into scratch memory. No memory is allocated by reset, and the container has no allocatedmemory after the reset is executed.\n*   The validate and validate_iterator functions provide explicit container and iterator validation. EASTL provides an option to do implicit automatic iterator and container validation, but full validation (which can be potentially extensive) has too much of a performance cost to execute implicitly, even in a debug build. So EASTL provides these explicit functions which can be called by the user at the appropriate time and in optimized builds as well as debug builds.\n\n## Allocator Design\n\nThe most significant difference between EASTL and standard C++ STL is that standard STL containers are templated on an allocator class with the interface defined in std::allocator. std::allocator is defined in the C++ standard as this:  \n\n```cpp\n// Standard C++ allocator\n\n\n\n  template <class T>\n\nclass allocator\n\n{\n\npublic:\n\n    typedef size_t    size_type;\n\n    typedef ptrdiff_t difference_type;\n\n    typedef T*        pointer;\n\n    typedef const T*  const_pointer;\n\n    typedef T&      \n reference;\n\n    typedef const\nT&  const_reference;\n\n    typedef T         value_type;\n\n\n\n    template <class U>\n\n    struct rebind { typedef allocator<U> other; };\n\n\n\n    allocator() throw();\n\n    allocator(const allocator&) throw();\n\n    template <class U>\n\n    allocator(const allocator<U>&) throw();\n\n\n\n    ~allocator()\nthrow();\n\n\n\n     pointer  \n    address(reference x) const;\n\n    const_pointer address(const_reference x)\nconst;\n\n    pointer       allocate(size_type, typename\nallocator<void>::const_pointer hint = 0);\n\n    void          deallocate(pointer p,\nsize_type n);\n\n    size_type     max_size() const\nthrow();\n\n    void          construct(pointer p,\nconst T& val);\n\n    void          destroy(pointer\np);\n\n};\n```\n\nEach STL container needs to have an allocator templated on container type T associated with it. The problem with this is that allocators for containers are defined at the class level and not the instance level. This makes it painful to define custom allocators for containers and adds to code bloat. Also, it turns out that the containers don't actually use allocator<T> but instead use allocator\\<T>::rebind\\<U>::other. Lastly, you cannot access this allocator after the container is constructed. There are some good academic reasons why the C++ standard works this way, but it results in a lot of unnecessary pain and makes concepts like memory tracking much harder to implement.\n\nWhat EASTL does is use a more familiar memory allocation pattern whereby there is only one allocator class interface and it is used by all containers. Additionally EASTL containers let you access their allocators and query them, name them, change them, etc.\n\nEASTL has chosen to make allocators not be copied between containers during container swap and assign operations. This means that if container A swaps its contents with container B, both containers retain their original allocators. Similarly, assigning container A to container B causes container B to retain its original allocator. Containers that are equivalent should report so via operator==; EASTL will do a smart swap if allocators are equal, and a brute-force swap otherwise.  \n\n```cpp\n// EASTL allocator  \n\nclass allocator  \n{  \npublic:  \n    allocator(const char* pName = NULL);  \n\n    void* allocate(size_t n, int flags = 0);  \n    void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);  \n    void  deallocate(void* p, size_t n);  \n\n    const char* get_name() const;  \n    void        set_name(const char* pName);  \n};  \n\nallocator* GetDefaultAllocator();\n```\n\n## Fixed Size Container Design\n\nEASTL supplies a set of fixed-size containers that the user can use, though the user can also implement their own versions. So in addition to class list there is class fixed_list. The fixed_list class implements a linked list via a fixed-size pool of contiguous memory which has no space overhead (unlike with a regular heap), doesn't cause fragmentation, and allocates very quickly.\n\nEASTL implements fixed containers via subclasses of regular containers which set the regular container's allocator to point to themselves. Thus the implementation for fixed_list is very tiny and consists of little more than constructor and allocator functions. This design has some advantages but has one small disadvantage. The primary advantages are primarily that code bloat is reduced and that the implementation is simple and the user can easily extend it. The primary disadvantage is that the parent list class ends up with a pointer to itself and thus has 4 bytes that could arguably be saved if system was designed differently. That different design would be to make the list class have a policy template parameter which specifies that it is a fixed pool container. EASTL chose not to follow the policy design because it would complicate the implementation, make it harder for the user to extend the container, and would potentially waste more memory due to code bloat than it would save due to the 4 byte savings it achieves in container instances.\n\n## Algorithm Design\n\nEASTL algorithms very much follow the philosophy of standard C++ algorithms, as this philosophy is sound and efficient. One of the primary aspects of algorithms is that they work on iterators and not containers. You will note for example that the find algorithm takes a first and last iterator as arguments and not a container. This has two primary benefits: it allows the user to specify a subrange of the container to search within and it allows the user to apply the find algorithm to sequences that aren't containers (e.g. a C array).\n\nEASTL algorithms are optimized at least as well as the best STL algorithms found in commercial libraries and are significantly optimized over the algorithms that come with the first-party STLs that come with compilers. Most significantly, EASTL algorithms take advantage of type traits of contained classes and take advantage of iterator types to optimize code generation. For example, if you resize an array of integers (or other \"pod\" type), EASTL will detect that this can be done with a memcpy instead of a slow object-by-object move as would Micrsoft STL.\n\nThe optimizations found in EASTL algorithms and the supporting code in EASTL type traits consistts of some fairly tricky advanced C++ and while it is fairly easy to read, it requires a C++ expert (language lawyer, really) to implement confidently. The result of this is that it takes more effort to develop and maintain EASTL than it would to maintain a simpler library. However, the performance advantages have been deemed worth the tradeoff.\n\n## Smart Pointer Design\n\nEASTL implements the following smart pointer types:\n\n*   shared_ptr\n*   shared_array\n*   weak_ptr\n*   instrusive_ptr\n*   scoped_ptr\n*   scoped_array\n*   linked_ptr\n*   linked_array\n\nAll but linked_ptr/linked_array are well-known smart pointers from the Boost library. The behaviour of these smart pointers is very similar to those from Boost with two exceptions:\n\n*   EASTL smart pointers allow you to assign an allocator to them.\n*   EASTL shared_ptr implements deletion via a templated parameter instead of a dynamically allocated virtual member object interface.\n\nWith respect to assigning an allocator, this gives EASTL more control over memory allocation and tracking, as Boost smart pointers unilaterally use global operator new to allocate memory from the global heap.\n\nWith respect to shared_ptr deletion, EASTL's current design of using a templated parameter is questionable, but does have some reason. The advantage is that EASTL avoids a heap allocation, avoids virtual function calls, and avoids templated class proliferation. The disadvantage is that EASTL shared_ptr containers which hold void pointers can't call the destructors of their contained objects unless the user manually specifies a custom deleter template parameter. This is case whereby EASTL is more efficient but less safe. We can revisit this topic in the future if it becomes an issue.\n\n## list::size is O(n)\n\nAs of this writing, EASTL has three linked list classes: list, slist, and intrusive_list. In each of these classes, the size of the list is not cached in a member size variable. The result of this is that getting the size of a list is not a fast operation, as it requires traversing the list and counting the nodes. We could make the list::size function be fast by having a member mSize variable which tracks the size as we insert and delete items. There are reasons for having such functionality and reasons for not having such functionality. We currently choose to not have a member mSize variable as it would add four bytes to the class, add a tiny amount of processing to functions such as insert and erase, and would only serve to improve the size function, but no others. In the case of intrusive_list, it would do additional harm. The alternative argument is that the C++ standard states that std::list should be an O(1) operation (i.e. have a member size variable), that many C++ standard library list implementations do so, that the size is but an integer which is quick to update, and that many users expect to have a fast size function. In the final analysis, we are developing a library for game development and performance is paramount, so we choose to not cache the list size. The user can always implement a size cache himself.\n\n## basic_string doesn't use copy-on-write\n\nThe primary benefit of CoW is that it allows for the sharing of string data between two string objects. Thus if you say this:\n\n```cpp\nstring a(\"hello\");  \nstring b(a);\n```\n\nthe \"hello\" will be shared between a and b. If you then say this:\n\n```cpp\na = \"world\";\n```\n\nthen `a` will release its reference to \"hello\" and leave b with the only reference to it. Normally this functionality is accomplished via reference counting and with atomic operations or mutexes.\n\nThe C++ standard does not say anything about basic_string and CoW. However, for a basic_string implementation to be standards-conforming, a number of issues arise which dictate some things about how one would have to implement a CoW string. The discussion of these issues will not be rehashed here, as you can read the references below for better detail than can be provided in the space we have here. However, we can say that the C++ standard is sensible and that anything we try to do here to allow for an efficient CoW implementation would result in a generally unacceptable string interface.\n\nThe disadvantages of CoW strings are:\n\n*   A reference count needs to exist with the string, which increases string memory usage.\n*   With thread safety, atomic operations and mutex locks are expensive, especially on weaker memory systems such as console gaming platforms.\n*   All non-const string accessor functions need to do a sharing check the the first such check needs to detach the string. Similarly, all string assignments need to do a sharing check as well. If you access the string before doing an assignment, the assignment doesn't result in a shared string, because the string has already been detached.\n*   String sharing doesn't happen the large majority of the time. In some cases, the total sum of the reference count memory can exceed any memory savings gained by the strings that share representations. \n\nThe addition of a cow_string class is under consideration for EASTL. There are conceivably some systems which have string usage patterns which would benefit from CoW sharing. Such functionality is best saved for a separate string implementation so that the other string uses aren't penalized.\n\nThis is a good starting HTML reference on the topic:\n\n> [http://www.gotw.ca/publications/optimizations.htm](http://www.gotw.ca/publications/optimizations.htm)\n\nHere is a well-known Usenet discussion on the topic:\n\n> [http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d](http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d)\n\n----------------------------------------------\nEnd of document\n"
  },
  {
    "path": "doc/EASTL.natvis",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!-- \n     This is a Microsoft natvis file, which allows visualization of complex variables in the\n     Microsoft debugger starting with VS2012. It's a successor to the AutoExp.dat file format. \n\n     This file needs to go into your C:\\Users\\<user>\\Documents\\Visual Studio 2011\\Visualizers\\\n     folder. Microsoft documentation states that it should go into a 2012 folder, but testing \n     in June of 2013 suggests that it still needs to be the 2011 folder.\n\n     You don't need to restart Visual Studio to use it, you just need to restart the debug \n     session. You can have multiple .natvis files and they will all be used.\n\n\t VS2017 natvis documentation:\n\thttps://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects\n-->\n\n<AutoVisualizer xmlns=\"http://schemas.microsoft.com/vstudio/debugger/natvis/2010\">\n\n<Type Name=\"eastl::unique_ptr&lt;*&gt;\">\n\t<DisplayString Condition=\"mPair.mFirst != nullptr\">({(void*)mPair.mFirst} = {*mPair.mFirst})</DisplayString>\n\t<DisplayString Condition=\"mPair.mFirst == nullptr\">({nullptr})</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"[pointer]\">(void*)mPair.mFirst</Item>\n\t\t<Item Name=\"[value]\">*mPair.mFirst</Item>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::shared_ptr&lt;*&gt;\">\n\t<DisplayString Condition=\"mpValue != nullptr\">({(void*)mpValue} = {*mpValue})</DisplayString>\n\t<DisplayString Condition=\"mpValue == nullptr\">({nullptr})</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"[pointer]\">(void*)mpValue</Item>\n\t\t<Item Name=\"[value]\">*mpValue</Item>\n\t\t<Item Name=\"[reference count]\">mpRefCount->mRefCount</Item>\n\t\t<Item Name=\"[weak reference count]\">mpRefCount->mWeakRefCount</Item>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::weak_ptr&lt;*&gt;\">\n\t<DisplayString>{((mpRefCount &amp;&amp; mpRefCount-&gt;mRefCount) ? mpValue : nullptr)}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>mpRefCount &amp;&amp; mpRefCount-&gt;mRefCount ? mpValue : nullptr</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::array&lt;*,*&gt;\">\n\t<DisplayString Condition=\"$T2 == 0\">[{$T2}] {{}}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 1\">[{$T2}] {{ {*mValue} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 2\">[{$T2}] {{ {*mValue}, {*(mValue+1)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 3\">[{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 4\">[{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 5\">[{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)}, {*(mValue+4)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 6\">[{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)}, {*(mValue+4)}, {*(mValue+5)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 &gt; 6\">[{$T2}] {{ {*mValue}, {*(mValue+1)}, {*(mValue+2)}, {*(mValue+3)}, {*(mValue+4)}, {*(mValue+5)}, ... }}</DisplayString>\n\t<Expand>\n        <Item Name=\"[size]\">$T2</Item>\n        <ArrayItems>\n            <Size>$T2</Size>\n            <ValuePointer>mValue</ValuePointer>\n        </ArrayItems>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::basic_string&lt;*&gt;\">\n\t<DisplayString Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">\"{mPair.mFirst.heap.mpBegin,sb}\"</DisplayString>\n\t<DisplayString Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">\"{mPair.mFirst.sso.mData,sb}\"</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"[length]\"   Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">mPair.mFirst.heap.mnSize</Item>\n\t\t<Item Name=\"[capacity]\" Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">(mPair.mFirst.heap.mnCapacity &amp; ~kHeapMask)</Item>\n\t\t<Item Name=\"[value]\"    Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">mPair.mFirst.heap.mpBegin,sb</Item>\n\n\t\t<Item Name=\"[length]\"   Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">(SSOLayout::SSO_CAPACITY - mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize)</Item>\n\t\t<Item Name=\"[capacity]\" Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">SSOLayout::SSO_CAPACITY</Item>\n\t\t<Item Name=\"[value]\"    Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">mPair.mFirst.sso.mData,sb</Item>\n\n\t\t<Item Name=\"[uses heap]\">!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)</Item>\n\t</Expand>\n</Type>\n\n  \n<Type Name=\"eastl::basic_string&lt;wchar_t,*&gt;\">\n\t<DisplayString Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">{mPair.mFirst.heap.mpBegin,su}</DisplayString>\n\t<DisplayString Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">{mPair.mFirst.sso.mData,su}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"[length]\"   Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">mPair.mFirst.heap.mnSize</Item>\n\t\t<Item Name=\"[capacity]\" Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">(mPair.mFirst.heap.mnCapacity &amp; ~kHeapMask)</Item>\n\t\t<Item Name=\"[value]\"    Condition=\"!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">mPair.mFirst.heap.mpBegin,su</Item>\n\n\t\t<Item Name=\"[length]\"   Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">(SSOLayout::SSO_CAPACITY - mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize)</Item>\n\t\t<Item Name=\"[capacity]\" Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">SSOLayout::SSO_CAPACITY</Item>\n\t\t<Item Name=\"[value]\"    Condition=\"!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)\">mPair.mFirst.sso.mData,su</Item>\n\n\t\t<Item Name=\"[uses heap]\">!!(mPair.mFirst.sso.mRemainingSizeField.mnRemainingSize &amp; kSSOMask)</Item>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::pair&lt;*&gt;\">\n\t<DisplayString>({first}, {second})</DisplayString>\n    <Expand>\n        <Item Name=\"first\">first</Item>\n        <Item Name=\"second\">second</Item>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::span&lt;*,-1&gt;\" Priority=\"High\">\n\t<DisplayString Condition=\"mStorage.mnSize == 0\">[{mStorage.mnSize}] {{}}</DisplayString>\n\t<DisplayString Condition=\"mStorage.mnSize == 1\">[{mStorage.mnSize}] {{ {*mStorage.mpData} }}</DisplayString>\n\t<DisplayString Condition=\"mStorage.mnSize == 2\">[{mStorage.mnSize}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)} }}</DisplayString>\n\t<DisplayString Condition=\"mStorage.mnSize == 3\">[{mStorage.mnSize}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)} }}</DisplayString>\n\t<DisplayString Condition=\"mStorage.mnSize == 4\">[{mStorage.mnSize}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)} }}</DisplayString>\n\t<DisplayString Condition=\"mStorage.mnSize == 5\">[{mStorage.mnSize}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)}, {*(mStorage.mpData+4)} }}</DisplayString>\n\t<DisplayString Condition=\"mStorage.mnSize == 6\">[{mStorage.mnSize}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)}, {*(mStorage.mpData+4)}, {*(mStorage.mpData+5)} }}</DisplayString>\n\t<DisplayString Condition=\"mStorage.mnSize &gt; 6\">[{mStorage.mnSize}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)}, {*(mStorage.mpData+4)}, {*(mStorage.mpData+5)}, ... }}</DisplayString>\n\t<Expand>\n\t\t<Synthetic Name=\"Specialization\">\n\t\t\t<DisplayString>DynamicSize</DisplayString>\n\t\t</Synthetic>\n\t\t<Item Name=\"[size]\">mStorage.mnSize</Item>\n\t\t<ArrayItems>\n\t\t\t<Size>mStorage.mnSize</Size>\n\t\t\t<ValuePointer>mStorage.mpData</ValuePointer>\n\t\t</ArrayItems>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::span&lt;*,*&gt;\">\n\t<DisplayString Condition=\"$T2 == 0\">[{$T2}] {{}}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 1\">[{$T2}] {{ {*mStorage.mpData} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 2\">[{$T2}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 3\">[{$T2}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 4\">[{$T2}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 5\">[{$T2}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)}, {*(mStorage.mpData+4)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 == 6\">[{$T2}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)}, {*(mStorage.mpData+4)}, {*(mStorage.mpData+5)} }}</DisplayString>\n\t<DisplayString Condition=\"$T2 &gt; 6\">[{$T2}] {{ {*mStorage.mpData}, {*(mStorage.mpData+1)}, {*(mStorage.mpData+2)}, {*(mStorage.mpData+3)}, {*(mStorage.mpData+4)}, {*(mStorage.mpData+5)}, ... }}</DisplayString>\n\t<Expand>\n\t\t<Synthetic Name=\"Specialization\">\n\t\t\t<DisplayString>ConstantSize</DisplayString>\n\t\t</Synthetic>\n\t\t<Item Name=\"[size]\">$T2</Item>\n\t\t<ArrayItems>\n\t\t\t<Size>$T2</Size>\n\t\t\t<ValuePointer>mStorage.mpData</ValuePointer>\n\t\t</ArrayItems>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::VectorBase&lt;*&gt;\">\n\t<DisplayString Condition=\"mpEnd == mpBegin\">[{mpEnd - mpBegin}] {{}}</DisplayString>\n\t<DisplayString Condition=\"mpEnd - mpBegin == 1\">[{mpEnd - mpBegin}] {{ {*mpBegin} }}</DisplayString>\n\t<DisplayString Condition=\"mpEnd - mpBegin == 2\">[{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)} }}</DisplayString>\n\t<DisplayString Condition=\"mpEnd - mpBegin == 3\">[{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)} }}</DisplayString>\n\t<DisplayString Condition=\"mpEnd - mpBegin == 4\">[{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)} }}</DisplayString>\n\t<DisplayString Condition=\"mpEnd - mpBegin == 5\">[{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)}, {*(mpBegin+4)} }}</DisplayString>\n\t<DisplayString Condition=\"mpEnd - mpBegin == 6\">[{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)}, {*(mpBegin+4)}, {*(mpBegin+5)} }}</DisplayString>\n\t<DisplayString Condition=\"mpEnd - mpBegin &gt; 6\">[{mpEnd - mpBegin}] {{ {*mpBegin}, {*(mpBegin+1)}, {*(mpBegin+2)}, {*(mpBegin+3)}, {*(mpBegin+4)}, {*(mpBegin+5)}, ... }}</DisplayString>\n    <Expand>\n        <Item Name=\"[size]\">mpEnd - mpBegin</Item>\n        <Item Name=\"[capacity]\">mCapacityAllocator.mFirst - mpBegin</Item>\n        <ArrayItems>\n            <Size>mpEnd - mpBegin</Size>\n            <ValuePointer>mpBegin</ValuePointer>\n        </ArrayItems>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::DequeBase&lt;*,*,*&gt;\">\n\t<DisplayString Condition=\"mItBegin.mpCurrent == mItEnd.mpCurrent\">\n\t\t[0] {{}}\n\t</DisplayString>\n\t<DisplayString Condition=\"(mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin) == 1\">\n\t\t[1] {{ {*mItBegin.mpCurrent} }}\n\t</DisplayString>\n\t<DisplayString Condition=\"(mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin) != 0\">\n\t\t[{(mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin)}] \n\t\t{{ \n\t\t\t{*mItBegin.mpCurrent}, \n\t\t\t... \n\t\t}}\n\t</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"[size]\">(mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin)</Item>\n\t\t<IndexListItems>\n            <Size>(mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) * $T3 + (mItEnd.mpCurrent-mItEnd.mpBegin) - (mItBegin.mpCurrent-mItBegin.mpBegin)</Size>\n            <ValueNode>mItBegin.mpCurrentArrayPtr[(mItBegin.mpCurrent-mItBegin.mpBegin + $i) / $T3][(mItBegin.mpCurrent-mItBegin.mpBegin + $i) % $T3]</ValueNode>\n        </IndexListItems>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::DequeIterator&lt;*&gt;\">\n\t<DisplayString>{*mpCurrent}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"Value\">*mpCurrent</Item>\n\t\t<Item Name=\"Previous\" Condition=\"mpCurrent == mpBegin\">*(*(mpCurrentArrayPtr-1) + (mpEnd-mpBegin) - 1)</Item>\n\t\t<Item Name=\"Previous\" Condition=\"mpCurrent != mpBegin\">*(mpCurrent-1)</Item>\n\t\t<Item Name=\"Next\" Condition=\"mpCurrent+1 == mpEnd\">**(mpCurrentArrayPtr+1)</Item>\n\t\t<Item Name=\"Next\" Condition=\"mpCurrent+1 != mpEnd\">*(mpCurrent+1)</Item>\n\t\t<Item Name=\"Begin\">mpCurrent == mpBegin</Item>\n\t\t<Item Name=\"End\">mpCurrent+1 == mpEnd</Item>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::queue&lt;*&gt;\">\n\t<AlternativeType Name=\"eastl::priority_queue&lt;*&gt;\" />\n\t<AlternativeType Name=\"eastl::stack&lt;*&gt;\" />\n\t<DisplayString>{c}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>c</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::ListBase&lt;*&gt;\">\n\t<DisplayString Condition=\"mNodeAllocator.mFirst.mpNext == &amp;mNodeAllocator.mFirst\">\n\t\t[0] {{}}\n\t</DisplayString>\n    <DisplayString Condition=\"mNodeAllocator.mFirst.mpNext != &amp;mNodeAllocator.mFirst &amp;&amp; mNodeAllocator.mFirst.mpNext-&gt;mpNext == &amp;mNodeAllocator.mFirst\">\n\t\t[1] {{ {((eastl::ListNode&lt;$T1&gt;*)mNodeAllocator.mFirst.mpNext)-&gt;mValue} }}\n\t</DisplayString>\n\t<DisplayString Condition=\"mNodeAllocator.mFirst.mpNext != &amp;mNodeAllocator.mFirst &amp;&amp; mNodeAllocator.mFirst.mpNext-&gt;mpNext != &amp;mNodeAllocator.mFirst &amp;&amp; mNodeAllocator.mFirst.mpNext-&gt;mpNext-&gt;mpNext == &amp;mNodeAllocator.mFirst\">\n\t\t[2] \n\t\t{{ \n\t\t\t{((eastl::ListNode&lt;$T1&gt;*)mNodeAllocator.mFirst.mpNext)-&gt;mValue}, \n\t\t\t{((eastl::ListNode&lt;$T1&gt;*)mNodeAllocator.mFirst.mpNext-&gt;mpNext)-&gt;mValue} \n\t\t}}\n\t</DisplayString>\n\t<DisplayString Condition=\"mNodeAllocator.mFirst.mpNext != &amp;mNodeAllocator.mFirst &amp;&amp; mNodeAllocator.mFirst.mpNext-&gt;mpNext != &amp;mNodeAllocator.mFirst &amp;&amp; mNodeAllocator.mFirst.mpNext-&gt;mpNext-&gt;mpNext != &amp;mNodeAllocator.mFirst\">\n\t\t[?] \n\t\t{{ \n\t\t\t{((eastl::ListNode&lt;$T1&gt;*)mNodeAllocator.mFirst.mpNext)-&gt;mValue}, \n\t\t\t{((eastl::ListNode&lt;$T1&gt;*)mNodeAllocator.mFirst.mpNext-&gt;mpNext)-&gt;mValue}, \n\t\t\t...\n\t\t}}\n\t</DisplayString>\n\t<Expand>\n\t\t<Synthetic Name=\"NOTE!\">\n\t\t  <DisplayString>Content of lists will repeat indefinitely. Keep that in mind!</DisplayString> \n\t\t</Synthetic>  \n        <LinkedListItems>\n            <HeadPointer>mNodeAllocator.mFirst.mpNext</HeadPointer>\n            <NextPointer>mpNext</NextPointer>\n            <ValueNode>((eastl::ListNode&lt;$T1&gt;*)this)-&gt;mValue</ValueNode>\n        </LinkedListItems>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::ListNode&lt;*&gt;\">\n\t<DisplayString>{mValue}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"Value\">mValue</Item>\n\t\t<Item Name=\"Next\">*(eastl::ListNode&lt;$T1&gt;*)mpNext</Item>\n\t\t<Item Name=\"Previous\">*(eastl::ListNode&lt;$T1&gt;*)mpPrev</Item>\n\t\t<Synthetic Name=\"NOTE!\">\n\t\t  <DisplayString>Content of lists will repeat indefinitely. Keep that in mind!</DisplayString> \n\t\t</Synthetic>  \n\t\t<Synthetic Name=\"List\">\n\t\t  <DisplayString>The rest of the list follows:</DisplayString> \n\t\t</Synthetic>\n        <LinkedListItems>\n            <HeadPointer>(eastl::ListNode&lt;$T1&gt;*)mpNext-&gt;mpNext</HeadPointer>\n            <NextPointer>(eastl::ListNode&lt;$T1&gt;*)mpNext</NextPointer>\n            <ValueNode>mValue</ValueNode>\n        </LinkedListItems>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::ListIterator&lt;*&gt;\">\n\t<DisplayString>{*mpNode}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>*(eastl::ListNode&lt;$T1&gt;*)mpNode</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::SListBase&lt;*&gt;\">\n\t<DisplayString Condition=\"mNode.mpNext == 0\">\n\t\t[0] {{}}\n\t</DisplayString>\n    <DisplayString Condition=\"mNode.mpNext != 0 &amp;&amp; mNode.mpNext-&gt;mpNext == 0\">\n\t\t[1] \n\t\t{{ \n\t\t\t{((eastl::SListNode&lt;$T1&gt;*)mNode.mpNext)-&gt;mValue} \n\t\t}}\n\t</DisplayString>\n\t<DisplayString Condition=\"mNode.mpNext != 0 &amp;&amp; mNode.mpNext-&gt;mpNext != 0 &amp;&amp; mNode.mpNext-&gt;mpNext-&gt;mpNext == 0\">\n\t\t[2] \n\t\t{{ \n\t\t\t{((eastl::SListNode&lt;$T1&gt;*)mNode.mpNext)-&gt;mValue}, \n\t\t\t{((eastl::SListNode&lt;$T1&gt;*)mNode.mpNext-&gt;mpNext)-&gt;mValue} \n\t\t}}\n\t</DisplayString>\n\t<DisplayString Condition=\"mNode.mpNext != 0 &amp;&amp; mNode.mpNext-&gt;mpNext != 0 &amp;&amp; mNode.mpNext-&gt;mpNext-&gt;mpNext != 0\">\n\t\t[?] \n\t\t{{ \n\t\t\t{((eastl::SListNode&lt;$T1&gt;*)mNode.mpNext)-&gt;mValue}, \n\t\t\t{((eastl::SListNode&lt;$T1&gt;*)mNode.mpNext-&gt;mpNext)-&gt;mValue},\n\t\t\t...\n\t\t}}\n\t</DisplayString>\n\t<Expand>\n        <LinkedListItems>\n            <HeadPointer>mNode.mpNext</HeadPointer>\n            <NextPointer>mpNext</NextPointer>\n            <ValueNode>((eastl::SListNode&lt;$T1&gt;*)this)-&gt;mValue</ValueNode>\n        </LinkedListItems>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::SListNode&lt;*&gt;\">\n\t<DisplayString>{mValue}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"Value\">mValue</Item>\n\t\t<Item Name=\"Next\">*(eastl::SListNode&lt;$T1&gt;*)mpNext</Item>\n\t\t<Synthetic Name=\"List\">\n\t\t  <DisplayString>The rest of the list follows:</DisplayString> \n\t\t</Synthetic>\n\t\t<LinkedListItems>\n            <HeadPointer>mpNext == nullptr ? nullptr : (eastl::SListNode&lt;$T1&gt;*)mpNext-&gt;mpNext</HeadPointer>\n            <NextPointer>(eastl::SListNode&lt;$T1&gt;*)mpNext</NextPointer>\n            <ValueNode>mValue</ValueNode>\n        </LinkedListItems>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::SListIterator&lt;*&gt;\">\n\t<DisplayString>{*mpNode}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>*(eastl::SListNode&lt;$T1&gt;*)mpNode</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::intrusive_list_base\">\n\t<DisplayString Condition=\"mAnchor.mpNext == &amp;mAnchor\">[0] {{}}</DisplayString>\n    <DisplayString Condition=\"mAnchor.mpNext != &amp;mAnchor &amp;&amp; mAnchor.mpNext-&gt;mpNext == &amp;mAnchor\">[1] {{ {mAnchor.mpNext} }}</DisplayString>\n\t<DisplayString Condition=\"mAnchor.mpNext != &amp;mAnchor &amp;&amp; mAnchor.mpNext-&gt;mpNext != &amp;mAnchor\">[?] {{ {mAnchor.mpNext}, ... }}</DisplayString>\n\t<Expand>\n\t\t<Synthetic Name=\"NOTE!\">\n\t\t  <DisplayString>Content of intrusive lists will repeat indefinitely. Keep that in mind!</DisplayString> \n\t\t</Synthetic>  \n        <LinkedListItems>\n            <HeadPointer>mAnchor.mpNext</HeadPointer>\n            <NextPointer>mpNext</NextPointer>\n            <ValueNode>*this</ValueNode>\n        </LinkedListItems>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::intrusive_list&lt;*&gt;\">\n\t<DisplayString Condition=\"mAnchor.mpNext == &amp;mAnchor\">[0] {{}}</DisplayString>\n\t<DisplayString Condition=\"mAnchor.mpNext != &amp;mAnchor &amp;&amp; mAnchor.mpNext-&gt;mpNext == &amp;mAnchor\">[1] {{ {mAnchor.mpNext} }}</DisplayString>\n\t<DisplayString Condition=\"mAnchor.mpNext != &amp;mAnchor &amp;&amp; mAnchor.mpNext-&gt;mpNext != &amp;mAnchor\">[?] {{ {mAnchor.mpNext}, ... }}</DisplayString>\n\t<Expand>\n\t\t<Synthetic Name=\"NOTE!\">\n\t\t\t<DisplayString>Content of intrusive lists will repeat indefinitely. Keep that in mind!</DisplayString>\n\t\t</Synthetic>\n\t\t<LinkedListItems>\n\t\t\t<HeadPointer>mAnchor.mpNext</HeadPointer>\n\t\t\t<NextPointer>mpNext</NextPointer>\n\t\t\t<ValueNode>*(($T1*)this)</ValueNode>\n\t\t</LinkedListItems>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::intrusive_list_iterator&lt;*&gt;\">\n\t<DisplayString>{*($T1*)mpNode}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>*($T1*)mpNode</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::set&lt;*&gt;\">\n\t<AlternativeType Name=\"eastl::multiset&lt;*&gt;\" />\n    <DisplayString Condition=\"mnSize == 0\">\n\t\t[0] {{}}\n\t</DisplayString>\n\t<DisplayString Condition=\"mnSize == 1\">\n\t\t[1] \n\t\t{{ \n\t\t\t{((eastl::rbtree_node&lt;$T1&gt;*)mAnchor.mpNodeLeft)-&gt;mValue} \n\t\t}}\n\t</DisplayString>\n\t<DisplayString Condition=\"mnSize &gt; 1\">\n\t\t[{mnSize}] \n\t\t{{ \n\t\t\t{((eastl::rbtree_node&lt;$T1&gt;*)mAnchor.mpNodeLeft)-&gt;mValue}, \n\t\t\t...\n\t\t}}\n\t</DisplayString>\n    <Expand>\n\t\t<Item Name=\"[size]\">mnSize</Item>\n        <TreeItems>\n            <Size>mnSize</Size>\n            <HeadPointer>mAnchor.mpNodeParent</HeadPointer>\n            <LeftPointer>mpNodeLeft</LeftPointer>\n            <RightPointer>mpNodeRight</RightPointer>\n            <ValueNode>((eastl::rbtree_node&lt;$T1&gt;*)this)-&gt;mValue</ValueNode>\n        </TreeItems>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::rbtree&lt;*,*&gt;\">\n\t<DisplayString Condition=\"mnSize == 0\">\n\t\t[0] {{}}\n\t</DisplayString>\n\t<DisplayString Condition=\"mnSize == 1\">\n\t\t[1] \n\t\t{{ \n\t\t\t{((eastl::rbtree_node&lt;$T2&gt;*)mAnchor.mpNodeLeft)-&gt;mValue} \n\t\t}}\n\t</DisplayString>\n\t<DisplayString Condition=\"mnSize &gt; 1\">\n\t\t[{mnSize}] \n\t\t{{ \n\t\t\t{((eastl::rbtree_node&lt;$T2&gt;*)mAnchor.mpNodeLeft)-&gt;mValue}, \n\t\t\t...\n\t\t}}\n\t</DisplayString>\n    <Expand>\n\t\t<Item Name=\"[size]\">mnSize</Item>\n        <TreeItems>\n            <Size>mnSize</Size>\n            <HeadPointer>mAnchor.mpNodeParent</HeadPointer>\n            <LeftPointer>mpNodeLeft</LeftPointer>\n            <RightPointer>mpNodeRight</RightPointer>\n            <ValueNode>((eastl::rbtree_node&lt;$T2&gt;*)this)-&gt;mValue</ValueNode>\n        </TreeItems>\n    </Expand>\n</Type>\n\n<Type Name=\"eastl::rbtree_node&lt;*&gt;\">\n\t<DisplayString>{mValue}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"Value\">mValue</Item>\n\t\t<Synthetic Name=\"NOTE!\">\n\t\t  <DisplayString>It is possible to expand parents that do not exist.</DisplayString> \n\t\t</Synthetic>\n\t\t<Item Name=\"Parent\">*(eastl::rbtree_node&lt;$T1&gt;*)mpNodeParent</Item>\n\t\t<Item Name=\"Left\">*(eastl::rbtree_node&lt;$T1&gt;*)mpNodeLeft</Item>\n\t\t<Item Name=\"Right\">*(eastl::rbtree_node&lt;$T1&gt;*)mpNodeRight</Item>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::rbtree_iterator&lt;*&gt;\">\n\t<DisplayString>{*(eastl::rbtree_node&lt;$T1&gt;*)mpNode}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"Node\">*(eastl::rbtree_node&lt;$T1&gt;*)mpNode</Item>\n\t</Expand>\n</Type>\n\n\n<Type Name=\"eastl::hashtable&lt;*&gt;\">\n  <DisplayString Condition=\"mnElementCount == 0\">[{mnElementCount}] {{}}</DisplayString>\n  <DisplayString Condition=\"mnElementCount != 0\">[{mnElementCount}] {{ ... }}</DisplayString>\n  <Expand>\n    <ArrayItems IncludeView=\"detailed\">\n      <Size>mnBucketCount</Size>\n      <ValuePointer>mpBucketArray</ValuePointer>\n    </ArrayItems>\n    <CustomListItems ExcludeView=\"detailed\">\n      <Variable Name=\"bucketIndex\" InitialValue=\"0\"/>\n      <Variable Name=\"entry\" InitialValue =\"mpBucketArray[bucketIndex]\"/>\n      <Loop>\n        <Item Condition=\"entry != nullptr\">entry->mValue</Item>\n        <If Condition=\"entry != nullptr\">\n          <Exec>entry = entry->mpNext</Exec>\n        </If>\n        <If Condition=\"entry == nullptr\">\n          <Exec>bucketIndex++</Exec>\n          <Break Condition=\"bucketIndex == mnBucketCount\"/>\n          <Exec>entry = mpBucketArray[bucketIndex]</Exec>\n        </If>\n      </Loop>\n    </CustomListItems>\n  </Expand>\n</Type>\n\n<!-- specifically for hash_map (instead of base implementation hashtable),\n     show the key as name, and value as value, instead of index -> pair<key, value> -->\n<Type Name=\"eastl::hash_map&lt;*&gt;\">\n  <DisplayString Condition=\"mnElementCount == 0\">[{mnElementCount}] {{}}</DisplayString>\n  <DisplayString Condition=\"mnElementCount != 0\">[{mnElementCount}] {{ ... }}</DisplayString>\n  <Expand>\n    <CustomListItems ExcludeView=\"detailed\">\n      <Variable Name=\"bucketIndex\" InitialValue=\"0\"/>\n      <Variable Name=\"entry\" InitialValue =\"mpBucketArray[bucketIndex]\"/>\n      <Loop>\n        <Item Name=\"[{entry->mValue.first}]\" Condition=\"entry != nullptr\">entry->mValue.second</Item>\n        <If Condition=\"entry != nullptr\">\n          <Exec>entry = entry->mpNext</Exec>\n        </If>\n        <If Condition=\"entry == nullptr\">\n          <Exec>bucketIndex++</Exec>\n          <Break Condition=\"bucketIndex == mnBucketCount\"/>\n          <Exec>entry = mpBucketArray[bucketIndex]</Exec>\n        </If>\n      </Loop>\n    </CustomListItems>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::hash_node&lt;*&gt;\">\n\t<DisplayString Condition=\"this != 0 &amp;&amp; mpNext != 0\"> {mValue}, {*mpNext}</DisplayString>\n\t<DisplayString Condition=\"this != 0 &amp;&amp; mpNext == 0\"> {mValue}</DisplayString>\n\t<DisplayString Condition=\"this == 0\"></DisplayString>\n\t<Expand>\n\t\t<LinkedListItems>\n            <HeadPointer>this</HeadPointer>\n            <NextPointer>mpNext</NextPointer>\n            <ValueNode>mValue</ValueNode>\n        </LinkedListItems>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::hashtable_iterator_base&lt;*&gt;\">\n\t<DisplayString>{mpNode-&gt;mValue}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>mpNode-&gt;mValue</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::reverse_iterator&lt;*&gt;\">\n\t<DisplayString>{*(mIterator-1)}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>mIterator-1</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::bitset&lt;*&gt;\">\n  <DisplayString>{{count = {kSize}}}</DisplayString>\n  <Expand>\n    <Item Name=\"[count]\">kSize</Item>\n    <CustomListItems>\n      <Variable Name=\"iWord\" InitialValue=\"0\" />\n      <Variable Name=\"iBitInWord\" InitialValue=\"0\" />\n      <Variable Name=\"bBitValue\" InitialValue=\"false\" />\n\n      <Size>kSize</Size>\n\n      <Loop>\n        <Exec>bBitValue = ((mWord[iWord] >> iBitInWord) % 2) != 0 ? true : false</Exec>\n        <Item>bBitValue</Item>\n        <Exec>iBitInWord++</Exec>\n        <If Condition=\"iBitInWord == kBitsPerWord\">\n          <Exec>iWord++</Exec>\n          <Exec>iBitInWord = 0</Exec>\n        </If>\n      </Loop>\n    </CustomListItems>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::ring_buffer&lt;*,*,*&gt;\">\n  <DisplayString>{c}</DisplayString>\n  <Expand>\n    <ExpandedItem>c</ExpandedItem>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::basic_string_view&lt;*&gt;\">\n\t<DisplayString>{mpBegin,[mnCount]}</DisplayString>\n\t<StringView>mpBegin,[mnCount]</StringView>\n</Type>\n\n<Type Name=\"eastl::compressed_pair_imp&lt;*&gt;\">\n\t<DisplayString Condition=\"($T3) == 0\" Optional=\"true\">({mFirst}, {mSecond})</DisplayString>\n\t<DisplayString Condition=\"($T3) == 1\" Optional=\"true\">({mSecond})</DisplayString>\n\t<DisplayString Condition=\"($T3) == 2\" Optional=\"true\">({mFirst})</DisplayString>\n\t<DisplayString Condition=\"($T3) == 3\" Optional=\"true\">(empty)</DisplayString>\n\t<DisplayString Condition=\"($T3) == 4\" Optional=\"true\">(empty)</DisplayString>\n\t<DisplayString Condition=\"($T3) == 5\" Optional=\"true\">({mFirst}, {mSecond})</DisplayString>\n</Type>\n\n<Type Name=\"eastl::optional&lt;*&gt;\">\n\t<Intrinsic Name=\"value\" Expression=\"*($T1*)&amp;val\"/>\n\t<DisplayString Condition=\"!engaged\">nullopt</DisplayString>\n\t<DisplayString Condition=\"engaged\">{value()}</DisplayString>\n\t<Expand>\n\t\t<Item Condition=\"engaged\" Name=\"value\">value()</Item>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::expected&lt;*&gt;\">\n\t<DisplayString Condition=\"!mHasValue\">{mError} (Error)</DisplayString>\n\t<DisplayString Condition=\"mHasValue\">{mValue}</DisplayString>\n  <Expand>\n    <Item Condition=\"!mHasValue\" Name=\"mError\">mError</Item>\n    <Item Condition=\"mHasValue\" Name=\"mValue\">mValue</Item>\n    <Item Name=\"mHasValue\">mHasValue</Item>\n  </Expand>\n</Type>\n\n <Type Name=\"eastl::expected&lt;void,*&gt;\">\n\t<DisplayString Condition=\"mHasValue\">void</DisplayString>\n\t<DisplayString Condition=\"!mHasValue\">{mError} (Error)</DisplayString>\n  <Expand>\n    <Item Condition=\"!mHasValue\" Name=\"mError\">mError</Item>\n    <Item Name=\"mHasValue\">mHasValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::ratio&lt;*&gt;\">\n\t<DisplayString>{$T1} to {$T2}}</DisplayString>\n</Type>\n\n\n<Type Name=\"eastl::chrono::duration&lt;*,eastl::ratio&lt;1,1000000000&gt; &gt;\">\n\t<DisplayString>{mRep} nanoseconds</DisplayString>\n</Type>\n\n<Type Name=\"eastl::chrono::duration&lt;*,eastl::ratio&lt;1,1000000&gt; &gt;\">\n\t<DisplayString>{mRep} microseconds</DisplayString>\n</Type>\n\n<Type Name=\"eastl::chrono::duration&lt;*,eastl::ratio&lt;1,1000&gt; &gt;\">\n\t<DisplayString>{mRep} milliseconds</DisplayString>\n</Type>\n\n<Type Name=\"eastl::chrono::duration&lt;*,eastl::ratio&lt;1,1&gt; &gt;\">\n\t<DisplayString>{mRep} seconds</DisplayString>\n</Type>\n\n<Type Name=\"eastl::chrono::duration&lt;*,eastl::ratio&lt;60,1&gt; &gt;\">\n\t<DisplayString>{mRep} minutes</DisplayString>\n</Type>\n\n<Type Name=\"eastl::chrono::duration&lt;*,eastl::ratio&lt;3600,1&gt; &gt;\">\n\t<DisplayString>{mRep} hours</DisplayString>\n</Type>\n\n<Type Name=\"eastl::chrono::duration&lt;*,eastl::ratio&lt;*,*&gt; &gt;\">\n\t<DisplayString>{mRep} duration with ratio = [{$T2} : {$T3}] </DisplayString>\n</Type>\n\n\n\n<Type Name=\"eastl::function&lt;*&gt;\">\n\t<DisplayString Condition=\"mInvokeFuncPtr == nullptr\">empty</DisplayString>\n\t<DisplayString>{mInvokeFuncPtr}</DisplayString>\n</Type>\n\n\n<Type Name=\"eastl::reference_wrapper&lt;*&gt;\">\n\t<DisplayString>{*val}</DisplayString>\n</Type>\n\n<!--\n\tThis implementation isn't ideal because it can't switch between showing inline value vs values stored in a heap allocation.\n\tWe are hitting the limit of natvis scripting that we can't workaround unless we change the implementation of eastl::any.\n-->\n<Type Name=\"eastl::any\">\n\t<DisplayString Condition=\"m_handler == nullptr\">empty</DisplayString>\n\t<DisplayString Condition=\"m_handler != nullptr\">{m_storage.external_storage}</DisplayString>\n</Type>\n\n\n<Type Name=\"eastl::atomic&lt;*&gt;\">\n\t<DisplayString>{mAtomic}</DisplayString>\n\t<Expand>\n\t\t<ExpandedItem>mAtomic</ExpandedItem>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::atomic_flag\">\n\t<DisplayString>{mFlag.mAtomic}</DisplayString>\n</Type>\n\n<Type Name=\"eastl::variant&lt;*&gt;\">\n\t<Intrinsic Name=\"index\" Expression=\"(int)mIndex\"/>\n\t<DisplayString Condition=\"index() == size_t(-1)\">[valueless_by_exception]</DisplayString>\n\t<DisplayString Condition=\"index() ==  0\" Optional=\"true\">{{ index=0, value={($T1*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  1\" Optional=\"true\">{{ index=1, value={($T2*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  2\" Optional=\"true\">{{ index=2, value={($T3*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  3\" Optional=\"true\">{{ index=3, value={($T4*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  4\" Optional=\"true\">{{ index=4, value={($T5*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  5\" Optional=\"true\">{{ index=5, value={($T6*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  6\" Optional=\"true\">{{ index=6, value={($T7*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  7\" Optional=\"true\">{{ index=7, value={($T8*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  8\" Optional=\"true\">{{ index=8, value={($T9*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  9\" Optional=\"true\">{{ index=9, value={($T10*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  10\" Optional=\"true\">{{ index=10, value={($T11*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  11\" Optional=\"true\">{{ index=11, value={($T12*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  12\" Optional=\"true\">{{ index=12, value={($T13*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  13\" Optional=\"true\">{{ index=13, value={($T14*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  14\" Optional=\"true\">{{ index=14, value={($T15*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  15\" Optional=\"true\">{{ index=15, value={($T16*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  16\" Optional=\"true\">{{ index=16, value={($T17*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  17\" Optional=\"true\">{{ index=17, value={($T18*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  18\" Optional=\"true\">{{ index=18, value={($T19*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  19\" Optional=\"true\">{{ index=19, value={($T20*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  20\" Optional=\"true\">{{ index=20, value={($T21*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  21\" Optional=\"true\">{{ index=21, value={($T22*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  22\" Optional=\"true\">{{ index=22, value={($T23*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  23\" Optional=\"true\">{{ index=23, value={($T24*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  24\" Optional=\"true\">{{ index=24, value={($T25*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  25\" Optional=\"true\">{{ index=25, value={($T26*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  26\" Optional=\"true\">{{ index=26, value={($T27*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  27\" Optional=\"true\">{{ index=27, value={($T28*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  28\" Optional=\"true\">{{ index=28, value={($T29*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  29\" Optional=\"true\">{{ index=29, value={($T30*)mBuffer.mCharData}}</DisplayString>\n\t<DisplayString Condition=\"index() ==  30\" Optional=\"true\">{{ index=30, value={($T31*)mBuffer.mCharData}}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"index\">index()</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  0\" Optional=\"true\">($T1*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  1\" Optional=\"true\">($T2*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  2\" Optional=\"true\">($T3*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  3\" Optional=\"true\">($T4*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  4\" Optional=\"true\">($T5*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  5\" Optional=\"true\">($T6*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  6\" Optional=\"true\">($T7*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  7\" Optional=\"true\">($T8*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  8\" Optional=\"true\">($T9*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() ==  9\" Optional=\"true\">($T10*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 10\" Optional=\"true\">($T11*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 11\" Optional=\"true\">($T12*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 12\" Optional=\"true\">($T13*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 13\" Optional=\"true\">($T14*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 14\" Optional=\"true\">($T15*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 15\" Optional=\"true\">($T16*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 16\" Optional=\"true\">($T17*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 17\" Optional=\"true\">($T18*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 18\" Optional=\"true\">($T19*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 19\" Optional=\"true\">($T20*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 20\" Optional=\"true\">($T21*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 21\" Optional=\"true\">($T22*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 22\" Optional=\"true\">($T23*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 23\" Optional=\"true\">($T24*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 24\" Optional=\"true\">($T25*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 25\" Optional=\"true\">($T26*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 26\" Optional=\"true\">($T27*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 27\" Optional=\"true\">($T28*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 28\" Optional=\"true\">($T29*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 29\" Optional=\"true\">($T30*)mBuffer.mCharData</Item>\n\t\t<Item Name=\"[value]\" Condition=\"index() == 30\" Optional=\"true\">($T31*)mBuffer.mCharData</Item>\n\t</Expand>\n</Type>\n\n\n<Type Name=\"eastl::tuple&lt;&gt;\">\n  <DisplayString IncludeView=\"noparens\"></DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand/>\n</Type>\n\n<Type Name=\"eastl::tuple&lt;*&gt;\">\n  <DisplayString IncludeView=\"noparens\">{(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue}</DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand>\n    <Item Name=\"[0]\">(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::tuple&lt;*,*&gt;\">\n  <DisplayString IncludeView=\"noparens\">{(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue}</DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand>\n    <Item Name=\"[0]\">(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[1]\">(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::tuple&lt;*,*,*&gt;\">\n  <DisplayString IncludeView=\"noparens\">{(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue}</DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand>\n    <Item Name=\"[0]\">(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[1]\">(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[2]\">(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::tuple&lt;*,*,*,*&gt;\">\n  <DisplayString IncludeView=\"noparens\">{(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue}</DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand>\n    <Item Name=\"[0]\">(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[1]\">(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[2]\">(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[3]\">(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::tuple&lt;*,*,*,*,*&gt;\">\n  <DisplayString IncludeView=\"noparens\">{(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;4,$T5,0&gt;*)&amp;mImpl)).mValue}</DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand>\n    <Item Name=\"[0]\">(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[1]\">(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[2]\">(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[3]\">(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[4]\">(*((eastl::Internal::TupleLeaf&lt;4,$T5,0&gt;*)&amp;mImpl)).mValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::tuple&lt;*,*,*,*,*,*&gt;\">\n  <DisplayString IncludeView=\"noparens\">{(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;4,$T5,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;5,$T6,0&gt;*)&amp;mImpl)).mValue}</DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand>\n    <Item Name=\"[0]\">(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[1]\">(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[2]\">(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[3]\">(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[4]\">(*((eastl::Internal::TupleLeaf&lt;4,$T5,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[5]\">(*((eastl::Internal::TupleLeaf&lt;5,$T6,0&gt;*)&amp;mImpl)).mValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::tuple&lt;*,*,*,*,*,*,*&gt;\">\n  <DisplayString IncludeView=\"noparens\">{(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;4,$T5,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;5,$T6,0&gt;*)&amp;mImpl)).mValue}, {(*((eastl::Internal::TupleLeaf&lt;6,$T7,0&gt;*)&amp;mImpl)).mValue}</DisplayString>\n  <DisplayString ExcludeView=\"noparens\">({*this,view(noparens)})</DisplayString>\n  <Expand>\n    <Item Name=\"[0]\">(*((eastl::Internal::TupleLeaf&lt;0,$T1,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[1]\">(*((eastl::Internal::TupleLeaf&lt;1,$T2,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[2]\">(*((eastl::Internal::TupleLeaf&lt;2,$T3,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[3]\">(*((eastl::Internal::TupleLeaf&lt;3,$T4,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[4]\">(*((eastl::Internal::TupleLeaf&lt;4,$T5,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[5]\">(*((eastl::Internal::TupleLeaf&lt;5,$T6,0&gt;*)&amp;mImpl)).mValue</Item>\n    <Item Name=\"[6]\">(*((eastl::Internal::TupleLeaf&lt;6,$T7,0&gt;*)&amp;mImpl)).mValue</Item>\n  </Expand>\n</Type>\n\n<Type Name=\"eastl::basic_flags&lt;*,eastl::flag_marshaller&lt;eastl::maskflag_tag,*&gt;&gt;\">\n\t<DisplayString Condition=\"m_mask == 0\">(nothing)</DisplayString>\n\t<DisplayString>{static_cast&lt;flag_type&gt;(m_mask),en}</DisplayString>\n\t<Expand>\n\t\t<Item Name=\"m_mask\">m_mask,bb</Item>\n\t\t<Item Name=\"bit 0\" Condition=\"m_mask &amp; (1 &lt;&lt; 0)\">(flag_type)(1 &lt;&lt; 0),en</Item>\n\t\t<Item Name=\"bit 1\" Condition=\"m_mask &amp; (1 &lt;&lt; 1)\">(flag_type)(1 &lt;&lt; 1),en</Item>\n\t\t<Item Name=\"bit 2\" Condition=\"m_mask &amp; (1 &lt;&lt; 2)\">(flag_type)(1 &lt;&lt; 2),en</Item>\n\t\t<Item Name=\"bit 3\" Condition=\"m_mask &amp; (1 &lt;&lt; 3)\">(flag_type)(1 &lt;&lt; 3),en</Item>\n\t\t<Item Name=\"bit 4\" Condition=\"m_mask &amp; (1 &lt;&lt; 4)\">(flag_type)(1 &lt;&lt; 4),en</Item>\n\t\t<Item Name=\"bit 5\" Condition=\"m_mask &amp; (1 &lt;&lt; 5)\">(flag_type)(1 &lt;&lt; 5),en</Item>\n\t\t<Item Name=\"bit 6\" Condition=\"m_mask &amp; (1 &lt;&lt; 6)\">(flag_type)(1 &lt;&lt; 6),en</Item>\n\t\t<Item Name=\"bit 7\" Condition=\"m_mask &amp; (1 &lt;&lt; 7)\">(flag_type)(1 &lt;&lt; 7),en</Item>\n\n\t\t<Item Name=\"bit 8\" Condition=\"m_mask &amp; (1 &lt;&lt; 8)\">(flag_type)(1 &lt;&lt; 8),en</Item>\n\t\t<Item Name=\"bit 9\" Condition=\"m_mask &amp; (1 &lt;&lt; 9)\">(flag_type)(1 &lt;&lt; 9),en</Item>\n\t\t<Item Name=\"bit 10\" Condition=\"m_mask &amp; (1 &lt;&lt; 10)\">(flag_type)(1 &lt;&lt; 10),en</Item>\n\t\t<Item Name=\"bit 11\" Condition=\"m_mask &amp; (1 &lt;&lt; 11)\">(flag_type)(1 &lt;&lt; 11),en</Item>\n\t\t<Item Name=\"bit 12\" Condition=\"m_mask &amp; (1 &lt;&lt; 12)\">(flag_type)(1 &lt;&lt; 12),en</Item>\n\t\t<Item Name=\"bit 13\" Condition=\"m_mask &amp; (1 &lt;&lt; 13)\">(flag_type)(1 &lt;&lt; 13),en</Item>\n\t\t<Item Name=\"bit 14\" Condition=\"m_mask &amp; (1 &lt;&lt; 14)\">(flag_type)(1 &lt;&lt; 14),en</Item>\n\t\t<Item Name=\"bit 15\" Condition=\"m_mask &amp; (1 &lt;&lt; 15)\">(flag_type)(1 &lt;&lt; 15),en</Item>\n\n\t\t<Item Name=\"bit 16\" Condition=\"m_mask &amp; (1 &lt;&lt; 16)\">(flag_type)(1 &lt;&lt; 16),en</Item>\n\t\t<Item Name=\"bit 17\" Condition=\"m_mask &amp; (1 &lt;&lt; 17)\">(flag_type)(1 &lt;&lt; 17),en</Item>\n\t\t<Item Name=\"bit 18\" Condition=\"m_mask &amp; (1 &lt;&lt; 18)\">(flag_type)(1 &lt;&lt; 18),en</Item>\n\t\t<Item Name=\"bit 19\" Condition=\"m_mask &amp; (1 &lt;&lt; 19)\">(flag_type)(1 &lt;&lt; 19),en</Item>\n\t\t<Item Name=\"bit 20\" Condition=\"m_mask &amp; (1 &lt;&lt; 20)\">(flag_type)(1 &lt;&lt; 20),en</Item>\n\t\t<Item Name=\"bit 21\" Condition=\"m_mask &amp; (1 &lt;&lt; 21)\">(flag_type)(1 &lt;&lt; 21),en</Item>\n\t\t<Item Name=\"bit 22\" Condition=\"m_mask &amp; (1 &lt;&lt; 22)\">(flag_type)(1 &lt;&lt; 22),en</Item>\n\t\t<Item Name=\"bit 23\" Condition=\"m_mask &amp; (1 &lt;&lt; 23)\">(flag_type)(1 &lt;&lt; 23),en</Item>\n\n\t\t<Item Name=\"bit 24\" Condition=\"m_mask &amp; (1 &lt;&lt; 24)\">(flag_type)(1 &lt;&lt; 24),en</Item>\n\t\t<Item Name=\"bit 25\" Condition=\"m_mask &amp; (1 &lt;&lt; 25)\">(flag_type)(1 &lt;&lt; 25),en</Item>\n\t\t<Item Name=\"bit 26\" Condition=\"m_mask &amp; (1 &lt;&lt; 26)\">(flag_type)(1 &lt;&lt; 26),en</Item>\n\t\t<Item Name=\"bit 27\" Condition=\"m_mask &amp; (1 &lt;&lt; 27)\">(flag_type)(1 &lt;&lt; 27),en</Item>\n\t\t<Item Name=\"bit 28\" Condition=\"m_mask &amp; (1 &lt;&lt; 28)\">(flag_type)(1 &lt;&lt; 28),en</Item>\n\t\t<Item Name=\"bit 29\" Condition=\"m_mask &amp; (1 &lt;&lt; 29)\">(flag_type)(1 &lt;&lt; 29),en</Item>\n\t\t<Item Name=\"bit 30\" Condition=\"m_mask &amp; (1 &lt;&lt; 30)\">(flag_type)(1 &lt;&lt; 30),en</Item>\n\t\t<Item Name=\"bit 31\" Condition=\"m_mask &amp; (1 &lt;&lt; 31)\">(flag_type)(1 &lt;&lt; 31),en</Item>\n\t</Expand>\n</Type>\n\n<Type Name=\"eastl::basic_flags&lt;*,eastl::flag_marshaller&lt;eastl::bitflag_tag,*&gt;&gt;\">\n\t<!-- when we have a single flag, display that -->\n\t<DisplayString Condition=\"(1 &lt;&lt; __log2(m_mask)) == m_mask\">{static_cast&lt;flag_type&gt;(__log2(m_mask)),en}</DisplayString>\n\t<!-- we lack the technology to show every flag, so just say there is multiple -->\n\t<DisplayString Condition=\"m_mask != 0\">(multiple values)</DisplayString>\n\t<!-- empty -->\n\t<DisplayString>(nothing)</DisplayString>\n\n\t<Expand>\n\t\t<Item Name=\"m_mask\">m_mask,bb</Item>\n\t\t<Item Name=\"bit 0\" Condition=\"m_mask &amp; (1 &lt;&lt; 0)\">(flag_type)(0),en</Item>\n\t\t<Item Name=\"bit 1\" Condition=\"m_mask &amp; (1 &lt;&lt; 1)\">(flag_type)(1),en</Item>\n\t\t<Item Name=\"bit 2\" Condition=\"m_mask &amp; (1 &lt;&lt; 2)\">(flag_type)(2),en</Item>\n\t\t<Item Name=\"bit 3\" Condition=\"m_mask &amp; (1 &lt;&lt; 3)\">(flag_type)(3),en</Item>\n\t\t<Item Name=\"bit 4\" Condition=\"m_mask &amp; (1 &lt;&lt; 4)\">(flag_type)(4),en</Item>\n\t\t<Item Name=\"bit 5\" Condition=\"m_mask &amp; (1 &lt;&lt; 5)\">(flag_type)(5),en</Item>\n\t\t<Item Name=\"bit 6\" Condition=\"m_mask &amp; (1 &lt;&lt; 6)\">(flag_type)(6),en</Item>\n\t\t<Item Name=\"bit 7\" Condition=\"m_mask &amp; (1 &lt;&lt; 7)\">(flag_type)(7),en</Item>\n\t\t\n\t\t<Item Name=\"bit 8\" Condition=\"m_mask &amp; (1 &lt;&lt; 8)\">(flag_type)(8),en</Item>\n\t\t<Item Name=\"bit 9\" Condition=\"m_mask &amp; (1 &lt;&lt; 9)\">(flag_type)(9),en</Item>\n\t\t<Item Name=\"bit 10\" Condition=\"m_mask &amp; (1 &lt;&lt; 10)\">(flag_type)(10),en</Item>\n\t\t<Item Name=\"bit 11\" Condition=\"m_mask &amp; (1 &lt;&lt; 11)\">(flag_type)(11),en</Item>\n\t\t<Item Name=\"bit 12\" Condition=\"m_mask &amp; (1 &lt;&lt; 12)\">(flag_type)(12),en</Item>\n\t\t<Item Name=\"bit 13\" Condition=\"m_mask &amp; (1 &lt;&lt; 13)\">(flag_type)(13),en</Item>\n\t\t<Item Name=\"bit 14\" Condition=\"m_mask &amp; (1 &lt;&lt; 14)\">(flag_type)(14),en</Item>\n\t\t<Item Name=\"bit 15\" Condition=\"m_mask &amp; (1 &lt;&lt; 15)\">(flag_type)(15),en</Item>\n\t\t\n\t\t<Item Name=\"bit 16\" Condition=\"m_mask &amp; (1 &lt;&lt; 16)\">(flag_type)(16),en</Item>\n\t\t<Item Name=\"bit 17\" Condition=\"m_mask &amp; (1 &lt;&lt; 17)\">(flag_type)(17),en</Item>\n\t\t<Item Name=\"bit 18\" Condition=\"m_mask &amp; (1 &lt;&lt; 18)\">(flag_type)(18),en</Item>\n\t\t<Item Name=\"bit 19\" Condition=\"m_mask &amp; (1 &lt;&lt; 19)\">(flag_type)(19),en</Item>\n\t\t<Item Name=\"bit 20\" Condition=\"m_mask &amp; (1 &lt;&lt; 20)\">(flag_type)(20),en</Item>\n\t\t<Item Name=\"bit 21\" Condition=\"m_mask &amp; (1 &lt;&lt; 21)\">(flag_type)(21),en</Item>\n\t\t<Item Name=\"bit 22\" Condition=\"m_mask &amp; (1 &lt;&lt; 22)\">(flag_type)(22),en</Item>\n\t\t<Item Name=\"bit 23\" Condition=\"m_mask &amp; (1 &lt;&lt; 23)\">(flag_type)(23),en</Item>\n\t\t\n\t\t<Item Name=\"bit 24\" Condition=\"m_mask &amp; (1 &lt;&lt; 24)\">(flag_type)(24),en</Item>\n\t\t<Item Name=\"bit 25\" Condition=\"m_mask &amp; (1 &lt;&lt; 25)\">(flag_type)(25),en</Item>\n\t\t<Item Name=\"bit 26\" Condition=\"m_mask &amp; (1 &lt;&lt; 26)\">(flag_type)(26),en</Item>\n\t\t<Item Name=\"bit 27\" Condition=\"m_mask &amp; (1 &lt;&lt; 27)\">(flag_type)(27),en</Item>\n\t\t<Item Name=\"bit 28\" Condition=\"m_mask &amp; (1 &lt;&lt; 28)\">(flag_type)(28),en</Item>\n\t\t<Item Name=\"bit 29\" Condition=\"m_mask &amp; (1 &lt;&lt; 29)\">(flag_type)(29),en</Item>\n\t\t<Item Name=\"bit 30\" Condition=\"m_mask &amp; (1 &lt;&lt; 30)\">(flag_type)(30),en</Item>\n\t\t<Item Name=\"bit 31\" Condition=\"m_mask &amp; (1 &lt;&lt; 31)\">(flag_type)(31),en</Item>\n\t</Expand>\n</Type>\n</AutoVisualizer>\n"
  },
  {
    "path": "doc/FAQ.md",
    "content": "# EASTL FAQ\n\nWe provide a FAQ (frequently asked questions) list here for a number of commonly asked questions about EASTL and STL in general. Feel free to suggest new FAQ additions based on your own experience.\n\n## Information\n\n1. [What is EASTL?](#info1-what-is-eastl)\n2. [What uses are EASTL suitable for?](#info2-what-uses-are-eastl-suitable-for)\n3. [How does EASTL differ from standard C++ STL?](#info3-how-does-eastl-differ-from-standard-c-stl)\n4. [Is EASTL thread-safe?](#info4-is-eastl-thread-safe)\n5. [What platforms/compilers does EASTL support?](#info5-what-platformscompilers-does-eastl-support)\n6. [Why is there EASTL when there is the STL?](#info6-why-is-there-eastl-when-there-is-the-stl)\n7. [Can I mix EASTL with standard C++ STL?](#info7-can-i-mix-eastl-with-standard-c-stl)\n8. [Where can I learn more about STL and EASTL?](#info8-where-can-i-learn-more-about-stl-and-eastl)\n9. [What is the legal status of EASTL?](#info9-what-is-the-legal-status-of-eastl)\n10. [Does EASTL deal with compiler exception handling settings?](#info10-does-eastl-deal-with-compiler-exception-handling-settings)\n11. [What C++ language features does EASTL use (e.g. virtual functions)?](#info11-what-c-language-features-does-eastl-use-eg-virtual-functions)\n12. [What compiler warning levels does EASTL support?](#info12-what-compiler-warning-levels-does-eastl-support)\n13. [Is EASTL compatible with Lint?](#info13-is-eastl-compatible-with-lint)\n14. [What compiler settings do I need to compile EASTL?](#info14-what-compiler-settings-do-i-need-to-compile-eastl)\n15. [How hard is it to incorporate EASTL into my project?](#info15-how-hard-is-it-to-incorporate-eastl-into-my-project)\n16. [Should I use EASTL instead of std STL or instead of my custom library?](#info16-should-i-use-eastl-instead-of-std-stl-or-instead-of-my-custom-library)\n17. [I think I've found a bug. What do I do?](#info17-i-think-ive-found-a-bug-what-do-i-do)\n18. [Can EASTL be used by third party EA developers?](#info18-can-eastl-be-used-by-third-party-ea-developers)\n\n## Performance\n\n1. [How efficient is EASTL compared to standard C++ STL implementations?](#perf1-how-efficient-is-eastl-compared-to-standard-c-stl-implementations)\n2. [How efficient is EASTL in general?](#perf2-how-efficient-is-eastl-in-general)\n3. [Strings don't appear to use the \"copy-on-write\" optimization. Why not?](#perf3-strings-dont-appear-to-use-the-copy-on-write-cow-optimization-why-not)\n4. [Does EASTL cause code bloat, given that it uses templates?](#perf4-does-eastl-cause-code-bloat-given-that-it-uses-templates)\n5. [Don't STL and EASTL containers fragment memory?](#perf5-dont-stl-and-eastl-containers-fragment-memory)\n6. [I don't see container optimizations for equivalent scalar types such as pointer types. Why?](#perf6-i-dont-see-container-optimizations-for-equivalent-scalar-types-such-as-pointer-types-why)\n7. [I've seen some STL's provide a default quick \"node allocator\" as the default allocator. Why doesn't EASTL do this?](#perf7-ive-seen-some-stls-provide-a-default-quick-node-allocator-as-the-default-allocator-why-doesnt-eastl-do-this)\n8. [Templates sometimes seem to take a long time to compile. Why do I do about that?](#perf8-templates-sometimes-seem-to-take-a-long-time-to-compile-why-do-i-do-about-that)\n9. [How do I assign a custom allocator to an EASTL container?](#cont8-how-do-i-assign-a-custom-allocator-to-an-eastl-container)\n10. [How well does EASTL inline?](#perf10-how-well-does-eastl-inline)\n11. [How do I control function inlining?](#perf11-how-do-i-control-function-inlining)\n12. [C++ / EASTL seems to bloat my .obj files much more than C does.](#perf12-c--eastl-seems-to-bloat-my-obj-files-much-more-than-c-does)\n13. [What are the best compiler settings for EASTL?](#perf13-what-are-the-best-compiler-settings-for-eastl)\n\n## Problems\n\n1. [I'm getting screwy behavior in sorting algorithms or sorted containers. What's wrong?](#prob1-im-getting-screwy-behavior-in-sorting-algorithms-or-sorted-containers-whats-wrong)\n2. [I am getting compiler warnings (e.g. C4244, C4242 or C4267) that make no sense. Why?](#prob2-i-am-getting-compiler-warnings-eg-c4244-c4242-or-c4267-that-make-no-sense-why)\n3. [I am getting compiler warning C4530, which complains about exception handling and \"unwind semantics.\" What gives?](#prob3-i-am-getting-compiler-warning-c4530-which-complains-about-exception-handling-and-unwind-semantics-what-gives)\n4. [Why are tree-based containers hard to read with a debugger?](#prob4-why-are-tree-based-eastl-containers-hard-to-read-with-a-debugger)\n5. [The EASTL source code is sometimes rather complicated looking. Why is that?](#prob5-the-eastl-source-code-is-sometimes-rather-complicated-looking-why-is-that)\n6. [When I get compilation errors, they are very long and complicated looking. What do I do?](#prob6-when-i-get-compilation-errors-they-are-very-long-and-complicated-looking-what-do-i-do)\n7. [Templates sometimes seem to take a long time to compile. Why do I do about that?](#prob7-templates-sometimes-seem-to-take-a-long-time-to-compile-why-do-i-do-about-that)\n8. [I get the compiler error: \"template instantiation depth exceeds maximum of 17. use -ftemplate-depth-NN to increase the maximum\"](#prob8-i-get-the-compiler-error-template-instantiation-depth-exceeds-maximum-of-17-use--ftemplate-depth-nn-to-increase-the-maximum)\n9. [I'm getting errors about min and max while compiling.](#prob9-im-getting-errors-about-min-and-max-while-compiling)\n10. [C++ / EASTL seems to bloat my .obj files much more than C does.](#prob10-c--eastl-seems-to-bloat-my-obj-files-much-more-than-c-does)\n11. [I'm getting compiler errors regarding operator new being previously defined.](#prob11-im-getting-compiler-errors-regarding-placement-operator-new-being-previously-defined)\n12. [I'm getting errors related to wchar_t string  functions such as wcslen().](#prob12-im-getting-errors-related-to-wchar_t-string--functions-such-as-wcslen)\n13. [I'm getting compiler warning C4619: there is no warning number Cxxxx (e.g. C4217).](#prob13-im-getting-compiler-warning-c4619-there-is-no-warning-number-cxxxx-eg-c4217)\n14. [My stack-based fixed_vector is not respecting the object alignment requirements.](#prob14-my-stack-based-fixed_vector-is-not-respecting-the-object-alignment-requirements)\n15. [I am getting compiler errors when using GCC under XCode (Macintosh/iphone).](#prob15-i-am-getting-compiler-errors-when-using-gcc-under-xcode-macintoshiphone)\n16. [I am getting linker errors about Vsnprintf8 or Vsnprintf16.](#prob16-i-am-getting-linker-errors-about-vsnprintf8-or-vsnprintf16)\n17. [I am getting compiler errors about UINT64_C or UINT32_C.](#prob17-i-am-getting-compiler-errors-about-uint64_c-or-uint32_c)\n18. [I am getting a crash with a global EASTL container.](#prob18-i-am-getting-a-crash-with-a-global-eastl-container)\n19. [Why doesn't EASTL support passing NULL to functions with pointer arguments?](#prob19-why-doesnt-eastl-support-passing-null-string-functions)\n\n## Debug\n\n1. [How do I get VC++ mouse-overs to view templated data?](#debug1-how-do-i-set-the-vc-debugger-to-display-eastl-container-data-with-tooltips)\n2. [How do I view containers if the visualizer/tooltip support is not present?](#debug2-how-do-i-view-containers-if-the-visualizertooltip-support-is-not-present)\n3. [The EASTL source code is sometimes rather complicated looking. Why is that?](#debug3-the-eastl-source-code-is-sometimes-rather-complicated-looking-why-is-that)\n4. [When I get compilation errors, they are very long and complicated looking. What do I do?](#debug4-when-i-get-compilation-errors-they-are-very-long-and-complicated-looking-what-do-i-do)\n5. [How do I measure hash table balancing?](#debug5-how-do-i-measure-hash-table-balancing)\n\n## Containers\n\n1. [Why do some containers have \"fixed\" versions (e.g. fixed_list) but others(e.g. deque) don't have fixed versions?](#cont1-why-do-some-containers-have-fixed-versions-eg-fixed_list-but-otherseg-deque-dont-have-fixed-versions)\n2. [Can I mix EASTL with standard C++ STL?](#cont2-can-i-mix-eastl-with-standard-c-stl)\n3. [Why are there so many containers?](#cont3-why-are-there-so-many-containers)\n4. [Don't STL and EASTL containers fragment memory?](#cont4-dont-stl-and-eastl-containers-fragment-memory)\n5. [I don't see container optimizations for equivalent scalar types such as pointer types. Why?](#cont5-i-dont-see-container-optimizations-for-equivalent-scalar-types-such-as-pointer-types-why)\n6. [What about alternative container and algorithm implementations (e.g. treaps, skip lists, avl trees)?](#cont6-what-about-alternative-container-and-algorithm-implementations-eg-treaps-skip-lists-avl-trees)\n7. [Why are containers hard to read with a debugger?](#cont7-why-are-tree-based-eastl-containers-hard-to-read-with-a-debugger)\n8. [How do I assign a custom allocator to an EASTL container?](#cont8-how-do-i-assign-a-custom-allocator-to-an-eastl-container)\n9. [How do I set the VC++ debugger to display EASTL container data with tooltips?](#cont9-how-do-i-set-the-vc-debugger-to-display-eastl-container-data-with-tooltips)\n10. [How do I use a memory pool with a container?](#cont10-how-do-i-use-a-memory-pool-with-a-container)\n11. [How do I write a comparison (operator<()) for a struct that contains two or more members?](#cont11-how-do-i-write-a-comparison-operator-for-a-struct-that-contains-two-or-more-members)\n12. [Why doesn't container X have member function Y?](#cont12-why-doesnt-container-x-have-member-function-y)\n13. [How do I search a map of strings via a char pointer efficiently? If I use map.find(\"hello\") it creates a temporary string, which is inefficient.](#cont13-how-do-i-search-a-map-of-strings-via-a-char-pointer-efficiently-if-i-use-mapfindhello-it-creates-a-temporary-string-which-is-inefficient)\n14. [Why are set and hash_set iterators const (i.e. const_iterator)?](#cont14-why-are-set-and-hash_set-iterators-const-ie-const_iterator)\n15. [How do I prevent my hash container from re-hashing?](#cont15-how-do-i-prevent-my-hash-container-from-re-hashing)\n16. [Which uses less memory, a map or a hash_map?](#cont16-which-uses-less-memory-a-map-or-a-hash_map)\n17. [How do I write a custom hash function?](#cont17-how-do-i-write-a-custom-hash-function)\n18. [How do I write a custom compare function for a map or set?](#cont18-how-do-i-write-a-custom-compare-function-for-a-map-or-set)\n19. [How do I force my vector or string capacity down to the size of the container?](#cont19-how-do-i-force-my-vector-or-string-capacity-down-to-the-size-of-the-container)\n20. [How do I iterate a container while (selectively) removing items from it?](#cont20-how-do-i-iterate-a-container-while-selectively-removing-items-from-it)\n21. [How do I store a pointer in a container?](#cont21-how-do-i-store-a-pointer-in-a-container)\n22. [How do I make a union of two containers? difference? intersection?](#cont22-how-do-i-make-a-union-of-two-containers-difference-intersection)\n23. [How do I override the default global allocator?](#cont23-how-do-i-override-the-default-global-allocator)\n24. [How do I do trick X with the string container?](#cont24-how-do-i-do-trick-x-with-the-string-container)\n25. [How do EASTL smart pointers compare to Boost smart pointers?](#cont25-how-do-eastl-smart-pointers-compare-to-boost-smart-pointers)\n26. [How do your forward-declare an EASTL container?](#cont26-how-do-your-forward-declare-an-eastl-container)\n27. [How do I make two containers share a memory pool?](#cont27-how-do-i-make-two-containers-share-a-memory-pool)\n28. [Can I use a std (STL) allocator with EASTL?](#cont28-can-i-use-a-std-stl-allocator-with-eastl)\n29. [What are the requirements of classes stored in containers?](#what-are-the-requirements-of-classes-stored-in-containers)\n\n## Algorithms\n\n1. [I'm getting screwy behavior in sorting algorithms or sorted containers. What's wrong?](#algo1-im-getting-screwy-behavior-in-sorting-algorithms-or-sorted-containers-whats-wrong)\n2. [How do I write a comparison (operator<()) for a struct that contains two or more members?](#algo2-how-do-i-write-a-comparison-operator-for-a-struct-that-contains-two-or-more-members)\n3. [How do I sort something in reverse order?](#algo3-how-do-i-sort-something-in-reverse-order)\n4. [I'm getting errors about min and max while compiling.](#algo4-im-getting-errors-about-min-and-max-while-compiling)\n5. [Why don't algorithms take a container as an argument instead of iterators? A container would be more convenient.](#algo5-why-dont-algorithms-take-a-container-as-an-argument-instead-of-iterators-a-container-would-be-more-convenient)\n6. [Given a container of pointers, how do I find an element by value (instead of by pointer)?](#algo6-given-a-container-of-pointers-how-do-i-find-an-element-by-value-instead-of-by-pointer)\n7. [When do stored objects need to support opertor < vs. when do they need to support operator ==?](#algo7-when-do-stored-objects-need-to-support-operator--vs-when-do-they-need-to-support-operator-)\n8. [How do I sort via pointers or array indexes instead of objects directly?](#algo8-how-do-i-sort-via-pointers-or-array-indexes-instead-of-objects-directly)\n\n## Iterators\n\n1. [What's the difference between iterator, const iterator, and const_iterator?](#iter1-whats-the-difference-between-iterator-const-iterator-and-const_iterator)\n2. [How do I tell from an iterator what type of thing it is iterating?](#iter2-how-do-i-tell-from-an-iterator-what-type-of-thing-it-is-iterating)\n3. [How do I iterate a container while (selectively) removing items from it?](#iter3-how-do-i-iterate-a-container-while-selectively-removing-items-from-it)\n4. [What is an insert_iterator?](#iter4-what-is-an-insert_iterator)\n\n## Information\n\n### Info.1 What is EASTL?\n\nEASTL refers to \"EA Standard Template Library.\" It is a C++ template library that is analogous to the template facilities of the C++ standard library, which are often referred to as the STL. EASTL consists of the following systems:\n\n* Containers\n* Iterators\n* Algorithms\n* Utilities\n* Smart pointers\n* Type traits\n\nOf these, the last two (smart pointers and type traits) do not have analogs in standard C++. With respect to the other items, EASTL provides extensions and optimizations over the equivalents in standard C++ STL.\n\nEASTL is a professional-level implementation which outperforms commercial implementations (where functionality overlaps) and is significantly easier to read and debug.\n\n### Info.2 What uses are EASTL suitable for?\n\nEASTL is suitable for any place where templated containers and algorithms would be appropriate. Thus any C++ tools could use it and many C++ game runtimes could use it, especially 2005+ generation game platforms. EASTL has optimizations that make it more suited to the CPUs and memory systems found on console platforms. Additionally, EASTL has some type-traits and iterator-traits-derived template optimizations that make it generally more efficient than home-brew templated containers.\n\n### Info.3 How does EASTL differ from standard C++ STL?\n\nThere are three kinds of ways that EASTL differs from standard STL:\n\n* EASTL equivalents to STL sometimes differ.\n* EASTL implementations sometimes differ from STL implementations of the same thing.\n* EASTL has functionality that doesn't exist in STL.\n\nWith respect to item #1, the changes are such that they benefit game development and and not the type that could silently hurt you if you were more familiar with STL interfaces.\n\nWith respect to item #2, where EASTL implementations differ from STL implementations it is almost always due to improvements being made in the EASTL versions or tradeoffs being made which are considered better for game development.\n\nWith respect to item #3, there are a number of facilities that EASTL has that STL doesn't have, such as intrusive_list and slist containers, smart pointers, and type traits. All of these are facilities that assist in making more efficient game code and data.\n\nWays in which EASTL is better than standard STL:\n\n* Has higher performance in release builds, sometimes dramatically so.\n* Has significantly higher performance in debug builds, due to less call overhead.\n* Has extended per-container functionality, particularly for game development.\n* Has additional containers that are useful for high performance game development.\n* Is easier to read, trace, and debug.\n* Memory allocation is much simpler and more controllable.\n* Has higher portability, as there is a single implementation for all platforms.\n* Has support of object alignment, whereas such functionality is not natively supported by STL.\n* We have control over it, so we can modify it as we like.\n* Has stricter standards for container design and behavior, particularly as this benefits game development.\n\nWays in which EASTL is worse than standard STL:\n\n* Standard STL implementations are currently very reliable and weather-worn, whereas EASTL is less tested.\n* Standard STL is automatically available with just about every C++ compiler vendor's library.\n* Standard STL is supported by the compiler vendor and somewhat by the Internet community.\n\n#### EASTL coverage of std STL\n\n* list\n* vector\n* deque\n* string\n* set\n* multiset\n* map\n* multimap\n* bitset\n* queue\n* stack\n* priority_queue\n* memory\n* numeric\n* algorithm (all but inplace_merge, prev_permutation, next_permutation, nth_element, includes, unique_copy)\n* utility\n* functional\n* iterator\n\nEASTL additions/amendments to std STL\n\n* allocators work in a simpler way.\n* exception handling can be disabled.\n* all containers expose/declare their node size, so you can make a node allocator for them.\n* all containers have reset(), which unilaterally forgets their contents.\n* all containers have validate() and validate_iterator() functions.\n* all containers understand and respect object alignment requirements.\n* all containers guarantee no memory allocation upon being newly created as empty.\n* all containers and their iterators can be viewed in a debugger (no other STL does this, believe it or not).\n* linear containers guarantee linear memory.\n* vector has push_back(void).\n* vector has a data() function.\n* vector<bool> is actually a vector of type bool.\n* vector and string have set_capacity().\n* string has sprintf(), append_sprintf(), trim(), compare_i(), make_lower(), make_upper().\n* deque allows you to specify the subarray size.\n* list has a push_back(void) and push_back(void) function.\n* hash_map, hash_set, etc. have find_as().\n\nEASTL coverage of TR1 (tr1 refers to proposed additions for the next C++ standard library, ~2008)\n\n* array\n* type_traits (there are about 30 of these)\n* unordered_set (EASTL calls it hash_set)\n* unordered_multiset\n* unordered_map\n* unordered_multimap\n* shared_ptr, shared_array, weak_ptr, scoped_ptr, scoped_array, intrusive_ptr\n\nEASTL additional functionality (not found elsewhere)\n\n* fixed_list\n* fixed_slist\n* fixed_vector\n* fixed_string\n* fixed_substring\n* fixed_set\n* fixed_multiset\n* fixed_map\n* fixed_multimap\n* fixed_hash_set\n* fixed_hash_multiset\n* fixed_hash_map\n* fixed_hash_multimap\n* vector_set\n* vector_multiset\n* vector_map\n* vector_multimap\n* intrusive_list\n* intrusive_slist\n* intrusive_sdlist\n* intrusive_hash_set\n* intrusive_hash_multiset\n* intrusive_hash_map\n* intrusive_hash_multimap\n* slist (STLPort's STL has this)\n* heap\n* linked_ptr, linked_array\n* sparse_matrix (this is not complete as of this writing)\n* ring_buffer\n* compressed_pair\n* call_traits\n* binary_search_i, change_heap, find_first_not_of, find_last_of, find_last_not_of, identical\n* comb_sort, bubble_sort, selection_sort, shaker_sort, bucket_sort\n* equal_to_2, not_equal_to_2, str_equal_to, str_equal_to_i\n\n### Info.4 Is EASTL thread-safe?\n\nIt's not simple enough to simply say that EASTL is thread-safe or thread-unsafe. However, we can say that with respect to thread safety that EASTL does the right thing.\n\nIndividual EASTL containers are not thread-safe. That is, access to an instance of a container from multiple threads at the same time is unsafe if any of those accesses are modifying operations. A given container can be read from multiple threads simultaneously as well as any other standalone data structure. If a user wants to be able to have modifying access an instance of a container from multiple threads, it is up to the user to ensure that proper thread synchronization occurs. This usually means using a mutex.\n\nEASTL classes other than containers are the same as containers with respect to thread safety. EASTL functions (e.g. algorithms) are inherently thread-safe as they have no instance data and operate entirely on the stack. As of this writing, no EASTL function allocates memory and thus doesn't bring thread safety issues via that means.\n\nThe user may well need to be concerned about thread safety with respect to memory allocation. If the user modifies containers from multiple threads, then allocators are going to be accessed from multiple threads. If an allocator is shared across multiple container instances (of the same type of container or not), then mutexes (as discussed above) the user uses to protect access to individual instances will not suffice to provide thread safety for allocators used across multiple instances. The conventional solution here is to use a mutex within the allocator if it is expected to be used by multiple threads.\n\nEASTL uses neither static nor global variables and thus there are no inter-instance dependencies that would make thread safety difficult for the user to implement.\n\n### Info.5 What platforms/compilers does EASTL support?\n\nEASTL's support depends entirely on the compiler and not on the platform. EASTL works on any C++ compiler that completely conforms the C++ language standard. Additionally, EASTL is 32 bit and 64 bit compatible. Since EASTL does not use the C or C++ standard library (with a couple small exceptions), it doesn't matter what kind of libraries are provided (or not provided) by the compiler vendor. However, given that we need to work with some compilers that aren't 100% conforming to the language standard, it will be useful to make a list here of these that are supported and those that are not:\n\n| Compiler | Status | Notes |\n|---------|--------|-------|\n| GCC 2.9x | Supported | However, GCC 2.9x has some issues that you may run into that cause you to use EASTL facilities differently than a fully compliant compiler would allow. |\n| GCC 3.x+ | Supported | This compiler is used by the Mac OSX, and Linux platforms. |\n| MSVC 6.0 | Not supported | This compiler is too weak in the area of template and namespace support. |\n| MSVC 7.0+ | Supported | This compiler is used by the PC and Win CE platforms |\n| Borland 5.5+ | Not supported | Borland can successfully compile many parts of EASTL, but not all parts. |\n| EDG | Supported | This is the compiler front end to some other compilers, such as Intel, and Comeau C++. |\n| IBM XL 5.0+ | Supported | This compiler is sometimes used by PowerPC platforms such as Mac OSX and possibly future console platforms. |\n\n### Info.6 Why is there EASTL when there is the STL?\n\nThe STL is largely a fine library for general purpose C++. However, we can improve upon it for our uses and gain other advantages as well. The primary motivations for the existence of EASTL are the following:\n\n* Some STL implementations (especially Microsoft STL) have inferior performance characteristics that make them unsuitable for game development. EASTL is faster than all existing STL implementations.\n* The STL is sometimes hard to debug, as most STL implementations use cryptic variable names and unusual data structures.\n* STL allocators are sometimes painful to work with, as they have many requirements and cannot be modified once bound to a container.\n* The STL includes excess functionality that can lead to larger code than desirable. It's not very easy to tell programmers they shouldn't use that functionality.\n* The STL is implemented with very deep function calls. This results is unacceptable performance in non-optimized builds and sometimes in optimized builds as well.\n* The STL doesn't support alignment of contained objects.\n* STL containers won't let you insert an entry into a container without supplying an entry to copy from. This can be inefficient.\n* Useful STL extensions (e.g. slist, hash_map, shared_ptr) found in existing STL implementations such as STLPort are not portable because they don't exist in other versions of STL or aren't consistent between STL versions.\n* The STL lacks useful extensions that game programmers find useful (e.g. intrusive_list) but which could be best optimized in a portable STL environment.\n* The STL has specifications that limit our ability to use it efficiently. For example, STL vectors are not guaranteed to use contiguous memory and so cannot be safely used as an array.\n* The STL puts an emphasis on correctness before performance, whereas sometimes you can get significant performance gains by making things less academcially pure.\n* STL containers have private implementations that don't allow you to work with their data in a portable way, yet sometimes this is an important thing to be able to do (e.g. node pools).\n* All existing versions of STL allocate memory in empty versions of at least some of their containers. This is not ideal and prevents optimizations such as container memory resets that can greatly increase performance in some situations.\n* The STL is slow to compile, as most modern STL implementations are very large.\n* There are legal issues that make it hard for us to freely use portable STL implementations such as STLPort.\n* We have no say in the design and implementation of the STL and so are unable to change it to work for our needs.\n* Note that there isn't actually anything in the C++ standard called \"STL.\" STL is a term that merely refers to the templated portion of the C++ standard library.\n\n### Info.7 Can I mix EASTL with standard C++ STL?\n\nThis is possible to some degree, though the extent depends on the implementation of C++ STL. One of things that makes interoperability is something called iterator categories. Containers and algorithms recognize iterator types via their category and STL iterator categories are not recognized by EASTL and vice versa.\n\nThings that you definitely can do:\n\n* #include both EASTL and standard STL headers from the same .cpp file.\n* Use EASTL containers to hold STL containers.\n* Construct an STL reverse_iterator from an EASTL iterator.\n* Construct an EASTL reverse_iterator from an STL iterator.\n\nThings that you probably will be able to do, though a given std STL implementation may prevent it:\n\n* Use STL containers in EASTL algorithms.\n* Use EASTL containers in STL algorithms.\n* Construct or assign to an STL container via iterators into an EASTL container.\n* Construct or assign to an EASTL container via iterators into an STL container.\n*\nThings that you would be able to do if the given std STL implementation is bug-free:\n\n* Use STL containers to hold EASTL containers. Unfortunately, VC7.x STL has a confirmed bug that prevents this. Similarly, STLPort versions prior to v5 have a similar but.\n\nThings that you definitely can't do:\n\n* Use an STL allocator directly with an EASTL container (though you can use one indirectly).\n* Use an EASTL allocator directly with an STL container (though you can use one indirectly).\n\n### Info.8 Where can I learn more about STL and EASTL?\n\nEASTL is close enough in philosophy and functionality to standard C++ STL that most of what you read about STL applies to EASTL. This is particularly useful with respect to container specifications. It would take a lot of work to document EASTL containers and algorithms in fine detail, whereas most standard STL documentation applies as-is to EASTL. We won't cover the differences here, as that's found in another FAQ entry.\n\nThat being said, we provide a list of sources for STL documentation that may be useful to you, especially if you are less familiar with the concepts of STL and template programming in general.\n\n* The SGI STL web site. Includes a good STL reference.\n* CodeProject STL introduction.\n* Scott Meyers Effective STL book.\n* The Microsoft online STL documentation. Microsoft links go bad every couple months, so try searching for STL at the * Microsoft MSDN site.\n* The Dinkumware online STL documentation.\n* The C++ standard, which is fairly readable. You can buy an electronic version for about $18 and in the meantime you can make do with draft revisions of it off the Internet by searching for \"c++ draft standard\".\n* STL performance tips, by Pete Isensee\n* STL algorithms vs. hand-written loops, by Scott Meyers.\n\n### Info.9 What is the legal status of EASTL?\n\nEASTL is usable for all uses within Electronic Arts, both for internal usage and for shipping products for all platforms. All source code was written by a single EA engineer. Any externally derived code would be explicitly stated as such and approved by the legal department if such code ever gets introduced. As of EASTL v1.0, the red_black_tree.cpp file contains two functions derived from the original HP STL and have received EA legal approval for usage in any product.\n\n### Info.10 Does EASTL deal with compiler exception handling settings?\n\nEASTL has automatic knowledge of the compiler's enabling/disabling of exceptions. If your compiler is set to disable exceptions, EASTL automatically detects so and executes without them. Also, you can force-enable or force-disable that setting to override the automatic behavior by #defining EASTL_EXCEPTIONS_ENABLED to 0 or 1. See EASTL's config.h for more information.\n\n### Info.11 What C++ language features does EASTL use (e.g. virtual functions)?\n\nEASTL uses the following C++ language features:\n\n* Template functions, classes, member functions.\n* Multiple inheritance.\n* Namespaces.\n* Operator overloading.\n\nEASTL does not use the following C++ language features:\n\n* Virtual functions / interfaces.\n* RTTI (dynamic_cast).\n* Global and static variables. There are a couple class static const variables, but they act much like enums.\n* Volatile declarations\n* Template export.\n* Virtual inheritance.\n\nEASTL may use the following C++ language features:\n\n* Try/catch. This is an option that the user can enable and it defaults to whatever the compiler is set to use.\n* Floating point math. Hash containers have one floating point calculation, but otherwise floating point is not used.\n\nNotes:\n\n* EASTL uses rather little of the standard C or C++ library and uses none of the C++ template library (STL) and iostream library. The memcpy family of functions is one example EASTL C++ library usage.\n* EASTL never uses global new / delete / malloc / free. All allocations are done via user-specified allocators, though a default allocator definition is available.\n\n\n### Info.12 What compiler warning levels does EASTL support?\n\nFor VC++ EASTL should compile without warnings on level 4, and should compile without warnings for \"warnings disabled by default\" except C4242, C4514, C4710, C4786, and C4820. These latter warnings are somewhat draconian and most EA projects have little choice but to leave them disabled.\n\nFor GCC, EASTL should compile without warnings with -Wall. Extensive testing beyond that hasn't been done.\n\nHowever, due to the nature of templated code generation and due to the way compilers compile templates, unforeseen warnings may occur in user code that may or may not be addressible by modifying EASTL.\n\n### Info.13 Is EASTL compatible with Lint?\n\nAs of EASTL 1.0, minimal lint testing has occurred. Testing with the November 2005 release of Lint (8.00t) demonstrated bugs in Lint that made its analysisnot very useful. For example, Lint seems to get confused about the C++ typename keyword and spews many errors with code that uses it. We will work with the makers of Lint to get this resolved so that Lint can provide useful information about EASTL.\n\n### Info.14 What compiler settings do I need to compile EASTL?\n\nEASTL consists mostly of header files with templated C++ code, but there are also a few .cpp files that need to be compiled and linked in order to use some of the modules. EASTL will compile in just about any environment. As mentioned elsewhere in this FAQ, EASTL can be compiled at the highest warning level of most compilers, transparently deals with compiler exception handling settings, is savvy to most or all compilation language options (e.g. wchar_t is built-in or not, for loop variables are local or not), and has almost no platform-specific or compiler-specific code. For the most part, you can just drop it in and it will work. The primary thing that needs to be in place is that EASTL .cpp files need to be compiled with the same struct padding/alignment settings as other code in the project. This of course is the same for just about any C++ source code library.\n\nSee the Performance section of this FAQ for a discussion of the optimal compiler settings for EASTL performance.\n\n### Info.15 How hard is it to incorporate EASTL into my project?\n\nIt's probably trivial.\n\nEASTL has only one dependency: EABase. And EASTL auto-configures itself for most compiler environments and for the most typical configuration choices. Since it is fairly highly warning-free, you won't likely need to modify your compiler warning settings, even if they're pretty stict. EASTL has a few .cpp files which need to be compiled if you want to use the modules associated with those files. You can just compile those files with your regular compiler settings. Alternatively, you can use one of the EASTL project files.\n\nIn its default configuration, the only thing you need to provide to make EASTL work is to define implementations of the following operator new functions:\n\n```cpp\n#include <new>\n\nvoid* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\nvoid* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\n```\nThe flags and debugFlags arguments correspond to PPMalloc/RenderWare GeneralAllocator/GeneralAllocatorDebug Malloc equivalents.\n\n### Info.16 Should I use EASTL instead of std STL or instead of my custom library?\n\nThere are reasons you may want to use EASTL; there are reasons you may not want to use it. Ditto for std STL or any other library. Here we present a list of reasons (+ and -) for why you might want to use one or another. However, it should be noted that while EASTL contains functionality found in std STL, it has another ~40% of functionality not found in std STL, so EASTL and std STL (and whatever other template library you may have) are not mutually exclusive.\n\n**EASTL**\n* \\+ Has higher performance than any commercial STL, especially on console platforms.\n* \\+ Has extended functionality tailored for game development.\n* \\+ Is highly configurable, and we own it so it can be amended at will. Std STL is owned by a third party committee.\n* \\+ Is much easier to read and debug than other similar libraries, especiallly std STL.\n\n\n* \\- Is highly unit tested, but does not have the same level as std STL.\n* \\- Is more complicated than many users' lite template libraries, and may put off some beginners.\n* \\- EASTL  \n\n**Std STL**\n\n* \\+ Is highly portable; your STL code will likely compile and run anywhere.\n* \\+ Works without the need to install or download any package to use it. It just works.\n* \\+ Is highly reliable and supported by the compiler vendor. You can have confidence in it.\n* \\+ Some std STL versions (e.g. STLPort, VC8 STL) have better runtime debug checking than EASTL.\n\n\n* \\- Has (sometimes greatly) variable implementations, behavior, and performance between implementations.\n* \\- Is usually hard to read and debug.\n* \\- Doesn't support some of the needs of game development, such as aligned allocations, named allocations, intrusive containers, etc.\n* \\- Is not as efficient as EASTL, especially on console platforms.\n\n**Your own library**\n(please forgive us for implying there may be weaknesses in your libraries)\n\n* \\+ You have control over it and can make it work however you want.\n* \\+ You can fix bugs in it on the spot and have the fix in your codebase immediately.\n* \\+ Your own library can be highly integrated into your application code or development environment.\n\n\n* \\- Many custom libraries don't have the same level of testing as libraries such as std STL or EASTL.\n* \\- Many custom libraries don't have the same breadth or depth as std STL or especially EASTL.\n* \\- Many custom libraries don't have the level of performance tuning that std STL or especially EASTL has.\n\n### Info.17 I think I've found a bug. What do I do?\n\n**Verify that you indeed have a bug**\n\nThere are various levels of bugs that can occur, which include the following:\n\n* Compiler warnings generated by EASTL.\n* Compiler errors generated by EASTL (failure to compile well-formed code).\n* Runtime misbehavior by EASTL (function does the wrong thing).\n* Runtime crash or data corruption by EASTL.\n* Mismatch between EASTL documentation and behavior.\n* Mismatch between EASTL behavior and user's expections (mis-design).\n\nAny of the above items can be the fault of EASTL. However, the first four can also be the fault of the user. Your primary goal in verifying a potential bug is to determine if it is an EASTL bug or a user bug. Template errors can sometimes be hard to diagnose. It's probably best if you first show the problem to somebody you know to make sure you are not missing something obvious. Creating a reproducible case may be useful in helping convince yourself, but as is mentioned below, this is not required in order to report the bug.\n\n**Report the bug**\n\nThe first place to try is the standard EA centralized tech support site. As of this writing (10/2005), that tech site is http://eatech/. Due to the frequent technology churn that seems to occur within Electronic Arts, the bug reporting system in place when you read this may not be the one that was in place when this FAQ entry was written. If the tech site route fails, consider directly contacting the maintainer of the EASTL package.\n\nIn reporting a bug, it is nice if there is a simple reproducible case that can be presented. However, such a case requires time to create, and so you are welcome to initially simply state what you think the bug is without producing a simple reproducible case. It may be that this is a known bug or it may be possible to diagnose the bug without a reproducible case. If more information is needed then the step of trying to produce a reproducible case may be necessary.\n\n### Info.18 Can EASTL be used by third party EA developers?\n\nEASTL and other core technologies authored by EA (and not licensed from other companies) can be used in source and binary form by designated 3rd parties. The primary case where there is an issue is if the library contains platform specific code for a platform that the 3rd party is not licensed for. In that case the platform-specific code would need to be removed. This doesn’t apply to EASTL, nor many of the other core tech packages.\n\n## Performance\n\n### Perf.1 How efficient is EASTL compared to standard C++ STL implementations?\n\nWith respect to the functionality that is equivalent between EASTL and standard STL, the short answer to this is that EASTL is as at least as efficient as othe STL implementations and in a number of aspects is more so. EASTL has functionality such as intrusive_list and linked_ptr that don't exist in standard STL but are explicitly present to provide significant optimizations over standard STL.\n\nThe medium length answer is that EASTL is significantly more efficient than Dinkumware STL, and Microsoft Windows STL. EASTL is generally more efficient than Metrowerks STL, but Metrowerks has a few tricks up its sleeve which EASTL doesn't currently implement. EASTL is roughly equal in efficiency to STLPort and GCC 3.x+ STL, though EASTL has some optimizations that these do not.\n\nThe long answer requires a breakdown of the functionality between various versions of the STL.\n\n### Perf.2 How efficient is EASTL in general?\n\nThis question is related to the question, \"How efficient are templates?\" If you understand the effects of templates then you can more or less see the answer for EASTL. Templates are more efficient than the alternative when they are used appropriately, but can be less efficient than the alternative when used under circumstances that don't call for them. The strength of templates is that the compiler sees all the code and data types at compile time and can often reduce statements to smaller and faster code than with conventional non-templated code. The weakness of templates is that the sometimes produce more code and can result in what is often called \"code bloat\". However, it's important to note that unused template functions result in no generated nor linked code, so if you have a templated class with 100 functions but you only use one, only that one function will be compiled.\n\nEASTL is a rather efficient implementation of a template library and pulls many tricks of the trade in terms of squeezing optimal performance out of the compiler. The only way to beat it is to write custom code for the data types you are working with, and even then people are sometimes surprised to find that their hand-implemented algorithm works no better or even worse than the EASTL equivalent. But certainly there are ways to beat templates, especially if you resort to assembly language programming and some kinds of other non-generic tricks.\n\n### Perf.3 Strings don't appear to use the \"copy-on-write\" (CoW) optimization. Why not?\n\n**Short answer**\nCoW provides a benefit for a small percentage of uses but provides a disadvantage for the large majority of uses.\n\n**Long answer**\nThe primary benefit of CoW is that it allows for the sharing of string data between two string objects. Thus if you say this:\n\n```cpp\nstring a(\"hello\");\nstring b(a);\n```\n\nthe \"hello\" will be shared between a and b. If you then say this:\n\n```cpp\na = \"world\";\n```\n\nthen *a*  will release its reference to \"hello\" and leave b with the only reference to it. Normally this functionality is accomplished via reference counting and with atomic operations or mutexes.\n\nThe C++ standard does not say anything about basic_string and CoW. However, for a basic_string implementation to be standards-conforming, a number of issues arise which dictate some things about how one would have to implement a CoW string. The discussion of these issues will not be rehashed here, as you can read the references below for better detail than can be provided in the space we have here. However, we can say that the C++ standard is sensible and that anything we try to do here to allow for an efficient CoW implementation would result in a generally unacceptable string interface.\n\nThe disadvantages of CoW strings are:\n\n* A reference count needs to exist with the string, which increases string memory usage.\n* With thread safety, atomic operations and mutex locks are expensive, especially on weaker memory systems such as console gaming platforms.\n* All non-const string accessor functions need to do a sharing check the the first such check needs to detach the string. Similarly, all string assignments need to do a sharing check as well. If you access the string before doing an assignment, the assignment doesn't result in a shared string, because the string has already been detached.\n* String sharing doesn't happen the large majority of the time. In some cases, the total sum of the reference count memory can exceed any memory savings gained by the strings that share representations.\n\nThe addition of a cow_string class is under consideration for EASTL. There are conceivably some systems which have string usage patterns which would benefit from CoW sharing. Such functionality is best saved for a separate string implementation so that the other string uses aren't penalized.\n\nReferences\n\nThis is a good starting HTML reference on the topic:\n    http://www.gotw.ca/publications/optimizations.htm\n\nHere is a well-known Usenet discussion on the topic:\n    http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d\n\n### Perf.4 Does EASTL cause code bloat, given that it uses templates?\n\nThe reason that templated functions and classes might cause an increase in code size because each template instantiation theoretically creates a unique piece of code. For example, when you compile this code:\n\n```cpp\ntemplate <typename T>\nconst T min(const T a, const T b)\n    { return b < a ? b : a; }\n\nint    i = min<int>(3, 4);\ndouble d = min<double>(3.0, 4.0);\n```\n\nthe compiler treats it as if you wrote this:\n\n```cpp\nint min(const int a, const int b)\n    { return b < a ? b : a; }\n\ndouble min(const double a, const double b)\n    { return b < a ? b : a; }\n```\n\nImagine this same effect happening with containers such as list and map and you can see how it is that templates can cause code proliferation.\n\nA couple things offset the possibility of code proliferation: inlining and folding. In practice the above 'min' function would be converted to inlined functions by the compiler which occupy only a few CPU instructions. In many of the simplest cases the inlined version actually occupies less code than the code required to push parameters on the stack and execute a function call. And they will execute much faster as well.\n\nCode folding (a.k.a. \"COMDAT folding\", \"duplicate stripping\", \"ICF\" / \"identical code folding\") is a compiler optimization whereby the compiler realizes that two independent functions have compiled to the same code and thus can be reduced to a single function. The Microsoft VC++ compiler (Since VS2005), and GCC (v 4.5+) can do these kinds of optimizations on all platforms. This can result, for example, in all templated containers of pointers (e.g. vector<char*>, vector<Widget*>, etc.) to be linked as a single implementation. This folding occurs at a function level and so individual member functions can be folded while other member functions are not. A side effect of this optimization is that you aren't likely to gain much much declaring containers of void* instead of the pointer type actually contained.\n\nThe above two features reduce the extent of code proliferation, but certainly don't eliminate it. What you need to think about is how much code might be generated vs. what your alternatives are. Containers like vector can often inline completely away, whereas more complicated containers such as map can only partially be inlined. In the case of map, if you need an such a container for your Widgets, what alternatives do you have that would be more efficient than instantiating a map? This is up to you to answer.\n\nIt's important to note that C++ compilers will throw away any templated functions that aren't used, including unused member functions of templated classes. However, some argue that by having many functions available to the user that users will choose to use that larger function set rather than stick with a more restricted set.\n\nAlso, don't be confused by syntax bloat vs. code bloat. In looking at templated libraries such as EASTL you will notice that there is sometimes a lot of text in the definition of a template implementation. But the actual underlying code is what you need to be concerned about.\n\nThere is a good Usenet discussion on this topic at: http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/2b00649a935997f5\n\n### Perf.5 Don't STL and EASTL containers fragment memory?\n\nThey only fragment memory if you use them in a way that does so. This is no different from any other type of container used in a dynamic way. There are various solutions to this problem, and EASTL provides additional help as well:\n\n* For vectors, use the reserve function (or the equivalent constructor) to set aside a block of memory for the container. The container will not reallocate memory unless you try grow beyond the capacity you reserve.\n* EASTL has \"fixed\" variations of containers which allow you to specify a fixed block of memory which the container uses for its memory. The container will not allocate any memory with these types of containers and all memory will be cache-friendly due to its locality.\n* You can assign custom allocators to containers instead of using the default global allocator. You would typically use an allocator that has its own private pool of memory.\n* Where possible, add all a container's elements to it at once up front instead of adding them over time. This avoids memory fragmentation and increase cache coherency.\n\n### Perf.6 I don't see container optimizations for equivalent scalar types such as pointer types. Why?\n\nMetrowerks (and no other, as of this writing) STL has some container specializations for type T* which maps them to type void*. The idea is that a user who declares a list of Widget* and a list of Gadget* will generate only one container: a list of void*. As a result, code generation will be smaller. Often this is done only in optimized builds, as such containers are harder to view in debug builds due to type information being lost.\n\nThe addition of this optimization is under consideration for EASTL, though it might be noted that optimizing compilers such as VC++ are already capable of recognizing duplicate generated code and folding it automatically as part of link-time code generation (LTCG) (a.k.a. \"whole program optimization\"). This has been verified with VC++, as the following code and resulting disassembly demonstrate:\n\n```cpp\neastl::list<int*>        intPtrList;\neastl::list<TestObject*> toPtrList;\n\neastl_size_t n1 = intPtrList.size();\neastl_size_t n2 = toPtrList.size();\n\n0042D288  lea         edx,[esp+14h]\n0042D28C  call        eastl::list<TestObject>::size (414180h)\n0042D291  push        eax\n0042D292  lea         edx,[esp+24h]\n0042D296  call        eastl::list<TestObject>::size (414180h)\n```\n\nNote that in the above case the compiler folded the two implementations of size() into a single implementation.\n\n### Perf.7 I've seen some STL's provide a default quick \"node allocator\" as the default allocator. Why doesn't EASTL do this?\n\n**Short answer**\n\nThis is a bad, misguided idea.\n\n**Long answer**\n\nThese node allocators implement a heap for all of STL with buckets for various sizes of allocations and implemented fixed-size pools for each of these buckets. These pools are attractive at first because they do well in STL comparison benchmarks, especially when thread safety is disabled. Such benchmarks make it impossible to truly compare STL implementations because you have two different allocators in use and in some cases allocator performance can dominate the benchmark. However, the real problem with these node allocators is that they badly fragment and waste memory. The technical discussion of this topic is outside the scope of this FAQ, but you can learn more about it by researching memory management on the Internet. Unfortunately, the people who implement STL libraries are generally not experts on the topic of memory management. A better approach, especially for game development, is for the user to decide when fixed-size pools are appropriate and use them via custom allocator assignment to containers.\n\n### Perf.8 Templates sometimes seem to take a long time to compile. Why do I do about that?\n\nC++ compilers are generally slower than C compilers, and C++ templates are generally slower to compile than regular C++ code. EASTL has some extra functionality (such as type_traits and algorithm specializations) that is not found in most other template libraries and significantly improves performance and usefulness but adds to the amount of code that needs to be compiled. Ironically, we have a case where more source code generates faster and smaller object code.\n\nThe best solution to the problem is to use pre-compiled headers, which are available on all modern ~2002+) compilers, such as VC6.0+, GCC 3.2+, and Metrowerks 7.0+. In terms of platforms this means all 2002+ platforms.\n\nSome users have been speeding up build times by creating project files that put all the source code in one large .cpp file. This has an effect similar to pre-compiled headers. It can go even faster than pre-compiled headers but has downsides in the way of convenience and portability.\n\n### Perf.10 How well does EASTL inline?\n\nEASTL is written in such as way as to be easier to inline than typical templated libraries such as STL. How is this so? It is so because EASTL reduces the inlining depth of many functions, particularly the simple ones. In doing so it makes the implementation less \"academic\" but entirely correct. An example of this is the vector operator[] function, which is implemented like so with Microsoft STL:\n\n```cpp\nreference operator[](size_type n) {\n   return *(begin() + n);\n}\n```\n\nEASTL implements the function directly, like so:\n\n```cpp\nreference operator[](size_type n) {\n    return *(mpBegin + n);\n}\n```\n\nBoth implementations are correct, but hte EASTL implementation will run faster in debug builds, be easier to debug, and will be more likely to be inlined when the usage of this function is within a hierarchy of other functions being inlined. It is not so simple to say that the Microsoft version will always inline in an optimized build, as it could be part of a chain and cause the max depth to be exceeded.\n\nThat being said, EASTL appears to inline fairly well under most circumstances, including with GCC, which is the poorest of the compilers in its ability to inline well.\n\n### Perf.11 How do I control function inlining?\n\nInlining is an important topic for templated code, as such code often relies on the compiler being able to do good function inlining for maximum performance. GCC, VC++, and Metrowerks are discussed here. We discuss compilation-level inlining and function-level inling here, though the latter is likely to be of more use to the user of EASTL, as it can externally control how EASTL is inlined. A related topic is GCC's template expansion depth, discussed elsewhere in this FAQ. We provide descriptions of inlining options here but don't currently have any advice on how to best use these with EASTL.\n\nCompilation-Level Inlining -- VC++\n\nVC++ has some basic functionality to control inlining, and the compiler is pretty good at doing aggressive inlining when optimizing on for all platforms.\n\n> **#pragma inline_depth( [0... 255] )**\n>\n> Controls the number of times inline expansion can occur by controlling the number of times that a series of function calls can be expanded (from 0 to 255 times). This pragma controls the inlining of functions marked inline and or inlined automatically under the /Ob2 option. The inline_depth pragma controls the number of times a series of function calls can be expanded. For example, if the inline depth is 4, and if A calls B and B then calls C, all three calls will be expanded inline. However, if the closest inline expansion is 2, only A and B are expanded, and C remains as a function call.\n\n> **#pragma inline_recursion( [{on | off}] )**\n>\n> Controls the inline expansion of direct or mutually recursive function calls. Use this pragma to control functions marked as inline and or functions that the compiler automatically expands under the /Ob2 option. Use of this pragma requires an /Ob compiler option setting of either 1 or 2. The default state for inline_recursion is off. The inline_recursion pragma controls how recursive functions are expanded. If inline_recursion is off, and if an inline function calls itself (either directly or indirectly), the function is expanded only once. If inline_recursion is on, the function is expanded multiple times until it reaches the value set by inline_depth, the default value of 8, or a capacity limit.\n\nCompilation-Level Inlining -- GCC\n\nGCC has a large set of options to control function inlining. Some options are available only  in GCC 3.0 and later and thus not present on older platforms.\n\n\n> **-fno-default-inline**\n>\n> Do not make member functions inline by default merely because they are defined inside the class scope (C++ only). Otherwise, when you specify -O, member functions defined inside class scope are compiled inline by default; i.e., you don't need to add 'inline' in front of the member function name.\n>\n> **-fno-inline**\n>\n> Don't pay attention to the inline keyword. Normally this option is used to keep the compiler from expanding any functions inline. Note that if you are not optimizing, no functions can be expanded inline.\n>\n> **-finline-functions**\n>\n> Integrate all simple functions into their callers. The compiler heuristically decides which functions are simple enough to be worth integrating in this way. If all calls to a given function are integrated, and the function is declared static, then the function is normally not output as assembler code in its own right. Enabled at level -O3.\n>\n> **-finline-limit=n**\n>\n> By default, GCC limits the size of functions that can be inlined. This flag allows the control of this limit for functions that are explicitly marked as inline (i.e., marked with the inline keyword or defined within the class definition in c++). n is the size of functions that can be inlined in number of pseudo instructions (not counting parameter handling). pseudo-instructions are an internal representation of function size. The default value of n is 600. Increasing this value can result in more inlined code at the cost of compilation time and memory consumption. Decreasing usually makes the compilation faster and less code will be inlined (which presumably means slower programs). This option is particularly useful for programs that use inlining heavily such as those based on recursive templates with C++.\n>\n> Inlining is actually controlled by a number of parameters, which may be specified individually by using --param name=value. The -finline-limit=n option sets some of these parameters as follows:\n>\n> ```\n> max-inline-insns-single\n>    is set to n/2.\n> max-inline-insns-auto\n>    is set to n/2.\n> min-inline-insns\n>    is set to 130 or n/4, whichever is smaller.\n> max-inline-insns-rtl\n>     is set to n.\n> ```\n>\n> See --param below for a documentation of the individual parameters controlling inlining.\n>\n> **-fkeep-inline-functions**\n>\n> Emit all inline functions into the object file, even if they are inlined where used.\n>\n> **--param name=value**\n>\n> In some places, GCC uses various constants to control the amount of optimization that is done. For example, GCC will not inline functions that contain more that a certain number of instructions. You can control some of these constants on the command-line using the --param option.\n>\n> max-inline-insns-single\n> Several parameters control the tree inliner used in gcc. This number sets the maximum number of instructions (counted in GCC's internal representation) in a single function that the tree inliner will consider for inlining. This only affects functions declared inline and methods implemented in a class declaration (C++). The default value is 450.\n>\n> max-inline-insns-auto\n> When you use -finline-functions (included in -O3), a lot of functions that would otherwise not be considered for inlining by the compiler will be investigated. To those functions, a different (more restrictive) limit compared to functions declared inline can be applied. The default value is 90.\n>\n>large-function-insns\n> The limit specifying really large functions. For functions larger than this limit after inlining inlining is constrained by --param large-function-growth. This parameter is useful primarily to avoid extreme compilation time caused by non-linear algorithms used by the backend. This parameter is ignored when -funit-at-a-time is not used. The default value is 2700.\n>\n> large-function-growth\n> Specifies maximal growth of large function caused by inlining in percents. This parameter is ignored when -funit-at-a-time is not used. The default value is 100 which limits large function growth to 2.0 times the original size.\n>\n> inline-unit-growth\n> Specifies maximal overall growth of the compilation unit caused by inlining. This parameter is ignored when -funit-at-a-time is not used. The default value is 50 which limits unit growth to 1.5 times the original size.\n>\n> max-inline-insns-recursive\n> max-inline-insns-recursive-auto\n> Specifies maximum number of instructions out-of-line copy of self recursive inline function can grow into by performing recursive inlining. For functions declared inline --param max-inline-insns-recursive is taken into acount. For function not declared inline, recursive inlining happens only when -finline-functions (included in -O3) is enabled and --param max-inline-insns-recursive-auto is used. The default value is 450.\n>\n> max-inline-recursive-depth\n> max-inline-recursive-depth-auto\n> Specifies maximum recursion depth used by the recursive inlining. For functions declared inline --param max-inline-recursive-depth is taken into acount. For function not declared inline, recursive inlining happens only when -finline-functions (included in -O3) is enabled and --param max-inline-recursive-depth-auto is used. The default value is 450.\n>\n> inline-call-cost\n> Specify cost of call instruction relative to simple arithmetics operations (having cost of 1). Increasing this cost disqualify inlinining of non-leaf functions and at same time increase size of leaf function that is believed to reduce function size by being inlined. In effect it increase amount of inlining for code having large abstraction penalty (many functions that just pass the argumetns to other functions) and decrease inlining for code with low abstraction penalty. Default value is 16.\n>\n> **-finline-limit=n**\n>\n> By default, GCC limits the size of functions that can be inlined. This flag allows the control of this limit for functions that are explicitly marked as inline (i.e., marked with the inline keyword or defined within the class definition in c++). n is the size of functions that can be inlined in number of pseudo instructions (not counting parameter handling). The default value of n is 600. Increasing this value can result in more inlined code at the cost of compilation time and memory consumption. Decreasing usually makes the compilation faster and less code will be inlined (which presumably means slower programs). This option is particularly useful for programs that use inlining heavily such as those based on recursive templates with C++.\n\nInlining is actually controlled by a number of parameters, which may be specified individually by using --param name=value. The -finline-limit=n option sets some of these parameters as follows:\n\n```\nmax-inline-insns-single\n   is set to n/2.\nmax-inline-insns-auto\n   is set to n/2.\nmin-inline-insns\n   is set to 130 or n/4, whichever is smaller.\nmax-inline-insns-rtl\n   is set to n.\n```\n\nSee below for a documentation of the individual parameters controlling inlining.\n\nNote: pseudo instruction represents, in this particular context, an abstract measurement of function's size. In no way, it represents a count of assembly instructions and as such its exact meaning might change from one release to an another.\n\nGCC additionally has the -Winline compiler warning, which emits a warning whenever a function declared as inline was not inlined.\n\nCompilation-Level Inlining -- Metrowerks\n\nMetrowerks has a number of pragmas (and corresponding compiler settings) to control inlining. These include always_inline, inline_depth, inline_max_size, and inline max_total_size.\n\n> ```\n> #pragma always_inline on | off | reset\n> ```\n>\n> Controls the use of inlined functions. If you enable this pragma, the compiler ignores all inlining limits and attempts to inline all functions where it is legal to do so. This pragma is deprecated. Use the inline_depth pragma instead.\n>\n> ```\n> #pragma inline_depth(n)\n> #pragma inline_depth(smart)\n> ```\n>\n> Controls how many passes are used to expand inline function. Sets the number of passes used to expand inline function calls. The number n is an integer from 0 to 1024 or the smart specifier. It also represents the distance allowed in the call chain from the last function up. For example, if d is the total depth of a call chain, then functions below (d-n) are inlined if they do not exceed the inline_max_size and inline_max_total_size settings which are discussed directly below.\n>\n> ```\n> #pragma inline_max_size(n);\n> #pragma inline_max_total_size(n);\n> ```\n>\n> The first pragma sets the maximum function size to be considered for inlining; the second sets the maximum size to which a function is allowed to grow after the functions it calls are inlined. Here, n is the number of statements, operands, and operators in the function, which turns out to be roughly twice the number of instructions generated by the function. However, this number can vary from function to function. For the inline_max_size pragma, the default value of n is 256; for the inline_max_total_size pragma, the default value of n is 10000. The smart specifier is the default mode, with four passes where the passes 2-4 are limited to small inline functions. All inlineable functions are expanded if inline_depth is set to 1-1024.\n\nFunction-Level Inlining -- VC++\n\n> To force inline usage under VC++, you use this:\n>\n> ```\n> __forceinline void foo(){ ... }\n> ```\n>\n> It should be noted that __forceinline has no effect if the compiler is set to disable inlining. It merely tells the compiler that when inlining is enabled that it shouldn't use its judgment to decide if the function should be inlined but instead to always inline it.\n>\n> To disable inline usage under VC++, you need to use this:\n>\n> ```\n>    #pragma inline_depth(0) // Disable inlining.\n>    void foo() { ... }\n>    #pragma inline_depth()  // Restore default.\n> ```\n>\n> The above is essentially specifying compiler-level inlining control within the code for a specific function.\n\n**Function-Level Inlining -- GCC / Metrowerks**\n\n> To force inline usage under GCC 3.1+, you use this:\n>\n> `inline void foo() __attribute__((always_inline)) { ... }`\n>\n> or\n>\n> `inline __attribute__((always_inline)) void foo() { ... }`\n>\n> To disable inline usage under GCC 3+, you use this:\n>\n> `void foo() __attribute__((noinline)) { ... }`\n>\n> or\n>\n> `inline __attribute__((noinline)) void foo() { ... }`\n\nEABase has some wrappers for this, such as EA_FORCE_INLINE.\n\n### Perf.12 C++ / EASTL seems to bloat my .obj files much more than C does.\n\nThere is no need to worry. The way most C++ compilers compile templates, they compile all seen template code into the current .obj module, which results in larger .obj files and duplicated template code in multiple .obj files. However, the linker will (and in fact must) select only a single version of any given function for the application, and these linked functions will usually be located contiguously.\n\nAdditionally, the debug information for template definitions is usually larger than that for non-templated C++ definitions, which itself is sometimes larger than C defintions due to name decoration.\n\n### Perf.13 What are the best compiler settings for EASTL?\n\nWe will discuss various aspects of this topic here. As of this writing, more EASTL research on this topic has been done on Microsoft compiler platforms (e.g. Win32) than GCC platforms. Thus currently this discussion focuses on VC++ optimization. Some of the concepts are applicable to GCC, though. EASTL has been sucessfully compiled and tested (the EASTL unit test) on our major development platforms with the highest optimization settings enabled, including GCC's infamous -O3 level.\n\n**Optimization Topics**\n\n* Function inlining.\n* Optimization for speed vs. optimization for size.\n* Link-time code generation (LTCG).\n* Profile-guided optimization (PGO).\n\n**Function inlining**\n\nEASTL is a template library and inlining is important for optimal speed. Compilers have various options for enabling inlining and those options are discussed in this FAQ in detail. Most users will want to enable some form of inlining when compiling EASTL and other templated libraries. For users that are most concerned about the compiler's inlining increasing code size may want to try the 'inline only functions marked as inline' compiler option. Here is a table of normalized results from the benchmark project (Win32 platform):\n| Inlining Disabled | Inline only 'inline' | Inline any |\n|------|------|------|------|\n| **Application size** | 100K | 86K | 86K |\n| **Execution time** | 100 | 75 | 75 |\n\nThe above execution times are highly simplified versions of the actual benchmark data but convey a sense of the general average behaviour that can be expected. In practice, simple functions such as vector::operator[] will execute much faster with inlining enabled but complex functions such as map::insert may execute no faster within inlining enabled.\n\n**Optimization for Speed / Size**\n\nOptimization for speed results in the compiler inlining more code than it would otherwise. This results in the inlined code executing faster than if it was not inlined. As mentioned above, basic function inlining can result in smaller code as well as faster code, but after a certain point highly inlined code becomes greater in size than less inlined code and the performance advantages of inlining start to lessen. The EASTL Benchmark project is a medium sized application that is about 80% templated and thus acts as a decent measure of the practical tradeoff between speed and size. Here is a table of normalized results from the benchmark project (Windows platform):\n| Size | Speed | Speed + LTCG | Speed + LTCG + PGO |\n|------|------|------|------|\n| **Application size** | 80K | 100K | 98K | 98K |\n| **Execution time** | 100 | 90 | 83 | 75 |\n\nWhat the above table is saying is that if you are willing to have your EASTL code be 20% larger, it will be 10% faster. Note that it doesn't mean that your app will be 20% larger, only the templated code in it like EASTL will be 20% larger.\n\n**Link-time code generation (LTCG)**\n\nLTCG is a mechanism whereby the compiler compiles the application as if it was all in one big .cpp file instead of separate .cpp files that don't see each other. Enabling LTCG optimizations is done by simply setting some compiler and linker settings and results in slower link times. The benchmark results are presented above and for the EASTL Benchmark project show some worthwhile improvement.\n\n**Profile-guided optimization (PGO)**\n\nPGO is a mechanism whereby the compiler uses profiling information from one or more runs to optimize the compilation and linking of an application. Enabling PGO optimizations is done by setting some linker settings and doing some test runs of the application, then linking the app with the test run results. Doing PGO optimizations is a somewhat time-consuming task but the benchmark results above demonstrate that for the EASTL Benchmark project that PGO is worth the effort.\n\n## Problems\n\n### Prob.1 I'm getting screwy behavior in sorting algorithms or sorted containers. What's wrong?\n\nIt may possible that you are seeing floating point roundoff problems. Many STL algorithms require object comparisons to act consistently. However, floating point values sometimes compare differently between uses because in one situation a value might be in 32 bit form in system memory, whereas in anther situation that value might be in an FPU register with a different precision. These are difficult problems to track down and aren't the fault of EASTL or whatever similar library you might be using. There are various solutions to the problem, but the important thing is to find a way to force the comparisons to be consistent.\n\nThe code below was an example of this happening, whereby the object pA->mPos was stored in system memory while pB->mPos was stored in a register and comparisons were inconsistent and a crash ensued.\n\n```cpp\nclass SortByDistance : public binary_function<WorldTreeObject*, WorldTreeObject*, bool>\n{\nprivate:\n    Vector3 mOrigin;\n\npublic:\n    SortByDistance(Vector3 origin) {\n        mOrigin = origin;\n    }\n\n    bool operator()(WorldTreeObject* pA, WorldTreeObject* pB) const {\n         return ((WorldObject*)pA)->mPos - mOrigin).GetLength()\n              < ((WorldObject*)pB)->mPos - mOrigin).GetLength();\n    }\n};\n```\n\nAnother thing to watch out for is the following mistake:\n\n```cpp\nstruct ValuePair\n{\n    uint32_t a;\n    uint32_t b;\n};\n\n// Improve speed by casting the struct to uint64_t\nbool operator<(const ValuePair& vp1, const ValuePair& vp2)\n    { return *(uint64_t*)&vp1 < *(uint64_t*)&vp2; }\n```\n\nThe problem is that the ValuePair struct has 32 bit alignment but the comparison assumes 64 bit alignment. The code above has been observed to crash on the PowerPC 64-based machines. The resolution is to declare ValuePair as having 64 bit alignment.\n\n### Prob.2 I am getting compiler warnings (e.g. C4244, C4242 or C4267) that make no sense. Why?\n\nOne cause of this occurs with VC++ when you have code compiled with the /Wp64 (detect 64 bit portability issues) option. This causes pointer types to have a hidden flag called __w64 attached to them by the compiler. So 'ptrdiff_t' is actually known by the compiler as '__w64 int', while 'int' is known by the compilers as simply 'int'. A problem occurs here when you use templates. For example, let's say we have this templated function\n\n``` cpp\ntemplate <typename T>\nT min(const T a, const T b) {\n    return b < a ? b : a;\n}\n```\n\nIf you compile this code:\n\n```cpp\nptrdiff_t a = min(ptrdiff_t(0), ptrdiff_t(1));\nint       b = min((int)0, (int)1);\n```\n\nYou will get the following warning for the second line, which is somewhat nonsensical:\n\n`warning C4244: 'initializing' : conversion from 'const ptrdiff_t' to 'int', possible loss of data`\n\nThis could probably be considered a VC++ bug, but in the meantime you have little choice but to ignore the warning or disable it.\n\n### Prob.3 I am getting compiler warning C4530, which complains about exception handling and \"unwind semantics.\" What gives?\n\nVC++ has a compiler option (/EHsc) that allows you to enable/disable exception handling stack unwinding but still enable try/catch. This is useful because it can save a lot in the way of code generation for your application. Disabling stack unwinding will decrease the size of your executable on at least the Win32 platform by 10-12%.\n\nIf you have stack unwinding disabled, but you have try/catch statements, VC++ will generate the following warning:\n\n`warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc`\n\nAs of EASTL v1.0, this warning has been disabled within EASTL for EASTL code. However, non-EASTL code such as std STL code may still cause this warning to be triggered. In this case there is not much you can do about this other than to disable the warning.\n\n### Prob.4 Why are tree-based EASTL containers hard to read with a debugger?\n\n**Short answer**\n\nMaximum performance and design mandates.\n\n**Long answer**\n\nYou may notice that when you have a tree-based container (e.g. set, map)  in the debugger that it isn't automatically able to recognize the tree nodes as containing instances of your contained object. You can get the debugger to do what you want with casting statements in the debug watch window, but this is not an ideal solution. The reason this is happening is that node-based containers always use an anonymous node type as the base class for container nodes. This is primarily done for performance, as it allows the node manipulation code to exist as a single non-templated library of functions and it saves memory because containers will have one or two base nodes as container 'anchors' and you don't want to allocate a node of the size of the user data when you can just use a base node. See list.h for an example of this and some additional in-code documentation on this.\n\nAdditionally, EASTL has the design mandate that an empty container constructs no user objects. This is both for performance reasons and because it doing so would skew the user's tracking of object counts and might possibly break some expectation the user has about object lifetimes.\n\nCurrently this debug issue exists only with tree-based containers. Other node-based containers such as list and slist use a trick to get around this problem in debug builds.\n\nSee [Debug.2](#debug2-how-do-i-view-containers-if-the-visualizertooltip-support-is-not-present) for more.\n\n### Prob.5 The EASTL source code is sometimes rather complicated looking. Why is that?\n\n**Short answer**\n\nMaximum performance.\n\n**Long answer**\nEASTL uses templates, type_traits, iterator categories, redundancy reduction, and branch reduction in order to achieve optimal performance. A side effect of this is that there are sometimes a lot of template parameters and multiple levels of function calls due to template specialization. The ironic thing about this is that this makes the code (an optimized build, at least) go faster, not slower. In an optimized build the compiler will see through the calls and template parameters and generate a direct optimized inline version.\n\nAs an example of this, take a look at the implementation of the copy implementation in algorithm.h. If you are copying an array of scalar values or other trivially copyable values, the compiler will see how the code directs this to the memcpy function and will generate nothing but a memcpy in the final code. For non-memcpyable data types the compiler will automatically understand that in do the right thing.\n\nEASTL's primary objective is maximal performance, and it has been deemed worthwhile to make the code a little less obvious in order to achieve this goal. Every case where EASTL does something in an indirect way is by design and usually this is for the purpose of achieving the highest possible performance.\n\n### Prob.6 When I get compilation errors, they are very long and complicated looking. What do I do?\n\nAssuming the bugs are all worked out of EASTL, these errors really do indicate that you have something wrong. EASTL is intentionally very strict about types, as it tries to minimize the chance of users errors. Unfortunately, there is no simple resolution to the problem of long compiler errors other than to deal with them. On the other hand, once you've dealt with them a few times, you tend to realize that most of time they are the same kinds of errors and\n\nTop five approaches to dealing with long compilation errors:\n\n1. Look at the line where the compilation error occurred and ignore the text of the error and just look at obvious things that might be wrong.\n2. Consider the most common typical causes of templated compilation errors and consider if any of these might be your problem. Usually one of them are.\n3. Either read through the error (it's not as hard as it may look on the surface) or copy the error to a text file and remove the extraneous\n4. Compile the code under GCC instead of MSVC, as GCC warnings and errors tend to be more helpful than MSVC's. Possibly also consider compiling an isolated version under Comeau C++'s free online compiler at www.comeaucomputing.com or the Dinkumware online compiler at http://dinkumware.com/exam/.\n5. Try using an STL filter (http://www.bdsoft.com/tools/stlfilt.html) which automatically boils down template errors to simpler forms. We haven't tried this yet with EASTL. Also there is the more generic TextFilt (http://textfilt.sourceforge.net/).\n\nTop five causes of EASTL compilation errors:\n\n1. const-correctness. Perhaps a quarter of container template errors are due to the user not specifying const correctly.\n2. Missing hash function. hash_map, hash_set, etc. require that you either specify a hash function or one exists for your class. See functional.h for examples of declarations of hash functions for common data types.\n3. Missing operators. Various containers and algorithms require that certain operators exist for your contained classes. For example, list requires that you can test contained objects for equivalence (i.e. operator==), while map requires that you can test contained objects for \"less-ness\" (operator <). If you define a Widget class and don't have a way to compare two Widgets, you will get errors when trying to put them into a map.\n4. Specifying the wrong data type. For example, it is a common mistake to forget that when you insert into a map, you need to insert a pair of objects and not just your key or value type.\n5. Incorrect template parameters. When declaring a template instantiation (e.g. map<int, int, less<int> >) you simply need to get the template parameters correct. Also note that when you have \">>\" next to each other that you need to separate them by one space (e.g. \"> >\").\n\n### Prob.7 Templates sometimes seem to take a long time to compile. Why do I do about that?\n\nC++ compilers are generally slower than C compilers, and C++ templates are generally slower to compile than regular C++ code. EASTL has some extra functionality (such as type_traits and algorithm specializations) that is not found in most other template libraries and significantly improves performance and usefulness but adds to the amount of code that needs to be compiled. Ironically, we have a case where more source code generates faster and smaller object code.\n\nThe best solution to the problem is to use pre-compiled headers, which are available on all modern ~2002+) compilers, such as VC6.0+, GCC 3.2+, and Metrowerks 7.0+. In terms of platforms this means all 2002+ platforms.\n\nSome users have been speeding up build times by creating project files that put all the source code in one large .cpp file. This has an effect similar to pre-compiled headers. It can go even faster than pre-compiled headers but has downsides in the way of convenience and portability.\n\n### Prob.8 I get the compiler error: \"template instantiation depth exceeds maximum of 17. use -ftemplate-depth-NN to increase the maximum\".\n\nThis is a GCC error that occurs when a templated function calls a templated function which calls a templated function, etc. past a depth of 17. You can use the GCC command line argument -ftemplate-depth-40 (or some other high number) to get around this. As note below, the syntax starting with GCC 4.5 has changed slightly.\n\nThe primary reason you would encounter this with EASTL is type traits that are used by algorithms. The type traits library is a (necessarily) highly templated set of types and functions which adds at most about nine levels of inlining. The copy and copy_backward algorithms have optimized pathways that add about four levels of inlining. If you have just a few more layers on top of that in container or user code then the default limit of 17 can be exceeded. We are investigating ways to reduce the template depth in the type traits library, but only so much can be done, as most compilers don't support type traits natively. Metrowerks is the current exception.\n\nFrom the GCC documentation:\n\n```\n-ftemplate-depth-n\n\nSet the maximum instantiation depth for template classes to n.\nA limit on the template instantiation depth is needed to detect\nendless recursions during template class instantiation ANSI/ISO\nC++ conforming programs must not rely on a maximum depth greater than 17.\nNote that starting with GCC 4.5 the syntax is -ftemplate-depth=N instead of -ftemplate-depth-n.\n```\n\n### Prob.9 I'm getting errors about min and max while compiling.\n\nYou need to define NOMINMAX under VC++ when this occurs, as it otherwise defines min and max macros that interfere. There may be equivalent issues with other compilers. Also, VC++ has a specific <minmax.h> header file which defines min and max macros but which doesn't pay attention to NOMINMAX and so in that case there is nothing to do but not include that file or to undefine min and max. minmax.h is not a standard file and its min and max macros are not standard C or C++ macros or functions.\n\n### Prob.10 C++ / EASTL seems to bloat my .obj files much more than C does.\n\nThere is no need to worry. The way most C++ compilers compile templates, they compile all seen template code into the current .obj module, which results in larger .obj files and duplicated template code in multiple .obj files. However, the linker will (and must) select only a single version of any given function for the application, and these linked functions will usually be located contiguously.\n\n### Prob.11 I'm getting compiler errors regarding placement operator new being previously defined.\n\nThis can happen if you are attempting to define your own versions of placement new/delete. The C++ language standard does not allow the user to override these functions. Section 18.4.3 of the standard states:\n\n> Placement forms\n> 1. These functions are reserved, a C++ program may not define functions that displace the versions in the Standard C++ library.\n\nYou may find that #defining __PLACEMENT_NEW_INLINE seems to fix your problems under VC++, but it can fail under some circumstances and is not portable and fails with other compilers, which don't have an equivalent workaround.\n\n### Prob.12 I'm getting errors related to wchar_t string  functions such as wcslen().\n\nEASTL requires EABase-related items that the following be so. If not, then EASTL gets confused about what types it can pass to wchar_t related functions.\n\n* The #define EA_WCHAR_SIZE is equal to sizeof(wchar_t).\n* If sizeof(wchar_t) == 2, then char16_t is typedef'd to wchar_t.\n* If sizeof(wchar_t) == 4, then char32_t is typedef'd to wchar_t.\n\nEABase v2.08 and later automatically does this for most current generation and all next generation platforms. With GCC 2.x, the user may need to predefine EA_WCHAR_SIZE to the appropriate value, due to limitations with the GCC compiler. Note that GCC defaults to sizeof(wchar_t) ==4, but it can be changed to 2 with the -fshort_wchar compiler command line argument. If you are using EASTL without EABase, you will need to make sure the above items are correctly defined.\n\n### Prob.13 I'm getting compiler warning C4619: there is no warning number Cxxxx (e.g. C4217).\n\nCompiler warning C4619 is a VC++ warning which is saying that the user is attempting to enable or disable a warning which the compiler doesn't recognize. This warning only occurs if the user has the compiler set to enable warnings that are normally disabled, regardless of the warning level. The problem, however, is that there is no easy way for user code to tell what compiler warnings any given compiler version will recognize. That's why Microsoft normally disables this warning.\n\nThe only practical solution we have for this is for the user to disable warning 4619 globally or an a case-by-case basis. EA build systems such as nant/framework 2's eaconfig will usually disable 4619. In general, global enabling of 'warnings that are disabled by default' often result in quandrys such as this.\n\n### Prob.14 My stack-based fixed_vector is not respecting the object alignment requirements.\n\nEASTL fixed_* containers rely on the compiler-supplied alignment directives, such as that implemented by EA_PREFIX_ALIGN. This is normally a good thing because it allows the memory to be local with the container. However, as documented by Microsoft at http://msdn2.microsoft.com/en-us/library/83ythb65(VS.71).aspx, this doesn't work for stack variables. The two primary means of working around this are:\n\n* Use something like AlignedObject<> from the EAStdC package's EAAllocator.h file.\n* Use eastl::vector with a custom allocator and have it provide aligned memory. EASTL automatically recognizes that the objects are aligned and will call the aligned version of your allocator allocate() function. You can get this aligned memory from the stack, if you need it, somewhat like how AlignedObject<> works.\n\n### Prob.15 I am getting compiler errors when using GCC under XCode (Macintosh/iphone).\n\nThe XCode environment has a compiler option which causes it to evaluate include directories recursively. So if you specify /a/b/c as an include directory, it will consider all directories underneath c to also be include directories. This option is enabled by default, though many XCode users disable it, as it is a somewhat dangerous option. The result of enabling this option with EASTL is that <EASTL/string.h> is used by the compiler when you say #include <string.h>. The solution is to disable this compiler option. It's probably a good idea to disable this option anyway, as it typically causes problems for users yet provides minimal benefits.\n\n### Prob.16 I am getting linker errors about Vsnprintf8 or Vsnprintf16.\n\nEASTL requires the user to provide a function called Vsnprintf8 if the string::sprintf function is used. vsnprintf is not a standard C function, but most C standard libraries provide some form of it, though in some ways their implementations differ, especially in what the return value means. Also, most implementations of vsnprintf are slow, mostly due to mutexes related to locale functionality. And you can't really use vendor vsnprintf on an SPU due to the heavy standard library size. EASTL is stuck because it doesn't want to depend on something with these problems. EAStdC provides a single consistent fast lightweight, yet standards-conforming, implementation in the form of Vsnprintf(char8_t*, ...), but EASTL can't have a dependency on EAStdC. So the user must provide an implementation, even if all it does is call EAStdC's Vsnprintf or the vendor vsnprintf for that matter.\n\nExample of providing Vsnprintf8 via EAStdC:\n\n```cpp\n#include <EAStdC/EASprintf.h>\n\nint Vsnprintf8(char8_t* pDestination, size_t n, const char8_t* pFormat, va_list arguments)\n{\n    return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n}\n\nint Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments)\n{\n    return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n}\n```\n\nExample of providing Vsnprintf8 via C libraries:\n\n```cpp\n#include <stdio.h>\n\nint Vsnprintf8(char8_t* p, size_t n, const char8_t* pFormat, va_list arguments)\n{\n    #ifdef _MSC_VER\n        return vsnprintf_s(p, n, _TRUNCATE, pFormat, arguments);\n    #else\n        return vsnprintf(p, n, pFormat, arguments);\n    #endif\n}\n\nint Vsnprintf16(char16_t* p, size_t n, const char16_t* pFormat, va_list arguments)\n{\n    #ifdef _MSC_VER\n        return vsnwprintf_s(p, n, _TRUNCATE, pFormat, arguments);\n    #else\n        return vsnwprintf(p, n, pFormat, arguments); // Won't work on Unix because its libraries implement wchar_t as int32_t.\n    #endif\n}\n```\n\n### Prob.17 I am getting compiler errors about UINT64_C or UINT32_C.\n\nThis is usually an order-of-include problem that comes about due to the implementation of __STDC_CONSTANT_MACROS in C++ Standard libraries. The C++ <stdint.h> header file defineds UINT64_C only if __STDC_CONSTANT_MACROS has been defined by the user or the build system; the compiler doesn't automatically define it. The failure you are seeing occurs because user code is #including a system header before #including EABase and without defining __STDC_CONSTANT_MACROS itself or globally. EABase defines __STDC_CONSTANT_MACROS and #includes the appropriate system header. But if the system header was already previously #included and __STDC_CONSTANT_MACROS was not defined, then UINT64_C doesn't get defined by anybody.\n\nThe real solution that the C++ compiler and standard library wants is for the app to globally define __STDC_CONSTANT_MACROS itself in the build.\n\n### Prob.18 I am getting a crash with a global EASTL container.\n\nThis usually due to compiler's lack of support for global (and static) C++ class instances. The crash is happening because the global variable exists but its constructor was not called on application startup and it's member data is zeroed bytes. To handle this you need to manually initialize such variables. There are two primary ways:\n\nFailing code:\n\n```cpp\neastl::list<int> gIntList; // Global variable.\n\nvoid DoSomething()\n{\n    gIntList.push_back(1); // Crash. gIntList was never constructed.\n}\n```\n\nDeclaring a pointer solution:\n\n```cpp\neastl::list<int>* gIntList = NULL;\n\nvoid DoSomething()\n{\n    if(!gIntList) // Or move this to an init function.\n        gIntList = new eastl::list<int>;\n\n    gIntList->push_back(1); // Success\n}\n```\n\nManual constructor call solution:\n\n```cpp\neastl::list<int> gIntList;\n\nvoid InitSystem()\n{\n    new(&gIntList) eastl::list<int>;\n}\n\nvoid DoSomething()\n{\n    gIntList.push_back(1); // Success\n}\n```\n\n### Prob.19 Why doesn't EASTL support passing NULL string functions?\n\nThe primary argument is to make functions safer for use. Why crash on NULL pointer access when you can make the code safe? That's a good argument. The counter argument, which EASTL currently makes, is:\n\n> It breaks consistency with the C++ STL library and C libraries, which require strings to be valid.\n>\n> It makes the coder slower and bigger for all users, though few need NULL checks.\nThe specification for how to handle NULL is simple for some cases but not simple for others. Operator < below a case where the proper handling of it in a consistent way is not simple, as all comparison code (<, >, ==, !=, >=, <=) in EASTL must universally and consistently handle the case where either or both sides are NULL. A NULL string seems similar to an empty string, but doesn't always work out so simply.\n>\n> What about other invalid string pointers? NULL is merely one invalid value of many, with its only distinction being that sometimes it's intentionally NULL (as opposed to being NULL due to not being initialized).\nHow and where to implement the NULL checks in such a way as to do it efficiently is not always simple, given that public functions call public functions.\n>\n> It's arguable (and in fact the the intent of the C++ standard library) that using pointers that are NULL is a user/app mistake. If we really want to be safe then we should be using string objects for everything. You may not entirely buy this argument in practice, but on the other hand one might ask why is the caller of EASTL using a NULL pointer in the first place? The answer of course is that somebody gave it to him.\n\n## Debug\n\n### Debug.1 How do I set the VC++ debugger to display EASTL container data with tooltips?\n\nSee [Cont.9](#cont9-how-do-i-set-the-vc-debugger-to-display-eastl-container-data-with-tooltips)\n\n### Debug.2 How do I view containers if the visualizer/tooltip support is not present?\n\nHere is a table of answers about how to manually inspect containers in the debugger.\n\n| Container | Approach |\n|------|------|\n| slist<br>fixed_slist | slist is a singly-linked list. Look at the slist mNode variable. You can walk the list by looking at mNode.mpNext, etc. |\n| list<br>fixed_list | list is a doubly-linked list. Look at the list mNode variable. You can walk the list forward by looking at mNode.mpNext, etc. and backward by looking at mpPrev, etc. |\n| intrusive_list<br>intrusive_slist† | Look at the list mAnchor node. This lets you walk forward and backward in the list via mpNext and mpPrev. |\n| array | View the array mValue member in the debugger. It's simply a C style array. |\n| vector<br>fixed_vector | View the vector mpBegin value in the debugger. If the string is long, use \", N\" to limit the view length, as with someVector.mpBegin, 32 |\n| vector_set<br>vector_multiset<br>vector_map<br>vector_multimap | These are containers that are implemented as a sorted vector, deque, or array. They are searched via a standard binary search. You can view them the same way you view a vector or deque. |\n| deque | deque is implemented as an array of arrays, where the arrays implement successive equally-sized segments of the deque. The mItBegin deque member points the deque begin() position. |\n| bitvector | Look at the bitvector mContainer variable. If it's a vector, then see vector above. |\n| bitset | Look at the bitset mWord variable. The bitset is nothing but one or more uint32_t mWord items. |\n| set<br>multiset<br>fixed_set<br>fixed_multiset | The set containers are implemented as a tree of elements. The set mAnchor.mpNodeParent points to the top of the tree; the mAnchor.mpNodeLeft points to the far left node of the tree (set begin()); the mAnchor.mpNodeRight points to the right of the tree (set end()). |\n| map<br>multimap<br>fixed_map<br>fixed_multimap | The map containers are implemented as a tree of pairs, where pair.first is the map key and pair.second is the map value. The map mAnchor.mpNodeParent points to the top of the tree; the mAnchor.mpNodeLeft points to the far left node of the tree (map begin()); the mAnchor.mpNodeRight points to the right of the tree (map end()). |\n| hash_map<br>hash_multimap<br>fixed_hash_map<br>fixed_hash_multimap | hash tables in EASTL are implemented as an array of singly-linked lists. The array is the mpBucketArray member. Each element in the list is a pair, where the first element of the pair is the map key and the second is the map value. |\n| intrusive_hash_map<br>intrusive_hash_multimap<br>intrusive_hash_set<br>intrusive_hash_multiset | intrusive hash tables in EASTL are implemented very similarly to regular hash tables. See the hash_map and hash_set entries for more info. |\n| hash_set<br>hash_multiset<br>fixed_hash_set<br>fixed_hash_map | hash tables in EASTL are implemented as an array of singly-linked lists. The array is the mpBucketArray member. |\n| basic_string<br>fixed_string<br>fixed_substring | View the string mpBegin value in the debugger. If the string is long, use \", N\" to limit the view length, as with someString.mpBegin, 32 |\n| heap | A heap is an array of data (e.g. EASTL vector) which is organized in a tree whereby the highest priority item is array[0], The next two highest priority items are array[1] and [2]. Underneath [1] in priority are items [3] and [4], and underneath item [2] in priority are items [5] and [6]. etc. |\n| stack | View the stack member c value in the debugger. That member will typically be a list or deque. |\n| queue | View the queue member c value in the debugger. That member will typically be a list or deque. |\n| priority_queue | View the priority_queue member c value in the debugger. That member will typically be a vector or deque which is organized as a heap. See the heap section above for how to view a heap. |\n| smart_ptr | View the mpValue member. |\n\n### Debug.3 The EASTL source code is sometimes rather complicated looking. Why is that?\n\n**Short answer**\n\nMaximum performance.\n\n**Long answer**\n\nEASTL uses templates, type_traits, iterator categories, redundancy reduction, and branch reduction in order to achieve optimal performance. A side effect of this is that there are sometimes a lot of template parameters and multiple levels of function calls due to template specialization. The ironic thing about this is that this makes the code (an optimized build, at least) go faster, not slower. In an optimized build the compiler will see through the calls and template parameters and generate a direct optimized inline version.\n\nAs an example of this, take a look at the implementation of the copy implementation in algorithm.h. If you are copying an array of scalar values or other trivially copyable values, the compiler will see how the code directs this to the memcpy function and will generate nothing but a memcpy in the final code. For non-memcpyable data types the compiler will automatically understand that in do the right thing.\n\nEASTL's primary objective is maximal performance, and it has been deemed worthwhile to make the code a little less obvious in order to achieve this goal. Every case where EASTL does something in an indirect way is by design and usually this is for the purpose of achieving the highest possible performance.\n\n### Debug.4 When I get compilation errors, they are very long and complicated looking. What do I do?\n\nAssuming the bugs are all worked out of EASTL, these errors really do indicate that you have something wrong. EASTL is intentionally very strict about types, as it tries to minimize the chance of users errors. Unfortunately, there is no simple resolution to the problem of long compiler errors other than to deal with them. On the other hand, once you've dealt with them a few times, you tend to realize that most of time they are the same kinds of errors and\n\nTop five approaches to dealing with long compilation errors:\n\n1.Look at the line where the compilation error occurred and ignore the text of the error and just look at obvious things that might be wrong.\n2. Consider the most common typical causes of templated compilation errors and consider if any of these might be your problem. Usually one of them are.\n3. Either read through the error (it's not as hard as it may look on the surface) or copy the error to a text file and remove the extraneous\n4. Compile the code under GCC instead of MSVC, as GCC warnings and errors tend to be more helpful than MSVC's. Possibly also consider compiling an isolated version under Comeau C++'s free online compiler at www.comeaucomputing.com or the Dinkumware online compiler at http://dinkumware.com/exam/.\n5. Try using an STL filter (http://www.bdsoft.com/tools/stlfilt.html) which automatically boils down template errors to simpler forms. We haven't tried this yet with EASTL. Also there is the more generic TextFilt (http://textfilt.sourceforge.net/).\n\nTop five causes of EASTL compilation errors:\n\n1. const-correctness. Perhaps a quarter of container template errors are due to the user not specifying const correctly.\n2. Missing hash function. hash_map, hash_set, etc. require that you either specify a hash function or one exists for your class. See functional.h for examples of declarations of hash functions for common data types.\n3. Missing operators. Various containers and algorithms require that certain operators exist for your contained classes. For example, list requires that you can test contained objects for equivalence (i.e. operator==), while map requires that you can test contained objects for \"less-ness\" (operator <). If you define a Widget class and don't have a way to compare two Widgets, you will get errors when trying to put them into a map.\n4. Specifying the wrong data type. For example, it is a common mistake to forget that when you insert into a map, you need to insert a pair of objects and not just your key or value type.\n5. Incorrect template parameters. When declaring a template instantiation (e.g. map<int, int, less<int> >) you simply need to get the template parameters correct. Also note that when you have \">>\" next to each other that you need to separate them by one space (e.g. \"> >\").\n\n### Debug.5 How do I measure hash table balancing?\n\nThe following functionality lets you spelunk hash container layout.\n\n* There is the load_factor function which tells you the overall hashtable load, but doesn't tell you if a load is unevenly distributed.\n* You can control the load factor and thus the automated bucket redistribution with set_load_factor.\n* The local_iterator begin(size_type n) and local_iterator end(size_type) functions lets you iterate each bucket individually. You can use this to examine the elements in a bucket.\n* You can use the above to get the size of any bucket, but there is also simply the bucket_size(size_type n) function.\n* The bucket_count function tells you the count of buckets. So with this you can completely visualize the layout of the hash table.\n* There is also iterator find_by_hash(hash_code_t c), for what it's worth.\n\nThe following function draws an ASCII bar graph of the hash table for easy visualization of bucket distribution:\n\n```cpp\n#include <EASTL/hash_map.h>\n#include <EASTL/algorithm.h>\n#include <stdio.h>\n\ntemplate <typename HashTable>\nvoid VisualizeHashTableBuckets(const HashTable& h)\n{\n    eastl_size_t bucketCount       = h.bucket_count();\n    eastl_size_t largestBucketSize = 0;\n\n    for(eastl_size_t i = 0; i < bucketCount; i++)\n        largestBucketSize = eastl::max_alt(largestBucketSize, h.bucket_size(i));\n\n    YourPrintFunction(\"\\n --------------------------------------------------------------------------------\\n\");\n\n    for(eastl_size_t i = 0; i < bucketCount; i++)\n    {\n        const eastl_size_t k = h.bucket_size(i) * 80 / largestBucketSize;\n\n        char buffer[16];\n        sprintf(buffer, \"%3u|\", (unsigned)i);\n        YourPrintFunction(buffer);\n\n        for(eastl_size_t j = 0; j < k; j++)\n            YourPrintFunction(\"*\");\n\n        YourPrintFunction(\"\\n\");\n    }\n\n    YourPrintFunction(\" --------------------------------------------------------------------------------\\n\");\n}\n```\n\nThis results in a graph that looks like the following (with one horizontal bar per bucket). This hashtable has a large number of collisions in each of its 10 buckets.\n\n```\n   ------------------------------------------------------\n 0|********************************************\n 1|************************************************\n 2|***************************************\n 3|********************************************\n 4|*****************************************************\n 5|*************************************************\n 6|****************************************\n 7|***********************************************\n 8|********************************************\n 9|**************************************\n10|********************************************\n   -----------------------------------------------------\n```\n\n## Containers\n\n### Cont.1 Why do some containers have \"fixed\" versions (e.g. fixed_list) but others(e.g. deque) don't have fixed versions?\n\nRecall that fixed containers are those that are implemented via a single contiguous block of memory and don't use a general purpose heap to allocate memory from. For example, fixed_list is a list container that implements its list by a user-configurable fixed block of memory. Such containers have an upper limit to how many items they can hold, but have the advantage of being more efficient with memory use and memory access coherency.\n\nThe reason why some containers don't have fixed versions is that such functionality doesn't make sense with these containers. Containers which don't have fixed versions include:\n\n```\narray, deque, bitset, stack, queue, priority_queue,\nintrusive_list, intrusive_hash_map, intrusive_hash_set,\nintrusive_hash_multimap, intrusive_hash_multimap,\nvector_map, vector_multimap, vector_set, vector_multiset.\n```\n\nSome of these containers are adapters which wrap other containers and thus there is no need for a fixed version because you can just wrap a fixed container. In the case of intrusive containers, the user is doing the allocation and so there are no memory allocations. In the case of array, the container is a primitive type which doesn't allocate memory. In the case of deque, it's primary purpose for being is to dynamically resize and thus the user would likely be better of using a fixed_vector.\n\n### Cont.2 Can I mix EASTL with standard C++ STL?\n\nThis is possible to some degree, though the extent depends on the implementation of C++ STL. One of things that makes interoperability is something called iterator categories. Containers and algorithms recognize iterator types via their category and STL iterator categories are not recognized by EASTL and vice versa.\n\nThings that you definitely can do:\n\n* #include both EASTL and standard STL headers from the same .cpp file.\n* Use EASTL containers to hold STL containers.\n* Construct an STL reverse_iterator from an EASTL iterator.\n* Construct an EASTL reverse_iterator from an STL iterator.\n\nThings that you probably will be able to do, though a given std STL implementation may prevent it:\n\n* Use STL containers in EASTL algorithms.\n* Use EASTL containers in STL algorithms.\n* Construct or assign to an STL container via iterators into an EASTL container.\n* Construct or assign to an EASTL container via iterators into an STL container.\n\nThings that you would be able to do if the given std STL implementation is bug-free:\n\n* Use STL containers to hold EASTL containers. Unfortunately, VC7.x STL has a confirmed bug that prevents this. Similarly, STLPort versions prior to v5 have a similar but.\n\nThings that you definitely can't do:\n\n* Use an STL allocator directly with an EASTL container (though you can use one indirectly).\n* Use an EASTL allocator directly with an STL container (though you can use one indirectly).\n\n### Cont.3 Why are there so many containers?\n\nEASTL has a large number of container types (e.g vector, list, set) and often has a number of variations of given types (list, slist, intrusive_list, fixed_list). The reason for this is that each container is tuned and to a specific need and there is no single container that works for all needs. The more the user is concerned about squeezing the most performance out of their system, the more the individual container variations become significant. It's important to note that having additional container types generally does not mean generating additional code or code bloat. Templates result in generated code regardless of what templated class they come from, and so for the most part you get optimal performance by choosing the optimal container for your needs.\n\n### Cont.4 Don't STL and EASTL containers fragment memory?\n\nThey only fragment memory if you use them in a way that does so. This is no different from any other type of container used in a dynamic way. There are various solutions to this problem, and EASTL provides additional help as well:\n\nFor vectors, use the reserve function (or the equivalent constructor) to set aside a block of memory for the container. The container will not reallocate memory unless you try grow beyond the capacity you reserve.\nEASTL has \"fixed\" variations of containers which allow you to specify a fixed block of memory which the container uses for its memory. The container will not allocate any memory with these types of containers and all memory will be cache-friendly due to its locality.\nYou can assign custom allocators to containers instead of using the default global allocator. You would typically use an allocator that has its own private pool of memory.\nWhere possible, add all a container's elements to it at once up front instead of adding them over time. This avoids memory fragmentation and increase cache coherency.\n\n### Cont.5 I don't see container optimizations for equivalent scalar types such as pointer types. Why?\n\nMetrowerks (and no other, as of this writing) STL has some container specializations for type T* which maps them to type void*. The idea is that a user who declares a list of Widget* and a list of Gadget* will generate only one container: a list of void*. As a result, code generation will be smaller. Often this is done only in optimized builds, as such containers are harder to view in debug builds due to type information being lost.\n\nThe addition of this optimization is under consideration for EASTL, though it might be noted that optimizing compilers such as VC++ are already capable of recognizing duplicate generated code and folding it automatically as part of link-time code generation (LTCG) (a.k.a. \"whole program optimization\"). This has been verified with VC++, as the following code and resulting disassembly demonstrate:\n\n```cpp\neastl::list<int*>        intPtrList;\neastl::list<TestObject*> toPtrList;\n\neastl_size_t n1 = intPtrList.size();\neastl_size_t n2 = toPtrList.size();\n\n0042D288  lea         edx,[esp+14h]\n0042D28C  call        eastl::list<TestObject>::size (414180h)\n0042D291  push        eax\n0042D292  lea         edx,[esp+24h]\n0042D296  call        eastl::list<TestObject>::size (414180h)\n```\n\nNote that in the above case the compiler folded the two implementations of size() into a single implementation.\n\n### Cont.6 What about alternative container and algorithm implementations (e.g. treaps, skip lists, avl trees)?\n\nEASTL chooses to implement some alternative containers and algorithms and not others. It's a matter of whether or not the alternative provides truly complementary or improved functionality over existing containers. The following is a list of some implemented and non-implemented alternatives and the rationale behind each:\n\nImplemented:\n\n* intrusive_list, etc. -- Saves memory and improves cache locality.\n* vector_map, etc. -- Saves memory and improves cache locality.\n* ring_buffer -- Useful for some types of operations and has no alternative.\n* shell_sort -- Useful sorting algorithm.\n* sparse_matrix -- Useful for some types of operations and has no alternative.\n\nNot implemented:\n\n* skip lists (alternative to red-black tree) -- These use more memory and usually perform worse than rbtrees.\n* treap (alternative to red-black tree) -- These are easier and smaller than rbtrees, but perform worse.\n* avl tree (alternative to red-black tree) -- These have slightly better search performance than rbtrees, but significantly worse * * insert/remove performance.\n* btree (alternative to red-black tree) --  These are no better than rbtrees.\n\nIf you have an idea of something that should be implemented, please suggest it or even provide at least a prototypical implementation.\n\n### Cont.7 Why are tree-based EASTL containers hard to read with a debugger?\n\n**Short answer**\n\nMaximum performance and design mandates.\n\n**Long answer**\n\nYou may notice that when you have a tree-based container (e.g. set, map)  in the debugger that it isn't automatically able to recognize the tree nodes as containing instances of your contained object. You can get the debugger to do what you want with casting statements in the debug watch window, but this is not an ideal solution. The reason this is happening is that node-based containers always use an anonymous node type as the base class for container nodes. This is primarily done for performance, as it allows the node manipulation code to exist as a single non-templated library of functions and it saves memory because containers will have one or two base nodes as container 'anchors' and you don't want to allocate a node of the size of the user data when you can just use a base node. See list.h for an example of this and some additional in-code documentation on this.\n\nAdditionally, EASTL has the design mandate that an empty container constructs no user objects. This is both for performance reasons and because it doing so would skew the user's tracking of object counts and might possibly break some expectation the user has about object lifetimes.\n\nCurrently this debug issue exists only with tree-based containers. Other node-based containers such as list and slist use a trick to get around this problem in debug builds.\n\n### Cont.8 How do I assign a custom allocator to an EASTL container?\n\nThere are two ways of doing this:\n\n1. Use the set_allocator function that is present in each container.\n2. Specify a new allocator type via the Allocator template parameter that is present in each container.\n\nFor item #1, EASTL expects that you provide an instance of an allocator of the type that EASTL recognizes. This is simple but has the disadvantage that all such allocators must be of the same class. The class would need to have C++ virtual functions in order to allow a given instance to act differently from another instance.\n\nFor item #2, you specify that the container use your own allocator class. The advantage of this is that your class can be implemented any way you want and doesn't require virtual functions for differentiation from other instances. Due to the way C++ works your class would necessarily have to use the same member function names as the default allocator class type. In order to make things easier, we provide a skeleton allocator here which you can copy and fill in with your own implementation.\n\n```cpp\nclass custom_allocator\n{\npublic:\n    custom_allocator(const char* pName = EASTL_NAME_VAL(\"custom allocator\"))\n    {\n        #if EASTL_NAME_ENABLED\n            mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n        #endif\n\n        // Possibly do something here.\n    }\n\n    custom_allocator(const allocator& x, const char* pName = EASTL_NAME_VAL(\"custom allocator\"));\n    {\n        #if EASTL_NAME_ENABLED\n            mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n        #endif\n\n        // Possibly copy from x here.\n    }\n\n    ~custom_allocator();\n    {\n        // Possibly do something here.\n    }\n\n    custom_allocator& operator=(const custom_allocator& x)\n    {\n        // Possibly copy from x here.\n        return *this;\n    }\n\n    void* allocate(size_t n, int flags = 0)\n    {\n        // Implement the allocation here.\n    }\n\n    void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0)\n    {\n        // Implement the allocation here.\n    }\n\n    void deallocate(void* p, size_t n)\n    {\n        // Implement the deallocation here.\n    }\n\n    const char* get_name() const\n    {\n        #if EASTL_NAME_ENABLED\n            return mpName;\n        #else\n            return \"custom allocator\";\n        #endif\n    }\n\n    void set_name(const char* pName)\n    {\n        #if EASTL_NAME_ENABLED\n            mpName = pName;\n        #endif\n    }\n\nprotected:\n    // Possibly place instance data here.\n\n    #if EASTL_NAME_ENABLED\n        const char* mpName; // Debug name, used to track memory.\n    #endif\n};\n\n\ninline bool operator==(const allocator& a, const allocator& b)\n{\n    // Provide a comparison here.\n}\n\ninline bool operator!=(const allocator& a, const allocator& b)\n{\n    // Provide a negative comparison here.\n}\n```\n\nHere's an example of how to use the above custom allocator:\n\n```cpp\n// Declare a Widget list and have it default construct.\nlist<Widget, custom_allocator> widgetList;\n\n// Declare a Widget list and have it construct with a copy of some global allocator.\nlist<Widget, custom_allocator> widgetList2(gSomeGlobalAllocator);\n\n// Declare a Widget list and have it default construct, but assign\n// an underlying implementation after construction.\nlist<Widget, custom_allocator> widgetList;\nwidgetList.get_allocator().mpIAllocator = new WidgetAllocatorImpl;\n```\n\n### Cont.9 How do I set the VC++ debugger to display EASTL container data with tooltips?\n\nVisual Studio supports this via the AutoExp.dat file, an example of which is [present](./html/AutoExp.dat) with this documentation.\n\nSometimes the AutoExp.dat doesn't seem to work. Avery Lee's explanation:\n\n> If I had to take a guess, the problem is most likely in the cast to the concrete node type. These are always tricky because, for some strange reason, the debugger is whitespace sensitive with regard to specifying template types. You might try manually checking one of the routines of the specific map instantiation and checking that the placement of whitespace and const within the template expression still matches exactly. In some cases the compiler uses different whitespace rules depending on the value type which makes it impossible to correctly specify a single visualizer – this was the case for eastl::list<>, for which I was forced to include sections for both cases. The downside is that you have a bunch of (error) entries either way.\n\n### Cont.10 How do I use a memory pool with a container?\n\nUsing custom memory pools is a common technique for decreasing memory fragmentation and increasing memory cache locality. EASTL gives you the flexibility of defining your own memory pool systems for containers. There are two primary ways of doing this:\n\n* Assign a custom allocator to a container. eastl::fixed_pool provides an implementation.\n* Use one of the EASTL fixed containers, such as fixed_list.\n\n**Custom Allocator**\n\nIn the custom allocator case, you will want to create a memory pool and assign it to the container. For purely node-based containers such as list, slist, map, set, multimap, and multiset, your pool simply needs to be able to allocate list nodes. Each of these containers has a member typedef called node_type which defines the type of node allocated by the container. So if you have a memory pool that has a constructor that takes the size of pool items and the count of pool items, you would do this (assuming that MemoryPool implements the Allocator interface):\n\n```cpp\ntypedef list<Widget, MemoryPool> WidgetList;           // Declare your WidgetList type.\n\nMemoryPool myPool(sizeof(WidgetList::node_type), 100); // Make a pool of 100 Widget nodes.\nWidgetList myList(&myPool);                            // Create a list that uses the pool.\n```\n\nIn the case of containers that are array-based, such as vector and basic_string, memory pools don't work very well as these containers work on a realloc-basis instead of by adding incremental nodes. What what want to do with these containers is assign a sufficient block of memory to them and reserve() the container's capacity to the size of the memory.\n\nIn the case of mixed containers which are partly array-based and partly node based, such as hash containers and deque, you can use a memory pool for the nodes but will need a single array block to supply for the buckets (hash containers and deque both use a bucket-like system).\n\nYou might consider using eastl::fixed_pool as such an allocator, as it provides such functionality and allows the user to provide the actual memory used for the pool. Here is some example code:\n\n```cpp\nchar buffer[256];\n\nlist<Widget, fixed_pool> myList;\nmyList.get_allocator().init(buffer, 256);\nFixed Container\nIn the fixed container case, the container does all the work for you. To use a list which implements a private pool of memory, just declare it like so:\n\nfixed_list<Widget, 100> fixedList; // Declare a fixed_list that can hold 100 Widgets\n```\n\n### Cont.11 How do I write a comparison (operator<()) for a struct that contains two or more members?\n\nSee [Algo.2](#algo2-how-do-i-write-a-comparison-operator-for-a-struct-that-contains-two-or-more-members).\n\n### Cont.12 Why doesn't container X have member function Y?\n\nWhy don't the list or vector containers have a find() function? Why doesn't the vector container have a sort() function? Why doesn't the string container have a mid() function? These are common examples of such questions.\n\nThe answer usually boils down to two reasons:\n\n* The functionality exists in a more centralized location elsewhere, such as the algorithms.\n* The functionality can be had by using other member functions.\n\nIn the case of find and sort functions not being part of containers, the find algorithm and sort algorithm are centralized versions that apply to any container. Additionally, the algorithms allow you to specify a sub-range of the container on which to apply the algorithm. So in order to find an element in a list, you would do this:\n\n`list<int>::iterator i = find(list.begin(), list.end(), 3);`\n\nAnd in order to sort a vector, you would do this:\n\n```cpp\nquick_sort(v.begin(), v.end());   // Sort the entire array.\n\nquick_sort(&v[3], &v[8]);         // Sort the items at the indexes in the range of [3, 8).\n```\n\nIn the case of functionality that can be had by using other member functions, note that EASTL follows the philosophy that duplicated functionality should not exist in a container, with exceptions being made for cases where mistakes and unsafe practices commonly happen if the given function isn't present. In the case of string not having a mid function, this is because there is a string constructor that takes a sub-range of another string. So to make a string out of the middle of another, you would do this:\n\n`string strMid(str, 3, 5); // Make a new string of the characters from the source range of [3, 3+5).`\n\nIt might be noted that the EASTL string class is unique among EASTL containers in that it sometimes violates the minimum functionality rule. This is so because the std C++ string class similarly does so and EASTL aims to be compatible.\n\n### Cont.13 How do I search a map of strings via a char pointer efficiently? If I use map.find(\"hello\") it creates a temporary string, which is inefficient.\n\nThe problem is illustrated with this example:\n\n```cpp\nmap<string, Widget> swMap;\n  ...\nauto it = swMap.find(\"blue\"); // A temporary string object is created here, which allocates.\n```\n\nIn this example, the find function expects a string object and not a string literal and so the compiler uses the string conversion operator to (silently!) construct a temporary string object. There are several solutions to this problem:\n\n* Make the map a map of char pointers instead of string objects. Don't forget to write a custom compare or else the default comparison function will compare pointer values instead of string contents.\n* Declare the map type with a [transparent comparison type](https://en.cppreference.com/w/cpp/utility/functional#Transparent_function_objects) (eg. [`less<void>`](https://en.cppreference.com/w/cpp/utility/functional/less_void)). The above example becomes:\n```cpp\nmap<string, Widget, less<void>> swMap;\n  ...\nauto it = swMap.find(\"blue\"); // No string object created. Uses heterogeneous lookup, which calls less<void>::operator()(const char*).\n```\nThis is advantageous over `find_as` because eastl containers support this optimization for additional member functions that take a `key_type` parameter, ie. heterogeneous lookup, insertion and erasure.\n* Use the EASTL `find_as` function, which allows you to find an item in a container via an alternative key than the one the container uses. Using a [transparent comparison type](https://en.cppreference.com/w/cpp/utility/functional#Transparent_function_objects) with the container is safer than using `find_as` because the latter requires the user specify a comparison object which must have the same semantics as the container's comparison object, otherwise the behaviour is undefined.\n\n### Cont.14 Why are set and hash_set iterators const (i.e. const_iterator)?\n\nThe situation is illustrated with this example:\n\n```cpp\nset<int> intSet;\n\nintSet.insert(1);\nset<int>::iterator i = intSet.begin();\n*i = 2; // Error: iterator i is const.\n```\n\nIn this example, the iterator is a regular iterator and not a const_iterator, yet the compiler gives an error when trying to change the iterator value. The reason this is so is that a set is an ordered container and changing the value would make it out of order. Thus, set and multiset iterators are always const_iterators. If you need to change the value and are sure the change will not alter the container order, use const_cast or declare mutable member variables for your contained object. This resolution is the one blessed by the C++ standardization committee.\n\n### Cont.15 How do I prevent my hash container from re-hashing?\n\nIf you want to make a hashtable never re-hash (i.e. increase/reallocate its bucket count), call set_max_load_factor with a very high value such as 100000.f.\n\nSimilarly, you can control the bucket growth factor with the rehash_policy function. By default, when buckets reallocate, they reallocate to about twice their previous count. You can control that value as with the example code here:\n\n```cpp\nhash_set<int> hashSet;\nhashSet.rehash_policy().mfGrowthFactor = 1.5f\n```\n\n### Cont.16 Which uses less memory, a map or a hash_map?\n\nA hash_map will virtually always use less memory. A hash_map will use an average of two pointers per stored element, while a map uses three pointers per stored element.\n\n### Cont.17 How do I write a custom hash function?\n\nYou can look at the existing hash functions in functional.h, but we provide a couple examples here.\n\nTo write a specific hash function for a Widget class, you would do this:\n\n```cpp\nstruct WidgetHash {\n    size_t operator()(const Widget& w) const\n        { return w.id; }\n};\n\nhash_set<Widget, WidgetHash> widgetHashSet;\n```\n\nTo write a generic (templated) hash function for a set of similar classes (in this case that have an id member), you would do this:\n\n```cpp\ntemplate <typename T>\nstruct GeneralHash {\n    size_t operator()(const T& t) const\n        { return t.id; }\n};\n\nhash_set<Widget, GeneralHash<Widget> > widgetHashSet;\nhash_set<Dogget, GeneralHash<Dogget> > doggetHashSet;\n```\n\n### Cont.18 How do I write a custom compare function for a map or set?\n\nThe sorted containers require that an operator< exist for the stored values or that the user provide a suitable custom comparison function. A custom can be implemented like so:\n\n```cpp\nstruct WidgetLess {\n    bool operator()(const Widget& w1, const Widget& w2) const\n        { return w.id < w2.id; }\n};\n\nset<Widget, WidgetLess> wSet;\n```\n\nIt's important that your comparison function must be consistent in its behaviour, else the container will either be unsorted or a crash will occur. This concept is called \"strict weak ordering.\"\n\n### Cont.19 How do I force my vector or string capacity down to the size of the container?\n\nYou can simply use the set_capacity() member function which is present in both vector and string. This is a function that is not present in std STL vector and string functions.\n\n```cpp\neastl::vector<Widget> x;\nx.set_capacity();   // Shrink x's capacity to be equal to its size.\n\neastl::vector<Widget> x;\nx.set_capacity(0);  // Completely clear x.\n```\n\nTo compact your vector or string in a way that would also work with std STL you need to do the following.\n\nHow to shrink a vector's capacity to be equal to its size:\n\n```cpp\nstd::vector<Widget> x;\nstd::vector<Widget>(x).swap(x); // Shrink x's capacity.\n```\n\nHow to completely clear a std::vector (size = 0, capacity = 0, no allocation):\n\n```cpp\nstd::vector<Widget> x;\nstd::vector<Widget>().swap(x); // Completely clear x.\n```\n\n### Cont.20 How do I iterate a container while (selectively) removing items from it?\n\nAll EASTL containers have an erase function which takes an iterator as an argument and returns an iterator to the next item. Thus, you can erase items from a container while iterating it like so:\n\n```cpp\nset<int> intSet;\n\nset<int>::iterator i = intSet.begin();\n\nwhile(i != intSet.end())\n{\n    if(*i & 1)  // Erase all odd integers from the container.\n        i = intSet.erase(i);\n    else\n        ++i;\n}\n```\n\n### Cont.21 How do I store a pointer in a container?\n\nThe problem with storing pointers in containers is that clearing the container will not free the pointers automatically. There are two conventional resolutions to this problem:\n\nManually free pointers when removing them from containers.\nStore the pointer as a smart pointer instead of a \"raw\"pointer.\nThe advantage of the former is that it makes the user's intent obvious and prevents the possibility of smart pointer \"thrashing\" with some containers. The disadvantage of the former is that it is more tedicous and error-prone.\n\nThe advantage of the latter is that your code will be cleaner and will always be error-free. The disadvantage is that it is perhaps slightly obfuscating and with some uses of some containers it can cause smart pointer thrashing, whereby a resize of a linear container (e.g. vector) can cause shared pointers to be repeatedly incremented and decremented with no net effect.\n\nIt's important that you use a shared smart pointer and not an unshared one such as C++ auto_ptr, as the latter will result in crashes upon linear container resizes. Here we provide an example of how to create a list of smart pointers:\n\n```cpp\nlist< shared_ptr<Widget> > wList;\n\nwList.push_back(shared_ptr<Widget>(new Widget));\nwList.pop_back(); // The Widget will be freed.\n```\n\n### Cont.22 How do I make a union of two containers? difference? intersection?\n\nThe best way to accomplish this is to sort your container (or use a sorted container such as set) and then apply the set_union, set_difference, or set_intersection algorithms.\n\n### Cont.23 How do I override the default global allocator?\n\nThere are multiple ways to accomplish this. The allocation mechanism is defined in EASTL/internal/config.h and in allocator.h/cpp. Overriding the default global allocator means overriding these files, overriding what these files refer to, or changing these files outright. Here is a list of things you can do, starting with the simplest:\n\n* Simply provide the following versions of operator new (which EASTL requires, actually):\n```cpp\nvoid* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\nvoid* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\n```\n* Predefine the config.h macros for EASTLAlloc, EASTLFree, etc. See config.h for this.\n* Override config.h entirely via EASTL_USER_CONFIG_HEADER. See config.h for this.\n* Provide your own version of allocator.h/cpp\n* Provide your own version of config.h.\n\nIf you redefine the allocator class, you can make it work however you want.\n\nNote that config.h defines EASTLAllocatorDefault, which returns the default allocator instance. As documented in config.h, this is not a global allocator which implements all container allocations but is the allocator that is used when EASTL needs to allocate memory internally. There are very few cases where EASTL allocates memory internally, and in each of these it is for a sensible reason that is documented to behave as such.\n\n### Cont.24 How do I do trick X with the string container?\n\nThere seem to be many things users want to do with strings. Perhaps the most commonly requested EASTL container extensions are string class shortcut functions. While some of these requests are being considered, we provide some shortcut functions here.\n\n**find_and_replace**\n\n```cpp\ntemplate <typename String>\nvoid find_and_replace(String& s, const typename String::value_type* pFind, const typename String::value_type* pReplace)    \n{\n    for(size_t i; (i = source.find(pFind)) != T::npos; )\n        s.replace(i, eastl::CharStrlen(pFind), pReplace);\n}\n\nExample:\n    find_and_replace(s, \"hello\", \"hola\");\n```\n\n**trim front (multiple chars)**\n\n```cpp\ntemplate <typename String>\nvoid trim_front(String& s, const typename String::value_type* pValues)\n{\n    s.erase(0, s.find_first_not_of(pValues));\n}\n\nExample:\n    trim_front(s, \" \\t\\n\\r\");\n```\n\n**trim back (multiple chars)**\n\n```cpp\ntemplate <typename String>\nvoid trim_front(String& s, const typename String::value_type* pValues)\n{\n    s.resize(s.find_last_not_of(pValues) + 1);\n}\n\nExample:\n    trim_back(s, \" \\t\\n\\r\");\n```\n\n**prepend**\n\n```cpp\ntemplate <typename String>\nvoid prepend(String& s, const typename String::value_type* p)\n{\n    s.insert(0, p);\n}\n\nExample:\n    prepend(s, \"log: \");\n```\n\n**begins_with**\n\n```cpp\ntemplate <typename String>\nbool begins_with(const String& s, const typename String::value_type* p)\n{\n    return s.compare(0, eastl::CharStrlen(p), p) == 0;\n}\n\nExample:\n    if(begins_with(s, \"log: \")) ...\n```\n\n**ends_with**\n\n```cpp\ntemplate <typename String>\nbool ends_with(const String& s, const typename String::value_type* p)\n{\n    const typename String::size_type n1 = s.size();\n    const typename String::size_type n2 = eastl::CharStrlen(p);\n    return ((n1 >= n2) && s.compare(n1 - n2, n2, p) == 0);\n}\n\nExample:\n    if(ends_with(s, \"test.\")) ...\n```\n\n**tokenize**\n\nHere is a simple tokenization function that acts very much like the C strtok function.\n\n```cpp\ntemplate <typename String>\nsize_t tokenize(const String& s, const typename String::value_type* pDelimiters,\n                String* resultArray, size_t resultArraySize)\n{\n    size_t n = 0;\n    typename String::size_type lastPos = s.find_first_not_of(pDelimiters, 0);\n    typename String::size_type pos     = s.find_first_of(pDelimiters, lastPos);\n\n    while((n < resultArraySize) && (pos != String::npos) || (lastPos != String::npos))\n    {\n        resultArray[n++].assign(s, lastPos, pos - lastPos);\n        lastPos = s.find_first_not_of(pDelimiters, pos);\n        pos     = s.find_first_of(pDelimiters, lastPos);\n    }\n\n    return n;\n}\n\nExample:\n   string resultArray[32];\ntokenize(s, \" \\t\", resultArray, 32));\n```\n\n### Cont.25 How do EASTL smart pointers compare to Boost smart pointers?\n\nEASTL's smart pointers are nearly identical to Boost (including all that crazy member template and dynamic cast functionality in shared_ptr), but are not using the Boost source code. EA legal has already stated that it is fine to have smart pointer classes with the same names and functionality as those present in Boost. EA legal specifically looked at the smart pointer classes in EASTL for this. There are two differences between EASTL smart pointers and Boost smart pointers:\n\n* EASTL smart pointers don't have thread safety built-in. It was deemed that this is too much overhead and that thread safety is something best done at a higher level. By coincidence the C++ library proposal to add shared_ptr also omits the thread safety feature. FWIW, I put a thread-safe shared_ptr in EAThread, though it doesn't attempt to do all the fancy member template things that Boost shared_ptr does. Maybe I'll add that some day if people care.\n* EASTL shared_ptr object deletion goes through a deletion object instead of through a virtual function interface. 95% of the time this makes no difference (aside from being more efficient), but the primary case where it matters is when you have shared_ptr<void> and assign to is something like \"new Widget\". The problem is that shared_ptr<void> doesn't know what destructor to call and so doesn't call a destructor unless you specify a custom destructor object as part of the template specification. I don't know what to say about this one, as it is less safe, but forcing everybody to have the overhead of additional templated classes and virtual destruction functions doesn't seem to be in the spirit of high performance or lean game development.\n\nThere is the possibility of making a shared_ptr_boost which is completely identical to Boost shared_ptr. So perhaps that will be done some day.\n\n### Cont.26 How do your forward-declare an EASTL container?\n\nHere is are some examples of how to do this:\n\n```cpp\nnamespace eastl\n{\n    template <typename T, typename Allocator> class basic_string;\n    typedef basic_string<char, allocator> string8;   // Forward declare EASTL's string8 type.\n\n    template <typename T, typename Allocator> class vector;\n    typedef vector<char, allocator> CharArray;\n\n    template <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode> class hash_set;\n\n    template <typename Key, typename T, typename Compare, typename Allocator> class map;\n}\n```\n\nThe forward declaration can be used to declare a pointer or reference to such a class. It cannot be used to declare an instance of a class or refer to class data, static or otherwise. Nevertheless, forward declarations for pointers and references are useful for reducing the number of header files a header file needs to include.\n\n### Cont.27 How do I make two containers share a memory pool?\n\nEASTL (and std STL) allocators are specified by value semantics and not reference semantics. Value semantics is more powerful (because a value can also be a reference, but not the other way around), but is not always what people expects if they're used to writing things the other way.\n\nHere is some example code:\n\n```cpp\nstruct fixed_pool_reference\n{\npublic:\n    fixed_pool_reference()\n    {\n        mpFixedPool = NULL;\n    }\n\n    fixed_pool_reference(eastl::fixed_pool& fixedPool)\n    {\n        mpFixedPool = &fixedPool;\n    }\n\n    fixed_pool_reference(const fixed_pool_reference& x)\n    {\n        mpFixedPool = x.mpFixedPool;\n    }\n\n    fixed_pool_reference& operator=(const fixed_pool_reference& x)\n    {\n        mpFixedPool = x.mpFixedPool;\n        return *this;\n    }\n\n    void* allocate(size_t /*n*/, int /*flags*/ = 0)\n    {\n        return mpFixedPool->allocate();\n    }\n\n    void* allocate(size_t /*n*/, size_t /*alignment*/, size_t /*offset*/, int /*flags*/ = 0)\n    {\n        return mpFixedPool->allocate();\n    }\n\n    void deallocate(void* p, size_t /*n*/)\n    {\n        return mpFixedPool->deallocate(p);\n    }\n\n    const char* get_name() const\n    {\n        return \"fixed_pool_reference\";\n    }\n\n    void set_name(const char* /*pName*/)\n    {\n    }\n\nprotected:\n    friend bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b);\n    friend bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b);\n\n    eastl::fixed_pool* mpFixedPool;\n};\n\ninline bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b)\n{\n    return (a.mpFixedPool == b.mpFixedPool);\n}\n\ninline bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b)\n{\n    return (a.mpFixedPool != b.mpFixedPool);\n}\n```\n\nExample usage of the above:\n\n```cpp\ntypedef eastl::list<int, fixed_pool_reference> IntList;\n\nIntList::node_type buffer[2];\neastl::fixed_pool  myPool(buffer, sizeof(buffer), sizeof(Int::node_type), 2);\n\nIntList myList1(myPool);\nIntList myList2(myPool);\n\nmyList1.push_back(37);\nmyList2.push_back(39);\n```\n\n### Cont.28 Can I use a std (STL) allocator with EASTL?\n\nNo. EASTL allocators are similar in interface to std STL allocators, but not 100% compatible. If it was possible to make them compatible with std STL allocators but also match the design of EASTL then compatibility would exist. The primary reasons for lack of compatibility are:\n\n* EASTL allocators have a different allocate function signature.\n* EASTL allocators have as many as four extra required functions: ctor(name), get_name(), set_name(), allocate(size, align, offset).\n* EASTL allocators have an additional allocate function specifically for aligned allocations, as listed directly above.\n\n### What are the requirements of classes stored in containers?\n\nClass types stored in containers must have:\n\n* a public copy constructor\n* a public assignment operator\n* a public destructor\n* an operator < that compares two such classes (sorted containers only).\n* an operator == that compares two such classes (hash containers only).\n\nRecall that the compiler generates basic versions these functions for you when you don't implement them yourself, so you can omit any of the above if the compiler-generated version is sufficient.\n\nFor example, the following code will act incorrectly, because the user forgot to implement an assignment operator. The compiler-generated assignment operator will assign the refCount value, which the user doesn't want, and which will be called by the vector during resizing.\n\n```cpp\nstruct NotAPod\n{\n   NotAPod(const NotAPod&) {} // Intentionally don't copy the refCount\n\n   int refCount; // refCounts should not be copied between NotAPod instances.\n};\n\neastl::vector<NotAPod> v;\n```\n\n## Algorithms\n\n### Algo.1 I'm getting screwy behavior in sorting algorithms or sorted containers. What's wrong?\n\nIt may possible that you are seeing floating point roundoff problems. Many STL algorithms require object comparisons to act consistently. However, floating point values sometimes compare differently between uses because in one situation a value might be in 32 bit form in system memory, whereas in anther situation that value might be in an FPU register with a different precision. These are difficult problems to track down and aren't the fault of EASTL or whatever similar library you might be using. There are various solutions to the problem, but the important thing is to find a way to force the comparisons to be consistent.\n\nThe code below was an example of this happening, whereby the object pA->mPos was stored in system memory while pB->mPos was stored in a register and comparisons were inconsistent and a crash ensued.\n\n```cpp\nclass SortByDistance : public binary_function<WorldTreeObject*, WorldTreeObject*, bool>\n{\nprivate:\n    Vector3 mOrigin;\n\npublic:\n    SortByDistance(Vector3 origin) {\n        mOrigin = origin;\n    }\n\n    bool operator()(WorldTreeObject* pA, WorldTreeObject* pB) const {\n        return ((WorldObject*)pA)->mPos - mOrigin).GetLength()\n             < ((WorldObject*)pB)->mPos - mOrigin).GetLength();\n    }\n};\n```\n\n### Algo.2 How do I write a comparison (operator<()) for a struct that contains two or more members?\n\nFor a struct with two members such as the following:\n\n```cpp\nstruct X {\n    Blah m1;\n    Blah m2;\n};\n```\n\nYou would write the comparison function like this:\n\n```cpp\nbool operator<(const X& a, const X& b) {\n    return (a.m1 == b.m1) ? (a.m2 < b.m2) : (a.m1 < b.m1);\n}\n```\n\nor, using only operator < but more instructions:\n\n```cpp\nbool operator<(const X& a, const X& b) {\n    return (a.m1 < b.m1) || (!(b.m1 < a.m1) && (a.m2 < b.m2));\n}\n```\n\nFor a struct with three members, you would have:\n\n```cpp\nbool operator<(const X& a, const X& b) {\n    if(a.m1 != b.m1)\n        return (a.m1 < b.m1);\n    if(a.m2 != b.m2)\n        return (a.m2 < b.m2);\n    return (a.mType < b.mType);\n}\n```\n\nAnd a somewhat messy implementation if you wanted to use only operator <.\n\nNote also that you can use the above technique to implement operator < for spatial types such as vectors, points, and rectangles. You would simply treat the members of the stuct as an array of values and ignore the fact that they have spatial meaning. All operator < cares about is that things order consistently.\n\n```cpp\nbool operator<(const Point2D& a, const Point2D& b) {\n    return (a.x == b.x) ? (a.y < b.y) : (a.x < b.x);\n}\n```\n\n### Algo.3 How do I sort something in reverse order?\n\nNormally sorting puts the lowest value items first in the sorted range. You can change this by simply reversing the comparison. For example:\n\n`sort(intVector.begin(), intVector.end(), greater<int>());`\n\nIt's important that you use operator > instead of >=. The comparison function must return false for every case where values are equal.\n\n### Algo.4 I'm getting errors about min and max while compiling.\n\nYou need to define NOMINMAX under VC++ when this occurs, as it otherwise defines min and max macros that interfere. There may be equivalent issues with other compilers. Also, VC++ has a specific <minmax.h> header file which defines min and max macros but which doesn't pay attention to NOMINMAX and so in that case there is nothing to do but not include that file or to undefine min and max. minmax.h is not a standard file and its min and max macros are not standard C or C++ macros or functions.\n\n### Algo.5 Why don't algorithms take a container as an argument instead of iterators? A container would be more convenient.\n\nHaving algorithms that use containers instead of algorithms would reduce reduce functionality with no increase in performance. This is because the use of iterators allows for the application of algorithms to sub-ranges of containers and allows for the application of algorithms to containers aren't formal C++ objects, such as C-style arrays.\n\nProviding additional algorithms that use containers would introduce redundancy with respect to the existing algorithms that use iterators.\n\n### Algo.6 Given a container of pointers, how do I find an element by value (instead of by pointer)?\n\nFunctions such as find_if help you find a T element in a container of Ts. But if you have a container of pointers such as vector<Widget*>, these functions will enable you to find an element that matches a given Widget* pointer, but they don't let you find an element that matches a given Widget object.\n\nYou can write your own iterating 'for' loop and compare values, or you can use a generic function object to do the work if this is a common task:\n\n```cpp\ntemplate<typename T>\nstruct dereferenced_equal\n{\n    const T& mValue;\n\n    dereferenced_equal(const T& value) : mValue(value) { }     \n    bool operator==(const T* pValue) const { return *pValue == mValue; }\n};\n\n...\n\nfind_if(container.begin(), container.end(), dereferenced_equal<Widget>(someWidget));\n```\n\n### Algo.7 When do stored objects need to support operator < vs. when do they need to support operator ==?\n\nAny object which is sorted needs to have operator < defined for it, implicitly via operator < or explicitly via a user-supplied Compare function. Sets and map containers require operator <, while sort, binary search, and min/max algorithms require operator <.\n\nAny object which is compareed for equality needs to have operator == defined for it, implicitly via operator == or explicitly via a user-supplied BinaryPredicate function. Hash containers required operator ==, while many of the algorithms other than those mentioned above for operator < require operator ==.\n\nSome algorithms and containers require neither < nor ==. Interestingly, no algorithm or container requires both < and ==.\n\n### Algo.8 How do I sort via pointers or array indexes instead of objects directly?\n\nPointers\n\n```cpp\nvector<TestObject>  toArray;\nvector<TestObject*> topArray;\n\nfor(eastl_size_t i = 0; i < 32; i++)\n   toArray.push_back(TestObject(rng.RandLimit(20)));\nfor(eastl_size_t i = 0; i < 32; i++) // This needs to be a second loop because the addresses might change in the first loop due to container resizing.\n   topArray.push_back(&toArray[i]);\n\nstruct TestObjectPtrCompare\n{\n    bool operator()(TestObject* a, TestObject* b)\n        { return a->mX < a->mX; }\n};\n\nquick_sort(topArray.begin(), topArray.end(), TestObjectPtrCompare());\n```\n\nArray indexes\n\n```cpp\nvector<TestObject>   toArray;\nvector<eastl_size_t> toiArray;\n\nfor(eastl_size_t i = 0; i < 32; i++)\n{\n    toArray.push_back(TestObject(rng.RandLimit(20)));\n    toiArray.push_back(i);\n}\n\nstruct TestObjectIndexCompare\n{\n    vector* mpArray;\n\n    TestObjectIndexCompare(vector<TestObject>* pArray) : mpArray(pArray) { }\n    TestObjectIndexCompare(const TestObjectIndexCompare& x) : mpArray(x.mpArray){ }\n    TestObjectIndexCompare& operator=(const TestObjectIndexCompare& x) { mpArray = x.mpArray; return *this; }\n\n    bool operator()(eastl_size_t a, eastl_size_t b)\n       { return (*mpArray)[a] < (*mpArray)[b]; }\n};\n\nquick_sort(toiArray.begin(), toiArray.end(), TestObjectIndexCompare(&toArray));\n```\n\nArray indexes (simpler version using toArray as a global variable)\n\n```cpp\nvector<TestObject>   toArray;\nvector<eastl_size_t> toiArray;\n\nfor(eastl_size_t i = 0; i < 32; i++)\n{\n    toArray.push_back(TestObject(rng.RandLimit(20)));\n    toiArray.push_back(i);\n}\n\nstruct TestObjectIndexCompare\n{\n    bool operator()(eastl_size_t a, eastl_size_t b)\n       { return toArray[a] < toArray[b]; }\n};\n\nquick_sort(toiArray.begin(), toiArray.end(), TestObjectIndexCompare(&toArray));\n```\n\n## Iterators\n\n### Iter.1 What's the difference between iterator, const iterator, and const_iterator?\n\nAn iterator can be modified and item it points to can be modified.\nA const iterator cannot be modified, but the items it points to can be modified.\nA const_iterator can be modified, but the items it points to cannot be modified.\nA const const_iterator cannot be modified, nor can the items it points to.\n\nThis situation is much like with char pointers:\n\n| Iterator type | Pointer equivalent |\n|------|------|\n| iterator | char* |\n| const iterator | char* const |\n| const_iterator | const char* |\n| const const_iterator | const char* const |\n\n### Iter.2 How do I tell from an iterator what type of thing it is iterating?\n\nUse the value_type typedef from iterator_traits, as in this example\n\n```cpp\ntemplate <typename Iterator>\nvoid DoSomething(Iterator first, Iterator last)\n{\n    typedef typename iterator_traits<Iterator>::value_type;\n\n    // use value_type\n}\n```\n\n### Iter.3 How do I iterate a container while (selectively) removing items from it?\n\nAll EASTL containers have an erase function which takes an iterator as an argument and returns an iterator to the next item. Thus, you can erase items from a container while iterating it like so:\n\n```cpp\nset<int> intSet;\nset<int>::iterator i = intSet.begin();\n\nwhile(i != intSet.end())\n{\n    if(*i & 1) // Erase all odd integers from the container.\n        i = intSet.erase(i);\n    else\n        ++i;\n}\n```\n\n### Iter.4 What is an insert_iterator?\n\nAn insert_iterator is a utility class which is like an iterator except that when you assign a value to it, the insert_iterator inserts the value into the container (via insert()) and increments the iterator. Similarly, there are front_insert_iterator and back_insert_iterator, which are similar to insert_iterator except that assigning a value to them causes then to call push_front and push_back, respectively, on the container. These utilities may seem a slightly abstract, but they have uses in generic programming.\n\n----------------------------------------------\nEnd of document\n"
  },
  {
    "path": "doc/Glossary.md",
    "content": "# EASTL Glossary\n\nThis document provides definitions to various terms related to EASTL. Items that are capitalized are items that are used as template parameters.\n\n|  |  |\n|------|------|\n| adapter | An adapter is something that encapsulates a component to provide another interface, such as a C++ class which makes a stack out of a list. |\n| algorithm | Algorithms are standalone functions which manipulate data which usually but not necessarily comes from a container. Some algorithms change the data while others don't. Examples are reverse, sort, find, and remove. |\n| associative container | An associative container is a variable-sized container that supports efficient retrieval of elements (values) based on keys. It supports insertion and removal of elements, but differs from a sequence in that it does not provide a mechanism for inserting an element at a specific position. Associative containers include map, multimap, set, multiset, hash_map, hash_multimap, hash_set, hash_multiset. |\n| array | An array is a C++ container which directly implements a C-style fixed array but which adds STL container semantics to it. |\n| basic_string | A templated string class which is usually used to store char or wchar_t strings. |\n| begin | The function used by all conventional containers to return the first item in the container. |\n| BidirectionalIterator | An input iterator which is like ForwardIterator except it can be read in a backward direction as well. |\n| BinaryOperation  | A function which takes two arguments and returns a value (which will usually be assigned to a third object). |\n| BinaryPredicate | A function which takes two arguments and returns true if some criteria is met (e.g. they are equal). |\n| binder1st, binder2nd | These are function objects which convert one function object into another.  In particular, they implement a binary function whereby you can specify one of the arguments.This is a somewhat abstract concept but has its uses. |\n| bit vector | A specialized container that acts like vector<bool> but is implemented via one bit per entry. STL vector<bool> is usually implemented as a bit vector but EASTL avoids this in favor of a specific bit vector container. |\n| bitset | An extensible yet efficient implementation of bit flags. Not strictly a conventional STL container and not the same thing as vector<bool> or a bit_vector, both of which are formal iterate-able containers. |\n| capacity | Refers to the amount of total storage available in an array-based container such as vector, string, and array. Capacity is always >= container size and is > size in order to provide extra space for a container to grow into. |\n| const_iterator | An iterator whose iterated items are cannot be modified. A const_iterator is akin to a const pointer such as 'const char*'. |\n| container | A container is an object that stores other objects (its elements), and that has methods for accessing its elements. In particular, every type that is a model of container has an associated iterator type that can be used to iterate through the container's elements. |\n| copy constructor | A constructor for a type which takes another object of that type as its argument. For a hypothetical Widget class, the copy constructor is of the form Widget(const Widget& src); |\n| Compare | A function which takes two arguments and returns the lesser of the two. |\n| deque | The name deque is pronounced \"deck\" and stands for \"double-ended queue.\"<br><br> A deque is very much like a vector: like vector, it is a sequence that supports random access to elements, constant time insertion and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle.<br><br> The main way in which deque differs from vector is that deque also supports constant time insertion and removal of elements at the beginning of the sequence. Additionally, deque does not have any member functions analogous to vector's capacity() and reserve(), and does not provide the guarantees on iterator validity that are associated with those member functions. |\n| difference_type | The typedef'd type used by all conventional containers and iterators to define the distance between two iterators. It is usually the same thing as the C/C++ ptrdiff_t data type. |\n| empty | The function used by all conventional containers to tell if a container has a size of zero. In many cases empty is more efficient than checking for size() == 0. |\n| element | An element refers to a member of a container. |\n| end | The function used by all conventional containers to return one-past the last item in the container. |\n| equal_range | equal_range is a version of binary search: it attempts to find the element value in an ordered range [first, last). The value returned by equal_range is essentially a combination of the values returned by lower_bound and upper_bound: it returns a pair of iterators i and j such that i is the first position where value could be inserted without violating the ordering and j is the last position where value could be inserted without violating the ordering. It follows that every element in the range [i, j) is equivalent to value, and that [i, j) is the largest subrange of [first, last) that has this property. |\n| explicit instantiation | Explicit instantiation lets you create an instantiation of a templated class or function without actually using it in your code. Since this is useful when you are creating library files that use templates for distribution, uninstantiated template definitions are not put into object files. An example of the syntax for explicit instantiation is:<br> `template class vector<char>;`<br> `template void min<int>(int, int);`<br> `template void min(int, int);` |\n| ForwardIterator | An input iterator which is like InputIterator except it can be reset back to the beginning. |\n| Function | A function which takes one argument and applies some operation to the target. |\n| function object, functor | A function object or functor is a class that has the function-call operator (<tt>operator()</tt>) defined. |\n| Generator | A function which takes no arguments and returns a value (which will usually be assigned to an object). |\n| hash_map, hash_multimap, hash_set, hash_multiset | The hash containers are implementations of map, multimap, set, and multiset via a hashtable instead of via a tree. Searches are O(1) (fast) but the container is not sorted. |\n| heap | A heap is a data structure which is not necessarily sorted but is organized such that the highest priority item is at the top. A heap is synonymous with a priority queue and has numerous applications in computer science. |\n| InputIterator | An input iterator (iterator you read from) which allows reading each element only once and only in a forward direction. |\n| intrusive_list, intrusive_hash_map, etc. | Intrusive containers are containers which don't allocate memory but instead use their contained object to manage the container's memory. While list allocates nodes (with mpPrev/mpNext pointers) that contain the list items, intrusive_list doesn't allocate nodes but instead the container items have the mpPrev/mpNext pointers. |\n| intrusive_ptr | intrusive_ptr is a smart pointer which doesn't allocate memory but instead uses the contained object to manage lifetime via addref and release functions. |\n| iterator | An iterator is the fundamental entity of reading and enumerating values in a container. Much like a pointer can be used to walk through a character array, an iterator is used to walk through a linked list. |\n| iterator category | An iterator category defines the functionality the iterator provides. The conventional iterator categories are InputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator, and OutputIterator. See the definitions of each of these for more information.Iterator category is synonymous with <span style=\"font-style: italic;\">iterator_tag</span>. |\n| iterator_tag | See <span style=\"font-style: italic;\">iterator category</span>. |\n| key_type, Key | A Key or key_type is the identifier used by associative (a.k.a. dictionary) containers (e.g. map, hash_map) to identify the type used to index the mapped_type. If you have a dictionary of strings that you access by an integer id, the ids are the keys and the strings are the mapped types. |\n| lexicographical compare | A lexicographical compare is a comparison of two containers that compares them element by element, much like the C strcmp function compares two strings. |\n| linked_ptr | A linked_ptr is a shared smart pointer which implements object lifetime via a linked list of all linked_ptrs that are referencing the object. linked_ptr, like intrusive_ptr, is a non-memory-allocating alternative to shared_ptr. |\n| list | A list is a doubly linked list. It is a sequence that supports both forward and backward traversal, and (amortized) constant time insertion and removal of elements at the beginning or the end, or in the middle. Lists have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed. The ordering of iterators may be changed (that is, list<T>::iterator might have a different predecessor or successor after a list operation than it did before), but the iterators themselves will not be invalidated or made to point to different elements unless that invalidation or mutation is explicit. |\n| lower_bound | lower_bound is a version of binary search: it attempts to find the element value in an ordered range [first, last). Specifically, it returns the first position where value could be inserted without violating the ordering. |\n| map | Map is a sorted associative container that associates objects of type Key with objects of type T. Map is a pair associative container, meaning that its value type is pair<const Key, T>. It is also a unique associative container, meaning that no two elements have the same key. It is implemented with a tree structure. |\n| mapped_type | A mapped_type is a typedef used by associative containers to identify the container object which is accessed by a key. If you have a dictionary of strings that you access by an integer id, the ids are the keys and the strings are the mapped types. |\n| member template | A member template is a templated function of a templated class. Thus with a member template function there are two levels of templating -- the class and the function. |\n| multimap,  | Multimap is a sorted associative container that associates objects of type Key with objects of type T. multimap is a pair associative container, meaning that its value type is pair<const Key, T>. It is also a multiple associative container, meaning that there is no limit on the number of elements with the same key.It is implemented with a tree structure. |\n| multiset | Multiset is a sorted associative container that stores objects of type Key. Its value type, as well as its key type, is Key. It is also a multiple associative container, meaning that two or more elements may be identical. It is implemented with a tree structure. |\n| node | A node is a little holder class used by many containers to hold the contained items. A linked-list, for example, defines a node which has three members: mpPrev, mpNext, and T (the contained object). |\n| npos | npos is used by the string class to identify a non-existent index. Some string functions return npos to indicate that the function failed. |\n| rel_ops | rel_ops refers to \"relational operators\" and is a set of templated functions which provide operator!= for classes that  have only operator== and provide operator > for classes that have only operator <, etc. Unfortunately, rel_ops have a habit of polluting the global operator space and creating conflicts. They must be used with discretion. |\n| reverse_iterator | A reverse_iterator is an iterator which wraps a bidirectional or random access iterator and allows the iterator to be read in reverse direction. The difference between using reverse_iterators and just decrementing regular iterators is that reverse_iterators use operator++ to move backwards and thus work in any algorithm that calls ++ to move through a container. |\n| OutputIterator | An output iterator (iterator you write to) which allows writing each element only once in only in a forward direction. |\n| POD | POD means Plain Old Data. It refers to C++ classes which act like built-in types and C structs. These are useful to distinguish because some algorithms can be made more efficient when they can detect that they are working with PODs instead of regular classes.  |\n| Predicate | A function which takes one argument returns true if the argument meets some criteria. |\n| priority_queue | A priority_queue is an adapter container which implements a heap via a random access container such as vector or deque. |\n| queue | A queue is an adapter container which implements a FIFO (first-in, first-out) container with which you can add items to the back and get items from the front. |\n| RandomAccessIterator | An input iterator which can be addressed like an array. It is a superset of all other input iterators. |\n| red-black tree | A red-black tree is a binary tree which has the property of being always balanced. The colors red and black are somewhat arbitrarily named monikers for nodes used to measure the balance of the tree. Red-black trees are considered the best all-around data structure for sorted containers. |\n| scalar | A scalar is a data type which is implemented via a numerical value. In C++ this means integers, floating point values, enumerations, and pointers.  |\n| scoped_ptr | A scoped_ptr is a smart pointer which is the same as C++ auto_ptr except that it cannot be copied. |\n| set | Set is a sorted associative container that stores objects of type Key. Its value type, as well as its key type, is Key. It is also a unique associative container, meaning that no two elements are the same.It is implemented with a tree structure. |\n| sequence | A sequence is a variable-sized container whose elements are arranged in a strict linear (though not necessarily contiguous) order. It supports insertion and removal of elements. Sequence containers include vector, deque, array, list, slist. |\n| size | All conventional containers have a size member function which returns the count of elements in the container. The efficiency of the size function differs between containers. |\n| size_type | The type that a container uses to define its size and counts. This is similar to the C/C++ size_t type but may be specialized for the container. |\n| skip list | A skip-list is a type of container which is an alternative to a binary tree for finding data. |\n| shared_ptr | A shared_ptr is a smart pointer which allows multiple references (via multiple shared_ptrs) to the same object. When the last shared_ptr goes away, the pointer is freed. shared_ptr is implemented via a shared count between all instances. |\n| slist | An slist is like a list but is singly-linked instead of doubly-linked. It can only be iterated in a forward-direction. |\n| smart pointer | Smart pointer is a term that identifies a family of utility classes which store pointers and free them when the class instance goes out of scope. Examples of smart pointers are shared_ptr, linked_ptr, intrusive_ptr, and scoped_ptr. |\n| splice | Splicing refers to the moving of a subsequence of one Sequence into another Sequence. |\n| stack | A stack is a adapter container which implements LIFO (last-in, first, out) access via another container such as a list or deque. |\n| STL | Standard Template Library.  |\n| StrictWeakOrdering | A BinaryPredicate that compares two objects, returning true if the first precedes the second. Like Compare but has additional requirements. Used for sorting routines.<br><br> This predicate must satisfy the standard mathematical definition of a strict weak ordering. A StrictWeakOrdering has to behave the way that \"less than\" behaves: if a is less than b then b is not less than a, if a is less than b and b is less than c then a is less than c, and so on. |\n| string | See basic_string. |\n| T | T is the template parameter name used by most containers to identify the contained element type.  |\n| template parameter | A template parameter is the templated type used to define a template function or class. In the declaration 'template <typename T> class vector{ },'  T is a template parameter. |\n| template specialization | A template specialization is a custom version of a template which overrides the default version and provides alternative functionality, often for the purpose of providing improved or specialized functionality. |\n| treap | A tree-like structure implemented via a heap. This is an alternative to a binary tree (e.g. red-black tree), skip-list, and sorted array as a mechanism for a fast-access sorted container. |\n| type traits | Type traits are properties of types. If you have a templated type T and you want to know if it is a pointer, you would use the is_pointer type trait. If you want to know if the type is a POD, you would use the is_pod type trait. Type traits are very useful for allowing the implementation of optimized generic algorithms and for asserting that types have properties expected by the function or class contract. For example, you can use type_traits to tell if a type can be copied via memcpy instead of a slower element-by-element copy. |\n| typename | Typename is a C++ keyword used in templated function implementations which identifies to the compiler that the following expression is a type and not a value. It is used extensively in EASTL, particularly in the algorithms. |\n| UnaryOperation | A function which takes one argument and returns a value (which will usually be assigned to second object). |\n| upper_bound | upper_bound is a version of binary search: it attempts to find the element value in an ordered range [first, last). Specifically, it returns the last position where value could be inserted without violating the ordering. |\n| value_type, Value | A value_type is a typedef used by all containers to identify the elements they contain. In most cases value_type is simply the same thing as the user-supplied T template parameter. The primary exception is the associative containers whereby value_type is the pair of key_type and mapped_type. |\n| vector | A vector is a Sequence that supports random access to elements, constant time insertion and removal of elements at the end, and linear time insertion and removal of elements at the beginning or in the middle. The number of elements in a vector may vary dynamically; memory management is automatic. Vector is the simplest of the container classes, and in many cases the most efficient. |\n| vector_map, vector_multimap, vector_set, vector_multiset | These are containers that implement the functionality of map, multimap, set, and multiset via a vector or deque instead of a tree. They use less memory and find items faster, but are slower to modify and modification invalidates iterators. |\n| weak_ptr | A weak_ptr is an adjunct to shared_ptr which doesn't increment the reference on the contained object but can safely tell you if the object still exists and access it if so. It has uses in preventing circular references in shared_ptrs. |\n\n----------------------------------------------\nEnd of document\n"
  },
  {
    "path": "doc/Gotchas.md",
    "content": "# EASTL Gotchas\n\nThere are some cases where the EASTL design results in \"gotchas\" or behavior that isn't necessarily what the new user would expect. These are all situations in which this behavior may be undesirable. One might ask, \"Why not change EASTL to make these gotchas go away?\" The answer is that in each case making the gotchas go away would either be impossible or would compromise the functionality of the library.\n\n## Summary\n\nThe descriptions here are intentionally terse; this is to make them easier to visually scan.\n\n1. [map::operator[] can create elements.](#mapoperator-can-create-elements)\n2. [char* converts to string silently.](#char-converts-to-string-silently)\n3. [char* is compared by ptr and not by contents.](#char-is-compared-by-ptr-and-not-by-contents)\n4. [Iterators can be invalidated by container mutations.](#iterators-can-be-invalidated-by-container-mutations)\n5. [Vector resizing may cause ctor/dtor cascades.](#vector-resizing-may-cause-ctordtor-cascades)\n6. [Vector and string insert/push_back/resize can reallocate.](#vector-and-string-insertpush_backresize-can-reallocate)\n7. [Deriving from containers may not work.](#deriving-from-containers-may-not-work)\n8. [set::iterator is const_iterator.](#setiterator-is-const_iterator)\n9. [Inserting elements means copying by value.](#inserting-elements-means-copying-by-value)\n10. [Containers of pointers can leak if you aren't careful.](#containers-of-pointers-can-leak-if-you-arent-careful)\n11. [Containers of auto_ptrs can crash.](#containers-of-auto_ptrs-can-crash)\n12. [Remove algorithms don't actually remove elements.](#remove-algorithms-dont-actually-remove-elements)\n13. [list::size() is O(n).](#listsize-is-on)\n14. [vector and deque::size() may incur integer division.](#vector-and-dequesize-may-incur-integer-division)\n15. [Be careful making custom Compare functions.](#be-careful-making-custom-compare-functions)\n16. [Comparisons involving floating point are dangerous.](#comparisons-involving-floating-point-are-dangerous)\n17. [Writing beyond string::size and vector::size is dangerous.](#writing-beyond-stringsize-and-vectorsize-is-dangerous)\n18. [Container operator=() doesn't copy allocators.](#container-operator-doesnt-copy-allocators)\n\n## Detail\n\n### map::operator[] can create elements.\n\nBy design, map operator[] creates a value for you if it isn't already present. The reason for this is that the alternative behavior would be to throw an exception, and such behavior isn't desirable. The resolution is to simply use the map::find function instead of operator[].\n\n### char* converts to string silently.\n\nThe string class has a non-explicit constructor that takes char* as an argument. Thus if you pass char* to a function that takes a string object, a temporary string will be created. In some cases this is undesirable behavior but the user may not notice it right away, as the compiler gives no warnings. The reason that the string constructor from char* is not declared explicit is that doing so would prevent the user from expressions such as: string s = \"hello\". In this example, no temporary string object is created, but the syntax is not possible if the char* constructor is declared explicit. Thus a decision to make the string char* constructor explicit involves tradeoffs.\n\nThere is an EASTL configuration option called EASTL_STRING_EXPLICIT which makes the string char* ctor explicit and avoids the behaviour described above.\n\n### char* is compared by ptr and not by contents.\n\nIf you have a set of strings declared as set<char*>, the find function will compare via the pointer value and not the string contents. The workaround is to make a set of string objects or, better, to supply a custom string comparison function to the set. The workaround is not to declare a global operator< for type char*, as that could cause other systems to break.\n\n### Iterators can be invalidated by container mutations\n\nWith some containers, modifications of them may invalidate iterators into them. With other containers, modifications of them only an iterator if the modification involves the element that iterator refers to. Containers in the former category include vector, deque, basic_string (string), vector_map, vector_multimap, vector_set, and vector_multiset. Containers in the latter category include list, slist, map, multimap, multiset, all hash containers, and all intrusive containers.\n\n### Vector resizing may cause ctor/dtor cascades.\n\nIf elements are inserted into a vector in middle of the sequence, the elements from the insertion point to the end will be copied upward. This will necessarily cause a series of element constructions and destructions as the elements are copied upward. Similarly, if an element is appended to a vector but the vector capacity is exhausted and needs to be reallocated, the entire vector will undergo a construction and destruction pass as the values are copied to the new storage. This issue exists for deque as well, though to a lesser degree. For vector, the resolution is to reserve enough space in your vector to prevent such reallocation. For deque the resolution is to set its subarray size to enough to prevent such reallocation. Another solution that can often be used is to design your element type to be trivially copyable. A good way to communicate this requirement/optimization is to static assert is_trivially_copyable<Type>. eastl optimizes such types to a memcpy/memmove, eliding a call to the copy constructor.\n\n### Vector and string insert/push_back/resize can reallocate.\n\nIf you create an empty vector and use push_back to insert 100 elements, the vector will reallocate itself at least three or four times during the operation. This can be an undesirable thing. The best thing to do if possible is to reserve the size you will need up front in the vector constructor or before you add any elements.\n\n### Deriving from containers may not work.\n\nEASTL containers are not designed with the guarantee that they can be arbitrarily subclassed. This is by design and is done for performance reasons, as such guarantees would likely involve making containers use virtual functions. However, some types of subclassing can be successful and EASTL does such subclassing internally to its advantage. The primary problem with subclassing results when a parent class function calls a function that the user wants to override. The parent class cannot see the overridden function and silent unpredictable behavior will likely occur. If your derived container acts strictly as a wrapper for the container then you will likely be able to successfully subclass it.\n\n### set::iterator is const_iterator.\n\nThe reason this is so is that a set is an ordered container and changing the value referred to by an iterator could make the set be out of order. Thus, set and multiset iterators are always const_iterators. If you need to change the value and are sure the change will not alter the container order, use const_cast or declare mutable member variables for your contained object. This resolution is the one blessed by the C++ standardization committee. This issue is addressed in more detail in the EASTL FAQ.\n\n### Inserting elements means copying by value.\n\nWhen you insert an element into a (non-intrusive) container, the container makes a copy of the element. There is no provision to take over ownership of an object from the user. The exception to this is of course when you use a container of pointers instead of a container of values. See the entry below regarding containers of pointers. Intrusive containers (e.g. intrusive_list) do in fact take over the user-provided value, and thus provide another advantage over regular containers in addition to avoiding memory allocation.\n\n### Containers of pointers can leak if you aren't careful.\n\nContainers of points don't know or care about the possibility that the pointer may have been allocated and need to be freed. Thus if you erase such elements from a container they are not freed. The resolution is to manually free the pointers when removing them or to instead use a container of smart pointers (shared smart pointers, in particular). This issue is addressed in more detail in the EASTL FAQ and the auto_ptr-related entry below.\n\n### Containers of auto_ptrs can crash\n\nWe suggested above that the user can use a container of smart pointers to automatically manage contained pointers. However, you don't want to use auto_ptr, as auto_ptrs cannot be safely assigned to each other; doing so results in a stale pointer and most likely a crash.\n\n### Remove algorithms don't actually remove elements.\n\nAlgorithms such as remove, remove_if, remove_heap, and unique do not erase elements from the sequences they work on. Instead, they return an iterator to the new end of the sequence and the user must call erase with that iterator in order to actually remove the elements from the container. This behavior exists because algorithms work on sequences via iterators and don't know how to work with containers. Only the container can know how to best erase its own elements. In each case, the documentation for the algorithm reminds the user of this behavior. Similarly, the copy algorithm copies elements from one sequence to another and doesn't modify the size of the destination sequence. So the destination must hold at least as many items as the source, and if it holds more items, you may want to erase the items at the end after the copy.\n\n### list::size() is O(n).\n\nBy this we mean that calling size() on a list will iterate the list and add the size as it goes. Thus, getting the size of a list is not a fast operation, as it requires traversing the list and counting the nodes. We could make list::size() be fast by having a member mSize variable. There are reasons for having such functionality and reasons for not having such functionality. We currently choose to not have a member mSize variable as it would add four bytes to the class, add processing to functions such as insert and erase, and would only serve to improve the size function, but no other function. The alternative argument is that the C++ standard states that std::list should be an O(1) operation (i.e. have a member size variable), most C++ standard library list implementations do so, the size is but an integer which is quick to update, and many users expect to have a fast size function. All of this applies to slist and intrusive_list as well.\n\nNote that EASTL's config.h file has an option in it to cause list and slist to cache their size with an mSize variable and thus make size() O(1). This option is disabled by default.\n\n### vector and deque::size() may incur integer division.\n\nSome containers (vector and deque in particular) calculate their size by pointer subtraction. For example, the implementation of vector::size() is 'return mpEnd - mpBegin'. This looks like a harmless subtraction, but if the size of the contained object is not an even power of two then the compiler will likely need to do an integer division to calculate the value of the subtracted pointers. One might suggest that vector use mpBegin and mnSize as member variables instead of mpBegin and mpEnd, but that would incur costs in other vector operations. The suggested workaround is to iterate a vector instead of using a for loop and operator[] and for those cases where you do use a for loop and operator[], get the size once at the beginning of the loop instead of repeatedly during the condition test.\n\n### Be careful making custom Compare functions.\n\nA Compare function compares two values and returns true if the first is less than the second. This is easy to understand for integers and strings, but harder to get right for more complex structures. Many a time have people decided to come up with a fancy mechanism for comparing values and made mistakes. The FAQ has a couple entries related to this. See [\"Writing a sort comparison function\"](https://devblogs.microsoft.com/oldnewthing/20031023-00/?p=42063) for a story about how this can go wrong by being overly clever. All comparisons in std STL and eastl, including user defined comparisons, must have strict weak ordering. See the [Compare](https://en.cppreference.com/w/cpp/named_req/Compare) named requirement for more info.\n\n### Comparisons involving floating point are dangerous.\n\nFloating point comparisons between two values that are very nearly equal can result in inconsistent results. Similarly, floating point comparisons between NaN values will always generate inconsistent results, as NaNs by definition always compare as non-equal. You thus need to be careful when using comparison functions that work with floating point values. Conversions to integral values may help the problem, but not necessarily.\n\n### Writing beyond string::size and vector::size is dangerous.\n\nA trick that often comes to mind when working with strings is to set the string capacity to some maximum value, strcpy data into it, and then resize the string when done. This can be done with EASTL, but only if you resize the string to the maximum value and not reserve the string to the maximum value. The reason is that when you resize a string from size (n) to size (n + count), the count characters are zeroed and overwrite the characters that you strcpyd.\n\nThe following code is broken:\n\n```cpp\nstring mDataDir;\n\n\n  mDataDir.reserve(kMaxPathLength); // reserve\n  strcpy(&mDataDir[0], \"blah/blah/blah\");\n\nmDataDir.resize(strlen(&mDataDir[0])); // Overwrites your blah/... with 00000...\n```\n\nThis following code is OK:\n\n```cpp\nstring mDataDir;\n\n\n  mDataDir.resize(kMaxPathLength); // resize\n  strcpy(&mDataDir[0], \"blah/blah/blah\");\n  \nmDataDir.resize(strlen(&mDataDir[0]));\n```\n\n### Container operator=() doesn't copy allocators.\n\nEASTL container assignment (e.g. vector::operator=(const vector&)) doesn't copy the allocator. There are good and bad reasons for doing this, but that's how it acts. So you need to beware that you need to assign the allocator separately or make a container subclass which overrides opeator=() and does this.\n\n----------------------------------------------\nEnd of document\n\n\n\n"
  },
  {
    "path": "doc/Introduction.md",
    "content": "# EASTL Introduction\n\nEASTL stands for Electronic Arts Standard Template Library. It is a C++ template library of containers, algorithms, and iterators useful for runtime and tool development across multiple platforms. It is a fairly extensive and robust implementation of such a library and has an emphasis on high performance above all other considerations.\n\n## Intended Audience\n\nThis is a short document intended to provide a basic introduction to EASTL for those new to the concept of EASTL or STL. If you are familiar with the C++ STL or have worked with other templated container/algorithm libraries, you probably don't need to read this. If you have no familiarity with C++ templates at all, then you probably will need more than this document to get you up to speed. In this case you need to understand that templates, when used properly, are powerful vehicles for the ease of creation of optimized C++ code. A description of C++ templates is outside the scope of this documentation, but there is plenty of such documentation on the Internet. See the EASTL FAQ.html document for links to information related to learning templates and STL.\n\n## EASTL Modules\n\nEASTL consists primarily of containers, algorithms, and iterators. An example of a container is a linked list, while an example of an algorithm is a sort function; iterators are the entities of traversal for containers and algorithms. EASTL containers a fairly large number of containers and algorithms, each of which is a very clean, efficient, and unit-tested implementation. We can say with some confidence that you are not likely to find better implementations of these (commercial or otherwise), as these are the result of years of wisdom and diligent work. For a detailed list of EASTL modules, see EASTL Modules.html.\n\n## EASTL Suitability\n\nWhat uses are EASTL suitable for? Essentially any situation in tools and shipping applications where the functionality of EASTL is useful. Modern compilers are capable of producing good code with templates and many people are using them in both current generation and future generation applications on multiple platforms from embedded systems to servers and mainframes.\n\n----------------------------------------------\nEnd of document"
  },
  {
    "path": "doc/Maintenance.md",
    "content": "# EASTL Maintenance\n\n## Introduction\n\nThe purpose of this document is to provide some necessary background for anybody who might do work on EASTL. Writing generic templated systems like EASTL can be surprisingly tricky. There are numerous details of the C++ language that you need to understand which don't usually come into play during the day-to-day C++ coding that many people do. It is easy to make a change to some function that seems proper and works for your test case but either violates the design expectations or simply breaks under other circumstances.\n\nIt may be useful to start with an example. Here we provide an implementation of the count algorithm which is seems simple enough. Except it is wrong and while it will compile in some cases it won't compile in others:\n\n```cpp\nint count(InputIterator first, InputIterator last, const T& value)\n{\n     int result = 0;\n\n     for(; first < last; ++first){\n         if(*first == value)\n             ++result;\n     }\n\n     return result;\n }\n ```\n\nThe problem is with the comparison 'first < last'. The count algorithm takes an InputIterator and operator< is not guaranteed to exist for any given InputIterator (and indeed while operator< exists for vector::iterator, it doesn't exist for list::iterator). The comparison in the above algorithm must instead be implemented as 'first != last'. If we were working with a RandomAccessIterator then 'first < last' would be valid.\n\nIn the following sections we cover various topics of interest regarding the development and maintentance of EASTL. Unfortunately, this document can't cover every aspect of EASTL maintenance issues, but at least it should give you a sense of the kinds of issues.\n\n## C++ Language Standard\n\nFirst and foremost, you need to be familiar with the C++ standard. In particular, the sections of the standard related to containers, algorithms, and iterators are of prime significance. We'll talk about some of this in more detail below. Similarly, a strong understanding of the basic data types is required. What is the difference between ptrdiff_t and intptr_t; unsigned int and size_t; char and signed char?\n\nIn addition to the C++ language standard, you'll want to be familiar with the C++ Defect Report. This is a continuously updated document which lists flaws in the original C++ language specification and the current thinking as the resolutions of those flaws. You will notice various references to the Defect Report in EASTL source code.\n\nAdditionally, you will want to be familiar with the C++ Technical Report 1 (as of this writing there is only one). This document is the evolving addendum to the C++ standard based on both the Defect Report and based on desired additions to the C++ language and standard library.\n\nAdditionally, you will probably want to have some familiarity with Boost. It also helps to keep an eye on comp.std.c++ Usenet discussions. However, watch out for what people say on Usenet. They tend to defend GCC, Unix, std STL, and C++ to a sometimes unreasonable degree. Many discussions ignore performance implications and concentrate only on correctness and sometimes academic correctness above usability.\n\n## Language Use\n\nMacros are (almost) not allowed in EASTL. A prime directive of EASTL is to be easier to read by users and most of the time macros are an impedence to this. So we avoid macros at all costs, even if it ends up making our development and maintenance more difficult. That being said, you will notice that the EASTL config.h file uses macros to control various options. This is an exception to the rule; when we talk about not using macros, we mean with the EASTL implementation itself.\n\nEASTL assumes a compliant and intelligent C++ compiler, and thus all language facilities are usable. However, we nevertheless choose to stay away from some language functionality. The primary language features we avoid are:\n\n*   RTTI (run-time-type-identification) (this is deemed too costly)\n*   Template export (few compilers support this)\n*   Exception specifications (most compilers ignore them)\n\nUse of per-platform or per-compiler code should be avoided when possible but where there is a significant advantage to be gained it can and indeed should be used. An example of this is the GCC __builtin_expect feature, which allows the user to give the compiler a hint about whether an expression is true or false. This allows for the generation of code that executes faster due to more intelligent branch prediction.\n\n## Prime Directives\n\nThe implementation of EASTL is guided foremost by the following directives which are listed in order of importance.\n\n1.  Efficiency (speed and memory usage)\n2.  Correctness (doesn't have bugs)\n3.  Portability (works on all required platforms with minimal specialized code)\n4.  Readability (code is legible and comments are present and useful)\n\nNote that unlike commercial STL implementations which must put correctness above all, we put a higher value on efficiency. As a result, some functionality may have some usage limitation that is not present in other similar systems but which allows for more efficient operation, especially on the platforms of significance to us.\n\nPortability is significant, but not critical. Yes, EASTL must compile and run on all platforms that we will ship games for. But we don't take that to mean under all compilers that could be conceivably used for such platforms. For example, Microsoft VC6 can be used to compile Windows programs, but VC6's C++ support is too weak for EASTL and so you simply cannot use EASTL under VC6.\n\nReadability is something that EASTL achieves better than many other templated libraries, particularly Microsoft STL and STLPort. We make every attempt to make EASTL code clean and sensible. Sometimes our need to provide optimizations (particularly related to type_traits and iterator types) results in less simple code, but efficiency happens to be our prime directive and so it overrides all other considerations.\n\n## Coding Conventions\n\nHere we provide a list of coding conventions to follow when maintaining or adding to EASTL, starting with the three language use items from above:\n\n*   No RTTI use.\n*   No use of exception specifications (e.g. appending the 'throw' declarator to a function).\n*   No use of exception handling itself except where explicitly required by the implementation (e.g. vector::at).\n*   Exception use needs to savvy to EASTL_EXCEPTIONS_ENABLED.\n*   No use of macros (outside of config.h). Macros make things more difficult for the user.\n*   No use of static or global variables.\n*   No use of global new, delete, malloc, or free. All memory must be user-specifyable via an Allocator parameter (default-specified or explicitly specified).\n*   Containers use protected member data and functions as opposed to private. This is because doing so allows subclasses to extend the container without the creation of intermediary functions. Recall from our [prime directives](#Prime_Directives) above that performance and simplicity overrule all.\n*   No use of multithreading primitives. \n*   No use of the export keyword.\n*   We don't have a rule about C-style casts vs. C++ static_cast<>, etc. We would always use static_cast except that debuggers can't evaluate them and so in practice they can get in the way of debugging and tracing. However, if the cast is one that users don't tend to need to view in a debugger, C++ casts are preferred.\n*   No external library dependencies whatsoever, including standard STL. EASTL is dependent on only EABase and the C++ compiler. \n*   All code must be const-correct. This isn't just for readability -- compilation can fail unless const-ness is used correctly everywhere. \n*   Algorithms do not refer to containers; they refer only to iterators.\n*   Algorithms in general do not allocate memory. If such a situation arises, there should be a version of the algorithm which allows the user to provide the allocator.\n*   No inferior implementations. No facility should be added to EASTL unless it is of professional quality.\n*   The maintainer should emulate the EASTL style of code layout, regardless of the maintainer's personal preferences. When in Rome, do as the Romans do. EASTL uses 4 spaces for indents, which is how the large majority of code within EA is written.\n*   No major changes should be done without consulting a peer group.\n\n## Compiler Issues\n\nHistorically, templates are the feature of C++ that has given C++ compilers the most fits. We are still working with compilers that don't completely and properly support templates. Luckily, most compilers are now good enough to handle what EASTL requires. Nevertheless, there are precautions we must take.\n\nIt turns out that the biggest problem in writing portable EASTL code is that VC++ allows you to make illegal statements which are not allowed by other compilers. For example, VC++ will allow you to neglect using the typename keyword in template references, whereas GCC (especially 3.4+) requires it.\n\nIn order to feel comfortable that your EASTL code is C++ correct and is portable, you must do at least these two things:\n\n*   Test under at least VS2005, GCC 3.4+, GCC 4.4+, EDG, and clang.\n*   Test all functions that you write, as compilers will often skip the compilation of a template function if it isn't used.\n\nThe two biggest issues to watch out for are 'typename' and a concept called \"dependent names\". In both cases VC++ will accept non-conforming syntax whereas most other compilers will not. Whenever you reference a templated type (and not a templated value) in a template, you need to prefix it by 'typename'. Whenever your class function refers to a base class member (data or function), you need to refer to it by \"this->\", \"base_type::\", or by placing a \"using\" statement in your class to declare that you will be referencing the given base class member.\n\n## Iterator Issues\n\nThe most important thing to understand about iterators is the concept of iterator types and their designated properties. In particular, we need to understand the difference between InputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator, and OutputIterator. These differences dictate both how we implement our algorithms and how we implement our optimizations. Please read the C++ standard for a reasonably well-implemented description of these iterator types.\n\nHere's an example from EASTL/algorithm.h which demonstrates how we use iterator types to optimize the reverse algorithm based on the kind of iterator passed to it:\n\n```cpp\ntemplate <class BidirectionalIterator>\ninline void reverse_impl(BidirectionalIterator first, BidirectionalIterator last, bidirectional_iterator_tag)\n{\n    for(; (first != last) && (first != --last); ++first) // We are not allowed to use operator <, <=, >, >= with\n        iter_swap(first, last);                          // a generic (bidirectional or otherwise) iterator.\n}\n\n\ntemplate <typename RandomAccessIterator>\ninline void reverse_impl(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)\n{\n    for(; first < --last; ++first) // With a random access iterator, we can use operator < to more efficiently implement\n        iter_swap(first, last);    // this algorithm. A generic iterator doesn't necessarily have an operator < defined.\n}\n\n\ntemplate <class BidirectionalIterator>\ninline void reverse(BidirectionalIterator first, BidirectionalIterator last)\n{\n    typedef typename iterator_traits<BidirectionalIterator>::iterator_category IC;\n    reverse_impl(first, last, IC());\n}\n```\n\n## Exception Handling\n\nYou will notice that EASTL uses try/catch in some places (particularly in containers) and uses the EASTL_EXCEPTIONS_ENABLED define. For starters, any EASTL code that uses try/catch should always be wrapped within #if EASTL_EXCEPTIONS_ENABLED (note: #if, not #ifdef).\n\nThis is simple enough, but what you may be wondering is how it is that EASTL decides to use try/catch for some sections of code and not for others. EASTL follows the C++ standard library conventions with respect to exception handling, and you will see similar exception handling in standard STL. The code that you need to wrap in try/catch is code that can throw a C++ exception (not to be confused with CPU exception) and needs to have something unwound (or fixed) as a result. The important thing is that the container be in a valid state after encountering such exceptions. In general the kinds of things that require such try/catch are:\n\n*   Memory allocation failures (which throw exceptions)\n*   Constructor exceptions\n\nTake a look at the cases in EASTL where try/catch is used and see what it is doing.\n\n## Type Traits\n\nEASTL provides a facility called type_traits which is very similar to the type_traits being proposed by the C++ TR1 (see above). type_traits are useful because they tell you about properties of types at compile time. This allows you to do things such as assert that a data type is scalar or that a data type is const. The way we put them to use in EASTL is to take advantage of them to implement different pathways for functions based on types. For example, we can copy a contiguous array of scalars much faster via memcpy than we can via a for loop, though we could not safely employ the for loop for a non-trivial C++ class.\n\nAs mentioned in the GeneralOptimizations section below, EASTL should take advantage of type_traits information to the extent possible to achive maximum effiiciency.\n\n## General Optimizations\n\nOne of the primary goals of EASTL is to achieve the highest possible efficiency. In cases where EASTL functionality overlaps standard C++ STL functionality, standard STL implementations provided by compiler vendors are a benchmark upon which EASTL strives to beat. Indeed EASTL is more efficient than all other current STL implementations (with some exception in the case of some Metrowerks STL facilities). Here we list some of the things to look for when considering optimization of EASTL code These items can be considered general optimization suggestions for any code, but this particular list applies to EASTL:\n\n*   Take advantage of type_traits to the extent possible (e.g. to use memcpy to move data instead of a for loop when possible).\n*   Take advantage of iterator types to the extent possible.\n*   Take advantage of the compiler's expectation that if statements are expected to evaluate as true and for loop conditions are expected to evaluate as false.\n*   Make inline-friendly code. This often means avoiding temporaries to the extent possible.\n*   Minimize branching (i.e. minimize 'if' statements). Where branching is used, make it so that 'if' statements execute as true.\n*   Use EASTL_LIKELY/EASTL_UNLIKELY to give branch hints to the compiler when you are confident it will be beneficial.\n*   Use restricted pointers (EABase's EA_RESTRICT or various compiler-specific versions of __restrict).\n*   Compare unsigned values to < max instead of comparing signed values to >= 0 && < max.\n*   Employ power of 2 integer math instead of math with any kind of integer.\n*   Use template specialization where possible to implement improved functionality.\n*   Avoid function calls when the call does something trivial. This improves debug build speed (which matters) and sometimes release build speed as well, though sometimes makes the code intent less clear. A comment next to the code saying what call it is replacing makes the intent clear without sacrificing performance.\n\n## Unit Tests\n\nWriting robust templated containers and algorithms is difficult or impossible without a heavy unit test suite in place. EASTL has a pretty extensive set of unit tests for all containers and algorithms. While the successful automated unit testing of shipping application programs may be a difficult thing to pull off, unit testing of libraries such as this is of huge importance and cannot be understated.\n\n*   When making a new unit test, start by copying one of the existing unit tests and follow its conventions.\n*   Test containers of both scalars and classes.\n*   Test algorithms on both container iterators (e.g. vector.begin()) and pointer iterators (e.g. int*).\n*   Make sure that algorithm or container member functions which take iterators work with the type of iterator they claim to (InputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator). \n*   Test for const-correctness. If a user is allowed to modify something that is supposed to be const, silent errors can go undetected.\n*   Make sure that unit tests cover all functions and all pathways of the tested code. This means that in writing the unit test you need to look at the source code to understand all the pathways.\n*   Consider using a random number generator (one is provided in the test library) to do 'monkey' testing whereby unexpected input is given to a module being tested. When doing so, make sure you seed the generator in a way that problems can be reproduced.\n*   While we avoid macros in EASTL user code, macros to assist in unit tests aren't considered a problem. However, consider that a number of macros could be replaced by templated functions and thus be easier to work with.\n*   Unit tests don't need to be efficient; feel free to take up all the CPU power and time you need to test a module sufficiently.\n*   EASTL containers are not thread-safe, by design. Thus there is no need to do multithreading tests as long as you stay away from the usage of static and global variables.\n*   Unit tests must succeed with no memory leaks and of course no memory corruption. The heap system should be configured to test for this, and heap validation functions are available to the unit tests while in the middle of runs.\n\n## Things to Keep in Mind\n\n*   When referring to EASTL functions and types from EASTL code, make sure to preface the type with the EASTL namespace. If you don't do this you can get collisions due to the compiler not knowing if it should use the EASTL namespace or the namespace of the templated type for the function or type.\n*   Newly constructed empty containers do no memory allocation. Some STL and other container libraries allocate an initial node from the class memory allocator. EASTL containers by design never do this. If a container needs an initial node, that node should be made part of the container itself or be a static empty node object.\n*   Empty containers (new or otherwise) contain no constructed objects, including those that might be in an 'end' node. Similarly, no user object (e.g. of type T) should be constructed unless required by the design and unless documented in the cotainer/algorithm contract. \n*   When creating a new container class, it's best to copy from an existing similar class to the extent possible. This helps keep the library consistent and resolves subtle problems that can happen in the construction of containers.\n*   Be very careful about tweaking the code. It's easy to think (for example) that a > could be switch to a >= where instead it is a big deal. Just about every line of code in EASTL has been thought through and has a purpose. Unit tests may or may not currently test every bit of EASTL, so you can't necessarily rely on them to give you 100% confidence in changes. If you are not sure about something, contact the original author and he will tell you for sure.\n*   Algorithm templates always work with iterators and not containers. A given container may of course implement an optimized form or an algorithm itself.\n*   Make sure everything is heavily unit tested. If somebody finds a bug, fix the bug and make a unit test to make sure the bug doesn't happen again.\n*   It's easy to get iterator categories confused or forgotten while implementing algorithms and containers.\n*   Watch out for the strictness of GCC 3.4+. There is a bit of syntax — especially related to templates — that other compilers accept but GCC 3.4+ will not.\n*   Don't forget to update the config.h EASTL_VERSION define before publishing.\n*   The vector and string classes define iterator to be T*. We want to always leave this so — at least in release builds — as this gives some algorithms an advantage that optimizers cannot get around.\n\n----------------------------------------------\nEnd of document\n"
  },
  {
    "path": "doc/Modules.md",
    "content": "# EASTL Modules\n\n## Introduction\n\nWe provide here a list of all top-level modules present or planned for future presence in EASTL. In some cases (e.g. algorithm), the module consists of many smaller submodules which are not described in detail here. In those cases you should consult the source code for those modules or consult the detailed documentation for those modules. This document is a high level overview and not a detailed document.\n\n## Module List\n\n| Module | Description |\n|------|------|\n| config | Configuration header. Allows for changing some compile-time options. |\n| slist <br>fixed_slist | Singly-linked list.<br> fixed_slist is a version which is implemented via a fixed block of contiguous memory.|\n| list<br> fixed_list | Doubly-linked list. |\n| intrusive_list<br> intrusive_slist | List whereby the contained item provides the node implementation. |\n| array | Wrapper for a C-style array which extends it to act like an STL container. |\n| vector<br> fixed_vector | Resizable array container.\n| vector_set<br> vector_multiset | Set implemented via a vector instead of a tree. Speed and memory use is improved but resizing is slower. |\n| vector_map<br> vector_multimap | Map implemented via a vector instead of a tree. Speed and memory use is improved but resizing is slower. |\n| deque | Double-ended queue, but also with random access. Acts like a vector but insertions and removals are efficient. |\n| bit_vector | Implements a vector of bool, but the actual storage is done with one bit per bool. Not the same thing as a bitset. |\n| bitset | Implements an efficient arbitrarily-sized bitfield. Note that this is not strictly the same thing as a vector of bool (bit_vector), as it is optimized to act like an arbitrary set of flags and not to be a generic container which can be iterated, inserted, removed, etc. |\n| set<br> multiset<br> fixed_set<br> fixed_multiset | A set is a sorted unique collection, multiset is sorted but non-unique collection. |\n| map<br> multimap<br> fixed_map<br> fixed_multimap | A map is a sorted associative collection implemented via a tree. It is also known as dictionary. |\n| hash_map<br> hash_multimap<br> fixed_hash_map<br> fixed_hash_multimap |  Map implemented via a hash table. |\n| intrusive_hash_map<br> intrusive_hash_multimap<br> intrusive_hash_set<br> intrusive_hash_multiset | hash_map whereby the contained item provides the node implementation, much like intrusive_list. |\n| hash_set<br> hash_multiset<br> fixed_hash_set<br> fixed_hash_map | Set implemented via a hash table.\n| basic_string<br> fixed_string<br> fixed_substring | basic_string is a character string/array.<br> fixed_substring is a string which is a reference to a range within another string or character array.<br> cow_string is a string which implements copy-on-write. |\n| algorithm | min/max, find, binary_search, random_shuffle, reverse, etc. |\n| sort | Sorting functionality, including functionality not in STL. quick_sort, heap_sort, merge_sort, shell_sort, insertion_sort, etc. |\n| numeric | Numeric algorithms: accumulate, inner_product, partial_sum, adjacent_difference, etc. |\n| heap | Heap structure functionality: make_heap, push_heap, pop_heap, sort_heap, is_heap, remove_heap, etc. |\n| stack | Adapts any container into a stack. |\n| queue | Adapts any container into a queue. |\n| priority_queue | Implements a conventional priority queue via a heap structure. |\n| type_traits | Type information, useful for writing optimized and robust code. Also used for implementing optimized containers and algorithms. |\n| utility | pair, make_pair, rel_ops, etc. |\n| functional | Function objects. |\n| iterator | Iteration for containers and algorithms. |\n| smart_ptr | Smart pointers: shared_ptr, shared_array, weak_ptr, scoped_ptr, scoped_array, linked_ptr, linked_array, intrusive_ptr. |\n \n\n## Module Behaviour\n\nThe overhead sizes listed here refer to an optimized release build; debug builds may add some additional overhead. Some of the overhead sizes may be off by a little bit (usually at most 4 bytes). This is because the values reported here are those that refer to when EASTL's container optimizations have been complete. These optimizations may not have been completed as you are reading this.\n\n| Container |Stores | Container Overhead (32 bit) | Container Overhead (64 bit) | Node Overhead (32 bit) | Node Overhead (64 bit) | Iterator category | size() efficiency | operator[] efficiency | Insert efficiency | Erase via Iterator efficiency | Find efficiency | Sort efficiency |\n|------|------|------|------|------|------|------|------|------|------|------|------|------|\n| slist | T | 8 | 16 | 4 | 8 | f | n | - | 1 | 1 | n | n+ |\n| list | T | 12 | 24 | 8 | 16 | b | n | - | 1 | 1 | n | n log(n) |\n| intrusive_slist | T | 4 | 8 | 4 | 8 | f | n | - | 1 | 1 | 1 | n+ |\n| intrusive_list | T | 8 | 16 | 8 | 16 | b | n | - | 1 | 1 | 1 | n log(n) |\n| array | T | 0 | 0 | 0 | 0 | r | 1 | 1 | - | - | n | n log(n) |\n| vector | T | 16 | 32 | 0 | 0 | r | 1 | 1 | 1 at end, else n | 1 at end, else n | n | n log(n) |\n| vector_set | T | 16 | 32 | 0 | 0 | r | 1 | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| vector_multiset | T | 16 | 32 | 0 | 0 | r | 1 | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| vector_map | Key, T | 16 | 32 | 0 | 0 | r | 1 | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| vector_multimap | Key, T | 16 | 32 | 0 | 0 | r | 1 | 1 | 1 at end, else n | 1 at end, else n | log(n) | 1 |\n| deque | T | 44 | 84 | 0 | 0 | r | 1 | 1 | 1 at begin or end, else n / 2 | 1 at begin or end, else n / 2 | n | n log(n) |\n| bit_vector | bool | 8 | 16 | 0 | 0 | r | 1 | 1 | 1 at end, else n | 1 at end, else n | n | n log(n) |\n| string (all types) | T | 16 | 32 | 0 | 0 | r | 1 | 1 | 1 at end, else n | 1 at end, else n | n | n log(n) |\n| set | T | 24 | 44 | 16 | 28 | b | 1 | - | log(n) | log(n) | log(n) | 1 |\n| multiset | T | 24 | 44 | 16 | 28 | b | 1 | - | log(n) | log(n) | log(n) | 1 |\n| map | Key, T | 24 | 44 | 16 | 28 | b | 1 | log(n) | log(n) | log(n) | log(n) | 1 |\n| multimap | Key, T | 24 | 44 | 16 | 28 | b | 1 | - | log(n) | log(n) | log(n) | 1 |\n| hash_set | T | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n| hash_multiset | T | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n| hash_map | Key, T | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n| hash_multimap | Key, T | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_set | T | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_multiset | T | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_map | T <small>(Key == T)</small> | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n| intrusive_hash_multimap | T <small>(Key == T) </small> | 16 | 20 | 4 | 8 | b | 1 | - | 1 | 1 | 1 | - |\n\n* \\- means that the operation does not exist.\n* 1 means amortized constant time. Also known as O(1)\n* n means time proportional to the container size. Also known as O(n)\n* log(n) means time proportional to the natural logarithm of the container size. Also known as O(log(n))\n* n log(n) means time proportional to log(n) times the size of the container. Also known as O(n log(n))\n* n+ means that the time is at least n, and possibly higher.\n* Iterator meanings are: f = forward iterator; b = bidirectional iterator, r = random iterator.\n* Overhead indicates approximate per-element overhead memory required in bytes. Overhead doesn't include possible additional overhead that may be imposed by the memory heap used to allocate nodes. General heaps tend to have between 4 and 16 bytes of overhead per allocation, depending on the heap.\n* Some overhead values are dependent on the structure alignment characteristics in effect. The values reported here are those that would be in effect for a system that requires pointers to be aligned on boundaries of their size and allocations with a minimum of 4 bytes (thus one byte values get rounded up to 4).\n* Some overhead values are dependent on the size_type used by containers. We assume a size_type of 4 bytes, even for 64 bit machines, as this is the EASTL default.\n* Inserting at the end of a vector may cause the vector to be resized; resizing a vector is O(n). However, the amortized time complexity for vector insertions at the end is constant.\n* Sort assumes the usage of the best possible sort for a large container of random data. Some sort algorithms (e.g. quick_sort) require random access iterators and so the sorting of some containers requires a different sort algorithm. We do not include bucket or radix sorts, as they are always O(n).\n* Some containers (e.g. deque, hash*) have unusual data structures that make per-container and per-node overhead calculations not quite account for all memory.\n\n----------------------------------------------\nEnd of document\n"
  },
  {
    "path": "doc/html/EASTL Benchmarks.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n    <title>EASTL Benchmarks</title>\n    <meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n    <meta content=\"Paul Pedriana\" name=\"author\">\n  \t<meta content=\"Presentation of various benchmarks of EASTL\" name=\"description\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n</head>\n\n\n<body>\n\n\n<h1>EASTL Benchmarks</h1>\n<h2>Introduction</h2>\n<p>This document provides a number of benchmark results of EASTL.\n  Where possible, these benchmarks are implemented as comparisons\n  with equivalent functionality found in other libraries such as\n  compiler STL libraries or other well-known libraries. These\n  comparison benchmarks concentrate on highlighting the differences\n  between implementations rather than the similarities. In many\n  mundane cases -- such as accessing a vector element via operator []\n  -- virtually all vector/array implementations you are likely to run\n  into will have identical performance.<br>\n  \n\n  \n<br>\n  \n\n  \nIt's also important to note that the platform you run on can make a\n  significant difference in the results. On a modern 3+GHz Windows PC\n  many operations are fast due to large memory caches, intelligent\n  branch prediction, and parallel instruction execution. However, on\n  embedded or console systems none of these may be the case. \n  <br>\n  \n\n  \n<br>\n  \n\n  \nWhile EASTL generally outperforms std STL, there are some benchmarks\n  here in which EASTL is slower than std STL. There are three primary\nexplanations of this:</p>\n<ol>\n\n\n\n  <li>EASTL is making some kind of speed, memory, or design tradeoff\nthat results in the given speed difference. In may such cases, EASTL\ngoes slower on one benchmark in order to go faster on another benchmark\ndeemed more important. This explanation constitutes about 60% of the\ncases.</li>\n\n\n\n  <li>Compiler optimizations and resulting code generation is\ncoincidencally favoring one kind of implementation over another, often\nwhen they are visually virtually identical. This explantation\nconstitutes about 30% of the cases.</li>\n\n\n\n  <li>EASTL is simply not yet as optimized as it could be. This\nexplanation constitutes about 10% of the cases (as of this writing\nthere are about three such functions throughout EASTL). </li>\n\n\n\n</ol>\n\n\n\n<h2>  Benchmarks</h2>\n<p>Below is a table of links to detailed benchmark results derived from\n  the Benchmark test present in the EASTL package. The detailed results\n  are present below the table. Additional platforms will be added as\n  results become available for those platforms. Debug benchmarks are\n  present because (lack of) debug performance can be significant for\n  highly templated libraries. EASTL has specific optimizations to enhance\n  debug performance relative to other standard libraries; in some cases\n  it is 10x or more faster than alternatives (though there are exceptions where EASTL is slower). Feel free to submit results\n  for additional compilers/platforms.<br>\n  \n\n  \n</p>\n<table style=\"text-align: left; width: 550px; margin-left: 40px;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n\n\n  <tbody>\n\n\n    <tr>\n\n\n      <td style=\"text-align: center;\"><span style=\"font-weight: bold;\">Platform</span></td>\n\n\n      <td style=\"text-align: center;\"><span style=\"font-weight: bold;\">Compiler</span></td>\n\n\n      <td style=\"font-weight: bold; text-align: center;\">STL type</td>\n\n\n      <td style=\"font-weight: bold; text-align: center;\">Build</td>\n\n\n      <td style=\"text-align: center;\"><span style=\"font-weight: bold;\">Results</span></td>\n\n\n    </tr>\n\n\n\n\n\n    <tr>\n\n\n      <td>Win32</td>\n\n\n      <td>VC++ 7.1</td>\n\n\n      <td>Microsoft (Dinkumware)</td>\n\n\n      <td>Debug</td>\n\n\n      <td><a href=\"#Win32.VC71.MS.Debug\">Detail</a></td>\n\n\n    </tr>\n\n\n    <tr>\n\n\n      <td>Win32</td>\n\n\n      <td>VC++ 7.1</td>\n\n\n      <td>Microsoft (Dinkumware)</td>\n\n\n      <td>Release</td>\n\n\n      <td><a href=\"#Win32.VC71.MS.Release\">Detail</a></td>\n\n\n    </tr>\n\n\n    <tr>\n\n\n      <td>Win32</td>\n\n\n      <td>VC++ 7.1</td>\n\n\n      <td>STLPort</td>\n\n\n      <td>Debug</td>\n\n\n      <td><a href=\"#Win32.VC71.STLPort.Debug\">Detail</a></td>\n\n\n    </tr>\n\n\n    <tr>\n\n\n      <td>Win32</td>\n\n\n      <td>VC++ 7.1</td>\n\n\n      <td>STLPort</td>\n\n\n      <td>Release</td>\n\n\n      <td><a href=\"#Win32.VC71.STLPort.Release\">Detail</a></td>\n\n\n    </tr>\n\n  \n  \n  </tbody>\n</table>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h2>\n  \n\n  \n\n  <a name=\"Win32.VC71.MS.Debug\"></a>Win32.VC71.MS.Debug<span style=\"font-weight: bold;\"></span><span style=\"font-weight: bold;\"></span></h2>\n<div style=\"margin-left: 40px;\">\n<pre>EASTL version: 0.96.00<br>Platform: Windows on X86<br>Compiler: Microsoft Visual C++ compiler, version 1310<br>Allocator: PPMalloc::GeneralAllocatorDebug. Thread safety enabled.<br>Build: Debug. Inlining disabled. STL debug features disabled.<br><br>Values are times to complete tests; smaller values are better.<br>Alarm indicates a greater than 10% difference.<br><br>Test                                               VC++        EASTL     Ratio     Alarm<br>----------------------------------------------------------------------------------------<br>algorithm/adj_find/vector&lt;TestObject&gt;          33061345      6497757      5.09         *<br>algorithm/copy/vector&lt;LargePOD&gt;                 5844906      4876076      1.20         *<br>algorithm/copy/vector&lt;uint32_t&gt;                 1634346       166065      9.84         *<br>algorithm/copy_backward/vector&lt;LargePOD&gt;        4515974      4638892      0.97<br>algorithm/copy_backward/vector&lt;uint32_t&gt;        1821168       121746     14.96         *<br>algorithm/count/vector&lt;uint64_t&gt;               17048884      2720766      6.27         *<br>algorithm/equal_range/vector&lt;uint64_t&gt;       1111147812    448756888      2.48         *<br>algorithm/fill/bool[]                           1728722        91936     18.80         *<br>algorithm/fill/char[]/'d'                       1299200        33745     38.50         *<br>algorithm/fill/vector&lt;char&gt;/'d'                10205092        33796    100.00         *<br>algorithm/fill/vector&lt;char&gt;/0                  10200748        33805    100.00         *<br>algorithm/fill/vector&lt;uint64_t&gt;                10416538      1399687      7.44         *<br>algorithm/fill/vector&lt;void*&gt;                   10221837      1307700      7.82         *<br>algorithm/fill_n/bool[]                         1399033        34196     40.91         *<br>algorithm/fill_n/char[]                         1299225        33754     38.49         *<br>algorithm/fill_n/vector&lt;uint64_t&gt;               5961637      1371900      4.35         *<br>algorithm/find_end/string/end                  16569373      2657372      6.24         *<br>algorithm/find_end/string/middle               16558638     20242410      0.82         *<br>algorithm/find_end/string/none                 16811207     40480468      0.42         *<br>algorithm/lex_cmp/schar[]                       1749674       194429      9.00         *<br>algorithm/lex_cmp/vector&lt;TestObject&gt;           32824195      5253587      6.25         *<br>algorithm/lex_cmp/vector&lt;uchar&gt;                29852034       202658    100.00         *<br>algorithm/lower_bound/vector&lt;TestObject&gt;      798624462    350027935      2.28         *<br>algorithm/min_element/vector&lt;TestObject&gt;       21675298      5314676      4.08         *<br>algorithm/rand_shuffle/vector&lt;uint64_t&gt;        84236190     43677506      1.93         *<br>algorithm/reverse/list&lt;TestObject&gt;              3007292      2105799      1.43         *<br>algorithm/reverse/vector&lt;TestObject&gt;            2974618      2124796      1.40         *<br>algorithm/search/string&lt;char&gt;                  16228158      3594268      4.52         *<br>algorithm/search_n/string&lt;char&gt;                16926985      1522096     11.12         *<br>algorithm/unique/vector&lt;TestObject&gt;            54206243      9988002      5.43         *<br>algorithm/unique/vector&lt;uint32_t&gt;              26940079      1741991     15.47         *<br>algorithm/unique/vector&lt;uint64_t&gt;              47621344      5213127      9.13         *<br>algorithm/upper_bound/vector&lt;uint32_t&gt;        372381295    137901552      2.70         *<br><br>bitset&lt;1500&gt;/&gt;&gt;=/1                             90196544     92539832      0.97<br>bitset&lt;1500&gt;/count                             50753832     53742117      0.94<br>bitset&lt;1500&gt;/flip                              86935875     85121117      1.02<br>bitset&lt;1500&gt;/reset                             78153837     79922611      0.98<br>bitset&lt;1500&gt;/set()                             79214968     79360658      1.00<br>bitset&lt;1500&gt;/set(i)                            11300589     12199651      0.93<br>bitset&lt;1500&gt;/test                              11282679     13186450      0.86         *<br><br>bitset&lt;15&gt;/&gt;&gt;=/1                               10500577      6000559      1.75         *<br>bitset&lt;15&gt;/count                                4000356      6399753      0.63         *<br>bitset&lt;15&gt;/flip                                 7268877      5647944      1.29         *<br>bitset&lt;15&gt;/reset                                8564235      5800163      1.48         *<br>bitset&lt;15&gt;/set()                                9935523      5914012      1.68         *<br>bitset&lt;15&gt;/set(i)                              11199703     12503637      0.90         *<br>bitset&lt;15&gt;/test                                10600623     12899592      0.82         *<br><br>bitset&lt;35&gt;/&gt;&gt;=/1                               13076052      6599834      1.98         *<br>bitset&lt;35&gt;/count                                4800384     11500330      0.42         *<br>bitset&lt;35&gt;/flip                                 7915439      5816313      1.36         *<br>bitset&lt;35&gt;/reset                                9400049      5803180      1.62         *<br>bitset&lt;35&gt;/set()                               10701152      5840316      1.83         *<br>bitset&lt;35&gt;/set(i)                              11342936     12271128      0.92<br>bitset&lt;35&gt;/test                                10670799     13099682      0.81         *<br><br>bitset&lt;75&gt;/&gt;&gt;=/1                               14198834     17151088      0.83         *<br>bitset&lt;75&gt;/count                                5795530      8576373      0.68         *<br>bitset&lt;75&gt;/flip                                 8516703      8922995      0.95<br>bitset&lt;75&gt;/reset                                9999970      8526095      1.17         *<br>bitset&lt;75&gt;/set()                               11124877      9009686      1.23         *<br>bitset&lt;75&gt;/set(i)                              11300563     12531618      0.90         *<br>bitset&lt;75&gt;/test                                11031913     13100523      0.84         *<br><br>deque&lt;ValuePair&gt;/erase                        743801706    335646802      2.22         *<br>deque&lt;ValuePair&gt;/insert                       742331809    341912866      2.17         *<br>deque&lt;ValuePair&gt;/iteration                     29097030     16315827      1.78         *<br>deque&lt;ValuePair&gt;/operator[]                    49859598     24026313      2.08         *<br>deque&lt;ValuePair&gt;/push_back                    424807033     34497608     12.31         *<br>deque&lt;ValuePair&gt;/push_front                   402313373     38006322     10.59         *<br>deque&lt;ValuePair&gt;/sort                         725101017    581796551      1.25         *<br><br>hash_map&lt;string, uint32_t&gt;/clear                 559462       961019      0.58         *<br>hash_map&lt;string, uint32_t&gt;/count               53377807      8091448      6.60         *<br>hash_map&lt;string, uint32_t&gt;/erase pos             613573       858084      0.72         *<br>hash_map&lt;string, uint32_t&gt;/erase range          5488748       461134     11.90         *<br>hash_map&lt;string, uint32_t&gt;/erase val           35760096     16379858      2.18         *<br>hash_map&lt;string, uint32_t&gt;/find                43490335     10324823      4.21         *<br>hash_map&lt;string, uint32_t&gt;/find_as/char*       49343818      8617139      5.73         *<br>hash_map&lt;string, uint32_t&gt;/insert             107420281    168690439      0.64         *<br>hash_map&lt;string, uint32_t&gt;/iteration            2456356      1255153      1.96         *<br>hash_map&lt;string, uint32_t&gt;/operator[]          47209502     12581624      3.75         *<br><br>hash_map&lt;uint32_t, TestObject&gt;/clear             533172       546449      0.98<br>hash_map&lt;uint32_t, TestObject&gt;/count           28667432      2899997      9.89         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase pos         683239       538289      1.27         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase range      9632676       253037     38.07         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase val       25466026      7752188      3.29         *<br>hash_map&lt;uint32_t, TestObject&gt;/find            20048253      4678502      4.29         *<br>hash_map&lt;uint32_t, TestObject&gt;/insert          71085798     37686187      1.89         *<br>hash_map&lt;uint32_t, TestObject&gt;/iteration        1460318      1338317      1.09<br>hash_map&lt;uint32_t, TestObject&gt;/operator[]      23226692      7888748      2.94         *<br><br>heap (uint32_t[])/make_heap                     5399966      6961305      0.78         *<br>heap (uint32_t[])/pop_heap                    108060534    103511318      1.04<br>heap (uint32_t[])/push_heap                    22595661     16640688      1.36         *<br>heap (uint32_t[])/sort_heap                    93559424     83076731      1.13         *<br><br>heap (vector&lt;TestObject&gt;)/make_heap            91770743     21724870      4.22         *<br>heap (vector&lt;TestObject&gt;)/pop_heap           1175599317    284007398      4.14         *<br>heap (vector&lt;TestObject&gt;)/push_heap           207804541     45918046      4.53         *<br>heap (vector&lt;TestObject&gt;)/sort_heap           970394145    208321477      4.66         *<br><br>list&lt;TestObject&gt;/ctor(it)                     805539509    760938607      1.06<br>list&lt;TestObject&gt;/ctor(n)                       80959236     75106995      1.08<br>list&lt;TestObject&gt;/erase                       1052543704   1044976137      1.01<br>list&lt;TestObject&gt;/find                          97785267     75970884      1.29         *<br>list&lt;TestObject&gt;/insert                       873895175    807051107      1.08<br>list&lt;TestObject&gt;/push_back                    812797710    780742425      1.04<br>list&lt;TestObject&gt;/remove                      1850600714   1436980599      1.29         *<br>list&lt;TestObject&gt;/reverse                      180270465     80466636      2.24         *<br>list&lt;TestObject&gt;/size/1                          440148       599642      0.73         *<br>list&lt;TestObject&gt;/size/10                         439433      1329817      0.33         *   EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/size/100                        439595     11030060      0.04         *   EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/splice                       177106094     69383027      2.55         *<br><br>map&lt;TestObject, uint32_t&gt;/clear                  508283       470807      1.08<br>map&lt;TestObject, uint32_t&gt;/count                43145354     14280357      3.02         *<br>map&lt;TestObject, uint32_t&gt;/equal_range          38594004     16520447      2.34         *<br>map&lt;TestObject, uint32_t&gt;/erase/key            33948082     16123175      2.11         *<br>map&lt;TestObject, uint32_t&gt;/erase/pos              578332       455201      1.27         *   MS uses a code bloating implementation of erase.<br>map&lt;TestObject, uint32_t&gt;/erase/range            387345       284538      1.36         *<br>map&lt;TestObject, uint32_t&gt;/find                 22897224     12766100      1.79         *<br>map&lt;TestObject, uint32_t&gt;/insert               61665800     47286928      1.30         *<br>map&lt;TestObject, uint32_t&gt;/iteration             1977202       745391      2.65         *<br>map&lt;TestObject, uint32_t&gt;/lower_bound          19892941     12260928      1.62         *<br>map&lt;TestObject, uint32_t&gt;/operator[]           24199084     15429634      1.57         *<br>map&lt;TestObject, uint32_t&gt;/upper_bound          19842409     12064441      1.64         *<br><br>set&lt;uint32_t&gt;/clear                             1027625      1000901      1.03<br>set&lt;uint32_t&gt;/count                            39730182     13329565      2.98         *<br>set&lt;uint32_t&gt;/equal_range                      34681649     14768827      2.35         *<br>set&lt;uint32_t&gt;/erase range                        841458       602030      1.40         *<br>set&lt;uint32_t&gt;/erase/pos                         1380485      1084303      1.27         *   MS uses a code bloating implementation of erase.<br>set&lt;uint32_t&gt;/erase/val                        31617425     13344023      2.37         *<br>set&lt;uint32_t&gt;/find                             19582428     10788864      1.82         *<br>set&lt;uint32_t&gt;/insert                           61434014     48232086      1.27         *<br>set&lt;uint32_t&gt;/iteration                         1512057       667820      2.26         *<br>set&lt;uint32_t&gt;/lower_bound                      18394885     10402785      1.77         *<br>set&lt;uint32_t&gt;/upper_bound                      17189083     10554425      1.63         *<br><br>sort/q_sort/TestObject[]                       87088799     15037988      5.79         *<br>sort/q_sort/TestObject[]/sorted                21502892      3284299      6.55         *<br>sort/q_sort/vector&lt;TestObject&gt;                 87962047     15004677      5.86         *<br>sort/q_sort/vector&lt;TestObject&gt;/sorted          21396523      3341163      6.40         *<br>sort/q_sort/vector&lt;ValuePair&gt;                  80334589     10429161      7.70         *<br>sort/q_sort/vector&lt;ValuePair&gt;/sorted           22133295      3230553      6.85         *<br>sort/q_sort/vector&lt;uint32&gt;                     72195388      5940302     12.15         *<br>sort/q_sort/vector&lt;uint32&gt;/sorted              19635171       995495     19.72         *<br><br>string&lt;char16_t&gt;/compare                      523013373    534722089      0.98<br>string&lt;char16_t&gt;/erase/pos,n                    3446597      3439492      1.00<br>string&lt;char16_t&gt;/find/p,pos,n                 383873158    441902786      0.87         *<br>string&lt;char16_t&gt;/find_first_not_of/p,pos,n       174157       134131      1.30         *<br>string&lt;char16_t&gt;/find_first_of/p,pos,n         11715423      8520944      1.37         *<br>string&lt;char16_t&gt;/find_last_of/p,pos,n           1871556      1226457      1.53         *<br>string&lt;char16_t&gt;/insert/pos,p                   3624877      3357058      1.08<br>string&lt;char16_t&gt;/iteration                   6766787933    581916665     11.63         *<br>string&lt;char16_t&gt;/operator[]                     4820827      2335579      2.06         *<br>string&lt;char16_t&gt;/push_back                     59812962      6757466      8.85         *<br>string&lt;char16_t&gt;/replace/pos,n,p,n              4371279      4459713      0.98<br>string&lt;char16_t&gt;/reserve                        2307530      1919386      1.20         *<br>string&lt;char16_t&gt;/rfind/p,pos,n                   734826       372615      1.97         *<br>string&lt;char16_t&gt;/size                             41608        28866      1.44         *<br>string&lt;char16_t&gt;/swap                           1033932      1490994      0.69         *<br><br>string&lt;char8_t&gt;/compare                        63086797     64194771      0.98<br>string&lt;char8_t&gt;/erase/pos,n                     2045687      1960270      1.04<br>string&lt;char8_t&gt;/find/p,pos,n                  123872549    471364764      0.26         *<br>string&lt;char8_t&gt;/find_first_not_of/p,pos,n        140013       130271      1.07<br>string&lt;char8_t&gt;/find_first_of/p,pos,n           8051906      8749994      0.92<br>string&lt;char8_t&gt;/find_last_of/p,pos,n            1318835      1230715      1.07<br>string&lt;char8_t&gt;/insert/pos,p                    1770610      1724234      1.03<br>string&lt;char8_t&gt;/iteration                      28112136      2544475     11.05         *<br>string&lt;char8_t&gt;/operator[]                      4810525      2255841      2.13         *<br>string&lt;char8_t&gt;/push_back                      54869634      6127447      8.95         *<br>string&lt;char8_t&gt;/replace/pos,n,p,n               2737578      2847900      0.96<br>string&lt;char8_t&gt;/reserve                         1123395       394902      2.84         *<br>string&lt;char8_t&gt;/rfind/p,pos,n                    737299       368518      2.00         *<br>string&lt;char8_t&gt;/size                              42245        26801      1.58         *<br>string&lt;char8_t&gt;/swap                            1036142      1491028      0.69         *<br><br>vector&lt;uint64&gt;/erase                           56417135     55770251      1.01<br>vector&lt;uint64&gt;/insert                          56617761     56100468      1.01<br>vector&lt;uint64&gt;/iteration                       10413895      1291269      8.06         *<br>vector&lt;uint64&gt;/operator[]                      23507193      3479390      6.76         *<br>vector&lt;uint64&gt;/push_back                       34687939     13806627      2.51         *<br>vector&lt;uint64&gt;/sort                           256886550     84669657      3.03         *<br><br></pre>\n\n\n\n\n\n</div>\n\n\n\n\n\n<h2>\n\n\n\n\n  <a name=\"Win32.VC71.MS.Release\"></a>Win32.VC71.MS.Release<span style=\"font-weight: bold;\"></span><span style=\"font-weight: bold;\"></span></h2>\n<div style=\"margin-left: 40px;\">\n<pre>EASTL version: 0.96.00<br>Platform: Windows on X86<br>Compiler: Microsoft Visual C++ compiler, version 1310<br>Allocator: PPMalloc::GeneralAllocator. Thread safety enabled.<br>Build: Full optimization. Inlining enabled.<br><br>Values are times to complete tests; smaller values are better.<br>Alarm indicates a greater than 10% difference.<br><br>Test                                               VC++        EASTL     Ratio     Alarm<br>----------------------------------------------------------------------------------------<br>algorithm/adj_find/vector&lt;TestObject&gt;           2783546      2750660      1.01<br>algorithm/copy/vector&lt;LargePOD&gt;                 6474025      4972738      1.30         *<br>algorithm/copy/vector&lt;uint32_t&gt;                  157267       173162      0.91<br>algorithm/copy_backward/vector&lt;LargePOD&gt;        4836406      4374780      1.11         *<br>algorithm/copy_backward/vector&lt;uint32_t&gt;         104780       120912      0.87         *<br>algorithm/count/vector&lt;uint64_t&gt;                1368440      1368696      1.00<br>algorithm/equal_range/vector&lt;uint64_t&gt;        114199387    102783938      1.11         *<br>algorithm/fill/bool[]                            253215        27353      9.26         *<br>algorithm/fill/char[]/'d'                        253164        27404      9.24         *<br>algorithm/fill/vector&lt;char&gt;/'d'                  253105        27362      9.25         *<br>algorithm/fill/vector&lt;char&gt;/0                    253275        27353      9.26         *<br>algorithm/fill/vector&lt;uint64_t&gt;                  397001       394323      1.01<br>algorithm/fill/vector&lt;void*&gt;                     547196       642362      0.85         *<br>algorithm/fill_n/bool[]                          229177        27361      8.38         *<br>algorithm/fill_n/char[]                          228845        27404      8.35         *<br>algorithm/fill_n/vector&lt;uint64_t&gt;                565233      1376822      0.41         *<br>algorithm/find_end/string/end                   2107116        82356     25.59         *<br>algorithm/find_end/string/middle                2111672       664283      3.18         *<br>algorithm/find_end/string/none                  2110423      1519596      1.39         *<br>algorithm/lex_cmp/schar[]                        741021       176162      4.21         *<br>algorithm/lex_cmp/vector&lt;TestObject&gt;            2610494      2642183      0.99<br>algorithm/lex_cmp/vector&lt;uchar&gt;                  697595       167866      4.16         *<br>algorithm/lower_bound/vector&lt;TestObject&gt;       62462233     58146664      1.07<br>algorithm/min_element/vector&lt;TestObject&gt;        4350385      2671227      1.63         *<br>algorithm/rand_shuffle/vector&lt;uint64_t&gt;        10868261     11300818      0.96<br>algorithm/reverse/list&lt;TestObject&gt;               483718       470024      1.03<br>algorithm/reverse/vector&lt;TestObject&gt;             476739       484322      0.98<br>algorithm/search/string&lt;char&gt;                   2560387      1259496      2.03         *<br>algorithm/search_n/string&lt;char&gt;                 2770991       458524      6.04         *<br>algorithm/unique/vector&lt;TestObject&gt;             4194520      4658910      0.90         *<br>algorithm/unique/vector&lt;uint32_t&gt;                538730       787924      0.68         *<br>algorithm/unique/vector&lt;uint64_t&gt;               3169829      2575636      1.23         *<br>algorithm/upper_bound/vector&lt;uint32_t&gt;         27495562     25321593      1.09<br><br>bitset&lt;1500&gt;/&gt;&gt;=/1                             33464228     33469719      1.00<br>bitset&lt;1500&gt;/count                             18736116     18814903      1.00<br>bitset&lt;1500&gt;/flip                              19299309     18605438      1.04<br>bitset&lt;1500&gt;/reset                             22200487     15262847      1.45         *<br>bitset&lt;1500&gt;/set()                             14418193     17557319      0.82         *<br>bitset&lt;1500&gt;/set(i)                             1599250      1599199      1.00<br>bitset&lt;1500&gt;/test                               1599241      1599233      1.00<br><br>bitset&lt;15&gt;/&gt;&gt;=/1                                2199222      2264442      0.97<br>bitset&lt;15&gt;/count                                1399406      1399193      1.00<br>bitset&lt;15&gt;/flip                                 1266712      1199197      1.06<br>bitset&lt;15&gt;/reset                                1399364      1399109      1.00<br>bitset&lt;15&gt;/set()                                1199197       999201      1.20         *<br>bitset&lt;15&gt;/set(i)                               1599258      1462952      1.09<br>bitset&lt;15&gt;/test                                 1599275      1599224      1.00<br><br>bitset&lt;35&gt;/&gt;&gt;=/1                                2599266      1933376      1.34         *<br>bitset&lt;35&gt;/count                                2599240      2592559      1.00<br>bitset&lt;35&gt;/flip                                 1693124      1199188      1.41         *<br>bitset&lt;35&gt;/reset                                1399406       999201      1.40         *<br>bitset&lt;35&gt;/set()                                1599403      1199205      1.33         *<br>bitset&lt;35&gt;/set(i)                               1599241      1599190      1.00<br>bitset&lt;35&gt;/test                                 1599250      1599232      1.00<br><br>bitset&lt;75&gt;/&gt;&gt;=/1                                4199332      4199213      1.00<br>bitset&lt;75&gt;/count                                2999497      2199341      1.36         *<br>bitset&lt;75&gt;/flip                                 2399499      1830178      1.31         *<br>bitset&lt;75&gt;/reset                                2199468      1199197      1.83         *<br>bitset&lt;75&gt;/set()                                1999387      1199851      1.67         *<br>bitset&lt;75&gt;/set(i)                               1599266      1599198      1.00<br>bitset&lt;75&gt;/test                                 1599241      1662651      0.96<br><br>deque&lt;ValuePair&gt;/erase                         90444165     37113253      2.44         *<br>deque&lt;ValuePair&gt;/insert                        93299349     36175167      2.58         *<br>deque&lt;ValuePair&gt;/iteration                      2756414      2122076      1.30         *<br>deque&lt;ValuePair&gt;/operator[]                     5117969      4632075      1.10<br>deque&lt;ValuePair&gt;/push_back                     30300757      3060357      9.90         *<br>deque&lt;ValuePair&gt;/push_front                    25498529      2808392      9.08         *<br>deque&lt;ValuePair&gt;/sort                         142283047    111292464      1.28         *<br><br>hash_map&lt;string, uint32_t&gt;/clear                 146769       389699      0.38         *<br>hash_map&lt;string, uint32_t&gt;/count               13059434      3460324      3.77         *<br>hash_map&lt;string, uint32_t&gt;/erase pos             184246       331925      0.56         *<br>hash_map&lt;string, uint32_t&gt;/erase range           382432       167237      2.29         *<br>hash_map&lt;string, uint32_t&gt;/erase val            6187898      3302114      1.87         *<br>hash_map&lt;string, uint32_t&gt;/find                11289369      3459024      3.26         *<br>hash_map&lt;string, uint32_t&gt;/find_as/char*       13559192      3662387      3.70         *<br>hash_map&lt;string, uint32_t&gt;/insert              17514012     14095176      1.24         *<br>hash_map&lt;string, uint32_t&gt;/iteration             801014       218450      3.67         *<br>hash_map&lt;string, uint32_t&gt;/operator[]          11457065      3690385      3.10         *<br><br>hash_map&lt;uint32_t, TestObject&gt;/clear             141865       265379      0.53         *<br>hash_map&lt;uint32_t, TestObject&gt;/count            1766045       703613      2.51         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase pos         172337       218458      0.79         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase range       537846       102340      5.26         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase val        2220132      1441787      1.54         *<br>hash_map&lt;uint32_t, TestObject&gt;/find             1612994      1043953      1.55         *<br>hash_map&lt;uint32_t, TestObject&gt;/insert           7141547      4348056      1.64         *<br>hash_map&lt;uint32_t, TestObject&gt;/iteration         199512       169328      1.18         *<br>hash_map&lt;uint32_t, TestObject&gt;/operator[]       1831733      1519707      1.21         *<br><br>heap (uint32_t[])/make_heap                     3366247      1949093      1.73         *<br>heap (uint32_t[])/pop_heap                     57280514     53779440      1.07<br>heap (uint32_t[])/push_heap                     9700217      7582935      1.28         *<br>heap (uint32_t[])/sort_heap                    47227751     46131948      1.02<br><br>heap (vector&lt;TestObject&gt;)/make_heap            11458442     11510819      1.00<br>heap (vector&lt;TestObject&gt;)/pop_heap            122897267    119061132      1.03<br>heap (vector&lt;TestObject&gt;)/push_heap            21688481     21176220      1.02<br>heap (vector&lt;TestObject&gt;)/sort_heap            90867380     88869523      1.02<br><br>list&lt;TestObject&gt;/ctor(it)                      74591104     69845817      1.07<br>list&lt;TestObject&gt;/ctor(n)                        6243998      5838582      1.07<br>list&lt;TestObject&gt;/erase                        299509298    206013676      1.45         *<br>list&lt;TestObject&gt;/find                          40927185     14514243      2.82         *<br>list&lt;TestObject&gt;/insert                        71277251     47234534      1.51         *<br>list&lt;TestObject&gt;/push_back                     73780527     44116725      1.67         *<br>list&lt;TestObject&gt;/remove                       786197776    326434612      2.41         *<br>list&lt;TestObject&gt;/reverse                       49283128     25029678      1.97         *<br>list&lt;TestObject&gt;/size/1                          159741       139400      1.15         *<br>list&lt;TestObject&gt;/size/10                         159324       346579      0.46         *   EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/size/100                        159188     97235419      0.00         *   EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/splice                        63548584     19322931      3.29         *<br><br>map&lt;TestObject, uint32_t&gt;/clear                  167408       170501      0.98<br>map&lt;TestObject, uint32_t&gt;/count                10213685      4748346      2.15         *<br>map&lt;TestObject, uint32_t&gt;/equal_range           9515053      5677558      1.68         *<br>map&lt;TestObject, uint32_t&gt;/erase/key             6646260      4302300      1.54         *<br>map&lt;TestObject, uint32_t&gt;/erase/pos              297135       327938      0.91             MS uses a code bloating implementation of erase.<br>map&lt;TestObject, uint32_t&gt;/erase/range            148614       163702      0.91<br>map&lt;TestObject, uint32_t&gt;/find                  5637531      4767055      1.18         *<br>map&lt;TestObject, uint32_t&gt;/insert                9591128      9030349      1.06<br>map&lt;TestObject, uint32_t&gt;/iteration              323595       325261      0.99<br>map&lt;TestObject, uint32_t&gt;/lower_bound           5398239      4784089      1.13         *<br>map&lt;TestObject, uint32_t&gt;/operator[]            5631250      5141166      1.10<br>map&lt;TestObject, uint32_t&gt;/upper_bound           5436336      4762431      1.14         *<br><br>set&lt;uint32_t&gt;/clear                              155983       156026      1.00<br>set&lt;uint32_t&gt;/count                             9635965      4392146      2.19         *<br>set&lt;uint32_t&gt;/equal_range                       8504157      5247832      1.62         *<br>set&lt;uint32_t&gt;/erase range                        140488       119408      1.18         *<br>set&lt;uint32_t&gt;/erase/pos                          260678       286697      0.91             MS uses a code bloating implementation of erase.<br>set&lt;uint32_t&gt;/erase/val                         6008225      4012825      1.50         *<br>set&lt;uint32_t&gt;/find                              5145432      4381945      1.17         *<br>set&lt;uint32_t&gt;/insert                            8087129      8697251      0.93<br>set&lt;uint32_t&gt;/iteration                          271507       304538      0.89         *<br>set&lt;uint32_t&gt;/lower_bound                       4666228      4404250      1.06<br>set&lt;uint32_t&gt;/upper_bound                       4623600      4402974      1.05<br><br>sort/q_sort/TestObject[]                        9596169      5578652      1.72         *<br>sort/q_sort/TestObject[]/sorted                  602463      1016132      0.59         *<br>sort/q_sort/vector&lt;TestObject&gt;                  9674828      5430199      1.78         *<br>sort/q_sort/vector&lt;TestObject&gt;/sorted            606908      1111647      0.55         *<br>sort/q_sort/vector&lt;ValuePair&gt;                   6284194      3423452      1.84         *<br>sort/q_sort/vector&lt;ValuePair&gt;/sorted             711629       569364      1.25         *<br>sort/q_sort/vector&lt;uint32&gt;                      5453379      2916146      1.87         *<br>sort/q_sort/vector&lt;uint32&gt;/sorted                537047       419144      1.28         *<br><br>string&lt;char16_t&gt;/compare                      435083295    251985824      1.73         *<br>string&lt;char16_t&gt;/erase/pos,n                    3454842      3451858      1.00<br>string&lt;char16_t&gt;/find/p,pos,n                 401954723    165298157      2.43         *<br>string&lt;char16_t&gt;/find_first_not_of/p,pos,n       131452        65374      2.01         *<br>string&lt;char16_t&gt;/find_first_of/p,pos,n         11657444      4144515      2.81         *<br>string&lt;char16_t&gt;/find_last_of/p,pos,n           1604248       567571      2.83         *<br>string&lt;char16_t&gt;/insert/pos,p                   3398734      3355460      1.01<br>string&lt;char16_t&gt;/iteration                    218856504    218771844      1.00<br>string&lt;char16_t&gt;/operator[]                      714161       240023      2.98         *<br>string&lt;char16_t&gt;/push_back                     34968235      2444897     14.30         *<br>string&lt;char16_t&gt;/replace/pos,n,p,n              4226693      4198498      1.01<br>string&lt;char16_t&gt;/reserve                        1901765       390805      4.87         *<br>string&lt;char16_t&gt;/rfind/p,pos,n                   195483       150985      1.29         *<br>string&lt;char16_t&gt;/size                             11169        11245      0.99<br>string&lt;char16_t&gt;/swap                           1459280       419807      3.48         *<br><br>string&lt;char8_t&gt;/compare                        63071275     77209580      0.82         *<br>string&lt;char8_t&gt;/erase/pos,n                     2008652      1944494      1.03<br>string&lt;char8_t&gt;/find/p,pos,n                  123201023    167536164      0.74         *<br>string&lt;char8_t&gt;/find_first_not_of/p,pos,n         93372        67864      1.38         *<br>string&lt;char8_t&gt;/find_first_of/p,pos,n           7542492      3375758      2.23         *<br>string&lt;char8_t&gt;/find_last_of/p,pos,n             933972       583576      1.60         *<br>string&lt;char8_t&gt;/insert/pos,p                    1737213      1750847      0.99<br>string&lt;char8_t&gt;/iteration                        893834       899130      0.99<br>string&lt;char8_t&gt;/operator[]                       817879       313437      2.61         *<br>string&lt;char8_t&gt;/push_back                      20857734      2004410     10.41         *<br>string&lt;char8_t&gt;/replace/pos,n,p,n               2578696      2607655      0.99<br>string&lt;char8_t&gt;/reserve                          915127        85289     10.73         *<br>string&lt;char8_t&gt;/rfind/p,pos,n                    196103       148894      1.32         *<br>string&lt;char8_t&gt;/size                              11619        11220      1.04<br>string&lt;char8_t&gt;/swap                            1461056       419874      3.48         *<br><br>vector&lt;uint64&gt;/erase                           55235116     55284587      1.00<br>vector&lt;uint64&gt;/insert                          55166046     55142755      1.00<br>vector&lt;uint64&gt;/iteration                         553954       509719      1.09<br>vector&lt;uint64&gt;/operator[]                       1284239       798516      1.61         *<br>vector&lt;uint64&gt;/push_back                        5399549      3867959      1.40         *<br>vector&lt;uint64&gt;/sort                            43636314     42619952      1.02<br></pre>\n\n\n\n\n\n</div>\n\n\n\n\n\n<h2>\n  \n  <a name=\"Win32.VC71.STLPort.Debug\"></a>Win32.VC71.STLPort.Debug<span style=\"font-weight: bold;\"></span><span style=\"font-weight: bold;\"></span></h2>\n<div style=\"margin-left: 40px;\">\n<pre>EASTL version: 0.96.00<br>Platform: Windows on X86<br>Compiler: Microsoft Visual C++ compiler, version 1310<br>Allocator: PPMalloc::GeneralAllocatorDebug. Thread safety enabled.<br>Build: Debug. Inlining disabled. STL debug features disabled.<br><br>Values are times to complete tests; smaller values are better.<br>Alarm indicates a greater than 10% difference.<br><br>Test                                            STLPort        EASTL     Ratio     Alarm<br>----------------------------------------------------------------------------------------<br>algorithm/adj_find/vector&lt;TestObject&gt;           5661170      5689517      1.00<br>algorithm/copy/vector&lt;LargePOD&gt;                 5573815      5124428      1.09<br>algorithm/copy/vector&lt;uint32_t&gt;                  148273       125782      1.18         *<br>algorithm/copy_backward/vector&lt;LargePOD&gt;        5429791      4834510      1.12         *<br>algorithm/copy_backward/vector&lt;uint32_t&gt;         156765       163038      0.96<br>algorithm/count/vector&lt;uint64_t&gt;                2730922      2730072      1.00<br>algorithm/equal_range/vector&lt;uint64_t&gt;        639366489    452896251      1.41         *<br>algorithm/fill/bool[]                           1299326        27361     47.49         *<br>algorithm/fill/char[]/'d'                         27378        27361      1.00<br>algorithm/fill/vector&lt;char&gt;/'d'                   34459        27361      1.26         *<br>algorithm/fill/vector&lt;char&gt;/0                   1299224        27361     47.48         *<br>algorithm/fill/vector&lt;uint64_t&gt;                 1400647      1400145      1.00<br>algorithm/fill/vector&lt;void*&gt;                    1308779      1309085      1.00<br>algorithm/fill_n/bool[]                         1299156        27352     47.50         *<br>algorithm/fill_n/char[]                         1299258        27369     47.47         *<br>algorithm/fill_n/vector&lt;uint64_t&gt;               1451162      1313632      1.10<br>algorithm/find_end/string/end                  13089999      2526412      5.18         *<br>algorithm/find_end/string/middle               12627412     20190101      0.63         *<br>algorithm/find_end/string/none                 12704185     40728803      0.31         *<br>algorithm/lex_cmp/schar[]                       1749844       195806      8.94         *<br>algorithm/lex_cmp/vector&lt;TestObject&gt;            5060968      4799882      1.05<br>algorithm/lex_cmp/vector&lt;uchar&gt;                 1668354       189490      8.80         *<br>algorithm/lower_bound/vector&lt;TestObject&gt;      450240945    353437573      1.27         *<br>algorithm/min_element/vector&lt;TestObject&gt;        5861744      5326371      1.10<br>algorithm/rand_shuffle/vector&lt;uint64_t&gt;        40780449     45780090      0.89         *<br>algorithm/reverse/list&lt;TestObject&gt;              2657678      2130627      1.25         *<br>algorithm/reverse/vector&lt;TestObject&gt;            2666424      2124889      1.25         *<br>algorithm/search/string&lt;char&gt;                   3110379      3613460      0.86         *<br>algorithm/search_n/string&lt;char&gt;                 3061665      1521261      2.01         *<br>algorithm/unique/vector&lt;TestObject&gt;            12423684      9485439      1.31         *<br>algorithm/unique/vector&lt;uint32_t&gt;               3718699      1726596      2.15         *<br>algorithm/unique/vector&lt;uint64_t&gt;               6205110      4591631      1.35         *<br>algorithm/upper_bound/vector&lt;uint32_t&gt;        185391094    139336317      1.33         *<br><br>bitset&lt;1500&gt;/&gt;&gt;=/1                            120666960     92449816      1.31         *   STLPort is broken, neglects wraparound check.<br>bitset&lt;1500&gt;/count                            201709793     52874726      3.81         *<br>bitset&lt;1500&gt;/flip                              87360297     81737071      1.07<br>bitset&lt;1500&gt;/reset                             23950178     77390323      0.31         *<br>bitset&lt;1500&gt;/set()                             84608107     76912011      1.10<br>bitset&lt;1500&gt;/set(i)                            18023620     12229604      1.47         *<br>bitset&lt;1500&gt;/test                              18006553     13276396      1.36         *<br><br>bitset&lt;15&gt;/&gt;&gt;=/1                               11935904      6012695      1.99         *   STLPort is broken, neglects wraparound check.<br>bitset&lt;15&gt;/count                                9368581      6022742      1.56         *<br>bitset&lt;15&gt;/flip                                11600706      6533635      1.78         *<br>bitset&lt;15&gt;/reset                                5830957      5874690      0.99<br>bitset&lt;15&gt;/set()                               11695328      5701621      2.05         *<br>bitset&lt;15&gt;/set(i)                              16363205     12570216      1.30         *<br>bitset&lt;15&gt;/test                                16743172     13201452      1.27         *<br><br>bitset&lt;35&gt;/&gt;&gt;=/1                               22950918      6774457      3.39         *   STLPort is broken, neglects wraparound check.<br>bitset&lt;35&gt;/count                               12655309     11736256      1.08<br>bitset&lt;35&gt;/flip                                13738575      5800042      2.37         *<br>bitset&lt;35&gt;/reset                               15561434      5800510      2.68         *<br>bitset&lt;35&gt;/set()                               13564283      5600709      2.42         *<br>bitset&lt;35&gt;/set(i)                              18519689     12199973      1.52         *<br>bitset&lt;35&gt;/test                                18000569     13103566      1.37         *<br><br>bitset&lt;75&gt;/&gt;&gt;=/1                               25579525     16669664      1.53         *   STLPort is broken, neglects wraparound check.<br>bitset&lt;75&gt;/count                               18740698      8480492      2.21         *<br>bitset&lt;75&gt;/flip                                13555630      8300335      1.63         *<br>bitset&lt;75&gt;/reset                               15200133      8200000      1.85         *<br>bitset&lt;75&gt;/set()                               14408112      8001959      1.80         *<br>bitset&lt;75&gt;/set(i)                              18137741     12374257      1.47         *<br>bitset&lt;75&gt;/test                                18422135     13100038      1.41         *<br><br>deque&lt;ValuePair&gt;/erase                        651933790    326443043      2.00         *<br>deque&lt;ValuePair&gt;/insert                       659786183    333304660      1.98         *<br>deque&lt;ValuePair&gt;/iteration                     23734592     16173706      1.47         *<br>deque&lt;ValuePair&gt;/operator[]                    59126816     23911774      2.47         *<br>deque&lt;ValuePair&gt;/push_back                     58056988     31859266      1.82         *<br>deque&lt;ValuePair&gt;/push_front                    57780891     31743199      1.82         *<br>deque&lt;ValuePair&gt;/sort                         818414195    596568113      1.37         *<br><br>hash_map&lt;string, uint32_t&gt;/clear                3422133      2204517      1.55         *<br>hash_map&lt;string, uint32_t&gt;/count                9869545      8624924      1.14         *<br>hash_map&lt;string, uint32_t&gt;/erase pos            3256350      2069299      1.57         *<br>hash_map&lt;string, uint32_t&gt;/erase range          3230203      1151392      2.81         *<br>hash_map&lt;string, uint32_t&gt;/erase val           16860362     15939778      1.06<br>hash_map&lt;string, uint32_t&gt;/find                10286971      9920910      1.04<br>hash_map&lt;string, uint32_t&gt;/find_as/char*      118136025      9458468     12.49         *<br>hash_map&lt;string, uint32_t&gt;/insert             188948336    174490082      1.08<br>hash_map&lt;string, uint32_t&gt;/iteration            4037049      2021036      2.00         *<br>hash_map&lt;string, uint32_t&gt;/operator[]          11472127     12887699      0.89         *<br><br>hash_map&lt;uint32_t, TestObject&gt;/clear            2522264      1331848      1.89         *<br>hash_map&lt;uint32_t, TestObject&gt;/count            3210739      2897063      1.11         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase pos        1862281      1304783      1.43         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase range       698079       579606      1.20         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase val        8806722      7041298      1.25         *<br>hash_map&lt;uint32_t, TestObject&gt;/find             3604875      4709645      0.77         *<br>hash_map&lt;uint32_t, TestObject&gt;/insert          40785711     40376342      1.01<br>hash_map&lt;uint32_t, TestObject&gt;/iteration        3064088      1508834      2.03         *<br>hash_map&lt;uint32_t, TestObject&gt;/operator[]       6053742      8176906      0.74         *<br><br>heap (uint32_t[])/make_heap                     5799813      5738596      1.01<br>heap (uint32_t[])/pop_heap                    113775168    102076134      1.11         *<br>heap (uint32_t[])/push_heap                    21649151     16854845      1.28         *<br>heap (uint32_t[])/sort_heap                    97535213     83290735      1.17         *<br><br>heap (vector&lt;TestObject&gt;)/make_heap            22215557     22277063      1.00<br>heap (vector&lt;TestObject&gt;)/pop_heap            275392171    277340039      0.99<br>heap (vector&lt;TestObject&gt;)/push_heap            51479442     47342577      1.09<br>heap (vector&lt;TestObject&gt;)/sort_heap           214474736    218497540      0.98<br><br>list&lt;TestObject&gt;/ctor(it)                     767753795    753421427      1.02<br>list&lt;TestObject&gt;/ctor(n)                       74185322     73386245      1.01<br>list&lt;TestObject&gt;/erase                       1021003824   1033873589      0.99<br>list&lt;TestObject&gt;/find                          77666072     74917622      1.04<br>list&lt;TestObject&gt;/insert                       788071150    774188737      1.02<br>list&lt;TestObject&gt;/push_back                    760490154    737327348      1.03<br>list&lt;TestObject&gt;/remove                      1682511938   1434771006      1.17         *<br>list&lt;TestObject&gt;/reverse                       87237327     80394623      1.09<br>list&lt;TestObject&gt;/size/1                         3828111       599530      6.39         *<br>list&lt;TestObject&gt;/size/10                        9600605      1329535      7.22         *   EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/size/100                      62952334     15022551      4.19         *   EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/splice                        96536412     60804817      1.59         *<br><br>map&lt;TestObject, uint32_t&gt;/clear                 1142127      1099066      1.04<br>map&lt;TestObject, uint32_t&gt;/count                19659726     14647548      1.34         *<br>map&lt;TestObject, uint32_t&gt;/equal_range          36680687     18219086      2.01         *<br>map&lt;TestObject, uint32_t&gt;/erase/key            28892154     16037774      1.80         *<br>map&lt;TestObject, uint32_t&gt;/erase/pos             1209643      1185495      1.02<br>map&lt;TestObject, uint32_t&gt;/erase/range            715402       670539      1.07<br>map&lt;TestObject, uint32_t&gt;/find                 21020992     13429575      1.57         *<br>map&lt;TestObject, uint32_t&gt;/insert               59530871     51120640      1.16         *<br>map&lt;TestObject, uint32_t&gt;/iteration              972825      1191946      0.82         *<br>map&lt;TestObject, uint32_t&gt;/lower_bound          18852651     12495034      1.51         *<br>map&lt;TestObject, uint32_t&gt;/operator[]           22889573     16676736      1.37         *<br>map&lt;TestObject, uint32_t&gt;/upper_bound          18603584     12406922      1.50         *<br><br>set&lt;uint32_t&gt;/clear                              919555       882988      1.04<br>set&lt;uint32_t&gt;/count                            17561110     12461084      1.41         *<br>set&lt;uint32_t&gt;/equal_range                      31522488     15230282      2.07         *<br>set&lt;uint32_t&gt;/erase range                        687582       564765      1.22         *<br>set&lt;uint32_t&gt;/erase/pos                         1044352      1045355      1.00<br>set&lt;uint32_t&gt;/erase/val                        25525304     12940774      1.97         *<br>set&lt;uint32_t&gt;/find                             17140751     10704866      1.60         *<br>set&lt;uint32_t&gt;/insert                           56035051     45555664      1.23         *<br>set&lt;uint32_t&gt;/iteration                          682669       640831      1.07<br>set&lt;uint32_t&gt;/lower_bound                      16339932     10475740      1.56         *<br>set&lt;uint32_t&gt;/upper_bound                      17779424     10652599      1.67         *<br><br>sort/q_sort/TestObject[]                       17000866     14823515      1.15         *<br>sort/q_sort/TestObject[]/sorted                 6658559      3263328      2.04         *<br>sort/q_sort/vector&lt;TestObject&gt;                 17476629     14953285      1.17         *<br>sort/q_sort/vector&lt;TestObject&gt;/sorted           6667034      3327435      2.00         *<br>sort/q_sort/vector&lt;ValuePair&gt;                  15391357     10820848      1.42         *<br>sort/q_sort/vector&lt;ValuePair&gt;/sorted            6617122      3232949      2.05         *<br>sort/q_sort/vector&lt;uint32&gt;                      8343906      6014846      1.39         *<br>sort/q_sort/vector&lt;uint32&gt;/sorted               3039430      1003127      3.03         *<br><br>string&lt;char16_t&gt;/compare                     1489709846    532664000      2.80         *<br>string&lt;char16_t&gt;/erase/pos,n                    3528690      3439864      1.03<br>string&lt;char16_t&gt;/find/p,pos,n                2521448321    443752189      5.68         *<br>string&lt;char16_t&gt;/find_first_not_of/p,pos,n       661206       137419      4.81         *<br>string&lt;char16_t&gt;/find_first_of/p,pos,n         54746434      8521335      6.42         *<br>string&lt;char16_t&gt;/find_last_of/p,pos,n          10607778      1212414      8.75         *<br>string&lt;char16_t&gt;/insert/pos,p                   3445016      3360126      1.03<br>string&lt;char16_t&gt;/iteration                    580955636    579452556      1.00<br>string&lt;char16_t&gt;/operator[]                     2206353      1987809      1.11         *<br>string&lt;char16_t&gt;/push_back                     22421368      6007808      3.73         *<br>string&lt;char16_t&gt;/replace/pos,n,p,n              5138454      4464786      1.15         *<br>string&lt;char16_t&gt;/reserve                     4922413418       335622    100.00         *<br>string&lt;char16_t&gt;/rfind/p,pos,n                  1440308       380578      3.78         *<br>string&lt;char16_t&gt;/size                             25355        25398      1.00<br>string&lt;char16_t&gt;/swap                           2122704      1490823      1.42         *<br><br>string&lt;char8_t&gt;/compare                        77222134     77443134      1.00<br>string&lt;char8_t&gt;/erase/pos,n                     1965344      1956521      1.00<br>string&lt;char8_t&gt;/find/p,pos,n                 2468091951    474205522      5.20         *<br>string&lt;char8_t&gt;/find_first_not_of/p,pos,n        660960       130211      5.08         *<br>string&lt;char8_t&gt;/find_first_of/p,pos,n          55020899      9240171      5.95         *<br>string&lt;char8_t&gt;/find_last_of/p,pos,n           10576210      1239053      8.54         *<br>string&lt;char8_t&gt;/insert/pos,p                    1822756      1750880      1.04<br>string&lt;char8_t&gt;/iteration                       2617889      2540148      1.03<br>string&lt;char8_t&gt;/operator[]                      2254794      2256443      1.00<br>string&lt;char8_t&gt;/push_back                      12463022      5210321      2.39         *<br>string&lt;char8_t&gt;/replace/pos,n,p,n               3744862      2855260      1.31         *<br>string&lt;char8_t&gt;/reserve                      1372046888       218815    100.00         *<br>string&lt;char8_t&gt;/rfind/p,pos,n                   1446232       366902      3.94         *<br>string&lt;char8_t&gt;/size                              26859        25431      1.06<br>string&lt;char8_t&gt;/swap                            2123350      1490509      1.42         *<br><br>vector&lt;uint64&gt;/erase                           55164013     56417449      0.98<br>vector&lt;uint64&gt;/insert                          55872973     56432664      0.99<br>vector&lt;uint64&gt;/iteration                        1329102      1324623      1.00<br>vector&lt;uint64&gt;/operator[]                       5264738      3136746      1.68         *<br>vector&lt;uint64&gt;/push_back                       14903245     13171175      1.13         *<br>vector&lt;uint64&gt;/sort                            88429095     88542171      1.00<br></pre>\n\n\n\n\n\n</div>\n\n\n\n\n\n<h2>\n\n\n\n\n  <a name=\"Win32.VC71.STLPort.Release\"></a>Win32.VC71.STLPort.Release<span style=\"font-weight: bold;\"></span><span style=\"font-weight: bold;\"></span></h2>\n<div style=\"margin-left: 40px;\">\n<pre>EASTL version: 0.96.00<br>Platform: Windows on X86<br>Compiler: Microsoft Visual C++ compiler, version 1310<br>Allocator: PPMalloc::GeneralAllocator. Thread safety enabled.<br>Build: Full optimization. Inlining enabled.<br><br>Values are times to complete tests; smaller values are better.<br>Alarm indicates a greater than 10% difference.<br><br>Test                                            STLPort        EASTL     Ratio     Alarm<br>----------------------------------------------------------------------------------------<br>algorithm/adj_find/vector&lt;TestObject&gt;           2741046      2731441      1.00<br>algorithm/copy/vector&lt;LargePOD&gt;                 6065923      5085142      1.19         *<br>algorithm/copy/vector&lt;uint32_t&gt;                  158304       165555      0.96<br>algorithm/copy_backward/vector&lt;LargePOD&gt;        4710258      4896476      0.96<br>algorithm/copy_backward/vector&lt;uint32_t&gt;         146030       142630      1.02<br>algorithm/count/vector&lt;uint64_t&gt;                1395921      1406334      0.99<br>algorithm/equal_range/vector&lt;uint64_t&gt;        211692764    118969493      1.78         *<br>algorithm/fill/bool[]                            366078        33737     10.85         *<br>algorithm/fill/char[]/'d'                         33736        33771      1.00<br>algorithm/fill/vector&lt;char&gt;/'d'                   28466        33720      0.84         *<br>algorithm/fill/vector&lt;char&gt;/0                    366086        33728     10.85         *<br>algorithm/fill/vector&lt;uint64_t&gt;                  466250       401591      1.16         *<br>algorithm/fill/vector&lt;void*&gt;                     521603       693481      0.75         *<br>algorithm/fill_n/bool[]                          599709        33762     17.76         *<br>algorithm/fill_n/char[]                          599573        33711     17.79         *<br>algorithm/fill_n/vector&lt;uint64_t&gt;                434971      1374084      0.32         *<br>algorithm/find_end/string/end                   1494742        85349     17.51         *<br>algorithm/find_end/string/middle                1480700       687208      2.15         *<br>algorithm/find_end/string/none                  1540540      1546431      1.00<br>algorithm/lex_cmp/schar[]                        921638       178797      5.15         *<br>algorithm/lex_cmp/vector&lt;TestObject&gt;            2623559      2643551      0.99<br>algorithm/lex_cmp/vector&lt;uchar&gt;                  960899       183608      5.23         *<br>algorithm/lower_bound/vector&lt;TestObject&gt;       60630534     56531528      1.07<br>algorithm/min_element/vector&lt;TestObject&gt;        4209022      2768527      1.52         *<br>algorithm/rand_shuffle/vector&lt;uint64_t&gt;        13762010     15969052      0.86         *<br>algorithm/reverse/list&lt;TestObject&gt;               673387       731825      0.92<br>algorithm/reverse/vector&lt;TestObject&gt;             634576       754511      0.84         *<br>algorithm/search/string&lt;char&gt;                   1262599      1387608      0.91<br>algorithm/search_n/string&lt;char&gt;                 1166242       458592      2.54         *<br>algorithm/unique/vector&lt;TestObject&gt;             4912193      5336317      0.92<br>algorithm/unique/vector&lt;uint32_t&gt;                809387       809081      1.00<br>algorithm/unique/vector&lt;uint64_t&gt;               4371814      2414255      1.81         *<br>algorithm/upper_bound/vector&lt;uint32_t&gt;         31899081     29555596      1.08<br><br>bitset&lt;1500&gt;/&gt;&gt;=/1                             63308136     40553560      1.56         *   STLPort is broken, neglects wraparound check.<br>bitset&lt;1500&gt;/count                             62523178     22799473      2.74         *<br>bitset&lt;1500&gt;/flip                              20302845     19919232      1.02<br>bitset&lt;1500&gt;/reset                             18892015     15403148      1.23         *<br>bitset&lt;1500&gt;/set()                             15803302     17322192      0.91<br>bitset&lt;1500&gt;/set(i)                             2799271      2999310      0.93<br>bitset&lt;1500&gt;/test                               2999293      2799262      1.07<br><br>bitset&lt;15&gt;/&gt;&gt;=/1                                1199239      3199256      0.37         *   STLPort is broken, neglects wraparound check.<br>bitset&lt;15&gt;/count                                3599461      2199231      1.64         *<br>bitset&lt;15&gt;/flip                                 1199231      1199188      1.00<br>bitset&lt;15&gt;/reset                                1199188      1199180      1.00<br>bitset&lt;15&gt;/set()                                1199214      1199180      1.00<br>bitset&lt;15&gt;/set(i)                               2599257      1399262      1.86         *<br>bitset&lt;15&gt;/test                                 2599274      2599283      1.00<br><br>bitset&lt;35&gt;/&gt;&gt;=/1                                6643974      4599239      1.44         *   STLPort is broken, neglects wraparound check.<br>bitset&lt;35&gt;/count                                5151331      5399438      0.95<br>bitset&lt;35&gt;/flip                                 1999404      1199273      1.67         *<br>bitset&lt;35&gt;/reset                                9805285      1399313      7.01         *<br>bitset&lt;35&gt;/set()                                2799279      1199248      2.33         *<br>bitset&lt;35&gt;/set(i)                               2799246      1599241      1.75         *<br>bitset&lt;35&gt;/test                                 2999234      2999251      1.00<br><br>bitset&lt;75&gt;/&gt;&gt;=/1                                7002045      6999333      1.00             STLPort is broken, neglects wraparound check.<br>bitset&lt;75&gt;/count                                5999351      3002259      2.00         *<br>bitset&lt;75&gt;/flip                                 3599334      3599163      1.00<br>bitset&lt;75&gt;/reset                                9799344      3399218      2.88         *<br>bitset&lt;75&gt;/set()                                3599232      3599062      1.00<br>bitset&lt;75&gt;/set(i)                               2799228      1599284      1.75         *<br>bitset&lt;75&gt;/test                                 2999250      2799339      1.07<br><br>deque&lt;ValuePair&gt;/erase                        127108651    115258113      1.10<br>deque&lt;ValuePair&gt;/insert                       137727889    116552332      1.18         *<br>deque&lt;ValuePair&gt;/iteration                      7144182      6009899      1.19         *<br>deque&lt;ValuePair&gt;/operator[]                    34241222     20535039      1.67         *<br>deque&lt;ValuePair&gt;/push_back                      6585800      3932126      1.67         *<br>deque&lt;ValuePair&gt;/push_front                     6805865      3993513      1.70         *<br>deque&lt;ValuePair&gt;/sort                         395352323    348778188      1.13         *<br><br>hash_map&lt;string, uint32_t&gt;/clear                 426640       447015      0.95<br>hash_map&lt;string, uint32_t&gt;/count                4359344      3883089      1.12         *<br>hash_map&lt;string, uint32_t&gt;/erase pos             584392       458142      1.28         *<br>hash_map&lt;string, uint32_t&gt;/erase range           221034       196078      1.13         *<br>hash_map&lt;string, uint32_t&gt;/erase val            3539867      3790813      0.93<br>hash_map&lt;string, uint32_t&gt;/find                 3966831      3811910      1.04<br>hash_map&lt;string, uint32_t&gt;/find_as/char*       11591612      4243710      2.73         *<br>hash_map&lt;string, uint32_t&gt;/insert              16763887     16719194      1.00<br>hash_map&lt;string, uint32_t&gt;/iteration             909968       478609      1.90         *<br>hash_map&lt;string, uint32_t&gt;/operator[]           4360041      4108313      1.06<br><br>hash_map&lt;uint32_t, TestObject&gt;/clear             302634       283722      1.07<br>hash_map&lt;uint32_t, TestObject&gt;/count             916487       907426      1.01<br>hash_map&lt;uint32_t, TestObject&gt;/erase pos         388042       321385      1.21         *<br>hash_map&lt;uint32_t, TestObject&gt;/erase range       122680       116280      1.06<br>hash_map&lt;uint32_t, TestObject&gt;/erase val        1710931      1729529      0.99<br>hash_map&lt;uint32_t, TestObject&gt;/find             1089462      1346527      0.81         *<br>hash_map&lt;uint32_t, TestObject&gt;/insert           4560310      5072350      0.90         *<br>hash_map&lt;uint32_t, TestObject&gt;/iteration         960117       495354      1.94         *<br>hash_map&lt;uint32_t, TestObject&gt;/operator[]       1872830      1890595      0.99<br><br>heap (uint32_t[])/make_heap                     3528418      3327257      1.06<br>heap (uint32_t[])/pop_heap                     63243859     61011853      1.04<br>heap (uint32_t[])/push_heap                    11602424     10045869      1.15         *<br>heap (uint32_t[])/sort_heap                    52965362     48744729      1.09<br><br>heap (vector&lt;TestObject&gt;)/make_heap            13191456     13089711      1.01<br>heap (vector&lt;TestObject&gt;)/pop_heap            148555656    144787742      1.03<br>heap (vector&lt;TestObject&gt;)/push_heap            28696689     26618830      1.08<br>heap (vector&lt;TestObject&gt;)/sort_heap           112473989    114018643      0.99<br><br>list&lt;TestObject&gt;/ctor(it)                      80186731     74006287      1.08<br>list&lt;TestObject&gt;/ctor(n)                        6232311      6128007      1.02<br>list&lt;TestObject&gt;/erase                        344556374    212877808      1.62         *<br>list&lt;TestObject&gt;/find                          39859075     14591347      2.73         *<br>list&lt;TestObject&gt;/insert                        86935153     56138233      1.55         *<br>list&lt;TestObject&gt;/push_back                     79569180     46700641      1.70         *<br>list&lt;TestObject&gt;/remove                       785786758    324201016      2.42         *<br>list&lt;TestObject&gt;/reverse                       45248186     24852759      1.82         *<br>list&lt;TestObject&gt;/size/1                          219844       219496      1.00<br>list&lt;TestObject&gt;/size/10                         519563       519579      1.00             EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/size/100                       4567194    101230266      0.05         *   EASTL intentionally implements list::size as O(n).<br>list&lt;TestObject&gt;/splice                        68321087     23601687      2.89         *<br><br>map&lt;TestObject, uint32_t&gt;/clear                  168011       180540      0.93<br>map&lt;TestObject, uint32_t&gt;/count                 4830439      5139287      0.94<br>map&lt;TestObject, uint32_t&gt;/equal_range           8700090      6158531      1.41         *<br>map&lt;TestObject, uint32_t&gt;/erase/key             6696776      4617038      1.45         *<br>map&lt;TestObject, uint32_t&gt;/erase/pos              309273       333183      0.93<br>map&lt;TestObject, uint32_t&gt;/erase/range            137419       136068      1.01<br>map&lt;TestObject, uint32_t&gt;/find                  4773498      4931352      0.97<br>map&lt;TestObject, uint32_t&gt;/insert                9651877      9311699      1.04<br>map&lt;TestObject, uint32_t&gt;/iteration              372946       416364      0.90         *<br>map&lt;TestObject, uint32_t&gt;/lower_bound           4784234      4915797      0.97<br>map&lt;TestObject, uint32_t&gt;/operator[]            5040254      5183147      0.97<br>map&lt;TestObject, uint32_t&gt;/upper_bound           4724292      4915984      0.96<br><br>set&lt;uint32_t&gt;/clear                              165300       173289      0.95<br>set&lt;uint32_t&gt;/count                             4958654      4885086      1.02<br>set&lt;uint32_t&gt;/equal_range                       8434134      5698681      1.48         *<br>set&lt;uint32_t&gt;/erase range                        145554       133960      1.09<br>set&lt;uint32_t&gt;/erase/pos                          299914       324760      0.92<br>set&lt;uint32_t&gt;/erase/val                         6506155      4335034      1.50         *<br>set&lt;uint32_t&gt;/find                              4866879      4556043      1.07<br>set&lt;uint32_t&gt;/insert                            8340523      8957257      0.93<br>set&lt;uint32_t&gt;/iteration                          294465       343442      0.86         *<br>set&lt;uint32_t&gt;/lower_bound                       4548095      4756498      0.96<br>set&lt;uint32_t&gt;/upper_bound                       4559196      4521498      1.01<br><br>sort/q_sort/TestObject[]                        7316766      7013894      1.04<br>sort/q_sort/TestObject[]/sorted                 1668439      1332885      1.25         *<br>sort/q_sort/vector&lt;TestObject&gt;                  7331530      7017260      1.04<br>sort/q_sort/vector&lt;TestObject&gt;/sorted           1601629      1247120      1.28         *<br>sort/q_sort/vector&lt;ValuePair&gt;                   7071643      7067869      1.00<br>sort/q_sort/vector&lt;ValuePair&gt;/sorted            2136390      1703799      1.25         *<br>sort/q_sort/vector&lt;uint32&gt;                      3292891      2943627      1.12         *<br>sort/q_sort/vector&lt;uint32&gt;/sorted                653693       473612      1.38         *<br><br>string&lt;char16_t&gt;/compare                      356579259    432760228      0.82         *<br>string&lt;char16_t&gt;/erase/pos,n                    3430422      3428645      1.00<br>string&lt;char16_t&gt;/find/p,pos,n                 229263402    225830975      1.02<br>string&lt;char16_t&gt;/find_first_not_of/p,pos,n       187391        81404      2.30         *<br>string&lt;char16_t&gt;/find_first_of/p,pos,n          4411831      4413532      1.00<br>string&lt;char16_t&gt;/find_last_of/p,pos,n            731655       726155      1.01<br>string&lt;char16_t&gt;/insert/pos,p                   3408628      3319726      1.03<br>string&lt;char16_t&gt;/iteration                    309993861    310333547      1.00<br>string&lt;char16_t&gt;/operator[]                      580839       579904      1.00<br>string&lt;char16_t&gt;/push_back                      3983338      2975553      1.34         *<br>string&lt;char16_t&gt;/replace/pos,n,p,n              4361095      4211504      1.04<br>string&lt;char16_t&gt;/reserve                      935141729       247010    100.00         *<br>string&lt;char16_t&gt;/rfind/p,pos,n                   248956       223397      1.11         *<br>string&lt;char16_t&gt;/size                             13311        13107      1.02<br>string&lt;char16_t&gt;/swap                            519129       579445      0.90         *<br><br>string&lt;char8_t&gt;/compare                        76695559     76828015      1.00<br>string&lt;char8_t&gt;/erase/pos,n                     1951566      1947282      1.00<br>string&lt;char8_t&gt;/find/p,pos,n                  185878944    185605039      1.00<br>string&lt;char8_t&gt;/find_first_not_of/p,pos,n        196877        81600      2.41         *<br>string&lt;char8_t&gt;/find_first_of/p,pos,n           4147685      4145356      1.00<br>string&lt;char8_t&gt;/find_last_of/p,pos,n             605897       598222      1.01<br>string&lt;char8_t&gt;/insert/pos,p                    1781592      1768264      1.01<br>string&lt;char8_t&gt;/iteration                        921502       921272      1.00<br>string&lt;char8_t&gt;/operator[]                       361250       359873      1.00<br>string&lt;char8_t&gt;/push_back                       3363288      2530493      1.33         *<br>string&lt;char8_t&gt;/replace/pos,n,p,n               2682600      2633130      1.02<br>string&lt;char8_t&gt;/reserve                       672517501        78387    100.00         *<br>string&lt;char8_t&gt;/rfind/p,pos,n                    226202       200013      1.13         *<br>string&lt;char8_t&gt;/size                              11280        11109      1.02<br>string&lt;char8_t&gt;/swap                             519393       559759      0.93<br><br>vector&lt;uint64&gt;/erase                           55184856     55192217      1.00<br>vector&lt;uint64&gt;/insert                          56764267     55682726      1.02<br>vector&lt;uint64&gt;/iteration                         423122       424039      1.00<br>vector&lt;uint64&gt;/operator[]                       1189397       860991      1.38         *<br>vector&lt;uint64&gt;/push_back                        5626609      4027317      1.40         *<br>vector&lt;uint64&gt;/sort                            49227036     49231362      1.00<br></pre>\n\n\n\n\n\n</div>\n\n\n\n\n\n<h2>\n\n\n\n\n\n\n\n\n<br>\n\n\n\n<hr style=\"width: 100%; height: 2px;\">\nEnd of document<br>\n\n\n\n<br>\n\n\n\n<br>\n\n\n\n<br>\n\n\n\n<br>\n\n\n\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL Best Practices.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n    <title>EASTL Best Practices</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Best practices for EASTL usage\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n    <style type=\"text/css\">\n<!--\n.style1 {font-size: 12pt}\n-->\n    </style>\n</head>\n<body>\n<h1>EASTL Best Practices</h1>\n<p>In this document we discuss best practices for using EASTL. The primary emphasis is on performance with a secondary\n  emphasis on correctness and maintainability. Some best practices apply only to some situations, and these will be\n  pointed out as we go along. In order to be easily digestible, we present these practices as a list of items in the tone\n  of the Effective C++ series of books.</p>\n<h2>Summary</h2>\n<p>The descriptions here are intentionally terse; this is to make them easier to visually scan.</p>\n<table style=\"text-align: left; width: 100%;\" border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Best.1\">Consider intrusive containers.</a></td>\n</tr>\n<tr>\n<td>2</td>\n<td><a href=\"#Best.2\">Consider fixed-size containers.</a></td>\n</tr>\n<tr>\n<td>3</td>\n<td><a href=\"#Best.3\">Consider custom allocators.</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Best.4\">Consider hash tables instead of maps.</a></td>\n</tr>\n<tr>\n<td>5</td>\n<td><a href=\"#Best.5\">Consider a vector_map (a.k.a. sorted vector) for unchanging data.</a></td>\n</tr>\n<tr>\n<td>6</td>\n<td><a href=\"#Best.6\">Consider slist instead of list.</a></td>\n</tr>\n<tr>\n<td>7</td>\n<td><a href=\"#Best.7\">Avoid redundant end() and size() in loops.</a></td>\n</tr>\n<tr>\n<td>8</td>\n<td><a href=\"#Best.8\">Iterate containers instead of using operator[].</a></td>\n</tr>\n<tr>\n<td>9</td>\n<td><a href=\"#Best.9\">Learn to use the string class appropriately.</a></td>\n</tr>\n<tr>\n<td>10</td>\n<td><a href=\"#Best.10\">Cache list size if you want size() to be O(1).</a></td>\n</tr>\n<tr>\n<td>11</td>\n<td><a href=\"#Best.11\">Use empty() instead of size() when possible.</a></td>\n</tr>\n<tr>\n<td>12</td>\n<td><a href=\"#Best.12\">Know your container efficiencies.</a></td>\n</tr>\n<tr>\n<td>13</td>\n<td><a href=\"#Best.13\">Use vector::reserve.</a></td>\n</tr>\n<tr>\n<td>14</td>\n<td><a href=\"#Best.14\">Use&nbsp;vector::set_capacity to trim memory usage.</a></td>\n</tr>\n<tr>\n<td>15</td>\n<td><a href=\"#Best.15\">Use swap() instead of a manually implemented version.</a></td>\n</tr>\n<tr>\n<td>16</td>\n<td><a href=\"#Best.16\">Consider storing pointers instead of objects.</a></td>\n</tr>\n<tr>\n<td>17</td>\n<td><a href=\"#Best.17\">Consider smart pointers instead of raw pointers.</a></td>\n</tr>\n<tr>\n<td>18</td>\n<td><a href=\"#Best.18\">Use iterator pre-increment instead of post-increment.</a></td>\n</tr>\n<tr>\n<td>19</td>\n<td><a href=\"#Best.19\">Make temporary references so the code can be traced/debugged.</a></td>\n</tr>\n<tr>\n<td>20</td>\n<td><a href=\"#Best.20\">Consider bitvector or bitset instead of vector&lt;bool&gt;.</a></td>\n</tr>\n<tr>\n<td>21</td>\n<td><a href=\"#Best.21\">Vectors can be treated as contiguous memory.</a></td>\n</tr>\n<tr>\n<td>22</td>\n<td><a href=\"#Best.22\">Search&nbsp;hash_map&lt;string&gt; via find_as() instead of find().</a></td>\n</tr>\n<tr>\n<td>23</td>\n<td><a href=\"#Best.23\">Take advantage of type_traits (e.g. <small style=\n\"font-family: Courier New;\">EASTL_DECLARE_TRIVIAL_RELOCATE</small>).</a></td>\n</tr>\n<tr>\n<td>24</td>\n<td><a href=\"#Best.24\">Name containers to track memory usage.</a></td>\n</tr>\n<tr>\n<td>25</td>\n<td><a href=\"#Best.25\">Learn the algorithms.</a></td>\n</tr>\n<tr>\n<td>26</td>\n<td><a href=\"#Best.26\">Pass and return containers by reference instead of value.</a></td>\n</tr>\n<tr>\n<td>27</td>\n<td><a href=\"#Best.27\">Consider using reset_lose_memory() for fast container teardown.</a></td>\n</tr>\n<tr>\n<td>28</td>\n<td><a href=\"#Best.28\">Consider using fixed_substring instead of copying strings.</a></td>\n</tr>\n<tr>\n  <td>29</td>\n  <td><a href=\"#Best.29\">Consider using vector::push_back(void).</a></td>\n</tr>\n</tbody>\n</table>\n<h2>Detail</h2>\n<p class=\"faq-question\"><a name=\"Best.1\"></a>1\n  Consider intrusive containers.\n</p>\n<p class=\"faq-answer\">Intrusive containers (such as intrusive_list) differ from regular containers (such as list) in that they use the stored objects to manage the linked list instead of using nodes allocated from a memory heap. The result is better usage of memory. Additionally intrusive_list objects can be removed from their list without knowing what list they belong to. To make an intrusive_list of Widgets, you have Widget inherit from intrusive_list_node or simply have mpPrev/mpNext member variables.</p>\n<p class=\"faq-answer\">To create an intrusive_list container, you can use the following code:</p>\n<p class=\"code-example\">class Widget : public intrusive_list_node<br>\n{ };<br>\n<br>\nintrusive_list&lt;Widget&gt; widgetList;<br>\nwidgetList.push_back(someWidget);</p>\n<p></p>\n<p class=\"faq-question\"><a name=\"Best.2\"></a>2\n  Consider fixed-size containers.\n</p>\n<p class=\"faq-answer\">Fixed-size containers (such as fixed_list) are variations of regular containers (such as list) in that they allocate from a fixed block of local memory instead of allocating from a generic heap. The result is better usage of memory due to reduced fragmentation, better cache behavior, and faster allocation/deallocation. The presence of fixed-size containers negate the most common complaint that people have about STL: that it fragments the heap or &quot;allocates all over the place.&quot;</p>\n<p class=\"faq-answer\">EASTL fixed containers include:</p>\n<ul>\n  <li>fixed_list</li>\n  <li>fixed_slist</li>\n  <li>fixed_vector</li>\n  <li>fixed_string</li>\n  <li>fixed_map</li>\n  <li>fixed_multimap</li>\n  <li>fixed_set</li>\n  <li>fixed_multiset</li>\n  <li>fixed_hash_map</li>\n  <li>fixed_hash_multimap</li>\n  <li>fixed_hash_set</li>\n  <li>fixed_hash_multiset</li>\n</ul>\n<p class=\"faq-answer\">To create a fixed_set, you can use the following code:</p>\n<p class=\"code-example\">fixed_set&lt;int, 25&gt; intSet; // Create a set capable of holding 25 elements.<br>\nintSet.push_back(37);</p>\n<p></p>\n<p class=\"faq-question\"><a name=\"Best.3\"></a>3\n  Consider custom allocators.\n</p>\n<p class=\"faq-answer\">While EASTL provides fixed-size containers in order to control container memory usage, EASTL lets you assign a custom allocator to any container. This lets you define your own memory pool. EASTL has a more flexible and powerful mechanism of doing this that standard STL, as EASTL understands object alignment requirements, allows for debug naming, allows for sharing allocators across containers, and allows dynamic allocator assignment.</p>\n<p class=\"faq-answer\">To create a list container that uses your custom allocator and uses block naming, you can use the following code:</p>\n<p class=\"code-example\">list&lt;int&gt; intList(pSomeAllocator, &quot;graphics/intList&quot;);<br>\nintList.push_back(37);</p>\n<p class=\"faq-question\"><a name=\"Best.4\"></a>4\nConsider hash tables instead of maps.</p>\n<p class=\"faq-answer\">Hash containers (such as hash_map) provide the same interface as associative containers (such as map) but have faster lookup and use less memory. The primary disadvantage relative to associative containers is that hash containers are not sorted.</p>\n<p class=\"faq-answer\">To make a hash_map (dictionary) of integers to strings, you can use the following code:</p>\n<p class=\"code-example\">hash_map&lt;int, const char*&gt; stringTable;<br>\nstringTable[37] = &quot;hello&quot;;</p>\n<p class=\"faq-question\"><a name=\"Best.5\"></a>5\n  Consider a vector_map (a.k.a. sorted vector) for unchanging data.\n</p>\n<p class=\"faq-answer\">You can improve speed, memory usage, and cache behavior by using a vector_map instead of a map (or vector_set instead of set, etc.). The primary disadvantage of vector_map is that insertions and removal of elements is O(n) instead of O(1). However, if your associative container is not going to be changing much or at all, you can benefit from using a vector_map. Consider calling reserve on the vector_map in order to set the desired capacity up front.</p>\n<p class=\"faq-answer\">To make a vector_set, you can use the following code:</p>\n<p class=\"code-example\">vector_set&lt;int&gt; intSet(16); // Create a vector_set with an initial capacity of 16.<br>\nintSet.insert(37);</p>\n<p class=\"faq-answer\">Note that you can use containers other than vector to implement vector_set. Here's how you do it with deque:</p>\n<p class=\"code-example\">vector_set&lt;int, less&lt;int&gt;, EASTLAllocatorType, deque&lt;int&gt; &gt; intSet;<br>\nintSet.insert(37);</p>\n<p class=\"faq-question\"><a name=\"Best.6\"></a>6\n  Consider slist instead of list.\n</p>\n<p class=\"faq-answer\">An slist is a singly-linked list; it is much like a list except that it can only be traversed in a forward direction and not a backward direction. The benefit is that each node is 4 bytes instead of 8 bytes. This is a small improvement, but if you don't need reverse iteration then it can be an improvement. There's also intrusive_slist as an option.</p>\n<p class=\"faq-answer\">To make an slist, you can use the following code:</p>\n<p class=\"code-example\">slist&lt;int&gt; intSlist;<br>\nintSlist.push_front(37);</p>\n<p class=\"faq-question\"><a name=\"Best.7\"></a>7\nAvoid redundant end() and size() in loops.</p>\n<p class=\"faq-answer\">Instead of writing code like this:<br>\n</p>\n<div class=\"code-example\" style=\"margin-left: 40px; font-family: Courier New;\"><small>for(deque&lt;int&gt;::iterator it = d.begin(); <span style=\"color: rgb(204, 0, 0);\">it != d.end()</span>; ++it)<br>\n&nbsp;&nbsp;&nbsp; ...</small></div>\n<span class=\"faq-answer\">write code like this:<br>\n</span>\n<div class=\"code-example\" style=\"margin-left: 40px; font-family: Courier New;\"><small>for(deque&lt;int&gt;::iterator it = d.begin(), itEnd = d.end(); <span style=\"color: rgb(51, 204, 0);\">it != itEnd</span>; ++it)<br>\n&nbsp;&nbsp;&nbsp; ...</small></div>\n<span class=\"faq-answer\">The latter avoids a function call and return of an object (which in deque's case happens to be more than just a pointer). The above only works when the container is unchanged or for containers that have a constant end value. By \"constant end value\" we mean containers which can be modified but end always remains the same.</span><br>\n<table style=\"text-align: left; width: 600px; margin-left: 40px;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n  <tbody>\n    <tr>\n      <td style=\"text-align: center;\">Constant begin</td>\n      <td style=\"text-align: center;\">Non-constant begin</td>\n      <td style=\"text-align: center;\">Constant end</td>\n      <td style=\"text-align: center;\">Non-constant end</td>\n    </tr>\n    <tr>\n      <td style=\"vertical-align: top;\">array<sup>1</sup></td>\n      <td style=\"vertical-align: top;\">string<br>\n        vector<br>\n        deque<br>\n        intrusive_list<br>\n        intrusive_slist<br>\n        vector_map<br>\n        vector_multimap<br>\n        vector_set<br>\n        vector_multiset<br>\n        bit_vector<br>\n        hash_map<br>\n        hash_multimap<br>\n        hash_set<br>\n        hash_multiset<br>\n        intrusive_hash_map<br>\n        intrusive_hash_multimap<br>\n        intrusive_hash_set<br>\n        intrusive_hash_multiset</td>\n      <td style=\"vertical-align: top;\">array<br>\n        list<br>\n        slist<br>\n        intrusive_list<br>\n        intrusive_slist<br>\n        map<br>\n        multimap<br>\n        set<br>\n        multiset<br>\n        hash_map<sup>2</sup><br>\n        hash_multimap<sup>2</sup><br>\n        hash_set<sup>2</sup><br>\n        hash_multiset<sup>2</sup><br>\n        intrusive_hash_map<br>\n        intrusive_hash_multimap<br>\n        intrusive_hash_set<br>\n        intrusive_hash_multiset</td>\n      <td style=\"vertical-align: top;\">string<br>\n        vector<br>\n        deque<br>\n        vector_map<br>\n        vector_multimap<br>\n        vector_set<br>\n        vector_multiset<br>\n        bit_vector<br></td>\n    </tr>\n  </tbody>\n</table>\n<div style=\"margin-left: 40px;\"><sup>1</sup> Arrays can be neither resized nor reallocated.<br>\n    <sup>2</sup> Constant end if the hashtable can't/won't re-hash. Non-constant if it can re-hash.</div>\n<p class=\"faq-question\">  <a name=\"Best.8\"></a>8\nIterate containers instead of using operator[].\n</p>\n<p class=\"faq-answer\">It's faster to iterate random access containers via iterators than via operator[], though operator[] usage may look simpler.</p>\n<p class=\"faq-answer\">Instead of doing this:</p>\n<p class=\"code-example\">for(unsigned i = 0, iEnd = intVector.size(); i != iEnd; ++i)<br>\n&nbsp;&nbsp;&nbsp;&nbsp;intVector[i] = 37;</p>\n<p class=\"faq-answer\">you can execute more efficiently by doing this:</p>\n<p class=\"code-example\">for(vector&lt;int&gt;::iterator it = intVector.begin(), itEnd = intVector.end(); it != itEnd; ++it)<br>\n&nbsp;&nbsp;&nbsp;&nbsp;*it = 37;</p>\n<p class=\"faq-question\">  <a name=\"Best.9\"></a>9\nLearn to use the string class appropriately.</p>\n<p class=\"faq-answer\">Oddly enough, the most mis-used STL container is easily the string class. The tales of string abuse could rival the 1001 Arabian Nights. Most of the abuses involve doing things in a harder way than need be. In examining the historical mis-uses of string, it is clear that many of the problems stem from the user thinking in terms of C-style string operations instead of object-oriented strings. This explains why statements such as&nbsp;<small><span style=\"font-family: Courier New;\">strlen(s.c_str())</span></small> are so common, whereas the user could just use <small><span style=\"font-family: Courier New;\">s.length()</span></small> instead and be both clearer and more efficient.<br>\n<br>\nHere we provide a table of actual collected examples of things done and how they could have been done instead.</p>\n<table style=\"text-align: left; width: 90%; margin-left: 40px;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n  <tbody>\n    <tr>\n      <td style=\"font-weight: bold;\">What was written</td>\n      <td style=\"font-weight: bold;\">What could have been written</td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n        s = s.Left(i) + '+' + s.Right(s.length() - i - 1);<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>s[i] = '+';</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n  string s(\"\"); // This is the most commonly found misuse.<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>string s;</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n  s = \"\";<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>s.clear();</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n        s.c_str()[0] = 'u';<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>s[0] = 'u';</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n        len = strlen(s.c_str());<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>len = s.length();</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n  s = string(\"u\");<br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>s = \"u\";</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n  puts(s + string(\"u\"));<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>puts(s + \"u\");</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n  string s(\" \");<br>\n        puts(s.c_str());<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>puts(\" \");</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n  s.sprintf(\"u\");<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>s = \"u\";</small></td>\n    </tr>\n    <tr>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small><br>\n        char array[32];<br>\n        sprintf(array, \"%d\", 10);<br>\n        s = string(array);<br>\n        <br>\n      </small></td>\n      <td class=\"style1\" style=\"font-family: Courier New;\"><small>s.sprintf(\"%d\", 10);</small></td>\n    </tr>\n  </tbody>\n</table>\n<p class=\"faq-answer\"><br>\nThe chances are that if you want to do something with a string, there is a very basic way to do it. You don't want your code to appear in a future version of the above table.</p>\n<p class=\"faq-question\">  <a name=\"Best.10\"></a>10\nCache list size if you want list::size() to be O(1).</p>\n<p class=\"faq-answer\">EASTL's list, slist, intrusive_list, and intrusive_slist containers have a size() implementation which is O(n). That is, these containers don't keep a count (cache) of the current list size and when you call the size() function they iterate the list. This is by design and the reasoning behind it has been deeply debated and considered (and is discussed in the FAQ and the list header file). In summary, list doesn't cache its size because the only function that would benefit is the size function while many others would be negatively impacted and the memory footprint would be negatively impacted, yet list::size is not a very frequently called function in well-designed code. At the same time, nothing prevents the user from caching the size himself, though admittedly it adds some tedium and risk to the code writing process.<br>\n  <br>\nHere's an example of caching the list size manually:<br>\n</p>\n<div class=\"code-example\" style=\"margin-left: 40px;\"><small><span style=\"font-family: Courier New;\">list&lt;int&gt; intList;<br>\n  size_t &nbsp; &nbsp;n = 0;<br>\n  <br>\n  intList.push_back(37);<br>\n  ++n;<br>\n  intList.pop_front();<br>\n  --n;</span></small></div>\n<p class=\"faq-question\">  <a name=\"Best.11\"></a>11\nUse empty() instead of size() when possible.\n</p>\n<p class=\"faq-answer\">All conventional containers have both an empty function and a size function. For all containers empty() executes with O(1) (constant time) efficiency. However, this is not so for size(), as some containers need to calculate the size and others need to do pointer subtraction (which may involve integer division) to find the size.</p>\n<p class=\"faq-question\"><a name=\"Best.12\"></a>12\nKnow your container efficiencies.</p>\n<p class=\"faq-answer\">The above two practices lead us to this practice, which is a generalization of the above.\n  We present a table of basic information for the conventional EASTL containers. The values are described at the\n  bottom.</p>\n<table style=\"width: 90%; margin-left: 40px;\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">\n  <tbody>\n    <tr>\n      <td style=\"width: 15%; vertical-align: top; height: 13px; font-weight: bold;\"><p>Container</p></td>\n      <td style=\"text-align: center;\">empty() efficiency</td>\n      <td style=\"text-align: center; font-weight: bold;\">size() efficiency</td>\n      <td style=\"text-align: center; font-weight: bold;\">operator[] efficiency</td>\n      <td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\"><p>insert() efficiency</p></td>\n      <td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\"><p>erase() efficiency</p></td>\n      <td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"7%\"><p>find() efficiency</p></td>\n      <td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\"><p>sort efficiency</p></td>\n    </tr>\n    <tr>\n      <td>slist</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">O(n)</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">O(1)</td>\n      <td style=\"text-align: center;\">O(1)</td>\n      <td style=\"text-align: center;\">O(n)</td>\n      <td style=\"text-align: center;\">O(n+)</td>\n    </tr>\n    <tr>\n      <td height=\"13\" valign=\"top\" width=\"15%\"><p>list</p></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\"><p>1</p></td>\n      <td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\"><p>1</p></td>\n      <td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"7%\"><p>n</p></td>\n      <td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\"><p>n log(n)</p></td>\n    </tr>\n    <tr>\n      <td>intrusive_slist</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">n+</td>\n    </tr>\n    <tr>\n      <td>intrusive_list</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">n log(n)</td>\n    </tr>\n    <tr>\n      <td>array</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">n log(n)</td>\n    </tr>\n    <tr>\n      <td>vector</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">n log(n)</td>\n    </tr>\n    <tr>\n      <td>vector_set</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>vector_multiset</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>vector_map</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>vector_multimap</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>deque</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at begin or end,<br>\n        else n / 2</td>\n      <td style=\"text-align: center;\">1&nbsp;at begin or end,<br>\n        else n / 2</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">n log(n)</td>\n    </tr>\n    <tr>\n      <td>bit_vector</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">n log(n)</td>\n    </tr>\n    <tr>\n      <td>string, cow_string</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1<sup>a</sup></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n      <td style=\"text-align: center;\">n</td>\n      <td style=\"text-align: center;\">n log(n)</td>\n    </tr>\n    <tr>\n      <td>set</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>multiset</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>map</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>multimap</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">log(n)</td>\n      <td style=\"text-align: center;\">1</td>\n    </tr>\n    <tr>\n      <td>hash_set</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n    <tr>\n      <td>hash_multiset</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1<br></td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n    <tr>\n      <td>hash_map</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n    <tr>\n      <td>hash_multimap</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n    <tr>\n      <td>intrusive_hash_set</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n    <tr>\n      <td>intrusive_hash_multiset</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n    <tr>\n      <td>intrusive_hash_map</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n    <tr>\n      <td>intrusive_hash_multimap</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">1</td>\n      <td style=\"text-align: center;\">-</td>\n    </tr>\n  </tbody>\n</table>\n<p class=\"faq-answer\"><br>\n  Notes:\n</p>\n<ul>\n  <li>- means that the operation does not exist.</li>\n  <li>1 means amortized constant time. Also known as O(1)</li>\n  <li>n means time proportional to the container size. Also known as O(n)</li>\n  <li>log(n) means time proportional to the natural logarithm of the container size. Also known as O(log(n))</li>\n  <li>n log(n) means time proportional to log(n) times the size of the container. Also known as O(n log(n))</li>\n  <li>n+ means that the time is at least n, and possibly higher.</li>\n  <li>Inserting at the end of a vector may cause the vector to be resized; resizing a vector is O(n). However, the amortized time complexity for vector insertions at the end is constant.</li>\n  <li>Sort assumes the usage of the best possible sort for a large container of random data. Some sort algorithms (e.g. quick_sort) require random access iterators and so the sorting of some containers requires a different sort algorithm. We do not include bucket or radix sorts, as they are always O(n).</li>\n  <li><sup>a</sup> vector, deque, string size is O(1) but involves pointer subtraction and thus&nbsp;integer division and so is not as efficient as containers that store the size directly.</li>\n</ul>\n<p class=\"faq-question\"><a name=\"Best.13\"></a>13\nUse vector::reserve.</p>\n<p class=\"faq-answer\">You can prevent vectors (and strings) from reallocating as you add items by specifying up front how many items you will be requiring. You can do this in the constructor or by calling the reserve function at any time. The capacity function returns the amount of space which is currently reserved.<br>\n  <br>\nHere's how you could specify reserved capacity in a vector:<br>\n</p>\n<div class=\"code-example\" style=\"margin-left: 40px; font-family: Courier New;\"><small>vector&lt;Widget&gt; v(37); &nbsp; // Reserve space to hold up to 37 items.<br>\n&nbsp; &nbsp; or<br>\nvector&lt;Widget&gt; v; &nbsp; &nbsp; &nbsp; // This empty construction causes to memory to be allocated or reserved.<br>\n  v.reserve(37);<br>\n</small></div>\n<span class=\"faq-answer\">The EASTL vector (and string) implementation looks like this:</span>\n<span class=\"code-example\"><small>template &lt;typename T&gt;<br>\n  class vector {<br>\n&nbsp;&nbsp;&nbsp; T* mpBegin; &nbsp; &nbsp; // Beginning of used element memory.<br>\n&nbsp; &nbsp; T* mpEnd; &nbsp; &nbsp; &nbsp; // End of used element memory.<br>\n&nbsp; &nbsp; T* mpCapacity; &nbsp;// End of storage capacity. Is &gt;= mpEnd<br>\n  </small> <small>}</small></span><small>  </small><span class=\"faq-answer\">\nAnother approach to being efficient with vector memory usage is to use fixed_vector.</span>\n  <p class=\"faq-question\"><a name=\"Best.14\"></a>14\nUse vector::set_capacity to trim memory usage.</p>\n<p class=\"faq-answer\">A commonly asked question about vectors and strings is, \"How do I reduce the capacity of a vector?\" The conventional solution for std STL is to use the somewhat non-obvious trick of using <small><span style=\n\"font-family: Courier New;\">vector&lt;Widget&gt;(v).swap(v)</span></small>. EASTL provides the same functionality via a member function called set_capacity() which is present in both the vector and string classes.&nbsp;<br>\n  <br>\nAn example of reducing a vector is the following:</p>\n<span class=\"code-example\"><small>vector&lt;Widget&gt; v;<br>\n...<br>\n</small> <small>v.set_capacity();</small></span><small>  </small><span class=\"faq-answer\">\nAn example of resizing to zero and completely freeing the memory of a vector is the following:<br>\n</span>\n<div class=\"code-example\" style=\"margin-left: 40px; font-family: Courier New;\"><small>vector&lt;Widget&gt; v;<br>\n  ...<br>\n  </small> <small>v.set_capacity(0);</small></div>\n<p class=\"faq-question\"><a name=\"Best.15\"></a>15 Use swap() instead of a manually implemented version.</p>\n<p class=\"faq-answer\">The generic swap algorithm provides a basic version for any kind of object. However, each EASTL container provides a specialization of swap which is optimized for that container. For example, the list container implements swap by simply swapping the internal member pointers and not by moving individual elements.</p>\n<p class=\"faq-question\">  <a name=\"Best.16\"></a>16\nConsider storing pointers instead of objects.</p>\n<p class=\"faq-answer\">There are times when storing pointers to objects is more efficient or useful than storing objects directly in containers. It can be more efficient to store pointers when the objects are big and the container may need to construct, copy, and destruct objects during sorting or resizing. Moving pointers is usually faster than moving objects. It can be useful to store pointers instead of objects when somebody else owns the objects or the objects are in another container. It might be useful for a Widget to be in a list and in a hash table at the same time.</p>\n<p class=\"faq-question\"><a name=\"Best.17\"></a>17\n  Consider smart pointers instead of raw pointers.\n</p>\n<p class=\"faq-answer\">If you take the above recommendation and store objects as pointers instead of as objects, you may want to consider storing them as smart pointers instead of as regular pointers. This is particularly useful for when you want to delete the object when it is removed from the container. Smart pointers will automatically delete the pointed-to object when the smart pointer is destroyed. Otherwise, you will have to be careful about how you work with the list so that you don't generate memory leaks. Smart pointers implement a shared reference count on the stored pointer, as so any operation you do on a smart pointer container will do the right thing. Any pointer can be stored in a smart pointer, and custom new/delete mechanisms can work with smart pointers. The primary smart pointer is shared_ptr.</p>\n<p class=\"faq-answer\">Here is an example of creating and using a shared_ptr:</p>\n<p class=\"code-example\">typedef shared_ptr&lt;Widget&gt; WPtr;<br>\n  list&lt;WPtr&gt; wList;<br>\n  <br>\n  wList.push_back(WPtr(new Widget)); // The user may&nbsp;have operator new/delete overrides.<br>\nwList.pop_back();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Implicitly deletes the Widget.</p>\n<p class=\"faq-answer\">Here is an example of creating and using a shared_ptr that uses a custom allocation and deallocation mechanism:</p>\n<p class=\"code-example\">typedef shared_ptr&lt;Widget, EASTLAllocatorType, WidgetDelete&gt; WPtr; // WidgetDelete is a custom destroyer.<br>\n  list&lt;WPtr&gt; wList;<br>\n  <br>\n  wList.push_back(WPtr(WidgetCreate(Widget))); // WidgetCreate is a custom allocator.<br>\nwList.pop_back(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Implicitly calls WidgetDelete.</p>\n<p class=\"faq-question\"><a name=\"Best.18\"></a>18\n  Use iterator pre-increment instead of post-increment.\n</p>\n<p class=\"faq-answer\">Pre-increment (e.g. ++x) of iterators is better than post-increment (x++) when the latter is not specifically needed. It is common to find code that uses post-incrementing when it could instead use pre-incrementing; presumably this is due to post-increment looking a little better visually. The problem is that the latter constructs a temporary object before doing the increment. With built-in types such as pointers and integers, the compiler will recognize that the object is a trivial built-in type and that the temporary is not needed, but the compiler cannot do this for other types, even if the compiler sees that the temporary is not used; this is because the constructor may have important side effects and the compiler would be broken if it didn't construct the temporary object.</p>\n<p class=\"faq-answer\">EASTL iterators are usually not trivial types and so it's best not to hope the compiler will do the best thing. Thus you should always play it safe an use pre-increment of iterators whenever post-increment is not required.</p>\n<p class=\"faq-answer\">Here is an example of using iterator pre-increment; for loops like this should always use pre-increment:</p>\n<p class=\"code-example\">for(set&lt;int&gt;::iterator it(intSet.begin()), itEnd(intSet.end()); it != itEnd; ++it)<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;*it = 37;</p>\n<p class=\"faq-question\">  <a name=\"Best.19\"></a>19\n  Make temporary references so the code can be traced/debugged.\n</p>\n<p class=\"faq-answer\">Users want to be able to inspect or modify variables which are referenced by iterators. While EASTL containers and iterators are designed to make this easier than other STL implementations, it makes things very easy if the code explicitly declares a reference to the iterated element. In addition to making the variable easier to debug, it also makes code easier to read and makes the debug (and possibly release) version of the application run more efficiently.</p>\n<p class=\"faq-answer\">Instead of doing this:</p>\n<p class=\"code-example\">for(list&lt;Widget&gt;::iterator it = wl.begin(), itEnd = wl.end(); it != itEnd; ++it) {<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;(*it).x = 37;<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;(*it).y = 38;<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;(*it).z = 39;<br>\n  }</p>\n<p class=\"faq-answer\">Consider doing this:</p>\n<p class=\"code-example\">for(list&lt;Widget&gt;::iterator it = wl.begin(), itEnd = wl.end(); it != itEnd; ++it) {<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;Widget&amp; w = *it; // The user can easily inspect or modify w here.<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;w.x = 37;<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;w.y = 38;<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;w.z = 39;<br>\n  }</p>\n<p class=\"faq-question\"><a name=\"Best.20\"></a>20\n  Consider bitvector or bitset instead of vector&lt;bool&gt;. </p>\n<p class=\"faq-answer\">In EASTL, a vector of bool is exactly that. It intentionally does not attempt to make a specialization which implements a packed bit array. The bitvector class is specifically designed for this purpose. There are arguments either way, but if vector&lt;bool&gt; were allowed to be something other than an array of bool, it would go against user expectations and prevent users from making a true array of bool. There's a mechanism for specifically getting the bit packing, and it is bitvector.</p>\n<p class=\"faq-answer\">Additionally there is bitset, which is not a conventional iterateable container but instead acts like bit flags. bitset may better suit your needs than bitvector if you need to do flag/bit operations instead of array operations. bitset does have an operator[], though.</p>\n<p class=\"faq-question\">  <a name=\"Best.21\"></a>21\nVectors can be treated as contiguous memory.</p>\n<p class=\"faq-answer\">EASTL vectors (and strings) guarantee that elements are present in a linear contiguous array. This means that you can use a vector as you would a C-style array by using the vector data() member function or by using &amp;v[0].</p>\n<p class=\"faq-answer\">To use a vector as a pointer to an array, you can use the following code:</p>\n<p class=\"code-example\">struct Widget {<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;uint32_t x;<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;uint32_t y;<br>\n  };<br>\n  <br>\n  vector&lt;Widget&gt; v;<br>\n  <br>\n  quick_sort((uint64_t*)v.data(), (uint64_t*)(v.data() + v.size()));</p>\n<p class=\"faq-question\"><a name=\"Best.22\"></a>22\nSearch&nbsp;hash_map&lt;string&gt; via find_as() instead of find(). </p>\n<p class=\"faq-answer\">EASTL hash tables offer a bonus function called find_as when lets you search a hash table by something other than the container type. This is particularly useful for hash tables of string objects that you want to search for by string literals (e.g. &quot;hello&quot;) or char pointers. If you search for a string via the find function, your string literal will necessarily be converted to a temporary string object, which is inefficient.</p>\n<p class=\"faq-answer\">To use find_as, you can use the following code:</p>\n<p class=\"code-example\">hash_map&lt;string, int&gt; hashMap;<br>\n  hash_map&lt;string, int&gt;::iterator it = hashMap.find_as(&quot;hello&quot;); // Using default hash and compare.</p>\n<p class=\"faq-question\">  <a name=\"Best.23\"></a>23\nTake advantage of type_traits (e.g. <small style=\n\"font-family: Courier New;\">EASTL_DECLARE_TRIVIAL_RELOCATE</small>).</p>\n<p class=\"faq-answer\">EASTL includes a fairly serious type traits library that is on par with the one found in Boost but offers some additional performance-enhancing help as well. The type_traits library provides information about class <span style=\"font-style: italic;\">types</span>, as opposed to class instances. For example, the is_integral type trait tells if a type is one of int, short, long, char, uint64_t, etc.<br>\n  <br>\nThere are three primary uses of type traits:</p>\n<ul>\n  <li>Allowing for optimized operations on some data types.</li>\n  <li>Allowing for different logic pathways based on data types.</li>\n  <li>Allowing for compile-type assertions about data type expectations.</li>\n</ul>\n<span class=\"faq-answer\">Most of the type traits are automatically detected and implemented by the compiler. However, EASTL&nbsp;allows for the user to explicitly give the compiler hints about type traits that the compiler cannot know, via the EASTL_DECLARE declarations. If the user has a class that is relocatable (i.e. can safely use memcpy to copy values), the user can use the EASTL_DECLARE_TRIVIAL_RELOCATE declaration to tell the compiler that the class can be copied via memcpy. This will automatically significantly speed up some containers and algorithms that use that class.<br>\n<br>\nHere is an example of using type traits to tell if a value is a floating point value or not:<br>\n</span>\n<div class=\"code-example\" style=\"margin-left: 40px; font-family: Courier New;\"><small>template &lt;typename T&gt;<br>\n  DoSomething(T t) {<br>\n&nbsp; &nbsp; assert(is_floating_point&lt;T&gt;::value);<br>\n  }</small></div>\n<span class=\"faq-answer\">Here is an example of declaring a class as relocatable and using it in a vector.<br>\n</span>\n<div class=\"code-example\" style=\"margin-left: 40px; font-family: Courier New;\"><small>EASTL_DECLARE_TRIVIAL_RELOCATE(Widget); // Usually you put this at the Widget class declaration.<br>\n  vector&lt;Widget&gt; wVector;<br>\n  wVector.erase(wVector.begin()); &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // This operation will be optimized via using memcpy.</small></div>\n<span class=\"faq-answer\">The following is a full list of the currently recognized type traits. Most of these are implemented as of this writing, but if there is one that is missing, feel free to contact the maintainer of this library and request that it be completed.</span>\n<ul>\n  <li>is_void</li>\n  <li>is_integral</li>\n  <li>is_floating_point</li>\n  <li>is_arithmetic</li>\n  <li>is_fundamental</li>\n  <li>is_const</li>\n  <li>is_volatile</li>\n  <li>is_abstract</li>\n  <li>is_signed</li>\n  <li>is_unsigned</li>\n  <li>is_array</li>\n  <li>is_pointer</li>\n  <li>is_reference</li>\n  <li>is_member_object_pointer</li>\n  <li>is_member_function_pointer</li>\n  <li>is_member_pointer</li>\n  <li>is_enum</li>\n  <li>is_union</li>\n  <li>is_class</li>\n  <li>is_polymorphic</li>\n  <li>is_function</li>\n  <li>is_object</li>\n  <li>is_scalar</li>\n  <li>is_compound</li>\n  <li>is_same</li>\n  <li>is_convertible</li>\n  <li>is_base_of</li>\n  <li>is_empty</li>\n  <li>is_pod</li>\n  <li>is_aligned</li>\n  <li>has_trivial_constructor</li>\n  <li>has_trivial_copy</li>\n  <li>has_trivial_assign</li>\n  <li>has_trivial_destructor</li>\n  <li>has_trivial_relocate<sup>1</sup></li>\n  <li>has_nothrow_constructor</li>\n  <li>has_nothrow_copy</li>\n  <li>has_nothrow_assign</li>\n  <li>has_virtual_destructor</li>\n  <li>alignment_of</li>\n  <li>rank</li>\n  <li>extent</li>\n</ul>\n<span class=\"faq-answer\"><sup>1</sup> has_trivial_relocate is not found in Boost nor the C++ standard update proposal. However, it is very useful in allowing for the generation of optimized object moving operations. It is similar to the is_pod type trait, but goes further and allows non-pod classes to be categorized as relocatable. Such categorization is something that no compiler can do, as only the user can know if it is such. Thus <small style=\n\"font-family: Courier New;\">EASTL_DECLARE_TRIVIAL_RELOCATE</small>&nbsp; is provided to allow the user to give the compiler a hint.</span>\n<p class=\"faq-question\">  <a name=\"Best.24\"></a>24\nName containers to track memory usage.\n</p>\n<p class=\"faq-answer\">All EASTL containers which allocate memory have a built-in function called set_name and have a constructor argument that lets you specify the container name. This name is used in memory tracking and allows for the categorization and measurement of memory usage. You merely need to supply a name for your container to use and it does the rest.</p>\n<p class=\"faq-answer\">Here is an example of creating a list and naming it &quot;collision list&quot;:</p>\n<p class=\"faq-answer\"><span class=\"code-example\">list&lt;CollisionData&gt; collisionList(allocator(&quot;collision list&quot;));</span>or<br>\n  <span class=\"code-example\">list&lt;CollisionData&gt; collisionList;<br>\ncollisionList.get_allocator().set_name(&quot;collision list&quot;);</span></p>\n<p class=\"faq-answer\">Note that EASTL containers do not copy the name contents but merely copy the name pointer. This is done for simplicity and efficiency. A user can get around this limitation by creating a persistently present string table. Additionally, the user can get around this by declaring static but non-const strings and modifying them at runtime.</p>\n<p class=\"faq-question\"><a name=\"Best.25\"></a>25\nLearn the algorithms.</p>\n<p><span class=\"faq-answer\">EASTL algorithms provide a variety of optimized implementations of fundamental algorithms. Many of the EASTL algorithms are the same as the STL algorithm set, though EASTL adds additional algorithms and additional optimizations not found in STL implementations such as Microsoft's. The copy algorithm, for example, will memcpy data types that have the has_trivial_relocate type trait instead of doing an element-by-element copy.<br>\n  <br>\n  The classifications we use here are not exactly the same as found in the C++ standard; they have been modified to be a little more intuitive. Not all the functions listed here may be yet available in EASTL as you read this. If you want some function then send a request to the maintainer. Detailed documentation for each algorithm is found in algorithm.h or the otherwise corresponding header file for the algorithm.<br>\n  <br>\n  <span style=\"font-weight: bold;\">Search</span></span></p>\n<ul>\n  <li>find, find_if</li>\n  <li>find_end</li>\n  <li>find_first_of</li>\n  <li>adjacent_find</li>\n  <li>binary_search</li>\n  <li>search,&nbsp;search_n</li>\n  <li>lower_bound</li>\n  <li>upper_bound</li>\n  <li>equal_range</li>\n</ul>\n<p class=\"faq-answer\" style=\"font-weight: bold;\">Sort</p>\n<ul>\n  <li>is_sorted</li>\n  <li>quick_sort</li>\n  <li>insertion_sort</li>\n  <li>shell_sort</li>\n  <li>heap_sort</li>\n  <li>merge_sort,&nbsp;merge_sort_buffer</li>\n  <li>merge</li>\n  <li>inplace_merge</li>\n  <li>partial_sort</li>\n  <li>stable_sort</li>\n  <li>partial_sort_copy</li>\n  <li>&lt;other sort functions found in the EASTL bonus directories&gt;</li>\n</ul>\n<p class=\"faq-answer\" style=\"font-weight: bold;\">Modifying</p>\n<ul>\n  <li>fill, fill_n</li>\n  <li>generate,&nbsp;generate_n</li>\n  <li>random_shuffle</li>\n  <li>swap</li>\n  <li>iter_swap</li>\n  <li>swap_ranges</li>\n  <li>remove,&nbsp;remove_if</li>\n  <li>remove_copy,&nbsp;remove_copy_if</li>\n  <li>replace,&nbsp;replace_if</li>\n  <li>replace_copy,&nbsp;replace_copy_if</li>\n  <li>reverse</li>\n  <li>reverse_copy</li>\n  <li>rotate</li>\n  <li>rotate_copy</li>\n  <li>partition</li>\n  <li>stable_partition</li>\n  <li>transform</li>\n  <li>next_permutation</li>\n  <li>prev_permutation</li>\n  <li>unique</li>\n  <li>unique_copy</li>\n</ul>\n<p class=\"faq-answer\" style=\"font-weight: bold;\">Non-Modifying</p>\n<ul>\n  <li>for_each</li>\n  <li>copy</li>\n  <li>copy_backward</li>\n  <li>count,&nbsp;count_if</li>\n  <li>equal</li>\n  <li>mismatch</li>\n  <li>min</li>\n  <li>max</li>\n  <li>min_element</li>\n  <li>max_element</li>\n  <li>lexicographical_compare</li>\n  <li>nth_element</li>\n</ul>\n<p class=\"faq-answer\" style=\"font-weight: bold;\">Heap</p>\n<ul>\n  <li>is_heap</li>\n  <li>make_heap</li>\n  <li>push_heap</li>\n  <li>pop_heap</li>\n  <li>change_heap</li>\n  <li>sort_heap</li>\n  <li>remove_heap</li>\n</ul>\n<p class=\"faq-answer\" style=\"font-weight: bold;\">Set</p>\n<ul>\n  <li>includes</li>\n  <li>set_difference</li>\n  <li>set_symmetric_difference</li>\n  <li>set_intersection</li>\n  <li>set_union</li>\n</ul>\n<p class=\"faq-question\">  <a name=\"Best.26\"></a>26\nPass and return containers by reference instead of value.</p>\n<p class=\"faq-answer\">If you aren't paying attention you might accidentally write code like this:</p>\n<p class=\"code-example\">void DoSomething(list&lt;Widget&gt; widgetList) {<br>\n  &nbsp;&nbsp;&nbsp;&nbsp;...<br>\n}</p>\n<p class=\"faq-answer\">The problem with the above is that widgetList is passed by value and not by reference. Thus the a copy of the container is made and passed instead of a reference of the container being passed. This may seem obvious to some but this happens periodically and the compiler gives no warning and the code will often execute properly, but inefficiently. Of course there are some occasions where you really do want to pass values instead of references.</p>\n<p class=\"faq-question\"><a name=\"Best.27\"></a>27\nConsider using reset_lose_memory() for fast container teardown.</p>\n<p class=\"faq-answer\">EASTL containers have a reset function which unilaterally resets the container to a newly constructed state. The contents of the container are forgotten; no destructors are called and no memory is freed. This is a risky but power function for the purpose of implementing very fast temporary containers. There are numerous cases in high performance programming when you want to create a temporary container out of a scratch buffer area, use the container, and then just &quot;vaporize&quot; it, as it would be waste of time to go through the trouble of clearing the container and destroying and freeing the objects. Such functionality is often used with hash tables or maps and with a stack allocator (a.k.a. linear allocator).</p>\n<p class=\"faq-answer\">Here's an example of usage of the reset function and a PPMalloc-like StackAllocator:</p>\n<p class=\"code-example\">pStackAllocator-&gt;push_bookmark();<br>\n  hash_set&lt;Widget, less&lt;Widget&gt;, StackAllocator&gt; wSet(pStackAllocator);<br>\n&lt;use wSet&gt;<br>\n  wSet.reset_lose_memory();<br>\n  pStackAllocator-&gt;pop_bookmark();</p>\n<p></p>\n<p class=\"faq-question\">  <a name=\"Best.28\"></a>28\nConsider using fixed_substring instead of copying strings.\n</p>\n<p class=\"faq-answer\">EASTL provides a fixed_substring class which uses a reference to a character segment instead of allocating its own string memory. This can be a more efficient way to work with strings under some circumstances.</p>\n<p class=\"faq-answer\">Here's an example of usage of fixed_substring:</p>\n<p class=\"code-example\">basic_string&lt;char&gt;&nbsp;str(&quot;hello world&quot;);<br>\n  fixed_substring&lt;char&gt; sub(str, 6, 5);&nbsp;// sub == &quot;world&quot;</p>\n<p class=\"faq-answer\">fixed_substring can refer to any character array and not just one that derives from a string object.</p>\n<p class=\"faq-question\"><a name=\"Best.29\" id=\"Best.29\"></a>29\n  Consider using vector::push_back(void).</p>\n<p class=\"faq-answer\">EASTL provides an alternative way to insert elements into containers that avoids copy construction and/or the creation of temporaries. Consider the following code:</p>\n<p class=\"code-example\">vector&lt;Widget&gt; widgetArray;<br>\n  widgetArray.push_back(Widget());</p>\n<p class=\"faq-answer\">The standard vector push_back function requires you to supply an object to copy from. This incurs the cost of the creation of a temporary and for some types of classes or situations this cost may be undesirable. It additionally requires that your contained class support copy-construction whereas you may not be able to support copy construction. As an alternative, EASTL provides a push_back(void) function which requires nothing to copy from but instead constructs the object in place in the container. So you can do this:</p>\n<p class=\"code-example\">vector&lt;Widget&gt; widgetArray;<br>\n  widgetArray.push_back();<br>\nwidgetArray.back().x = 0; // Example of how to reference the new object. </p>\n<p class=\"faq-answer\">Other containers with such copy-less functions include:</p>\n<p class=\"code-example\">vector::push_back()<br>\n  deque::push_back()<br>\n  deque::push_front()<br>\n  list::push_back()<br>\n  list::push_front()<br>\n  slist::push_front()<br>\n  map::insert(const key_type&amp; key) <br>\n  multimap::insert(const key_type&amp; key) <br>\n  hash_map::insert(const key_type&amp; key) <br>\n  hash_multimap::insert(const key_type&amp; key) </p>\n<p class=\"faq-answer\">Note that the map functions above allow you to insert a default value specified by key alone and not a value_type like with the other map insert functions.</p>\n<hr style=\"width: 100%; height: 2px;\">\n<p>End of document<br>\n<br>\n<br>\n<br>\n<br></p>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL Design.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n\t<title>EASTL Design</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Discusses various design aspects of EASTL.\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n</head>\n<body>\n<h1>EASTL Design</h1>\n<h2>  Introduction</h2>\n<p>EASTL (EA Standard Template Library) is designed to be a template library which encompasses and extends the\n  functionality of standard C++ STL while improving it in various ways useful to game development. Much of EASTL's design\n  is identical to standard STL, as the large majority of the STL is well-designed for many uses. The primary areas where\nEASTL deviates from standard STL implementations are essentially the following:</p>\n<ul>\n<li>EASTL has a simplified and more flexible custom allocation scheme.</li>\n<li>EASTL has significantly easier to read code.</li>\n<li>EASTL has extension containers and algorithms.</li>\n<li>EASTL has optimizations designed for game development.</li>\n</ul>\n<p>Of the above items, the only one which is an incompatible difference with STL is the case of memory allocation. The\n  method for defining a custom allocator for EASTL is slightly different than that of standard STL, though they are 90%\n  similar. The 10% difference, however, is what makes EASTL generally easier and more powerful to work with than standard\nSTL. Containers without custom allocators act identically between EASTL and standard STL.</p>\n<h2>Motivations</h2>\n<p>Our motifications for making EASTL drive the design of EASTL. As identified in the EASTL RFC (Request for Comment), the\n  primary reasons for implementing a custom version of the STL are:\n</p>\n<ul>\n<li><span class=\"458151900-03082005\"><font><font>Some STL implementations (especially Microsoft STL) have inferior\nperformance characteristics that make them unsuitable for game development. EASTL is faster than all existing STL\nimplementations.</font></font></span></li>\n<li>The STL is sometimes hard to debug, as most STL implementations use cryptic variable names and unusual data\nstructures.</li>\n<li>STL allocators are sometimes painful to work with, as they have many requirements and cannot be modified once bound\nto a container.</li>\n<li>The STL includes excess functionality that can lead to larger code than desirable. It's not very easy to tell\nprogrammers they shouldn't use that functionality.</li>\n<li>The STL is implemented with very deep function calls. This results is unacceptable performance in non-optimized\nbuilds and sometimes in optimized builds as well.</li>\n<li>The STL doesn't support alignment of contained objects.</li>\n<li>STL containers won't let you insert an entry into a container without supplying an entry to copy from. This can be\ninefficient.</li>\n<li>Useful STL extensions (e.g. slist, hash_map, shared_ptr) found in existing STL implementations such as STLPort are\nnot portable because they don't exist in other versions of STL or aren't consistent between STL versions.<br></li>\n<li>The STL lacks useful extensions that game programmers find useful (e.g. intrusive_list) but which could be best\noptimized in a portable STL environment.</li>\n<li>The STL has specifications that limit our ability to use it efficiently. For example, STL vectors are not\nguaranteed to use contiguous memory and so cannot be safely used as an array.</li>\n<li>The STL puts an emphasis on correctness before performance, whereas sometimes you can get significant performance\ngains by making things less academcially pure.</li>\n<li>STL containers have private implementations that don't allow you to work with their data in a portable way, yet\nsometimes this is an important thing to be able to do (e.g. node pools).</li>\n<li>All existing versions of STL allocate memory in empty versions of at least some of their containers. This is not\nideal and prevents optimizations such as container memory resets that can greatly increase performance in some\nsituations.</li>\n<li>The STL is slow to compile, as most modern STL implementations are very large.<br></li>\n<li>There are legal issues that make it hard for us to freely use portable STL implementations such as STLPort.</li>\n<li>We have no say in the design and implementation of the STL and so are unable to change it to work for our\nneeds.</li>\n</ul>\n<h2>Prime Directives</h2>\n<p>The implementation of EASTL is guided foremost by the\nfollowing directives which are listed in order of importance.</p>\n<ol>\n<li>Efficiency (speed and memory usage)</li>\n<li>Correctness</li>\n<li>Portability</li>\n<li>Readability</li>\n</ol>\n<p>Note that unlike commercial STL implementations which must put correctness above all, we put a higher value on\n  efficiency. As a result, some functionality may have some usage limitation that is not present in other similar systems\nbut which allows for more efficient operation, especially on the platforms of significance to us.</p>\n<p>Portability is significant, but not critical. Yes, EASTL must compile and run on all platforms that we will ship games\n  for. But we don't take that to mean under all compilers that could be conceivably used for such platforms. For example,\n  Microsoft VC6 can be used to compile Windows programs, but VC6's C++ support is too weak for EASTL and so you simply\ncannot use EASTL under VC6.</p>\n<p>Readability is something that EASTL achieves better than many other templated libraries, particularly Microsoft STL and\n  STLPort. We make every attempt to make EASTL code clean and sensible. Sometimes our need to provide optimizations\n  (particularly related to type_traits and iterator types) results in less simple code, but efficiency happens to be our\nprime directive and so it overrides all other considerations.</p>\n<h2>  Thread Safety</h2>\n<p>It's not simple enough to simply say that EASTL is thread-safe or thread-unsafe. However, we can say that with respect\nto thread safety that EASTL does the right thing.</p>\n<p>Individual EASTL containers are not thread-safe. That is,&nbsp;access to an instance of a container from multiple\n  threads at the same time is unsafe if any of those accesses are modifying operations. A given container can be read\n  from multiple threads simultaneously as well as any other standalone data structure. If a user wants to be able to have\n  modifying access an instance of a container from multiple threads, it is up to the user to ensure that proper thread\nsynchronization occurs. This usually means using a mutex.</p>\n<p>EASTL classes other than containers are the same as containers with respect to thread safety. EASTL functions (e.g.\n  algorithms) are inherently thread-safe as they have no instance data and operate entirely on the stack. As of this\nwriting, no EASTL function allocates memory and thus doesn't bring thread safety issues via that means.</p>\n<p>The user may well need to be concerned about thread safety with respect to memory allocation. If the user modifies\n  containers from multiple threads, then allocators are going to be accessed from multiple threads. If an allocator is\n  shared across multiple container instances (of the same type of container or not), then mutexes (as discussed above)\n  the user uses to protect access to indivudual instances will not suffice to provide thread safety for allocators used\n  across multiple instances. The conventional solution here is to use a mutex within the allocator if it is exected to be\nused by multiple threads.</p>\n<p>EASTL&nbsp;uses neither static nor global variables and thus there are no inter-instance dependencies that would make\nthread safety difficult for the user to implement.</p>\n<h2>  Container Design</h2>\n<p>All EASTL containers follow a set of consistent conventions. Here we define the prototypical container which has the\n  minimal functionality that all (non-adapter) containers must have. Some containers (e.g. stack) are explicitly adapter\n  containers and thus wrap or inherit the properties of the wrapped container in a way that is implementation\n  specific.<br>\n</p>\n<div class=\"code-example\" style=\"margin-left: 40px;\"><small><span style=\"font-family: Courier New;\">template &lt;class T, class Allocator =\nEASTLAllocator&gt;<br>\nclass container<br>\n{<br>\npublic:<br>\n&nbsp; &nbsp; typedef container&lt;T, Allocator&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this_type;<br>\n&nbsp;&nbsp;&nbsp; typedef\nT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value_type;<br>\n&nbsp;&nbsp;&nbsp; typedef T*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; pointer;<br>\n&nbsp;&nbsp;&nbsp; typedef const T*&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\n&nbsp; &nbsp;const_pointer;<br>\n&nbsp;&nbsp;&nbsp;&nbsp;typedef\nT&amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reference;<br>\n\n&nbsp;&nbsp;&nbsp;&nbsp;typedef const\nT&amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const_reference;<br>\n\n&nbsp;&nbsp;&nbsp;&nbsp;typedef\nptrdiff_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;difference_type;<br>\n\n&nbsp;&nbsp;&nbsp;&nbsp;typedef\nimpl_defined&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size_type;<br>\n\n&nbsp;&nbsp;&nbsp; typedef impl-defined&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\n&nbsp; &nbsp; iterator;<br>\n&nbsp;&nbsp;&nbsp; typedef impl-defined&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\n&nbsp; &nbsp; const_iterator;<br>\n&nbsp;&nbsp;&nbsp; typedef reverse_iterator&lt;iterator&gt; &nbsp; &nbsp; &nbsp; &nbsp; reverse_iterator;<br>\n&nbsp;&nbsp;&nbsp; typedef reverse_iterator&lt;const_iterator&gt; &nbsp; reverse_const_iterator;<br>\n&nbsp;&nbsp;&nbsp; typedef Allocator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\n&nbsp; &nbsp; &nbsp; &nbsp; allocator_type;<br>\n<br>\npublic:<br>\n&nbsp;&nbsp;&nbsp; container(</span></small><small><span style=\"font-family: Courier New;\">const</span></small>\n<small><span style=\"font-family: Courier New;\">allocator_type&amp; allocator = allocator_type());<br>\n&nbsp;&nbsp;&nbsp; container(const</span></small> <small><span style=\n\"font-family: Courier New;\">this_type</span></small><small><span style=\"font-family: Courier New;\">&amp;\nx</span></small><small><span style=\"font-family: Courier New;\">);<br>\n<br>\n&nbsp;&nbsp;&nbsp;&nbsp;</span></small><small><span style=\n\"font-family: Courier New;\">this_type</span></small><small><span style=\"font-family: Courier New;\">&amp;\noperator=(</span></small><small><span style=\"font-family: Courier New;\">this_type</span></small><small><span style=\n\"font-family: Courier New;\">&amp; x);<br>\n&nbsp; &nbsp; void swap(</span></small><small><span style=\n\"font-family: Courier New;\">this_type</span></small><small><span style=\"font-family: Courier New;\">&amp; x);<br>\n&nbsp;&nbsp;&nbsp; void reset();<br>\n<br>\n&nbsp;&nbsp;&nbsp; allocator_type&amp; get_allocator();<br>\n&nbsp;&nbsp;&nbsp; void &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;set_allocator(allocator_type&amp; allocator);<br>\n<br>\n&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin();<br>\n&nbsp;&nbsp;&nbsp;&nbsp;const_iterator begin() const;<br>\n&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end();<br>\n&nbsp;&nbsp;&nbsp;&nbsp;const_iterator end() const;<br>\n<br>\n&nbsp;&nbsp;&nbsp; bool validate() const;<br></span></small> <small><span style=\n\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; int&nbsp; validate_iterator(const_iterator i)\nconst;<br></span></small><br>\n<small><span style=\"font-family: Courier New;\">protected:<br>\n&nbsp;&nbsp;&nbsp; allocator_type mAllocator;<br>\n};<br>\n<br>\ntemplate &lt;class T,</span></small> <small><span style=\"font-family: Courier New;\">class\nAllocator</span></small><small><span style=\"font-family: Courier New;\">&gt;<br>\nbool operator==(const container&lt;T, Allocator&gt;&amp; a, const container&lt;T,</span></small> <small><span style=\n\"font-family: Courier New;\">Allocator</span></small><small><span style=\"font-family: Courier New;\">&gt;&amp; b);<br>\n<br>\ntemplate &lt;class T,</span></small> <small><span style=\"font-family: Courier New;\">class\nAllocator</span></small><small><span style=\"font-family: Courier New;\">&gt;<br>\nbool operator!=(const container&lt;T,</span></small> <small><span style=\n\"font-family: Courier New;\">Allocator</span></small><small><span style=\"font-family: Courier New;\">&gt;&amp; a, const\ncontainer&lt;T,</span></small> <small><span style=\n\"font-family: Courier New;\">Allocator</span></small><small><span style=\"font-family: Courier New;\">&gt;&amp;\nb);</span></small></div>\n<br>\nNotes:\n<ul>\n<li>Swapped containers do not swap their allocators.</li>\n<li>Newly constructed empty containers do no memory allocation. Some STL and other container libraries allocate an\ninitial node from the class memory allocator. EASTL containers by design never do this. If a container needs an initial\nnode, that node should be made part of the container itself or be a static empty node object.</li>\n<li>Empty containers (new or otherwise) contain no constructed objects, including those that might be in an 'end' node.\nSimilarly, no user object (e.g. of type T) should be constructed unless required by the design and unless documented in\nthe cotainer/algorithm contract.&nbsp;</li>\n<li>The reset function is a special extension function which unilaterally resets the container to an empty state\nwithout freeing the memory of the contained objects. This is useful for very quickly tearing down a container built\ninto scratch memory. No memory is allocated by reset, and the container has no allocatedmemory after the reset is\nexecuted.</li>\n<li>The validate and validate_iterator functions provide explicit container and iterator validation. EASTL provides an option to do implicit automatic iterator and container validation, but full validation (which can be potentially extensive) has too much of a performance cost to execute implicitly, even in a debug build. So EASTL provides these explicit functions which can be called by the user at the appropriate time and in optimized builds as well as debug builds. </li>\n</ul>\n<h2>Allocator Design</h2>\n<p>The most significant difference between EASTL and standard C++ STL is that standard STL containers are templated on an\n  allocator class with the interface defined in std::allocator. std::allocator is defined in the C++ standard as\n  this:<br>\n</p>\n<div class=\"code-example\" style=\"margin-left: 40px;\"><small><span style=\"font-family: Courier New;\">// Standard C++ allocator<br>\n  <br>\n  template &lt;class T&gt;<br>\nclass allocator</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">{</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">public:</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; typedef size_t &nbsp; &nbsp;size_type;</span><br style=\n\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; typedef ptrdiff_t difference_type;</span><br style=\n\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; typedef T* &nbsp; &nbsp; &nbsp;&nbsp; pointer;</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; typedef const T* &nbsp;const_pointer;</span><br style=\n\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; typedef T&amp; &nbsp; &nbsp; &nbsp;\n&nbsp;reference;</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; typedef const\nT&amp;&nbsp;&nbsp;const_reference;</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; typedef T &nbsp; &nbsp; &nbsp; &nbsp; value_type;</span><br style=\"font-family: Courier New;\">\n<br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; template &lt;class U&gt;<br>\n&nbsp; &nbsp;&nbsp;struct rebind { typedef allocator&lt;U&gt; other; };</span><br style=\"font-family: Courier New;\">\n<br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; allocator() throw();</span><br style=\n\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; allocator(const allocator&amp;) throw();</span><br style=\n\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; template &lt;class U&gt;<br>\n&nbsp; &nbsp; allocator(const allocator&lt;U&gt;&amp;) throw();<br>\n<br style=\"font-family: Courier New;\">\n</span> <span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp;~allocator()\nthrow();<br>\n<br style=\"font-family: Courier New;\">\n</span> <span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; pointer &nbsp;\n&nbsp; &nbsp; address(reference x) const;</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; const_pointer address(const_reference x)\nconst;</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; pointer &nbsp; &nbsp; &nbsp; allocate(size_type, typename\nallocator&lt;void&gt;::const_pointer hint = 0);</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; void &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;deallocate(pointer p,\nsize_type n);</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; size_type &nbsp; &nbsp; max_size() const\nthrow();</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; void &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;construct(pointer p,\nconst T&amp; val);</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; void &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;destroy(pointer\np);</span><br style=\"font-family: Courier New;\">\n<span style=\"font-family: Courier New;\">};</span></small></div>\n<p>  Each STL container needs to have an allocator templated on container type T associated with it. The problem with this\nis that allocators for containers are defined at the class level and not the instance level. This makes it painful to\ndefine custom allocators for containers and adds to code bloat. Also, it turns out that the containers don't actually\nuse allocator&lt;T&gt; but instead use allocator&lt;T&gt;::rebind&lt;U&gt;::other. Lastly, you cannot access this\nallocator after the container is constructed. There are some good academic reasons why the C++ standard works this way,\nbut it results in a lot of unnecessary pain and makes concepts like memory tracking much harder to implement.</p>\n<p>What EASTL does is use a more familiar memory allocation pattern whereby there is only one allocator class interface\n  and it is used by all containers. Additionally EASTL containers let you access their allocators and query them, name\nthem, change them, etc.</p>\n<p>EASTL has chosen to make allocators not be copied between containers during container swap and assign operations. This\n    means that if container A swaps its contents with container B, both containers retain their original allocators.\n    Similarly, assigning container A to container B causes container B to retain its original allocator. Containers that\n    are equivalent should report so via operator==; EASTL will do a smart swap if allocators are equal, and a brute-force\n    swap otherwise.<br>\n</p>\n<div class=\"code-example\" style=\"margin-left: 40px;\"><small><span style=\"font-family: Courier New;\">// EASTL allocator<br>\n<br>\nclass allocator<br>\n{<br>\npublic:<br>\n&nbsp;&nbsp;&nbsp; allocator(const char* pName = NULL);<br>\n<br>\n&nbsp;&nbsp;&nbsp; void* allocate(size_t n, int flags = 0);<br>\n&nbsp;&nbsp;&nbsp; void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);<br>\n&nbsp;&nbsp;&nbsp; void&nbsp; deallocate(void* p, size_t n);<br>\n<br>\n&nbsp;&nbsp;&nbsp; const char* get_name() const;<br>\n&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_name(const char* pName);<br>\n};<br>\n<br>\nallocator* GetDefaultAllocator();</span></small></div>\n<h2>Fixed Size Container Design</h2>\n<p>EASTL supplies a set of&nbsp;fixed-size containers that the user can use, though the user can also implement their own\n  versions. So in addition to class list there is class fixed_list. The fixed_list class implements a linked list via a\n  fixed-size pool of contiguous memory which has no space overhead (unlike with a regular heap), doesn't cause\nfragmentation, and allocates very quickly.</p>\n<p>EASTL implements fixed containers via subclasses of regular containers which set the regular container's allocator to\n  point to themselves. Thus the implementation for fixed_list is very tiny and consists of little more\n  than&nbsp;constructor and allocator functions. This design has some advantages but has one small disadvantage. The\n  primary advantages are primarily that code bloat is reduced and that the implementation is simple and the user can\n  easily extend it. The primary disadvantage is that the parent list class ends up with a pointer to itself and thus has\n  4 bytes that could arguably be saved if system was designed differently. That different design would be to make the\n  list class have a policy template parameter which specifies that it is a fixed pool container. EASTL chose not to\n  follow the policy design because it would complicate the implementation, make it harder for the user to extend the\n  container, and would potentially waste more memory due to code bloat than it would save due to the 4 byte savings it\nachieves in container instances.</p>\n<h2>Algorithm Design</h2>\n<p>EASTL algorithms very much follow the philosophy of standard C++ algorithms, as this philosophy is sound and efficient.\n  One of the primary aspects of algorithms is that they work on iterators and not containers. You will note for example\n  that the find algorithm takes a first and last iterator as arguments and not a container. This has two primary\n  benefits: it allows the user to specify a subrange of the container to search within and it allows the user to apply\nthe find algorithm to sequences that aren't containers (e.g. a C array).</p>\n<p>EASTL algorithms are optimized at least as well as the best STL algorithms found in commercial libraries and are\n  significantly optimized over the algorithms that come with the first-party STLs that come with compilers. Most significantly, EASTL algorithms take advantage of type traits of contained classes and\n  take advantage of iterator types to optimize code generation. For example, if you resize an array of integers (or other \"pod\" type), EASTL will detect that this can be done with a memcpy instead of a slow object-by-object move as would\nMicrsoft STL.</p>\n<p>The optimizations found in EASTL algorithms and the supporting code in EASTL type traits consistts of some fairly\n    tricky advanced C++ and while it is fairly easy to read, it requires a C++ expert (language lawyer, really) to\n    implement confidently. The result of this is that it takes more effort to develop and maintain EASTL than it would to\nmaintain a simpler library. However, the performance advantages have been deemed worth the tradeoff.</p>\n<h2>Smart Pointer Design</h2>\n<p>EASTL implements the following smart pointer types:</p>\n<ul>\n<li>shared_ptr</li>\n<li>shared_array</li>\n<li>weak_ptr</li>\n<li>instrusive_ptr</li>\n<li>scoped_ptr</li>\n<li>scoped_array</li>\n<li>linked_ptr</li>\n<li>linked_array</li>\n</ul>\nAll but linked_ptr/linked_array are well-known smart pointers from the Boost library. The behaviour of these smart\npointers is very similar to those from Boost with two exceptions:\n<ul>\n<li>EASTL smart pointers allow you to assign an allocator to them.</li>\n<li>EASTL shared_ptr implements deletion via a templated parameter instead of a dynamically allocated&nbsp;virtual\nmember object interface.</li>\n</ul>\n<p>With respect to assigning an allocator, this gives EASTL more control over memory allocation and tracking, as Boost\nsmart pointers unilaterally use global operator new to allocate memory from the global heap.</p>\n<p>With respect to shared_ptr deletion, EASTL's current design of using a templated parameter is questionable, but does\n  have some reason. The advantage is that EASTL avoids a heap allocation, avoids virtual function calls, and avoids\n  templated class proliferation. The disadvantage is that EASTL shared_ptr containers which hold void pointers can't call\n  the destructors of their contained objects unless the user manually specifies a custom deleter template parameter. This\n  is case whereby EASTL is more efficient but less safe. We can revisit this topic in the future if it becomes an\n  issue.</p>\n<h2>list::size is O(n)</h2>\n<p>As of this writing, EASTL has three linked list classes: list, slist, and intrusive_list. In each of these classes, the\n  size of the list is not cached in a member size variable. The result of this is that getting the size of a list is not\n  a fast operation, as it requires traversing the list and counting the nodes. We could make the list::size function be\n  fast by having a member mSize variable which tracks the size as we insert and delete items. There are reasons for\n  having such functionality and reasons for not having such functionality. We currently choose to not have a member mSize\n  variable as it would add four bytes to the class, add a tiny amount of processing to functions such as insert and\n  erase, and would only serve to improve the size function, but no others. In the case of intrusive_list, it would do\n  additional harm. The alternative&nbsp;argument is that the C++ standard states that std::list should be an O(1)\n  operation (i.e. have a member size variable), that many C++ standard library list&nbsp;implementations do so, that the\n  size is but an integer which is quick to update, and that many users expect to have a fast size function. In the final\n  analysis, we are developing a library for game development and performance is paramount, so we choose to not cache the\nlist size. The user can always implement a size cache himself.</p>\n<h2>basic_string doesn't use copy-on-write</h2>\n<p>The primary benefit of CoW is that it allows for the sharing of string data between two string objects. Thus if you say\n  this:</p>\n<p class=\"code-example\">  string a(\"hello\");<br style=\n\"font-family: Courier New;\">\n  string b(a);</p>\n<p>the \"hello\" will be shared between a and b. If you then say this:</p>\n<p class=\"code-example\">  a = \"world\";</p>\n<p>then <span style=\"font-family: Courier New;\">a</span> will release its reference to \"hello\" and leave b with the only\n  reference to it. Normally this functionality is accomplished via reference counting and with atomic operations or\nmutexes.</p>\n<p> The C++ standard does not say anything about basic_string and CoW. However, for a basic_string implementation to be\n  standards-conforming, a number of issues arise which dictate some things about how one would have to implement a CoW\n  string. The discussion of these issues will not be rehashed here, as you can read the references below for better\n  detail than can be provided in the&nbsp;space we have here. However, we can say that the C++ standard is sensible\n  and&nbsp;that anything we try to do here to allow for an efficient CoW implementation would result in a generally\nunacceptable string interface.</p>\n<p>The disadvantages of CoW strings are:</p>\n<ul>\n<li>A reference count needs to exist with the string, which increases string memory usage.</li>\n<li>With thread safety, atomic operations and mutex locks are expensive, especially&nbsp;on weaker memory systems such\nas console gaming platforms.</li>\n<li>All non-const string accessor functions need to do a sharing check the the first such check needs to detach the\nstring. Similarly, all string assignments need to do a sharing check as well. If you access the string before doing an\nassignment, the assignment doesn't result in a shared string, because the string has already been detached.</li>\n<li>String sharing doesn't happen the large majority of the time. In some cases,&nbsp;the total sum of the reference\ncount memory can exceed any memory savings gained by the strings that share representations.&nbsp;</li>\n</ul>\n<p>The addition of a cow_string class is under consideration for EASTL. There are conceivably some systems which have\n  string usage patterns which would benefit from CoW sharing. Such functionality is best saved for a separate\nstring&nbsp;implementation so that the other string uses aren't penalized.</p>\n<p>This is a good starting HTML reference on the topic:</p>\n<blockquote>\n  <p>\t\n    <a href=\n\"http://www.gotw.ca/publications/optimizations.htm\">http://www.gotw.ca/publications/optimizations.htm</a></p>\n</blockquote>\n<p>Here is a well-known Usenet discussion on the topic:</p>\n<blockquote>\n  <p><a href=\n\"http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d\">http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d</a></p>\n</blockquote>\n<hr style=\"width: 100%; height: 2px;\">\nEnd of document<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL FAQ.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n\t<title>EASTL FAQ</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Frequently asked questions about EASTL.\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n<style type=\"text/css\">\n<!--\n.style1 {font-family: \"Courier New\"}\n.style2 {color: #339900}\n.style3 {color: #FF0000}\n.style4 {color: #999999}\n.style5 {font-size: 10pt}\n-->\n</style>\n</head>\n<body>\n<h1>EASTL FAQ</h1>\n<p>We provide a FAQ (frequently asked questions) list here for a number of commonly asked questions about EASTL and STL in\ngeneral. Feel free to suggest new FAQ additions based on your own experience.</p>\n<h2>Information</h2>\n<table style=\"width: 100%;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" cols=\"2\">\n<tbody>\n<tr>\n<td>1</td>\n<td><a href=\"#Info.1\">What is EASTL?</a></td>\n</tr>\n<tr>\n<td>2</td>\n<td><a href=\"#Info.2\">What uses&nbsp;are EASTL suitable for?</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">3<br></td>\n<td style=\"vertical-align: top; text-align: left;\"><a href=\"#Info.3\">How does EASTL differ from standard C++\nSTL?</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Info.4\">Is EASTL thread-safe?</a></td>\n</tr>\n<tr>\n<td>5</td>\n<td><a href=\"#Info.5\">What platforms/compilers does EASTL support?</a></td>\n</tr>\n<tr>\n<td>6</td>\n<td><a href=\"#Info.6\">Why is there EASTL when there is the STL?</a></td>\n</tr>\n<tr>\n<td>7</td>\n<td><a href=\"#Info.7\">Can I mix EASTL with standard C++ STL?</a></td>\n</tr>\n<tr>\n<td>8</td>\n<td><a href=\"#Info.8\">Where can I learn more about STL and EASTL?</a></td>\n</tr>\n<tr>\n<td>9</td>\n<td><a href=\"#Info.9\">What is the legal status of EASTL?</a></td>\n</tr>\n<tr>\n<td>10</td>\n<td><a href=\"#Info.10\">Does EASTL deal with compiler exception handling settings?</a></td>\n</tr>\n<tr>\n<td>11</td>\n<td><a href=\"#Info.11\">What C++ language features does EASTL use (e.g. virtual functions)?</a></td>\n</tr>\n<tr>\n<td>12</td>\n<td><a href=\"#Info.12\">What compiler warning levels does EASTL support?</a></td>\n</tr>\n<tr>\n<td>13</td>\n<td><a href=\"#Info.13\">Is EASTL compatible with Lint?</a></td>\n</tr>\n<tr>\n<td>14</td>\n<td><a href=\"#Info.14\">What compiler settings do I need to compile EASTL?</a></td>\n</tr>\n<tr>\n<td>15</td>\n<td><a href=\"#Info.15\">How hard is it to incorporate EASTL into my project?</a></td>\n</tr>\n<tr>\n<td>16</td>\n<td><a href=\"#Info.16\">Should I use EASTL instead of std STL or instead of my custom&nbsp;library?</a></td>\n</tr>\n<tr>\n<td>17</td>\n<td><a href=\"#Info.17\">I think I've found a bug. What do I do?</a></td>\n</tr>\n<tr>\n<td>18</td>\n<td><a href=\"#Info.18\">Can EASTL be used by third party EA developers?</a></td>\n</tr>\n</tbody>\n</table>\n<h2>  Performance\n</h2>\n<table style=\"width: 100%;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" cols=\"2\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Perf.1\">How efficient is EASTL compared to standard C++ STL implementations?</a></td>\n</tr>\n<tr>\n<td>2</td>\n<td><a href=\"#Perf.2\">How efficient is EASTL in general?</a></td>\n</tr>\n<tr>\n<td>3</td>\n<td><a href=\"#Perf.3\">Strings don't appear to use the \"copy-on-write\" optimization. Why not?</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Perf.4\">Does EASTL cause code bloat, given that it uses templates?</a></td>\n</tr>\n<tr>\n<td>5</td>\n<td><a href=\"#Perf.5\">Don't STL and EASTL containers fragment memory?</a></td>\n</tr>\n<tr>\n<td>6</td>\n<td><a href=\"#Perf.6\">I don't see container optimizations for equivalent scalar types such as pointer types.\nWhy?</a></td>\n</tr>\n<tr>\n<td>7</td>\n<td><a href=\"#Perf.7\">I've seen some STL's provide a default quick \"node allocator\" as the default allocator. Why\ndoesn't EASTL do this?</a></td>\n</tr>\n<tr>\n<td>8</td>\n<td><a href=\"#Perf.8\">Templates sometimes seem to take a long time to compile. Why do I do about that?</a></td>\n</tr>\n<tr>\n<td>9</td>\n<td><a href=\"#Cont.8\">How do I assign a custom allocator to an EASTL container?</a></td>\n</tr>\n<tr>\n<td>10</td>\n<td><a href=\"#Perf.10\">How well does EASTL inline?</a></td>\n</tr>\n<tr>\n<td>11</td>\n<td><a href=\"#Perf.11\">How do I control function inlining?</a></td>\n</tr>\n<tr>\n<td>12</td>\n<td><a href=\"#Perf.12\">C++ / EASTL seems to bloat my .obj files much more than C does.</a></td>\n</tr>\n<tr>\n<td>13</td>\n<td><a href=\"#Perf.13\">What are the best compiler settings for EASTL?</a></td>\n</tr>\n</tbody>\n</table>\n<h2>Problems</h2>\n<table style=\"width: 100%;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" cols=\"2\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Prob.1\">I'm getting screwy behavior in sorting algorithms or sorted containers. What's wrong?</a></td>\n</tr>\n<tr>\n<td>2</td>\n        <td><a href=\"#Prob.2\">I am getting compiler warnings (e.g. C4244, C4242 or C4267) that make no sense. Why?</a></td>\n</tr>\n<tr>\n<td>3</td>\n<td><a href=\"#Prob.3\">I am getting compiler warning C4530, which complains about exception handling and \"unwind\nsemantics.\" What gives?</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Prob.4\">Why are tree-based containers hard to read with a debugger?</a></td>\n</tr>\n<tr>\n<td>5</td>\n<td><a href=\"#Prob.5\">The EASTL source code is sometimes rather complicated looking. Why is that?</a></td>\n</tr>\n<tr>\n<td>6</td>\n<td><a href=\"#Prob.6\">When I get compilation errors, they are very long and complicated looking. What do I do?</a></td>\n</tr>\n<tr>\n<td>7</td>\n<td><a href=\"#Prob.7\">Templates sometimes seem to take a long time to compile. Why do I do about that?</a></td>\n</tr>\n<tr>\n<td>8</td>\n<td><a href=\"#Prob.8\">I get the compiler error: <small>\"template instantiation depth exceeds maximum of 17.&nbsp;use\n-ftemplate-depth-NN to increase the maximum\"</small></a></td>\n</tr>\n<tr>\n<td>9</td>\n<td><a href=\"#Prob.9\">I'm getting errors about min and max while compiling.</a></td>\n</tr>\n<tr>\n<td>10</td>\n<td><a href=\"#Prob.10\">C++ / EASTL seems to bloat my .obj files much more than C does.</a></td>\n</tr>\n<tr>\n<td>11</td>\n<td><a href=\"#Prob.11\">I'm getting compiler errors regarding operator new being&nbsp;previously defined.</a></td>\n</tr>\n<tr>\n<td>12</td>\n<td><a href=\"#Prob.12\">I'm getting errors related to wchar_t string &nbsp;functions such as wcslen.</a></td>\n</tr>\n<tr>\n<td>13</td>\n<td><a href=\"#Prob.13\">I'm getting compiler warning C4619: there is no warning number Cxxxx (e.g. C4217).</a></td>\n</tr>\n<tr>\n<td>14</td>\n<td><a href=\"#Prob.14\">My stack-based fixed_vector is not respecting the object alignment requirements.</a></td>\n</tr>\n<tr>\n  <td>15</td>\n  <td><a href=\"#Prob.15\">I am getting compiler errors when using GCC under XCode (Macintosh/iphone).</a></td>\n</tr>\n<tr>\n  <td>16</td>\n  <td><a href=\"#Prob.16\">I am getting linker errors about Vsnprintf8 or Vsnprintf16.</a></td>\n</tr>\n<tr>\n  <td>17</td>\n  <td><a href=\"#Prob.17\">I am getting compiler errors about UINT64_C or UINT32_C</a>. </td>\n</tr>\n<tr>\n  <td>18</td>\n  <td><a href=\"#Prob.18\">I am getting a crash with a global EASTL container. </a></td>\n</tr>\n<tr>\n  <td>19</td>\n  <td><a href=\"#Prob.19\">Why doesn't EASTL support passing NULL to functions with pointer arguments? </a></td>\n</tr>\n</tbody>\n</table>\n<h2>Debug</h2>\n<table style=\"width: 100%;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" cols=\"2\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Debug.1\">How do I get VC++ mouse-overs to view templated data?</a></td>\n</tr>\n<tr>\n<td>2</td>\n<td><a href=\"#Debug.2\">How do I view containers if the visualizer/tooltip support is not present?</a></td>\n</tr>\n<tr>\n<td>3</td>\n<td><a href=\"#Debug.3\">The EASTL source code is sometimes rather complicated looking. Why is that?</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Debug.4\">When I get compilation errors, they are very long and complicated looking. What do I\ndo?</a></td>\n</tr>\n<tr>\n<td>5</td>\n<td><a href=\"#Debug.5\">How do I measure hash table balancing?</a></td>\n</tr>\n</tbody>\n</table>\n<h2>Containers</h2>\n<table style=\"width: 100%;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" cols=\"2\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Cont.1\">Why do some containers have \"fixed\" versions (e.g. fixed_list) but others(e.g. deque) don't have\nfixed versions?</a></td>\n</tr>\n<tr>\n<td>2</td>\n<td><a href=\"#Cont.2\">Can I mix EASTL with standard C++ STL?</a></td>\n</tr>\n<tr>\n<td>3</td>\n<td><a href=\"#Cont.3\">Why are there so many containers?</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Cont.4\">Don't STL and EASTL containers fragment memory?</a></td>\n</tr>\n<tr>\n<td>5</td>\n<td><a href=\"#Cont.5\">I don't see container optimizations for equivalent scalar types such as pointer types.\nWhy?</a></td>\n</tr>\n<tr>\n<td>6</td>\n<td><a href=\"#Cont.6\">What about alternative container and algorithm implementations (e.g. treaps, skip lists, avl\ntrees)?</a></td>\n</tr>\n<tr>\n<td>7</td>\n<td><a href=\"#Cont.7\">Why are containers hard to read with a debugger?</a></td>\n</tr>\n<tr>\n<td>8</td>\n<td><a href=\"#Cont.8\">How do I assign a custom allocator to an EASTL container?</a></td>\n</tr>\n<tr>\n<td>9</td>\n<td><a href=\"#Cont.9\">How do I set the VC++ debugger to display EASTL container data with tooltips?</a></td>\n</tr>\n<tr>\n<td>10</td>\n<td><a href=\"#Cont.10\">How do I use a memory pool with a container?</a></td>\n</tr>\n<tr>\n<td>11</td>\n<td><a href=\"#Cont.11\">How do I write a comparison (operator&lt;()) for a struct that contains two or more\nmembers?</a></td>\n</tr>\n<tr>\n<td>12</td>\n<td><a href=\"#Cont.12\">Why doesn't container X have member function Y?</a></td>\n</tr>\n<tr>\n<td>13</td>\n<td><a href=\"#Cont.13\">How do I search a hash_map of strings via a char pointer efficiently? If I use map.find(\"hello\")\nit creates a temporary string, which is inefficient.</a></td>\n</tr>\n<tr>\n<td>14</td>\n<td><a href=\"#Cont.14\">Why are set and hash_set iterators const (i.e. const_iterator)?</a></td>\n</tr>\n<tr>\n<td>15</td>\n<td><a href=\"#Cont.15\">How do I prevent my hash container from re-hashing?</a></td>\n</tr>\n<tr>\n<td>16</td>\n<td><a href=\"#Cont.16\">Which uses less memory, a map or a hash_map?</a></td>\n</tr>\n<tr>\n<td>17</td>\n<td><a href=\"#Cont.17\">How do I write a custom hash function?</a></td>\n</tr>\n<tr>\n<td>18</td>\n<td><a href=\"#Cont.18\">How do I write a custom compare function for a map or set?</a></td>\n</tr>\n<tr>\n<td>19</td>\n<td><a href=\"#Cont.19\">How do I force my vector or string capacity down to the size of the container?</a></td>\n</tr>\n<tr>\n<td>20</td>\n<td><a href=\"#Cont.20\">How do I iterate a container while (selectively) removing items from it?</a></td>\n</tr>\n<tr>\n<td>21</td>\n<td><a href=\"#Cont.21\">How do I store a pointer in a container?</a></td>\n</tr>\n<tr>\n<td>22</td>\n<td><a href=\"#Cont.22\">How do I make a union of two containers? difference? intersection?</a></td>\n</tr>\n<tr>\n<td>23</td>\n<td><a href=\"#Cont.23\">How do I override the default global allocator?</a></td>\n</tr>\n<tr>\n<td>24</td>\n<td><a href=\"#Cont.24\">How do I do trick X with the string class?</a></td>\n</tr>\n<tr>\n<td>25</td>\n<td><a href=\"#Cont.25\">How do EASTL smart pointers compare to Boost smart pointers?</a></td>\n</tr>\n<tr>\n<td>26</td>\n<td><a href=\"#Cont.26\">How do your forward-declare an EASTL container?</a></td>\n</tr>\n<tr>\n  <td>27</td>\n  <td><a href=\"#Cont.27\">How do I make two containers share a memory pool?</a></td>\n</tr>\n<tr>\n  <td>28</td>\n  <td><a href=\"#Cont.28\">Can I use a std (STL) allocator with EASTL?</a></td>\n</tr>\n<tr>\n  <td>29 </td>\n  <td><a href=\"#Cont.29\">What are the requirements of classes stored in containers? </a></td>\n</tr>\n</tbody>\n</table>\n<h2>Algorithms</h2>\n<table style=\"width: 100%;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" cols=\"2\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Algo.1\">I'm getting screwy behavior in sorting algorithms or sorted containers. What's wrong?</a></td>\n</tr>\n<tr>\n<td>2</td>\n<td><a href=\"#Algo.2\">How do I write a comparison (operator&lt;()) for a struct that contains two or more\nmembers?</a></td>\n</tr>\n<tr>\n<td>3</td>\n<td><a href=\"#Algo.3\">How do I sort something in reverse order?</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Algo.4\">I'm getting errors about min and max while compiling.</a></td>\n</tr>\n<tr>\n<td>5</td>\n<td><a href=\"#Algo.5\">Why don't algorithms take a container as an argument instead of iterators? A container would be\nmore convenient.</a></td>\n</tr>\n<tr>\n<td>6</td>\n<td><a href=\"#Algo.6\">Given a container of pointers, how do I find an element by value (instead of by\npointer)?</a></td>\n</tr>\n<tr>\n<td>7</td>\n<td><a href=\"#Algo.7\">When do stored objects need to support <small><span style=\"font-family: Courier New;\">opertor\n&lt;</span></small> vs. when do they need to support <small><span style=\"font-family: Courier New;\">operator\n==</span></small>?</a></td>\n</tr>\n<tr>\n  <td>8</td>\n  <td><a href=\"#Algo.8\">How do I sort via pointers or array indexes instead of objects directly?</a></td>\n</tr>\n</tbody>\n</table>\n<h2>Iterators</h2>\n<table style=\"width: 100%;\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" cols=\"2\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Iter.1\">What's the difference between iterator, const iterator, and const_iterator?</a></td>\n</tr>\n<tr>\n<td>2</td>\n<td><a href=\"#Iter.2\">How do I tell from an iterator what type of thing it is iterating?</a></td>\n</tr>\n<tr>\n<td>3</td>\n<td><a href=\"#Iter.3\">How do I iterate a container while (selectively) removing items from it?</a></td>\n</tr>\n<tr>\n<td>4</td>\n<td><a href=\"#Iter.4\">What is an insert_iterator?</a></td>\n</tr>\n</tbody>\n</table>\n<h2><br>\n  Information\n</h2>\n<p class=\"faq-question\"><a name=\"Info.1\"></a>Info.1\nWhat is EASTL?</p>\n<p class=\"faq-answer\">EASTL refers to &quot;EA Standard Template Library.&quot; It is a C++ template library that is analogous to the template facilities of the C++ standard library, which are often referred to as the STL. EASTL consists of the following systems: </p>\n<ul>\n  <li>Containers</li>\n  <li>Iterators</li>\n  <li>Algorithms</li>\n  <li>Utilities</li>\n  <li>Smart pointers</li>\n  <li>Type traits</li>\n</ul>\n<p class=\"faq-answer\">EASTL provides extensions and optimizations over the equivalents in standard C++ STL.</p>\n<p class=\"faq-answer\">EASTL is a professional-level implementation which outperforms commercial implementations (where functionality overlaps) and is significantly easier to read and debug.</p>\n<p class=\"faq-question\">  <a name=\"Info.2\"></a>Info.2\nWhat uses are EASTL suitable for?</p>\n<p class=\"faq-answer\">EASTL is suitable for any place where templated containers and algorithms would be appropriate. Thus any C++ tools could use it and many C++ game runtimes could use it, especially 2005+ generation game platforms. EASTL has optimizations that make it more suited to the CPUs and memory systems found on console platforms. Additionally, EASTL has some type-traits and iterator-traits-derived template optimizations that make it generally more efficient than home-brew templated containers.</p>\n<p class=\"faq-question\"><a name=\"Info.3\"></a>Info.3\nHow does EASTL differ from standard C++ STL?</p>\n<p class=\"faq-answer\">There are three kinds of ways that EASTL differs from standard STL: </p>\n<ol>\n  <li>EASTL equivalents to STL sometimes differ.</li>\n  <li>EASTL implementations sometimes differ from STL implementations of the same thing.</li>\n  <li>EASTL has functionality that doesn't exist in STL.</li>\n</ol>\n<p class=\"faq-answer\">With respect to item #1, the changes are such that they benefit game development and not the type that could silently hurt you if you were more familiar with STL interfaces.</p>\n<p class=\"faq-answer\">With respect to item #2, where EASTL implementations differ from STL implementations it is almost always due to improvements being made in the EASTL versions or tradeoffs being made which are considered better for game development.</p>\n<p class=\"faq-answer\">With respect to item #3, there are a number of facilities that EASTL has that STL doesn't have, such as intrusive_list and slist containers, smart pointers, and type traits. All of these are facilities that assist in making more efficient game code and data.</p>\n<p class=\"faq-answer\">Ways in which EASTL is better than standard STL: </p>\n<ul>\n  <li>Has higher performance in release builds, sometimes dramatically so.</li>\n  <li>Has significantly higher performance in debug builds, due to less call overhead.</li>\n  <li>Has extended per-container functionality, particularly for game development.</li>\n  <li>Has additional containers that are useful for high performance game development.</li>\n  <li>Is easier to read, trace, and debug.</li>\n  <li>Memory allocation is much simpler and more controllable.</li>\n  <li>Has higher portability, as there is a single implementation for all platforms.</li>\n  <li>Has support of&nbsp;object alignment, whereas such functionality is not natively supported by STL.</li>\n  <li>We have control over it, so we can modify it as we like.</li>\n  <li>Has stricter standards for container design and behavior, particularly as this benefits game development.</li>\n</ul>\n<p class=\"faq-answer\">Ways in which EASTL is worse than standard STL: </p>\n<ul>\n  <li>Standard STL implementations are currently very reliable and weather-worn, whereas EASTL is less tested.</li>\n  <li>Standard STL is automatically available with just about every C++ compiler vendor's library.</li>\n  <li>Standard STL is supported by the compiler vendor and somewhat by the Internet community.</li>\n</ul>\n<p style=\"font-weight: bold;\">EASTL coverage of std STL</p>\n<ul style=\"margin-top: 0in;\" type=\"disc\">\n  <li>list</li>\n  <li>vector</li>\n  <li>deque</li>\n  <li>string</li>\n  <li>set</li>\n  <li>multiset</li>\n  <li>map</li>\n  <li>multimap</li>\n  <li>bitset</li>\n  <li>queue</li>\n  <li>stack</li>\n  <li>priority_queue</li>\n  <li>memory</li>\n  <li>numeric</li>\n  <li>algorithm (all but inplace_merge, prev_permutation, next_permutation, nth_element, includes, unique_copy)</li>\n  <li>utility</li>\n  <li>functional</li>\n  <li>iterator</li>\n  <li>string_view</li>\n  <li>variant</li>\n  <li>any</li>\n  <li>optional</li>\n</ul>\n<p>EASTL additions/amendments to std STL</p>\n<ul style=\"margin-top: 0in;\" type=\"disc\">\n  <li>allocators work in a simpler way.</li>\n  <li>exception handling can be disabled.</li>\n  <li>all containers expose/declare their node size, so you can make a node allocator for them.</li>\n  <li>all containers have reset_lose_memory(), which unilaterally forgets their contents.</li>\n  <li>all containers have validate() and validate_iterator() functions.</li>\n  <li>all containers understand and respect object alignment requirements.</li>\n  <li>all containers guarantee no memory allocation upon being newly created as empty.</li>\n  <li>all containers and their iterators can be viewed in a debugger (no other STL does this, believe it or not).</li>\n  <li>linear containers guarantee linear memory.</li>\n  <li>vector has push_back(void).</li>\n  <li>vector has a data() function.</li>\n  <li>vector&lt;bool&gt; is actually a vector of type bool.</li>\n  <li>vector and string have set_capacity().</li>\n  <li>string has sprintf(), append_sprintf(), trim(), compare_i(), make_lower(), make_upper().</li>\n  <li>deque allows you to specify the subarray size.</li>\n  <li>list has a push_back(void) and push_back(void) function.</li>\n  <li>hash_map, hash_set, etc. have find_as().</li>\n</ul>\n<p><span style=\"font-weight: bold;\">EASTL coverage of TR1</span> <font face=\"Arial\" size=\"2\"><span style=\n\"font-size: 10pt; font-family: Arial;\">(tr1 refers to proposed additions for the next C++ standard library, ~2008)</span></font></p>\n<ul style=\"margin-top: 0in;\" type=\"disc\">\n  <li>array</li>\n  <li>type_traits (there are about 30 of these)</li>\n  <li>unordered_set (EASTL calls it hash_set)</li>\n  <li>unordered_multiset</li>\n  <li>unordered_map</li>\n  <li>unordered_multimap</li>\n  <li>shared_ptr, shared_array, weak_ptr, scoped_ptr, scoped_array, intrusive_ptr</li>\n</ul>\n<p><span style=\"font-weight: bold;\">EASTL additional functionality</span> <font face=\"Arial\" size=\"1\"><span style=\n\"font-size: 9pt; font-family: Arial;\">(not found elsewhere)</span></font></p>\n<ul style=\"margin-top: 0in;\" type=\"disc\">\n  <li>fixed_list</li>\n  <li>fixed_slist</li>\n  <li>fixed_vector</li>\n  <li>fixed_string</li>\n  <li>fixed_substring</li>\n  <li>fixed_set</li>\n  <li>fixed_multiset</li>\n  <li>fixed_map</li>\n  <li>fixed_multimap</li>\n  <li>fixed_hash_set</li>\n  <li>fixed_hash_multiset</li>\n  <li>fixed_hash_map</li>\n  <li>fixed_hash_multimap</li>\n  <li>fixed_function</li>\n  <li>vector_set</li>\n  <li>vector_multiset</li>\n  <li>vector_map</li>\n  <li>vector_multimap</li>\n  <li>intrusive_list</li>\n  <li>intrusive_slist</li>\n  <li>intrusive_sdlist</li>\n  <li>intrusive_hash_set</li>\n  <li>intrusive_hash_multiset</li>\n  <li>intrusive_hash_map</li>\n  <li>intrusive_hash_multimap</li>\n  <li>slist (STLPort's STL has this)</li>\n  <li>heap</li>\n  <li>linked_ptr, linked_array</li>\n  <li>sparse_matrix (this is not complete as of this writing)</li>\n  <li>ring_buffer</li>\n  <li>compressed_pair</li>\n  <li>call_traits</li>\n  <li>binary_search_i, change_heap, find_first_not_of, find_last_of, find_last_not_of, identical</li>\n  <li>comb_sort, bubble_sort, selection_sort, shaker_sort, bucket_sort</li>\n  <li>equal_to_2, not_equal_to_2, str_equal_to, str_equal_to_i<br>\n  </li>\n</ul>\n<p class=\"faq-question\">  <a name=\"Info.4\"></a>Info.4\nIs EASTL thread-safe?\n</p>\n<p class=\"faq-answer\">It's not simple enough to simply say that EASTL is thread-safe or thread-unsafe. However, we can say that with respect to thread safety that EASTL does the right thing.</p>\n<p class=\"faq-answer\">Individual EASTL containers are not thread-safe. That is,&nbsp;access to an instance of a container from multiple threads at the same time is unsafe if any of those accesses are modifying operations. A given container can be read from multiple threads simultaneously as well as any other standalone data structure. If a user wants to be able to have modifying access an instance of a container from multiple threads, it is up to the user to ensure that proper thread synchronization occurs. This usually means using a mutex.</p>\n<p class=\"faq-answer\">EASTL classes other than containers are the same as containers with respect to thread safety. EASTL functions (e.g. algorithms) are inherently thread-safe as they have no instance data and operate entirely on the stack. As of this writing, no EASTL function allocates memory and thus doesn't bring thread safety issues via that means.</p>\n<p class=\"faq-answer\">The user may well need to be concerned about thread safety with respect to memory allocation. If the user modifies containers from multiple threads, then allocators are going to be accessed from multiple threads. If an allocator is shared across multiple container instances (of the same type of container or not), then mutexes (as discussed above) the user uses to protect access to individual instances will not suffice to provide thread safety for allocators used across multiple instances. The conventional solution here is to use a mutex within the allocator if it is expected to be used by multiple threads.</p>\n<p class=\"faq-answer\">EASTL&nbsp;uses neither static nor global variables and thus there are no inter-instance dependencies that would make thread safety difficult for the user to implement.</p>\n<p class=\"faq-question\"><a name=\"Info.5\"></a>Info.5\nWhat platforms/compilers does EASTL support?</p>\n<p class=\"faq-answer\">EASTL's support depends entirely on the compiler and not on the platform. EASTL works on any C++ compiler that completely conforms the C++ language standard. Additionally, EASTL is 32 bit and 64 bit compatible. Since EASTL does not use the C or C++ standard library <small><span style=\n\"font-family: Arial Narrow;\">(with a couple small exceptions)</span></small>, it doesn't matter what kind of libraries are provided (or not provided) by the compiler vendor. However, given that we need to work with some compilers that aren't 100% conforming to the language standard, it will be useful to make a list here of these that are supported and those that are not:</p>\n<blockquote>\n  <table border=\"1\">\n    <tr>\n      <th scope=\"col\">Compiler</th>\n      <th scope=\"col\">Status</th>\n      <th scope=\"col\">Notes</th>\n    </tr>\n    <tr>\n      <td>GCC 3.x+</td>\n      <td>Not Supported</td>\n      <td>Not officially supported due to migration to Clang.</td>\n    </tr>\n    <tr>\n      <td>MSVC 12.0+</td>\n      <td>Supported</td>\n      <td>This compiler is used by the Windows based platforms</td>\n    </tr>\n    <tr>\n      <td>Clang 4.0+</td>\n      <td>Supported</td>\n      <td>This compiler is used by the Linux based platforms</td>\n    </tr>\n  </table>\n</blockquote>\n<p class=\"faq-question\"><a name=\"Info.6\"></a>Info.6\nWhy is there EASTL when there is the STL?</p>\n<p class=\"faq-answer\">The STL is largely a fine library for general purpose C++. However, we can improve upon it for our uses and gain other advantages as well. The primary motivations for the existence of EASTL are the following:</p>\n<ul>\n  <li class=\"458151900-03082005\"><font><font>Some STL implementations (especially Microsoft STL) have inferior performance characteristics that make them unsuitable for game development. EASTL is faster than all existing STL implementations.</font></font></li>\n  <li>The STL is sometimes hard to debug, as most STL implementations use cryptic variable names and unusual data structures.</li>\n  <li>STL allocators are sometimes painful to work with, as they have many requirements and cannot be modified once bound to a container.</li>\n  <li>The STL includes excess functionality that can lead to larger code than desirable. It's not very easy to tell programmers they shouldn't use that functionality.</li>\n  <li>The STL is implemented with very deep function calls. This results is unacceptable performance in non-optimized builds and sometimes in optimized builds as well.</li>\n  <li>The STL doesn't support alignment of contained objects.</li>\n  <li>STL containers won't let you insert an entry into a container without supplying an entry to copy from. This can be inefficient.</li>\n  <li>Useful STL extensions (e.g. slist, hash_map, shared_ptr) found in existing STL implementations such as STLPort are not portable because they don't exist in other versions of STL or aren't consistent between STL versions.<br>\n  </li>\n  <li>The STL lacks useful extensions that game programmers find useful (e.g. intrusive_list) but which could be best optimized in a portable STL environment.</li>\n  <li>The STL puts an emphasis on correctness before performance, whereas sometimes you can get significant performance gains by making things less academically pure.</li>\n  <li>STL containers have private implementations that don't allow you to work with their data in a portable way, yet sometimes this is an important thing to be able to do (e.g. node pools).</li>\n  <li>All existing versions of STL allocate memory in empty versions of at least some of their containers. This is not ideal and prevents optimizations such as container memory resets that can greatly increase performance in some situations.</li>\n  <li>The STL is slow to compile, as most modern STL implementations are very large.<br>\n  </li>\n  <li>There are legal issues that make it hard for us to freely use portable STL implementations such as STLPort.</li>\n  <li>We have no say in the design and implementation of the STL and so are unable to change it to work for our needs.</li>\n</ul>\n<p class=\"faq-answer\">Note that there isn't actually anything in the C++ standard called \"STL.\" STL is a term that merely refers to the templated portion of the C++ standard library.</p>\n<p class=\"faq-question\"><a name=\"Info.7\"></a>Info.7\nCan I mix EASTL with standard C++ STL?</p>\n<p class=\"faq-answer\">This is possible to some degree, though the extent depends on the implementation of C++ STL. One of things that makes interoperability is something called iterator categories. Containers and algorithms recognize iterator types via their category and STL iterator categories are not recognized by EASTL and vice versa.<br>\n<br>\nThings that you definitely can do: </p>\n<ul>\n  <li>#include both EASTL and standard STL headers from the same .cpp file.</li>\n  <li>Use EASTL containers to hold STL containers.</li>\n  <li>Construct an STL reverse_iterator from an EASTL&nbsp;iterator.</li>\n  <li>Construct an EASTL reverse_iterator from an&nbsp;STL&nbsp;iterator.</li>\n</ul>\n<p class=\"faq-answer\">Things that you probably will be able to do, though a given std STL implementation may prevent it:\n</p>\n<ul>\n  <li>Use STL containers in EASTL algorithms.</li>\n  <li>Use EASTL containers in STL algorithms.</li>\n  <li>Construct or assign to an STL container via iterators into an EASTL container.</li>\n  <li>Construct or assign to an EASTL container via iterators into an&nbsp;STL container.</li>\n</ul>\n<p class=\"faq-answer\">Things that you would be able to do if the given std STL implementation is bug-free:\n</p>\n<ul>\n  <li>Use STL containers to hold EASTL containers. Unfortunately, VC7.x STL has a confirmed bug that prevents this. Similarly, STLPort versions prior to v5 have a similar but.</li>\n</ul>\n<p class=\"faq-answer\">Things that you definitely can't do:</p>\n<ul>\n  <li>Use an STL allocator directly with an EASTL container (though you can use one indirectly).</li>\n  <li>Use an EASTL allocator directly with an STL container (though you can use one indirectly).</li>\n</ul>\n<p class=\"faq-question\">  <a name=\"Info.8\"></a>Info.8\nWhere can I learn more about STL and EASTL?\n</p>\n<p class=\"faq-answer\">EASTL is close enough in philosophy and functionality to standard C++ STL that most of what you read about STL applies to EASTL. This is particularly useful with respect to container specifications. It would take a lot of work to document EASTL containers and algorithms in fine detail, whereas most standard STL documentation applies as-is to EASTL. We won't cover the differences here, as that's found in another FAQ entry.</p>\n<p class=\"faq-answer\">That being said, we provide a list of sources for STL documentation that may be useful to you, especially if you are less familiar with the concepts of STL and template programming in general.</p>\n<ul>\n  <li>The SGI STL web site. Includes a good STL reference.</li>\n  <li>CodeProject STL introduction.</li>\n  <li>Scott Meyers Effective STL book.</li>\n  <li>The Microsoft online STL documentation. Microsoft links go bad every couple months, so try searching for STL at the Microsoft MSDN site.</li>\n  <li>The Dinkumware online STL documentation.&nbsp;</li>\n  <li>The C++ standard, which is fairly readable. You can buy an electronic version for about $18 and in the meantime you can make do with draft revisions of it off the Internet by searching for &quot;c++ draft standard&quot;.</li>\n  <li>STL performance tips, by Pete Isensee</li>\n  <li>STL algorithms vs. hand-written loops, by Scott Meyers.</li>\n  <li>cppreference.com</li>\n  <li>isocpp.org<li>\n</ul>\n<p class=\"faq-question\"><a name=\"Info.9\"></a>Info.9\nWhat is the legal status of EASTL?</p>\n<p class=\"faq-answer\">EASTL is usable for all uses within Electronic Arts, both for internal usage and for shipping products for all platforms. Any&nbsp;externally derived code would be explicitly stated as such and approved by the legal department if such code ever gets introduced. As of EASTL v1.0, the red_black_tree.cpp file contains two functions derived from the original HP STL and have received EA legal approval for usage in any product.</p>\n<p class=\"faq-question\"><a name=\"Info.10\"></a>Info.10\nDoes EASTL deal with compiler exception handling settings?</p>\n<p class=\"faq-answer\">EASTL has automatic knowledge of the compiler's enabling/disabling of exceptions. If your compiler is set to disable exceptions, EASTL automatically detects so and executes without them. Also, you can force-enable or force-disable that setting to override the automatic behavior by #defining EASTL_EXCEPTIONS_ENABLED to 0 or 1. See EASTL's config.h for more information.</p>\n<p class=\"faq-question\">  <a name=\"Info.11\"></a>Info.11\n  What C++ language features does EASTL use (e.g. virtual\nfunctions)?</p>\n<p class=\"faq-answer\">EASTL uses the following C++ language features: </p>\n<ul>\n  <li>Template functions, classes, member functions.</li>\n  <li>Multiple inheritance.</li>\n  <li>Namespaces.</li>\n  <li>Operator overloading.</li>\n</ul>\n<p class=\"faq-answer\">EASTL does not use the following C++ language features:\n</p>\n<ul>\n  <li>Virtual functions / interfaces.</li>\n  <li>RTTI (dynamic_cast).</li>\n  <li>Global and static variables. There are a couple class static const variables, but they act much like enums.</li>\n  <li>Volatile declarations</li>\n  <li>Template export.</li>\n  <li>Virtual inheritance.</li>\n</ul>\n<p class=\"faq-answer\">EASTL may use the following C++ language features:\n</p>\n<ul>\n  <li>Try/catch. This is an option that the user can enable and it defaults to whatever the compiler is set to use.</li>\n  <li>Floating point math. Hash containers have one floating point calculation, but otherwise floating point is not used.</li>\n</ul>\n<p class=\"faq-answer\">Notes:\n</p>\n<ul>\n  <li>EASTL uses rather little of the standard C or C++ library and uses none of the C++ template library (STL) and iostream library. The memcpy family of functions is one example EASTL C++ library usage.</li>\n  <li>EASTL never uses global new / delete / malloc / free. All allocations are done via user-specified allocators, though a default allocator definition is available.</li>\n</ul>\n<p class=\"faq-question\"><a name=\"Info.12\"></a>Info.12\n  What compiler warning levels does EASTL support?\n</p>\n<p class=\"faq-answer\">For VC++ EASTL should compile without warnings on level 4, and should compile without warnings for &quot;warnings disabled by default&quot; except C4242, C4514, C4710, C4786, and C4820. These latter warnings are somewhat draconian and most EA projects have little choice but to leave them disabled.</p>\n<p class=\"faq-answer\">For GCC, EASTL should compile without warnings with -Wall. Extensive testing beyond that hasn't been done.</p>\n<p class=\"faq-answer\">However, due to the nature of templated code generation and due to the way compilers compile templates, unforeseen warnings may occur in user code that may or may not be addressable by modifying EASTL.</p>\n<p class=\"faq-question\"><a name=\"Info.13\"></a>Info.13\n  Is EASTL compatible with Lint?\n</p>\n<p class=\"faq-answer\">As of EASTL 1.0, minimal lint testing has occurred. Testing with the November 2005 release of Lint (8.00t) demonstrated bugs in Lint that made its analysis not very useful. For example, Lint seems to get confused about the C++ typename keyword and spews many errors with code that uses it. We will work with the makers of Lint to get this resolved so that Lint can provide useful information about EASTL.</p>\n<p class=\"faq-question\"><a name=\"Info.14\"></a>Info.14\n  What compiler settings do I need to compile EASTL?\n</p>\n<p class=\"faq-answer\">EASTL consists mostly of header files with templated C++ code, but there are also a few .cpp files that need to be compiled and linked in order to use some of the modules. EASTL will compile in just about any environment. As mentioned elsewhere in this FAQ, EASTL can be compiled at the highest warning level of most compilers, transparently deals with compiler exception handling settings, is savvy to most or all compilation language options (e.g. wchar_t is built-in or not, for loop variables are local or not), and has almost no platform-specific or compiler-specific code. For the most part, you can just drop it in and it will work. The primary thing that needs to be in place is that EASTL .cpp files need to be compiled with the same struct padding/alignment settings as other code in the project. This of course is the same for just about any C++ source code library.</p>\n<p class=\"faq-answer\">See the Performance section of this FAQ for a discussion of the optimal compiler settings for EASTL performance.</p>\n<p class=\"faq-question\"><a name=\"Info.15\"></a>Info.15\nHow hard is it to incorporate EASTL into my project?</p>\n<p>It's probably trivial.<br>\n  <br>\nEASTL has only one dependency: EABase. And EASTL auto-configures itself for most compiler environments and for the most typical configuration choices. Since it is fairly highly warning-free, you won't likely need to modify your compiler warning settings, even if they're pretty strict. EASTL has a few .cpp files which need to be compiled if you want to use the modules associated with those files. You can just compile those files with your regular compiler settings. Alternatively, you can use one of the EASTL project files.<br>\n<br>\nIn its default configuration, the only thing you need to provide to make EASTL work is to define implementations of the following operator new functions:</p>\n<pre class=\"code-example\">#include &lt;new&gt;<br>\nvoid* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\nvoid* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);</pre>\nThe flags and debugFlags arguments correspond to PPMalloc/RenderWare GeneralAllocator/GeneralAllocatorDebug Malloc equivalents.<br>\n<p class=\"faq-question\"><a name=\"Info.16\"></a>Info.16\nShould I use EASTL instead of std STL or instead of my custom&nbsp;library?</p>\n<p class=\"faq-answer\">There are reasons you may want to use EASTL; there are reasons you may not want to use it. Ditto for std STL or any other library. Here we present a list of reasons (+ and -) for why you might want to use one or another. However, it should be noted that while EASTL contains functionality found in std STL, it has another ~40% of functionality not found in std STL, so EASTL and std STL (and whatever other template library you may have) are not mutually exclusive.<br>\n<br>\n<span style=\"font-weight: bold;\">EASTL</span><br>\n</p>\n<div class=\"faq-answer\" style=\"margin-left: 40px;\"><span style=\"font-family: Courier New,Courier,monospace;\">+</span> Has higher performance than any commercial STL, especially on console platforms.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> Has extended functionality tailored for game development.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> Is highly configurable, and we own it so it can be amended at will. Std STL is owned by a third party committee.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> Is much easier to read and debug than other similar libraries, especially std STL.<br>\n  <br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">-</span> Is highly unit tested, but does not have the same level as std STL.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">-</span> Is more complicated than many users' lite template libraries, and may put off some beginners.<br>\n<span style=\"font-family: Courier New,Courier,monospace;\">-</span> EASTL &nbsp;</div>\n<p>    <span class=\"faq-answer\" style=\"font-weight: bold;\">Std STL</span>\n</p>\n<div class=\"faq-answer\" style=\"margin-left: 40px;\"><span style=\"font-family: Courier New,Courier,monospace;\">+</span> Is highly portable; your STL code will likely compile and run anywhere.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> Works without the need to&nbsp;install or download any package to use it. It just works.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> Is highly reliable and supported by the compiler vendor. You can have confidence in it.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> Some std STL versions (e.g. STLPort, VC8 STL) have better runtime debug checking than EASTL.<br>\n  <br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">-</span> Has (sometimes greatly) variable implementations, behavior, and performance between implementations.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">-</span> Is usually hard to read and debug.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">-</span> Doesn't support some of the needs of game development, such as aligned allocations, named allocations, intrusive containers, etc.<br>\n<span style=\"font-family: Courier New,Courier,monospace;\">-</span> Is not as efficient as EASTL, especially on console platforms.</div>\n<p>  <span class=\"faq-answer\" style=\"font-weight: bold;\">Your own library</span>\n</p>\n<div class=\"faq-answer\" style=\"margin-left: 40px;\">(please forgive us for implying there may be weaknesses in your libraries)<br>\n\n  <p></p>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> You have control over it and can make it work however you want.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> You can fix bugs in it on the spot and have the fix in your codebase immediately.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">+</span> Your own library can be highly integrated into your application code or development environment.<br>\n  <br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">-</span> Many custom libraries don't have the same level of testing as libraries such as std STL or EASTL.<br>\n  <span style=\"font-family: Courier New,Courier,monospace;\">-</span> Many custom libraries don't have the same breadth or depth as std STL or especially EASTL.<br>\n<span style=\"font-family: Courier New,Courier,monospace;\">-</span> Many custom libraries don't have the level of performance tuning that std STL or especially EASTL has.</div>\n<p class=\"faq-question\"><a name=\"Info.17\"></a>Info.17\nI think I've found a bug. What do I do?</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Verify that you indeed have a bug</span><br>\nThere are various levels of bugs that can occur, which include the following: </p>\n<ol>\n  <li>Compiler warnings generated by EASTL.</li>\n  <li>Compiler errors generated by EASTL (failure to compile well-formed code).</li>\n  <li>Runtime misbehavior by EASTL (function does the wrong thing).</li>\n  <li>Runtime crash or data corruption by EASTL.</li>\n  <li>Mismatch between EASTL documentation and behavior.</li>\n  <li>Mismatch between EASTL behavior and user's expectations (mis-design).</li>\n</ol>\n<p class=\"faq-answer\">Any of the above items can be the fault of EASTL. However, the first four can also be the fault of the user. Your primary goal in verifying a potential bug is to determine if it is an EASTL bug or a user bug. Template errors can sometimes be hard to diagnose. It's probably best if you first show the problem to somebody you know to make sure you are not missing something obvious. Creating a reproducible case may be useful in helping convince yourself, but as is mentioned below, this is not required in order to report the bug.<br>\n  <br>\n  <span style=\"font-weight: bold;\">Report the bug</span><br>\nThe first place to try is the standard EA centralized tech support site. As of this writing (10/2005), that tech site is <a href=\"http://eatech/\">http://eatech/</a>. Due to the frequent technology churn that seems to occur within Electronic Arts, the bug reporting system in place when you read this may not be the one that was in place when this FAQ entry was written. If the tech site route fails, consider directly contacting the maintainer of the EASTL package.<br>\n<br>\nIn reporting a bug, it is nice if there is a simple reproducible case that can be presented. However, such a case requires time to create, and so you are welcome to initially simply state what you think the bug is without producing a simple reproducible case. It may be that this is a known bug or it may be possible to diagnose the bug without a reproducible case. If more information is needed then the step of trying to produce a reproducible case may be necessary.</p>\n<p class=\"faq-question\"><a name=\"Info.18\"></a>Info.18\n  Can EASTL be used by third party EA developers?</p>\n<p class=\"faq-answer\">EASTL and other core technologies authored by EA (and not licensed from other companies) can be used in source and binary form by designated 3rd parties. The primary case where there is an issue is if the library contains platform specific code for a platform that the 3rd party is not licensed for. In that case the platform-specific code would need to be removed. This doesn&rsquo;t apply to EASTL, nor many of the other core tech packages. </p>\n<h2><span style=\"font-weight: bold;\">Performance</span>\n</h2>\n\n<p class=\"faq-question\"><a name=\"Perf.1\"></a>Perf.1 How efficient is EASTL compared to standard C++ STL implementations?</p>\n<p class=\"faq-answer\">With respect to the functionality that is equivalent between EASTL and standard STL, the short answer to this is that EASTL is as at least as efficient as other STL implementations and in a number of aspects is more so. EASTL has functionality such as intrusive_list and linked_ptr that don't exist in standard STL but are explicitly present to provide significant optimizations over standard STL.</p>\n<p class=\"faq-answer\">The medium length answer is that EASTL is significantly more efficient than Dinkumware STL, and Microsoft Windows STL. EASTL is generally more efficient than Metrowerks STL, but Metrowerks has a few tricks up its sleeve which EASTL doesn't currently implement. EASTL is roughly equal in efficiency to STLPort and GCC 3.x+ STL, though EASTL has some optimizations that these do not.</p>\n<p class=\"faq-answer\">The long answer requires a breakdown of the functionality between various versions of the STL.</p>\n\n<p class=\"faq-question\"><a name=\"Perf.2\"></a>Perf.2 How efficient is EASTL in general?</p>\n<p class=\"faq-answer\">This question is related to the question, &quot;How efficient are templates?&quot; If you understand the effects of templates then you can more or less see the answer for EASTL. Templates are more efficient than the alternative when they are used appropriately, but can be less efficient than the alternative when used under circumstances that don't call for them. The strength of templates is that the compiler sees all the code and data types at compile time and can often reduce statements to smaller and faster code than with conventional non-templated code. The weakness of templates is that the sometimes produce more code and can result in what is often called &quot;code bloat&quot;. However, it's important to note that unused template functions result in no generated nor linked code, so if you have a templated class with 100 functions but you only use one, only that one function will be compiled.</p>\n<p class=\"faq-answer\">EASTL is a rather efficient implementation of a template library and pulls many tricks of the trade in terms of squeezing optimal performance out of the compiler. The only way to beat it is to write custom code for the data types you are working with, and even then people are sometimes surprised to find that their hand-implemented algorithm works no better or even worse than the EASTL equivalent. But certainly there are ways to beat templates, especially if you resort to assembly language programming and some kinds of other non-generic tricks.</p>\n\n<p class=\"faq-question\">  <a name=\"Perf.3\"></a>Perf.3 Strings don't appear to use the \"copy-on-write\" (CoW) optimization. Why not?</p>\n<p class=\"faq-answer\">\n<span style=\"font-weight: bold;\">Short answer</span><br>\nCoW provides a benefit for a small percentage of uses but provides a disadvantage for the large majority of uses.<br>\n<br>\n<span style=\"font-weight: bold;\">Long answer</span><br>\nThe primary benefit of CoW is that it allows for the sharing of string data between two string objects. Thus if you say this:\n<pre class=\"code-example\">string a(\"hello\");\nstring b(a);</pre>\nthe \"hello\" will be shared between a and b. If you then say this:\n<pre class=\"code-example\">a = \"world\";</pre>\nthen <span style=\"font-family: Courier New;\">a</span> will release its reference to \"hello\" and \nleave b with the only reference to it. Normally this functionality is accomplished via reference \ncounting and with atomic operations or mutexes.</p>\n\n<p class=\"faq-answer\">The C++ standard does not say anything about basic_string and CoW. \nHowever, for a basic_string implementation to be standards-conforming, a number of issues arise \nwhich dictate some things about how one would have to implement a CoW string. The discussion of \nthese issues will not be rehashed here, as you can read the references below for better detail \nthan can be provided in the space we have here. However, we can say that the C++ standard \nis sensible and that anything we try to do here to allow for an efficient CoW implementation \nwould result in a generally unacceptable string interface.</p>\n<p class=\"faq-answer\">The disadvantages of CoW strings are:</p>\n<ul>\n  <li>A reference count needs to exist with the string, which increases string memory usage.</li>\n  <li>With thread safety, atomic operations and mutex locks are expensive, especially on weaker memory systems such as console gaming platforms.</li>\n  <li>All non-const string accessor functions need to do a sharing check and the first such check needs to detach the string. Similarly, all string assignments need to do a sharing check as well. If you access the string before doing an assignment, the assignment doesn't result in a shared string, because the string has already been detached.</li>\n  <li>String sharing doesn't happen the large majority of the time. In some cases, the total sum of the reference count memory can exceed any memory savings gained by the strings that share representations.</li>\n</ul>\n<p class=\"faq-answer\">The addition of a cow_string class is under consideration for EASTL. There are conceivably some systems which have string usage patterns which would benefit from CoW sharing. Such functionality is best saved for a separate string implementation so that the other string uses aren't penalized.</p>\n<p class=\"faq-answer\">References</p>\n<p class=\"faq-answer\">This is a good starting HTML reference on the topic:<br>\n&nbsp; &nbsp; <a href=\"http://www.gotw.ca/publications/optimizations.htm\">http://www.gotw.ca/publications/optimizations.htm</a></p>\n<p class=\"faq-answer\">Here is a well-known Usenet discussion on the topic:<br>\n&nbsp; &nbsp; <a href=\"http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d\">http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d</a></p>\n\n<p class=\"faq-question\"><a name=\"Perf.4\"></a>Perf.4 Does EASTL cause code bloat, given that it uses templates?</p>\n<p class=\"faq-answer\">  The reason that templated functions and classes might cause an increase in code size\nbecause each template instantiation theoretically creates a unique piece of code. For example, when you compile this\ncode:</p>\n<pre class=\"code-example\">template &lt;typename T&gt;\nconst T min(const T a, const T b)\n&nbsp;&nbsp;&nbsp; { return b &lt; a ? b : a; }\n\nint &nbsp; &nbsp;i = min&lt;int&gt;(3, 4);\ndouble d = min&lt;double&gt;(3.0, 4.0);</pre>\n<p class=\"faq-answer\">the compiler treats it as if you wrote this:</p>\n<pre class=\"code-example\">int min(const int a, const int b)\n&nbsp;&nbsp;&nbsp; { return b &lt; a ? b : a; }<br>\ndouble min(const double a, const double b)\n&nbsp;&nbsp;&nbsp; { return b &lt; a ? b : a; }</pre>\n<p class=\"faq-answer\">Imagine this same effect happening with containers such as list and map and you can see how it is that templates can cause code proliferation.</p>\n<p class=\"faq-answer\">A couple things offset the possibility of code proliferation: inlining and folding. In practice the above 'min' function would be converted to&nbsp;inlined functions by the compiler which occupy only a few CPU instructions. In many of the simplest cases the inlined version actually occupies less code than the code required to push parameters on the stack and execute a function call. And they will execute much faster as well.</p>\n<p class=\"faq-answer\">Code folding (a.k.a. &quot;COMDAT folding&quot;, &quot;duplicate stripping&quot;, &quot;ICF&quot; / &quot;identical code folding&quot;) is a compiler optimization whereby the compiler realizes that two independent functions have compiled to the same code and thus can be reduced to a single function. The Microsoft VC++ compiler (Since VS2005), and GCC (v 4.5+) can do these kinds of optimizations on all platforms. This can result, for example, in all templated containers of pointers (e.g. vector&lt;char*&gt;, vector&lt;Widget*&gt;, etc.) to be linked as a single implementation. This folding occurs at a function level and so individual member functions can be folded while other member functions are not. A side effect of this optimization is that you aren't likely to gain much much declaring containers of void* instead of the pointer type actually contained.</p>\n<p class=\"faq-answer\">The above two features reduce the extent of code proliferation, but certainly don't eliminate it. What you need to think about is how much code might be generated vs. what your alternatives are. Containers like vector can often inline completely away, whereas more complicated containers such as map can only partially be inlined. In the case of map, if you need such a container for your Widgets, what alternatives do you have that would be more efficient than instantiating a map? This is up to you to answer.</p>\n<p class=\"faq-answer\">It's important to note that C++ compilers will throw away any templated functions that aren't used, including unused member functions of templated classes. However, some argue that by having many functions available to the user that users will choose to use that larger function set rather than stick with a more restricted set.</p>\n<p class=\"faq-answer\">Also, don't be confused by syntax bloat vs. code bloat. In looking at templated libraries such as EASTL you will notice that there is sometimes a lot of text in the definition of a template implementation. But the actual underlying code is what you need to be concerned about.</p>\n<p class=\"faq-answer\">There is a good Usenet discussion on this topic at: <small><a href=\n\"http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/2b00649a935997f5\">http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/2b00649a935997f5</a></small></p>\n<p class=\"faq-question\"><a name=\"Perf.5\"></a>Perf.5\nDon't STL and EASTL containers fragment memory?</p>\n<p class=\"faq-answer\">They only fragment memory if you use them in a way that does so. This is no different from any other type of container used in a dynamic way. There are various solutions to this problem, and EASTL provides additional help as well:</p>\n<ul>\n  <li>For vectors, use the reserve function (or the equivalent constructor) to set aside a block of memory for the container. The container will not reallocate memory unless you try grow beyond the capacity you reserve.</li>\n  <li>EASTL has \"fixed\" variations of containers which allow you to specify a fixed block of memory which the container uses for its memory. The container will not allocate any memory with these types of containers and all memory will be cache-friendly due to its locality.</li>\n  <li>You can assign custom allocators to containers instead of using the default global allocator. You would typically use an allocator that has its own private pool of memory.</li>\n  <li>Where possible, add all a container's elements to it at once up front instead of adding them over time. This avoids memory fragmentation and increase cache coherency.</li>\n</ul>\n\n<p class=\"faq-question\"><a name=\"Perf.6\"></a>Perf.6 I don't see container optimizations for equivalent scalar types such as pointer types. Why?</p>\n<p class=\"faq-answer\">Metrowerks (and no other, as of this writing) STL has some container specializations for type \nT* which maps them to type void*. The idea is that a user who declares a list of Widget* and a list of Gadget* \nwill generate only one container: a list of void*. As a result, code generation will be smaller. Often this is \ndone only in optimized builds, as such containers are harder to view in debug builds due to type information being lost.<br>\n<br>\nThe addition of this optimization is under consideration for EASTL, though it might be noted that optimizing \ncompilers such as VC++ are already capable of recognizing duplicate generated code and folding it automatically \nas part of link-time code generation (LTCG) (a.k.a. \"whole program optimization\"). This has been verified \nwith VC++, as the following code and resulting disassembly demonstrate:</p>\n<pre class=\"code-example\">eastl::list&lt;int*&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intPtrList;\neastl::list&lt;TestObject*&gt; toPtrList;\n\neastl_size_t n1 = intPtrList.size();\neastl_size_t n2 = toPtrList.size();\n\n0042D288&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edx,[esp+14h]\n0042D28C&nbsp; <span style=\"color: rgb(51, 51, 255);\">call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eastl::list&lt;TestObject&gt;::size (414180h)</span>\n0042D291&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax&nbsp;\n0042D292&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edx,[esp+24h]\n0042D296&nbsp; <span style=\"color: rgb(51, 51, 255);\">call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eastl::list&lt;TestObject&gt;::size (414180h)</span></pre>\n<p class=\"faq-answer\">Note that in the above case the compiler folded the two implementations of size() into a single implementation.</p>\n\n<p class=\"faq-question\"><a name=\"Perf.7\"></a>Perf.7\nI've seen some STL's provide a default quick \"node allocator\" as the default allocator. Why doesn't EASTL do this?</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Short answer<br>\n</span>This is a bad, misguided idea.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Long answer</span><br>\nThese node allocators implement a heap for all of STL with buckets for various sizes of allocations and implemented fixed-size pools for each of these buckets. These pools are attractive at first because they do well in STL comparison benchmarks, especially when thread safety is disabled. Such benchmarks make it impossible to truly compare STL implementations because you have two different allocators in use and in some cases allocator performance can dominate the benchmark. However, the real problem with these node allocators is that they badly fragment and waste memory. The technical discussion of this topic is outside the scope of this FAQ, but you can learn more about it by researching memory management on the Internet. Unfortunately, the people who implement STL libraries are generally not experts on the topic of memory management. A better approach, especially for game development, is for the user to decide when fixed-size pools are appropriate and use them via custom allocator assignment to containers.</p>\n<p class=\"faq-question\"><a name=\"Perf.8\"></a>Perf.8 Templates sometimes seem to take a long time to compile. Why do I do about that?\n</p>\n<p class=\"faq-answer\">C++ compilers are generally slower than C compilers, and C++ templates are generally slower to compile than regular C++ code. EASTL has some extra functionality (such as type_traits and algorithm specializations) that is not found in most other template libraries and significantly improves performance and usefulness but adds to the amount of code that needs to be compiled. Ironically, we have a case where more source code generates faster and smaller object code.</p>\n<p class=\"faq-answer\">The best solution to the problem is to use pre-compiled headers, which are available on all modern ~2002+) compilers, such as VC6.0+, GCC 3.2+, and Metrowerks 7.0+. In terms of platforms this means all 2002+ platforms.</p>\n<p class=\"faq-answer\">Some users have been speeding up build times by creating project files that put all the source code in one large .cpp file. This has an effect similar to pre-compiled headers. It can go even faster than pre-compiled headers but has downsides in the way of convenience and portability.</p>\n<p class=\"faq-question\"><a name=\"Perf.10\"></a>Perf.10\nHow well does EASTL inline?</p>\n<p class=\"faq-answer\">EASTL is written in such as way as to be easier to inline than typical templated libraries such as STL. How is this so? It is so because EASTL reduces the inlining depth of many functions, particularly the simple ones. In doing so it makes the implementation less \"academic\" but entirely correct. An example of this is the vector operator[] function, which is implemented like so with Microsoft STL:</p>\n<pre class=\"code-example\">reference operator[](size_type n) {\n&nbsp;&nbsp;&nbsp;return *(begin() + n);\n}</pre>\n<span class=\"faq-answer\">EASTL implements the function directly, like so:</span>\n<pre class=\"code-example\">reference operator[](size_type n) {\n&nbsp;&nbsp;&nbsp;&nbsp;return *(mpBegin + n);\n}</pre>\n<span class=\"faq-answer\">Both implementations are correct, but the EASTL implementation will run faster in debug builds, be easier to debug, and will be more likely to be inlined when the usage of this function is within a hierarchy of other functions being inlined. It is not so simple to say that the Microsoft version will always inline in an optimized build, as it could be part of a chain and cause the max depth to be exceeded.<br>\n<br>\nThat being said, EASTL appears to inline fairly well under most circumstances, including with GCC, which is the poorest of the compilers in its ability to inline well.</span>\n<p class=\"faq-question\"><a name=\"Perf.11\"></a>Perf.11\nHow do I control function inlining?</p>\n<p class=\"faq-answer\">Inlining is an important topic for templated code, as such code often relies on the compiler being able to do good function inlining for maximum performance. GCC,&nbsp;VC++, and Metrowerks are discussed here. We discuss compilation-level inlining and function-level inlining here, though the latter is likely to be of more use to the user of EASTL, as it can externally control how EASTL is inlined. A related topic is GCC's template expansion depth, discussed <a href=\n\"file:///f:/Projects/SharedProjects/Core/EASTL/doc/EASTL%20FAQ.html#29\">elsewhere</a> in this FAQ. We provide descriptions of inlining options here but don't currently have any advice on how to best use these with EASTL.</p>\n<p class=\"faq-answer\">Compilation-Level Inlining -- VC++</p>\n<p class=\"faq-answer\">VC++ has some basic functionality to control inlining, and the compiler is pretty good at doing aggressive inlining when optimizing on for all platforms.</p>\n<blockquote>\n  <p class=\"faq-answer\"><small><span style=\"font-family: Courier New;\"> #pragma inline_depth( [0... 255] )</span></small></p>\n  <p class=\"faq-answer\">Controls the number of times inline expansion can occur by controlling the number of times that a series of function calls can be expanded (from 0 to 255 times). This pragma controls the inlining of functions marked inline and or inlined automatically under the /Ob2 option. The inline_depth pragma controls the number of times a series of function calls can be expanded. For example, if the inline depth is 4, and if A calls B and B then calls C, all three calls will be expanded inline. However, if the closest inline expansion is 2, only A and B are expanded, and C remains as a function call.</p>\n  <p class=\"faq-answer\"><small><span style=\"font-family: Courier New;\">#pragma inline_recursion( [{on | off}] )</span></small></p>\n  <p class=\"faq-answer\">Controls the inline expansion of direct or mutually recursive function calls. Use this pragma to control functions marked as inline and or functions that the compiler automatically expands under the /Ob2 option. Use of this pragma requires an /Ob compiler option setting of either 1 or 2. The default state for inline_recursion is off. The inline_recursion pragma controls how recursive functions are expanded. If inline_recursion is off, and if an inline function calls itself (either directly or indirectly), the function is expanded only once. If inline_recursion is on, the function is expanded multiple times until it reaches the value set by inline_depth, the default value of 8, or a capacity limit.</p>\n</blockquote>\n<p class=\"faq-answer\">Compilation-Level Inlining -- GCC</p>\n<p class=\"faq-answer\">GCC has a large set of options to control function inlining. Some options are available only&nbsp; in GCC 3.0 and later and thus not present on older platforms.</p>\n<blockquote>\n  <table style=\"text-align: left; width: 100%;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n  <tbody>\n    <tr>\n      <td>-fno-default-inline</td>\n      <td>Do not make member functions inline by default merely because they are defined inside the class scope (C++ only). Otherwise, when you specify -O, member functions defined inside class scope are compiled inline by default; i.e., you don't need to add `inline' in front of the member function name.</td>\n    </tr>\n    <tr>\n      <td>-fno-inline</td>\n      <td>Don't pay attention to the inline keyword. Normally this option is used to keep the compiler from expanding any functions inline. Note that if you are not optimizing, no functions can be expanded inline.</td>\n    </tr>\n    <tr>\n      <td>-finline-functions</td>\n      <td>Integrate all simple functions into their callers. The compiler heuristically decides which functions are simple enough to be worth integrating in this way. If all calls to a given function are integrated, and the function is declared static, then the function is normally not output as assembler code in its own right. Enabled at level -O3.</td>\n    </tr>\n    <tr>\n      <td>-finline-limit=n</td>\n      <td>By default, GCC limits the size of functions that can be inlined. This flag allows the control of this limit for functions that are explicitly marked as inline (i.e., marked with the inline keyword or defined within the class definition in c++). n is the size of functions that can be inlined in number of pseudo instructions (not counting parameter handling). pseudo-instructions are an internal representation of function size. The default value of n is 600. Increasing this value can result in more inlined code at the cost of compilation time and memory consumption. Decreasing usually makes the compilation faster and less code will be inlined (which presumably means slower programs). This option is particularly useful for programs that use inlining heavily such as those based on recursive templates with C++.<br>\n        <br>\n        Inlining is actually controlled by a number of parameters, which may be specified individually by using --param name=value. The -finline-limit=n option sets some of these parameters as follows:<br>\n        <br>\n        max-inline-insns-single<br>\n&nbsp;&nbsp;&nbsp; is set to n/2.<br>\n        max-inline-insns-auto<br>\n&nbsp;&nbsp;&nbsp; is set to n/2.<br>\n        min-inline-insns<br>\n&nbsp;&nbsp;&nbsp; is set to 130 or n/4, whichever is smaller.<br>\n        max-inline-insns-rtl<br>\n&nbsp;&nbsp;&nbsp; is set to n.<br>\n        <br>\n        See&nbsp;--param below for a documentation of the individual parameters controlling inlining.</td>\n    </tr>\n    <tr>\n      <td>-fkeep-inline-functions</td>\n      <td>Emit&nbsp;all inline functions into the object file, even if they are inlined where used.</td>\n    </tr>\n    <tr>\n      <td>--param name=value</td>\n      <td>In some places, GCC uses various constants to control the amount of optimization that is done. For example, GCC will not inline functions that contain more that a certain number of instructions. You can control some of these constants on the command-line using the --param option.&nbsp;<br>\n        <br>\n        max-inline-insns-single<br>\n        Several parameters control the tree inliner used in gcc. This number sets the maximum number of instructions (counted in GCC's internal representation) in a single function that the tree inliner will consider for inlining. This only affects functions declared inline and methods implemented in a class declaration (C++). The default value is 450.<br>\n        <br>\n        max-inline-insns-auto<br>\n        When you use -finline-functions (included in -O3), a lot of functions that would otherwise not be considered for inlining by the compiler will be investigated. To those functions, a different (more restrictive) limit compared to functions declared inline can be applied. The default value is 90.<br>\n        <br>\n        large-function-insns<br>\n        The limit specifying really large functions. For functions larger than this limit after inlining inlining is constrained by --param large-function-growth. This parameter is useful primarily to avoid extreme compilation time caused by non-linear algorithms used by the backend. This parameter is ignored when -funit-at-a-time is not used. The default value is 2700.<br>\n        <br>\n        large-function-growth<br>\n        Specifies maximal growth of large function caused by inlining in percents. This parameter is ignored when -funit-at-a-time is not used. The default value is 100 which limits large function growth to 2.0 times the original size.<br>\n        <br>\n        inline-unit-growth<br>\n        Specifies maximal overall growth of the compilation unit caused by inlining. This parameter is ignored when -funit-at-a-time is not used. The default value is 50 which limits unit growth to 1.5 times the original size.<br>\n        <br>\n        max-inline-insns-recursive<br>\n        max-inline-insns-recursive-auto<br>\n        Specifies maximum number of instructions out-of-line copy of self recursive inline function can grow into by performing recursive inlining. For functions declared inline --param max-inline-insns-recursive is taken into acount. For function not declared inline, recursive inlining happens only when -finline-functions (included in -O3) is enabled and --param max-inline-insns-recursive-auto is used. The default value is 450.<br>\n        <br>\n        max-inline-recursive-depth<br>\n        max-inline-recursive-depth-auto<br>\n        Specifies maximum recursion depth used by the recursive inlining. For functions declared inline --param max-inline-recursive-depth is taken into acount. For function not declared inline, recursive inlining happens only when -finline-functions (included in -O3) is enabled and --param max-inline-recursive-depth-auto is used. The default value is 450.<br>\n        <br>\n        inline-call-cost<br>\n        Specify cost of call instruction relative to simple arithmetics operations (having cost of 1). Increasing this cost disqualify inlining of non-leaf functions and at same time increase size of leaf function that is believed to reduce function size by being inlined. In effect it increase amount of inlining for code having large abstraction penalty (many functions that just pass the arguments to other functions) and decrease inlining for code with low abstraction penalty. Default value is 16.</td>\n    </tr>\n    <tr>\n      <td>-finline-limit=n </td>\n      <td>By default, GCC limits the size of functions that can be inlined. This flag allows the control of this limit for functions that are explicitly marked as inline (i.e., marked with the inline keyword or defined within the class definition in c++). n is the size of functions that can be inlined in number of pseudo instructions (not counting parameter handling). The default value of n is 600. Increasing this value can result in more inlined code at the cost of compilation time and memory consumption. Decreasing usually makes the compilation faster and less code will be inlined (which presumably means slower programs). This option is particularly useful for programs that use inlining heavily such as those based on recursive templates with C++. </td>\n    </tr>\n  </tbody>\n</table>\n</blockquote>\n<p class=\"faq-answer\">Inlining is actually controlled by a number of parameters, which may be specified individually by using <samp><span class=\"option\">--param</span> <var>name</var><span class=\"option\">=</span><var>value</var></samp>. The <samp><span class=\"option\">-finline-limit=</span><var>n</var></samp> option sets some of these parameters as follows:</p>\n<blockquote>\n  <dl>\n    <dl>\n      <dt><code>max-inline-insns-single</code></dt>\n      <dd>is set to <var>n</var>/2.<br>\n      </dd>\n      <dt><code>max-inline-insns-auto</code></dt>\n      <dd>is set to <var>n</var>/2.<br>\n      </dd>\n      <dt><code>min-inline-insns</code></dt>\n      <dd>is set to 130 or <var>n</var>/4, whichever is smaller.<br>\n      </dd>\n      <dt><code>max-inline-insns-rtl</code></dt>\n      <dd>is set to <var>n</var>.</dd>\n    </dl>\n  </dl>\n</blockquote>\n<p class=\"faq-answer\">See below for a documentation of the individual parameters controlling inlining.</p>\n<p class=\"faq-answer\"><em>Note:</em> pseudo instruction represents, in this particular context, an abstract measurement of function's size. In no way, it represents a count of assembly instructions and as such its exact meaning might change from one release to an another.</p>\n<p class=\"faq-answer\">GCC additionally has the -Winline compiler warning, which emits a warning whenever a function declared as inline was not inlined.</p>\n<p class=\"faq-answer\">Compilation-Level Inlining -- Metrowerks</p>\n<p class=\"faq-answer\">Metrowerks has a number of pragmas (and corresponding compiler settings) to control inlining. These include always_inline, inline_depth, inline_max_size, and inline max_total_size.</p>\n<blockquote>\n  <p class=\"faq-answer\"><small><span style=\"font-family: Courier New;\">#pragma always_inline on | off | reset</span></small></p>\n  <p class=\"faq-answer\">Controls the use of inlined functions. If you enable this pragma, the compiler ignores all inlining limits and attempts to inline all functions where it is legal to do so. This pragma is&nbsp;deprecated. Use the inline_depth pragma instead.<br>\n    <br>\n    <small><span style=\"font-family: Courier New;\">#pragma inline_depth(n)</span><br>\n  <span style=\"font-family: Courier New;\">#pragma inline_depth(smart)</span></small></p>\n  <p class=\"faq-answer\">Controls how many passes are used to expand inline function. Sets the number of passes used to expand inline function calls. The number n is an integer from 0 to 1024 or the smart specifier. It also represents the distance allowed in the call chain from the last function up. For example, if d is the total depth of a call chain, then functions below (d-n) are inlined if they do not exceed the&nbsp;inline_max_size and&nbsp;inline_max_total_size settings which are discussed directly below.<br>\n    <br>\n    <small><span style=\"font-family: Courier New;\">#pragma inline_max_size(n);</span><br>\n  <span style=\"font-family: Courier New;\">#pragma inline_max_total_size(n);</span></small></p>\n  <p class=\"faq-answer\">The first pragma sets the maximum function size to be considered for inlining; the second sets the maximum size to which a function is allowed to grow after the functions it calls are inlined. Here, n is the number of statements, operands, and operators in the function, which<br>\n    turns out to be roughly twice the number of instructions generated by the function. However, this number can vary from function to function. For the inline_max_size pragma, the default value of n is 256; for the inline_max_total_size pragma, the default value of n is 10000. The smart specifier is the default mode, with four passes where the passes 2-4 are limited to small inline functions. All inlineable functions are expanded if inline_depth is set to 1-1024.</p>\n</blockquote>\n<p class=\"faq-answer\">Function-Level Inlining -- VC++</p>\n<blockquote>\n  <p class=\"faq-answer\">To force inline usage under VC++, you use this:</p>\n  <p class=\"faq-answer\">  <small><span style=\"font-family: Courier New;\">&nbsp; &nbsp; __forceinline void foo(){ ... }</span></small></p>\n  <p class=\"faq-answer\">It should be noted that __forceinline has no effect if the compiler is set to disable inlining. It merely tells the compiler that when inlining is enabled that it shouldn't use its judgment to decide if the function should be inlined but instead to always inline it.<br>\n    <br>\n    To disable inline usage under VC++, you need to use this:</p>\n  <p class=\"faq-answer\"><small><span style=\"font-family: Courier New;\">&nbsp; &nbsp; #pragma inline_depth(0) // Disable inlining.</span><br>\n    <span style=\"font-family: Courier New;\">&nbsp; &nbsp; void foo() { ... }</span><br>\n    <span style=\"font-family: Courier New;\">&nbsp; &nbsp; #pragma inline_depth()&nbsp; // Restore&nbsp;default.</span></small></p>\n  <p class=\"faq-answer\">The above is essentially specifying compiler-level inlining control within the code for a specific function.</p>\n</blockquote>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Function-Level Inlining --</span> <span style=\"font-weight: bold;\">GCC / Metrowerks</span></p>\n<blockquote>\n  <p class=\"faq-answer\">To force inline usage under GCC 3.1+, you use this:</p>\n  <p class=\"faq-answer\">  <small><span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp;&nbsp;inline void foo() __attribute__((always_inline)) { ... }</span><br>\n    <span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;</span></small> or<small><br>\n  <span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp;&nbsp;inline __attribute__((always_inline)) void foo() { ... }</span></small></p>\n  <p class=\"faq-answer\">To disable inline usage under GCC 3+, you use this:</p>\n  <p class=\"faq-answer\"><small><span style=\"font-family: Courier New;\">&nbsp; &nbsp; void foo() __attribute__((noinline)) { ... }</span><br>\n    </small> <small><span style=\"font-family: Courier New;\">&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;</span></small> or<small><br>\n    <span style=\"font-family: Courier New;\">&nbsp; &nbsp; inline __attribute__((noinline)) void foo() { ... }</span></small></p>\n  <p class=\"faq-answer\">EABase has some wrappers for this, such as EA_FORCE_INLINE.</p>\n</blockquote>\n<p class=\"faq-question\"><a name=\"Perf.12\"></a>Perf.12\n  C++ / EASTL seems to bloat my .obj files much more than C does.\n</p>\n<p class=\"faq-answer\">There is no need to worry. The way most C++ compilers compile templates, they compile all seen template code into the current .obj module, which results in larger .obj files and duplicated template code in multiple .obj files. However, the linker will (and in fact must) select only a single version of any given function for the application, and these linked functions will usually be located contiguously.</p>\n<p class=\"faq-answer\">Additionally, the debug information for template definitions is usually larger than that for non-templated C++ definitions, which itself is sometimes larger than C definitions due to name decoration.</p>\n<p class=\"faq-question\"><a name=\"Perf.13\"></a>Perf.13\nWhat are the best compiler settings for EASTL?</p>\n<p class=\"faq-answer\">We will discuss various aspects of this topic here. As of this writing, more EASTL research on this topic has been done on Microsoft compiler platforms (e.g. Win32) than GCC platforms. Thus currently this discussion focuses on VC++ optimization. Some of the concepts are applicable to GCC, though. EASTL has been successfully compiled and tested (the EASTL unit test) on our major development platforms with the highest optimization settings enabled, including GCC's infamous -O3 level.<br>\n<br>\n<span style=\"font-weight: bold;\">Optimization Topics</span></p>\n<ul>\n  <li>Function inlining.</li>\n  <li>Optimization for speed vs. optimization for size.</li>\n  <li>Link-time code generation (LTCG).</li>\n  <li>Profile-guided optimization (PGO).</li>\n</ul>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Function inlining</span><br>\n  EASTL is a template library and inlining is important for optimal speed. Compilers have various options for enabling inlining and those options are discussed in this FAQ in detail. Most users will want to enable some form of inlining when compiling EASTL and other templated libraries. For users that are most concerned about the compiler's inlining increasing code size may want to try the 'inline only functions marked as inline' compiler option. Here is a table of normalized results from the benchmark project (Win32 platform):<br>\n</p>\n<table style=\"text-align: left; margin-left: 40px; width: 696px; height: 88px;\" border=\"1\" cellpadding=\"2\" cellspacing=\n\"2\">\n  <tbody>\n    <tr>\n      <td style=\"font-weight: bold;\"></td>\n      <td style=\"font-weight: bold; text-align: center;\">Inlining Disabled</td>\n      <td style=\"font-weight: bold; text-align: center;\">Inline only 'inline'</td>\n      <td style=\"text-align: center;\">Inline any</td>\n    </tr>\n    <tr>\n      <td style=\"font-weight: bold;\">Application size</td>\n      <td style=\"text-align: center;\">100K</td>\n      <td style=\"text-align: center;\">86K</td>\n      <td style=\"text-align: center;\">86K</td>\n    </tr>\n    <tr>\n      <td style=\"font-weight: bold;\">Execution time</td>\n      <td style=\"text-align: center;\">100</td>\n      <td style=\"text-align: center;\">75</td>\n      <td style=\"text-align: center;\">75</td>\n    </tr>\n  </tbody>\n</table>\n<p class=\"faq-answer\"><br>\nThe above execution times are highly simplified versions of the actual benchmark data but convey a sense of the general average behaviour that can be expected. In practice, simple functions such as vector::operator[] will execute much faster with inlining enabled but complex functions such as map::insert may execute no faster within inlining enabled.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Optimization for Speed / Size</span><br>\n  Optimization for speed results in the compiler inlining more code than it would otherwise. This results in the inlined code executing faster than if it was not inlined. As mentioned above, basic function inlining can result in smaller code as well as faster code, but after a certain point highly inlined code becomes greater in size than less inlined code and the performance advantages of inlining start to lessen. The EASTL Benchmark project is a medium sized application that is about 80% templated and thus acts as a decent measure of the practical tradeoff between speed and size. Here is a table of normalized results from the benchmark project (Windows platform):<br>\n</p>\n<table style=\"text-align: left; margin-left: 40px; width: 696px; height: 88px;\" border=\"1\" cellpadding=\"2\" cellspacing=\n\"2\">\n  <tbody>\n    <tr>\n      <td style=\"font-weight: bold;\"></td>\n      <td style=\"font-weight: bold; text-align: center;\">Size</td>\n      <td style=\"font-weight: bold; text-align: center;\">Speed</td>\n      <td style=\"text-align: center;\">Speed + LTCG</td>\n      <td style=\"text-align: center;\">Speed + LTCG + PGO</td>\n    </tr>\n    <tr>\n      <td style=\"font-weight: bold;\">Application size</td>\n      <td style=\"text-align: center;\">80K</td>\n      <td style=\"text-align: center;\">100K</td>\n      <td style=\"text-align: center;\">98K</td>\n      <td style=\"text-align: center;\">98K</td>\n    </tr>\n    <tr>\n      <td style=\"font-weight: bold;\">Execution time</td>\n      <td style=\"text-align: center;\">100</td>\n      <td style=\"text-align: center;\">90</td>\n      <td style=\"text-align: center;\">83</td>\n      <td style=\"text-align: center;\">75</td>\n    </tr>\n  </tbody>\n</table>\n<p class=\"faq-answer\"><br>\nWhat the above table is saying is that if you are willing to have your EASTL code be 20% larger, it will be 10% faster. Note that it doesn't mean that your app will be 20% larger, only the templated code in it like EASTL will be 20% larger.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Link-time code generation (LTCG)</span><br>\n  LTCG is a mechanism whereby the compiler&nbsp;compiles the application as if it was all in one big .cpp file instead of separate .cpp files that don't see each other. Enabling LTCG optimizations is done by simply setting some compiler and linker settings and results in slower link times. The benchmark results are presented above and for the EASTL Benchmark project show some worthwhile improvement.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Profile-guided optimization (PGO)</span><br>\n  PGO is a mechanism whereby the compiler uses profiling information from one or more runs to optimize the compilation and linking of an application. Enabling PGO optimizations is done by setting some linker settings and doing some test runs of the application, then linking the app with the test run results. Doing PGO optimizations is a somewhat time-consuming task but the benchmark results above demonstrate that for the EASTL Benchmark project that PGO is worth the effort. </p>\n<h2>  Problems</h2>\n<p class=\"faq-question\"><a name=\"Prob.1\"></a>Prob.1 \nI'm getting screwy behavior in sorting algorithms or sorted containers. What's wrong?</p>\n<p class=\"faq-answer\">It may possible that you are seeing floating point roundoff problems. Many STL algorithms require object comparisons to act consistently. However, floating point values sometimes compare differently between uses because in one situation a value might be in 32 bit form in system memory, whereas in anther situation that value might be in an FPU register with a different precision. These are difficult problems to track down and aren't the fault of EASTL or whatever similar library you might be using. There are various solutions to the problem, but the important thing is to find a way to force the comparisons to be consistent.</p>\n<p class=\"faq-answer\">The code below was an example of this happening, whereby the object pA-&gt;mPos was stored in system memory while pB-&gt;mPos was stored in a register and comparisons were inconsistent and a crash ensued.<br>\n</p>\n<pre class=\"code-example\">class SortByDistance : public&nbsp;binary_function&lt;WorldTreeObject*, WorldTreeObject*, bool&gt;\n{\nprivate:\n&nbsp;&nbsp;&nbsp;&nbsp;Vector3 mOrigin;\n\npublic:\n&nbsp;&nbsp;&nbsp; SortByDistance(Vector3 origin) {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mOrigin = origin;\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; bool operator()(WorldTreeObject* pA, WorldTreeObject* pB) const {\n<span style=\"color: rgb(204, 0, 0);\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((WorldObject*)pA)-&gt;mPos - mOrigin).GetLength()</span>\n<span style=\"color: rgb(204, 0, 0);\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt; ((WorldObject*)pB)-&gt;mPos - mOrigin).GetLength();</span>\n&nbsp;&nbsp;&nbsp; }\n};</pre>\n<p class=\"faq-answer\">Another thing to watch out for is the following mistake:<br>\n</p>\n<pre class=\"code-example\">struct ValuePair\n{\n&nbsp;&nbsp;&nbsp; uint32_t a;\n&nbsp;&nbsp;&nbsp; uint32_t b;\n};\n\n// Improve speed by casting the struct to uint64_t\nbool operator&lt;(const ValuePair&amp; vp1, const ValuePair&amp; vp2)\n&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(204, 0, 0);\">{ return *(uint64_t*)&amp;vp1 &lt; *(uint64_t*)&amp;vp2; }</span></pre>\n<p class=\"faq-answer\">The problem is that the ValuePair struct has 32 bit alignment but the comparison assumes 64 bit alignment. The code above has been observed to crash on the PowerPC 64-based machines. The resolution is to declare ValuePair as having 64 bit alignment.<br>\n  \n</p>\n<p class=\"faq-question\"><a name=\"Prob.2\"></a>Prob.2 I am getting compiler warnings (e.g. C4244, C4242 or C4267) that make no sense. Why?</p>\n<span class=\"faq-answer\">One cause of this occurs with VC++ when you have code compiled with the /Wp64 (detect 64 bit portability issues) option. This causes pointer types to have a hidden flag called&nbsp;__w64 attached to them by the compiler. So 'ptrdiff_t' is actually known by the compiler as '__w64 int', while 'int' is known by the compilers as simply 'int'. A problem occurs here when you use templates. For example, let's say we have this templated function</span>\n<pre class=\"code-example\">template &lt;typename T&gt;\nT min(const T a, const T b) {\n&nbsp;&nbsp;&nbsp;&nbsp;return b &lt; a ? b : a;\n}</pre>\n<span class=\"faq-answer\">If you compile this code:</span>\n<pre class=\"code-example\">ptrdiff_t a = min(ptrdiff_t(0), ptrdiff_t(1));\nint &nbsp; &nbsp; &nbsp; b = min((int)0, (int)1);</pre>\n<span class=\"faq-answer\">You will get the following warning for the second line, which is somewhat nonsensical:</span>\n<pre class=\"code-example\">warning C4244: 'initializing' : conversion from 'const ptrdiff_t' to 'int', possible loss of data</pre>\n<p class=\"faq-answer\">  This could probably be considered a VC++ bug, but in the meantime you have little choice but to ignore the warning or disable it.</p>\n\n<p class=\"faq-question\"><a name=\"Prob.3\"></a>Prob.3\nI am getting compiler warning C4530, which complains about exception handling and \"unwind semantics.\" What gives?</p>\n<p class=\"faq-answer\">VC++ has a compiler option (/EHsc) that allows you to enable/disable exception handling stack unwinding but still enable try/catch. This is useful because it can save a lot in the way of code generation for your application. Disabling stack unwinding will decrease the size of your executable on at least the Win32 platform by 10-12%.<br>\n<br>\nIf you have stack unwinding disabled, but you have try/catch statements, VC++ will generate the following warning:</p>\n<pre class=\"code-example\">warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc</pre>\n<p class=\"faq-answer\">  As of EASTL v1.0, this warning has been disabled within EASTL for EASTL code. However, non-EASTL code such as std STL code may still cause this warning to be triggered. In this case there is not much you can do about this other than to disable the warning.</p>\n<p class=\"faq-question\">  <a name=\"Prob.4\"></a>Prob.4\n  Why are tree-based EASTL containers hard to read with a\ndebugger?</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Short answer<br>\n</span> Maximum performance and design mandates.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Long answer</span><br>\nYou may notice that when you have a tree-based container (e.g. set, map)&nbsp; in the debugger that it isn't automatically able to recognize the tree nodes as containing instances of your contained object. You can get the debugger to do what you want with casting statements in the debug watch window, but this is not an ideal solution. The reason this is happening is that node-based containers always use an anonymous node type as the base class for container nodes. This is primarily done for performance, as it allows the node manipulation code to exist as a single non-templated library of functions and it saves memory because containers will have one or two base nodes as container 'anchors' and you don't want to allocate a node of the size of the user data when you can just use a base node. See list.h for an example of this and some additional in-code documentation on this.</p>\n<p class=\"faq-answer\">Additionally, EASTL has the design mandate that an empty container constructs no user objects. This is both for performance reasons and because it doing so would skew the user's tracking of object counts and might possibly break some expectation the user has about object lifetimes.</p>\n<p class=\"faq-answer\">Currently this debug issue exists only with tree-based containers. Other node-based containers such as list and slist use a trick to get around this problem in debug builds.</p>\n<p class=\"faq-answer\">See <a href=\"#Debug.2\">Debug.2</a> for more.\n<p class=\"faq-question\"><a name=\"Prob.5\"></a>Prob.5\nThe EASTL source code is sometimes rather complicated looking. Why is that?</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Short answer</span><br>\nMaximum performance.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Long answer</span><br>\n  EASTL uses templates, type_traits, iterator categories, redundancy reduction, and branch reduction in order to achieve optimal performance. A side effect of this is that there are sometimes a lot of template parameters and multiple levels of function calls due to template specialization. The ironic thing about this is that this makes the code (an optimized build, at least) go faster, not slower. In an optimized build the compiler will see through the calls and template parameters and generate a direct optimized inline version.</p>\n<p class=\"faq-answer\">As an example of this, take a look at the implementation of the <span style=\"font-style: italic;\">copy</span> implementation in algorithm.h. If you are copying an array of scalar values or other trivially copyable values, the compiler will see how the code directs this to the memcpy function and will generate nothing but a memcpy in the final code. For non-memcpyable data types the compiler will automatically understand that in do the right thing.</p>\n<p class=\"faq-answer\">EASTL's primary objective is maximal performance, and it has been deemed worthwhile to make the code a little less obvious in order to achieve this goal. Every case where EASTL does something in an indirect way is by design and usually this is for the purpose of achieving the highest possible performance.</p>\n<p class=\"faq-question\"><a name=\"Prob.6\"></a>Prob.6\nWhen I get compilation errors, they are very long and complicated looking. What do I do?</p>\n<p class=\"faq-answer\">Assuming the bugs are all worked out of EASTL, these errors really do indicate that you have something wrong. EASTL is intentionally very strict about types, as it tries to minimize the chance of users errors. Unfortunately, there is no simple resolution to the problem of long compiler errors other than to deal with them. On the other hand, once you've dealt with them a few times, you tend to realize that most of time they are the same kinds of errors and</p>\n<p class=\"faq-answer\">Top five approaches to dealing with long compilation errors:</p>\n<ol>\n  <li>Look at the line where the compilation error occurred and ignore the text of the error and just look at obvious things that might be wrong.</li>\n  <li>Consider the most common typical causes of templated compilation errors and consider if any of these might be your problem. Usually one of them are.</li>\n  <li>Either read through the error (it's not as hard as it may look on the surface) or copy the error to a text file and remove the extraneous</li>\n  <li>Compile the code under GCC instead of MSVC, as GCC warnings and errors tend to be more helpful than MSVC's. Possibly also consider compiling an isolated version under Comeau C++'s free online compiler at www.comeaucomputing.com or the Dinkumware online compiler at http://dinkumware.com/exam/.&nbsp;</li>\n  <li>Try using an STL filter (http://www.bdsoft.com/tools/stlfilt.html) which automatically boils down template errors to simpler forms. We haven't tried this yet with EASTL. Also there is the more generic TextFilt (http://textfilt.sourceforge.net/).</li>\n</ol>\n<p class=\"faq-answer\">Top five causes of EASTL compilation errors:</p>\n<ol>\n  <li>const-correctness. Perhaps a quarter of container template errors are due to the user not specifying const correctly.</li>\n  <li>Missing hash function. hash_map, hash_set, etc. require that you either specify a hash function or one exists for your class. See functional.h for examples of declarations of hash functions for common data types.</li>\n  <li>Missing operators. Various containers and algorithms require that certain operators exist for your contained classes. For example, list requires that you can test contained objects for equivalence (i.e. operator==), while map requires that you can test contained objects for \"less-ness\" (operator &lt;). If you define a Widget class and don't have a way to compare two Widgets, you will get errors when trying to put them into a map.</li>\n  <li>Specifying the wrong data type. For example, it is a common mistake to forget that when you insert into a map, you need to insert a pair of objects and not just your key or value type.</li>\n  <li>Incorrect template parameters. When declaring a template instantiation (e.g. map&lt;int, int, less&lt;int&gt; &gt;) you simply need to get the template parameters correct. Also note that when you have \"<span style=\"font-family: Courier New;\">&gt;&gt;</span>\" next to each other that you need to separate them by one space (e.g. \"<span style=\"font-family: Courier New;\">&gt; &gt;</span>\").</li>\n</ol>\n<p class=\"faq-question\"><a name=\"Prob.7\"></a>Prob.7\n  Templates sometimes seem to take a long time to compile. Why do I do about that?\n</p>\n<p class=\"faq-answer\">C++ compilers are generally slower than C compilers, and C++ templates are generally slower to compile than regular C++ code. EASTL has some extra functionality (such as type_traits and algorithm specializations) that is not found in most other template libraries and significantly improves performance and usefulness but adds to the amount of code that needs to be compiled. Ironically, we have a case where more source code generates faster and smaller object code.</p>\n<p class=\"faq-answer\">The best solution to the problem is to use pre-compiled headers, which are available on all modern ~2002+) compilers, such as VC6.0+, GCC 3.2+, and Metrowerks 7.0+. In terms of platforms this means all 2002+ platforms.</p>\n<p class=\"faq-answer\">Some users have been speeding up build times by creating project files that put all the source code in one large .cpp file. This has an effect similar to pre-compiled headers. It can go even faster than pre-compiled headers but has downsides in the way of convenience and portability.</p>\n<p class=\"faq-question\"><a name=\"Prob.8\"></a>Prob.8\nI get the compiler error: \"template instantiation depth exceeds maximum of 17.&nbsp;use -ftemplate-depth-NN to increase the maximum\".&nbsp;</p>\n<p class=\"faq-answer\">This is a GCC error that occurs when a templated function calls a templated function which calls a templated function, etc. past a depth of 17. You can use the GCC command line argument -ftemplate-depth-40 (or some other high number) to get around this. As note below, the syntax starting with GCC 4.5 has changed slightly. </p>\n<p class=\"faq-answer\">The primary reason you would encounter this with EASTL is type traits that are used by algorithms. The type traits library is a (necessarily) highly templated set of types and functions which adds at most about nine levels of inlining. The copy and copy_backward algorithms have optimized pathways that add about four levels of inlining. If you have just a few more layers on top of that in container or user code then the default limit of 17 can be exceeded. We are investigating ways to reduce the template depth in the type traits library, but only so much can be done, as most compilers don't support type traits natively. Metrowerks is the current exception.</p>\n<p class=\"faq-answer\">From the GCC documentation:</p>\n<pre class=\"code-example\">-ftemplate-depth-n\n\nSet the maximum instantiation depth for template classes to n. \nA limit on the template instantiation depth is needed to detect \nendless recursions during template class instantiation ANSI/ISO \nC++ conforming programs must not rely on a maximum depth greater than 17.\n</pre>\n\n<p class=\"faq-answer\">Note that starting with GCC 4.5 the syntax is -ftemplate-depth=N instead of -ftemplate-depth-n.</p>\n<p class=\"faq-question\"><a name=\"Prob.9\"></a>Prob.9\n  I'm getting errors about min and max while compiling.</p>\n<p class=\"faq-answer\">You need to define NOMINMAX under VC++ when this occurs, as it otherwise defines min and max macros that interfere. There may be equivalent issues with other compilers. Also, VC++ has a specific &lt;minmax.h&gt; header file which defines min and max macros but which doesn't pay attention to NOMINMAX and so in that case there is nothing to do but not include that file or to undefine min and max. minmax.h is not a standard file and its min and max macros are not standard C or C++ macros or functions.</p>\n<p class=\"faq-question\"><a name=\"Prob.10\"></a>Prob.10\nC++ / EASTL seems to bloat my .obj files much more than C does.</p>\n<p class=\"faq-answer\">    There is no need to worry. The way most C++ compilers compile templates, they compile all\nseen template code into the current .obj module, which results in larger .obj files and duplicated template code in\nmultiple .obj files. However, the linker will (and must) select only a single version of any given function for the\napplication, and these linked functions will usually be located contiguously.</p>\n<p class=\"faq-question\">  <a name=\"Prob.11\"></a>Prob.11 \n  I'm getting compiler errors regarding placement operator new\nbeing&nbsp;previously defined.</p>\n<p class=\"faq-answer\">This can happen if you are attempting to define your own versions of placement new/delete. The C++ language standard does not allow the user to override these functions. Section 18.4.3 of the standard states:</p>\n<p class=\"faq-answer\">&nbsp;&nbsp;&nbsp;&nbsp; Placement forms<br>\n&nbsp;&nbsp;&nbsp;&nbsp; 1. These functions are reserved, a C++ program may not define functions that displace the versions in the Standard C++ library.</p>\n<p class=\"faq-answer\">You may find that #defining <small>__PLACEMENT_NEW_INLINE</small> seems to fix your problems under VC++, but it can fail under some circumstances and is not portable and fails with other compilers, which don't have an equivalent workaround.</p>\n<p class=\"faq-question\">  <a name=\"Prob.12\"></a>Prob.12\nI'm getting errors related to wchar_t string &nbsp;functions such as wcslen().</p>\n<p class=\"faq-answer\">EASTL requires EABase-related items that the following be so. If not, then EASTL gets confused about what types it can pass to wchar_t related functions.</p>\n<ul>\n  <li>The #define EA_WCHAR_SIZE is equal to sizeof(wchar_t).</li>\n  <li>If sizeof(wchar_t) == 2, then char16_t is typedef'd to wchar_t.</li>\n  <li>If sizeof(wchar_t) == 4, then char32_t is typedef'd to wchar_t.</li>\n</ul>\n<p class=\"faq-answer\">EABase v2.08 and later automatically does this for most current generation and all next generation platforms. With GCC 2.x, the user may need to predefine EA_WCHAR_SIZE to the appropriate value, due to limitations with the GCC compiler. Note that GCC defaults to sizeof(wchar_t) ==4, but it can be changed to 2 with the -fshort_wchar compiler command line argument. If you are using EASTL without EABase, you will need to make sure the above items are correctly defined.</p>\n<p class=\"faq-question\">  <a name=\"Prob.13\"></a>Prob.13\n  I'm getting compiler warning C4619: there is no warning number Cxxxx\n(e.g. C4217).</p>\n<p class=\"faq-answer\">Compiler warning C4619 is a VC++ warning which is saying that the user is attempting to enable or disable a warning which the compiler doesn't recognize. This warning only occurs if the user has the compiler set to enable warnings that are normally disabled, regardless of the warning level. The problem, however, is that there is no easy way for user code to tell what compiler warnings any given compiler version will recognize. That's why Microsoft normally disables this warning.</p>\n<p class=\"faq-answer\">The only practical solution we have for this is for the user to disable warning 4619 globally or an a case-by-case basis. EA build systems such as nant/framework 2's eaconfig will usually disable 4619. In general, global enabling of 'warnings that are disabled by default' often result in quandrys such as this.</p>\n<p class=\"faq-question\"><a name=\"Prob.14\"></a>Prob.14\nMy stack-based fixed_vector is not respecting the object alignment requirements.</p>\n<p class=\"faq-answer\">EASTL fixed_* containers rely on the compiler-supplied alignment directives, such as that implemented by EA_PREFIX_ALIGN. This is normally a good thing because it allows the memory to be local with the container. However, as documented by Microsoft at <a href=\"http://msdn2.microsoft.com/en-us/library/83ythb65(VS.71).aspx\"> http://msdn2.microsoft.com/en-us/library/83ythb65(VS.71).aspx</a>, this doesn't work for stack variables. The two primary means of working around this are: </p>\n<ul>\n  <li>Use something like AlignedObject&lt;&gt; from the EAStdC package's EAAllocator.h file. </li>\n  <li>Use eastl::vector with a custom allocator and have it provide aligned memory. EASTL automatically recognizes that the objects are aligned and will call the aligned version of your allocator allocate() function. You can get this aligned memory from the stack, if you need it, somewhat like how AlignedObject&lt;&gt; works. </li>\n</ul>\n<p class=\"faq-question\"><a name=\"Prob.15\" id=\"Prob.15\"></a>Prob.15 I am getting compiler errors when using GCC under XCode (Macintosh/iphone).</p>\n<p class=\"faq-answer\">The XCode environment has a compiler option which causes it to evaluate include directories recursively. So if you specify /a/b/c as an include directory, it will consider all directories underneath c to also be include directories. This option is enabled by default, though many XCode users disable it, as it is a somewhat dangerous option. The result of enabling this option with EASTL is that &lt;EASTL/string.h&gt; is used by the compiler when you say #include &lt;string.h&gt;. The solution is to disable this compiler option. It's probably a good idea to disable this option anyway, as it typically causes problems for users yet provides minimal benefits. </p>\n<p class=\"faq-question\"><a name=\"Prob.16\" id=\"Prob.16\"></a>Prob.16 I am getting linker errors about Vsnprintf8 or Vsnprintf16.</p>\n<p class=\"faq-answer\">EASTL requires the user to provide a function called Vsnprintf8 if the string::sprintf function is used. vsnprintf is not a standard C function, but most C standard libraries provide some form of it, though in some ways their implementations differ, especially in what the return value means. Also, most implementations of vsnprintf are slow, mostly due to mutexes related to locale functionality. And you can't really use vendor vsnprintf on an SPU due to the heavy standard library size. EASTL is stuck because it doesn't want to depend on something with these problems. EAStdC provides a single consistent fast lightweight, yet standards-conforming, implementation in the form of Vsnprintf(char8_t*, ...), but EASTL can't have a dependency on EAStdC. So the user must provide an implementation, even if all it does is call EAStdC's Vsnprintf or the vendor vsnprintf for that matter.</p>\n<p class=\"faq-answer\">Example of providing Vsnprintf8 via EAStdC:</p>\n<pre class=\"code-example\">#include &lt;EAStdC/EASprintf.h&gt;\n   \nint Vsnprintf8(char8_t* pDestination, size_t n, const char8_t* pFormat, va_list arguments)\n{\n    return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n}\n\nint Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments)\n{\n    return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n}</pre>\n<p>Example of providing Vsnprintf8 via C libraries:</p>\n<pre><span class=\"code-example\">#include &lt;stdio.h&gt;\n   \nint Vsnprintf8(char8_t* p, size_t n, const char8_t* pFormat, va_list arguments)\n{\n &nbsp;&nbsp;&nbsp;#ifdef _MSC_VER\n &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return vsnprintf_s(p, n, _TRUNCATE, pFormat, arguments);\n &nbsp;&nbsp;&nbsp;#else\n &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return vsnprintf(p, n, pFormat, arguments);\n &nbsp;&nbsp;&nbsp;#endif\n}\n\nint Vsnprintf16(char16_t* p, size_t n, const char16_t* pFormat, va_list arguments)\n{\n &nbsp;&nbsp;&nbsp;#ifdef _MSC_VER\n &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;return vsnwprintf_s(p, n, _TRUNCATE, pFormat, arguments);\n &nbsp;&nbsp;&nbsp;#else\n &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;return vsnwprintf(p, n, pFormat, arguments); <span class=\"code-example-comment\">// Won't work on Unix because its libraries implement wchar_t as int32_t.</span>\n &nbsp;&nbsp;&nbsp;#endif\n}</span></pre>\n<p class=\"faq-question\"><a name=\"Prob.17\" id=\"Prob.17\"></a>Prob.17 I am getting compiler errors about UINT64_C or UINT32_C.</p>\n<p class=\"faq-answer\">This is usually an order-of-include problem that comes about due to the implementation of __STDC_CONSTANT_MACROS in C++ Standard libraries. The C++ &lt;stdint.h&gt; header file defineds UINT64_C only if __STDC_CONSTANT_MACROS has been defined by the user or the build system; the compiler doesn't automatically define it. The failure you are seeing occurs because user code is #including a system header before #including EABase and without defining __STDC_CONSTANT_MACROS itself or globally. EABase defines __STDC_CONSTANT_MACROS and #includes the appropriate system header. But if the system header was already previously #included and __STDC_CONSTANT_MACROS was not defined, then UINT64_C doesn't get defined by anybody. </p>\n<p class=\"faq-answer\">The real solution that the C++ compiler and standard library wants is for the app to globally define __STDC_CONSTANT_MACROS itself in the build. </p>\n<p class=\"faq-question\"><a name=\"Prob.18\" id=\"Prob.18\"></a>Prob.18 I am getting a crash with a global EASTL container. </p>\n<p class=\"faq-answer\">This usually due to compiler's lack of support for global (and static) C++ class instances. The crash is happening because the global variable exists but its constructor was not called on application startup and it's member data is zeroed bytes. To handle this you need to manually initialize such variables. There are two primary ways:</p>\n<p class=\"faq-answer\">Failing code:</p>\n<pre class=\"code-example\">eastl::list&lt;int&gt; gIntList; // Global variable.\n   \nvoid DoSomething()\n{\n    gIntList.push_back(1); // <span class=\"style3\">Crash</span>. gIntList was never constructed.\n}</pre>\n<p class=\"faq-answer\">Declaring a pointer solution: </p>\n<pre class=\"code-example\">eastl::list&lt;int&gt;* gIntList = NULL;\n   \nvoid DoSomething()\n{\n    if(!gIntList) // Or move this to an init function.\n        gIntList = new eastl::list&lt;int&gt;;\n\n    gIntList-&gt;push_back(1); // <span class=\"style2\">Success</span>\n}</pre>\n<p class=\"faq-answer\">Manual constructor call solution: </p>\n<pre class=\"code-example\">eastl::list&lt;int&gt; gIntList;\n   \nvoid InitSystem()\n{\n    new(&amp;gIntList) eastl::list&lt;int&gt;;\n}\n\nvoid DoSomething()\n{\n    gIntList.push_back(1); // <span class=\"style2\">Success</span>\n}</pre>\n<p class=\"faq-question\"><a name=\"Prob.19\" id=\"Prob.19\"></a>Prob.19 Why doesn't EASTL support passing NULL string functions? </p>\n<p class=\"faq-answer\"></p>\n<p class=\"faq-answer\">The primary argument is to make functions safer for use. Why crash on NULL pointer access when you can make the code safe? That's a good argument. The counter argument, which EASTL currently makes, is: </p>\n<ul>\n  <li class=\"faq-answer\"> It breaks consistency with the C++ STL library and C libraries, which require strings to be valid.</li>\n  <li class=\"faq-answer\"> It makes the coder slower and bigger for all users, though few need NULL checks. </li>\n  <li class=\"faq-answer\"> The specification for how to handle NULL is simple for some cases but not simple for others. Operator &lt; below a case where the proper handling of it in a consistent way is not simple, as all comparison code (&lt;, &gt;, ==, !=, &gt;=, &lt;=) in EASTL must universally and consistently handle the case where either or both sides are NULL. A NULL string seems similar to an empty string, but doesn't always work out so simply.</li>\n  <li class=\"faq-answer\">What about other invalid string pointers? NULL is merely one invalid value of many, with its only distinction being that sometimes it's intentionally NULL (as opposed to being NULL due to not being initialized). </li>\n  <li class=\"faq-answer\"> How and where to implement the NULL checks in such a way as to do it efficiently is not always simple, given that public functions call public functions. </li>\n  <li class=\"faq-answer\">It's arguable (and in fact the intent of the C++ standard library) that using pointers that are NULL is a user/app mistake. If we really want to be safe then we should be using string objects for everything. You may not  entirely buy this argument in practice, but on the other hand one might ask why is the caller of EASTL using a NULL pointer in the first place? The answer of course is that somebody gave it to him. </li>\n</ul>\n<h2>Debug</h2>\n<p class=\"faq-question\"><a name=\"Debug.1\"></a>Debug.1\nHow do I set the VC++ debugger to display EASTL container data with tooltips?</p>\n<p class=\"faq-answer\">See <a href=\"#Cont.9\">Cont.9</a></p>\n<p class=\"faq-question\"><a name=\"Debug.2\"></a>Debug.2\nHow do I view containers if the visualizer/tooltip support is not present?</p>\n\n<p class=\"faq-answer\">Here is a table of answers about how to manually inspect containers in the debugger.</p>\n<blockquote>\n<table style=\"text-align: left; width: 100%;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\" id=\"table4\">\n  <tbody>\n    <tr>\n      <td style=\"font-weight: bold;\">&nbsp;Container</td>\n      <td style=\"font-weight: bold;\">Approach</td>\n    </tr>\n    <tr>\n      <td>slist<br>\n        fixed_slist</td>\n      <td>slist is a singly-linked list. Look at the slist mNode variable. You can walk the list by looking at mNode.mpNext, etc.</td>\n    </tr>\n    <tr>\n      <td>list<br>\n        fixed_list</td>\n      <td>list is a doubly-linked list. Look at the list mNode variable. You can walk the list forward by looking at mNode.mpNext, etc. and backward by looking at mpPrev, etc.</td>\n    </tr>\n    <tr>\n      <td>intrusive_list<br>\n        intrusive_slist<sup>&dagger;</sup></td>\n      <td>Look at the list mAnchor node. This lets you walk forward and backward in the list via mpNext and mpPrev.</td>\n    </tr>\n    <tr>\n      <td>array</td>\n      <td>View the array mValue member in the debugger. It's simply a C style array.</td>\n    </tr>\n    <tr>\n      <td>vector<br>\n        fixed_vector</td>\n      <td>View the vector mpBegin value in the debugger. If the string is long, use &quot;, N&quot; to limit the view length, as with someVector.mpBegin, 32</td>\n    </tr>\n    <tr>\n      <td>vector_set<br>\n        vector_multiset<br>\n        vector_map<br>\n        vector_multimap<br></td>\n      <td>These are containers that are implemented as a sorted vector, deque, or array. They are searched via a standard binary search. You can view them the same way you view a vector or deque.</td>\n    </tr>\n    <tr>\n      <td style=\"vertical-align: top;\">deque<br></td>\n      <td style=\"vertical-align: top;\">deque is implemented as an array of arrays, where the arrays implement successive equally-sized segments of the deque. The mItBegin deque member points the deque begin() position. </td>\n    </tr>\n    <tr>\n      <td>bitvector</td>\n      <td>Look at the bitvector mContainer variable. If it's a vector, then see vector above.</td>\n    </tr>\n    <tr>\n      <td>bitset</td>\n      <td>Look at the bitset mWord variable. The bitset is nothing but one or more uint32_t mWord items.</td>\n    </tr>\n    <tr>\n      <td>set<br>\n        multiset<br>\n        fixed_set<br>\n        fixed_multiset<br></td>\n      <td>The set containers are implemented as a tree of elements. The set mAnchor.mpNodeParent points to the top of the tree; the mAnchor.mpNodeLeft points to the far left node of the tree (set begin()); the mAnchor.mpNodeRight points to the right of the tree (set end()).</td>\n    </tr>\n    <tr>\n      <td>map<br>\n        multimap<br>\n        fixed_map<br>\n        fixed_multimap</td>\n      <td>The map containers are implemented as a tree of pairs, where pair.first is the map key and pair.second is the map value. The map mAnchor.mpNodeParent points to the top of the tree; the mAnchor.mpNodeLeft points to the far left node of the tree (map begin()); the mAnchor.mpNodeRight points to the right of the tree (map end()).</td>\n    </tr>\n    <tr>\n      <td>hash_map<br>\n        hash_multimap<br>\n        fixed_hash_map<br>\n        fixed_hash_multimap</td>\n      <td>hash tables in EASTL are implemented as an array of singly-linked lists. The array is the mpBucketArray member. Each element in the list is a pair, where the first element of the pair is the map key and the second is the map value.</td>\n    </tr>\n    <tr>\n      <td>intrusive_hash_map<br>\n        intrusive_hash_multimap<br>\n        intrusive_hash_set<br>\n        intrusive_hash_multiset</td>\n      <td>intrusive hash tables in EASTL are implemented very similarly to regular hash tables. See the hash_map and hash_set entries for more info.</td>\n    </tr>\n    <tr>\n      <td>hash_set<br>\n        hash_multiset<br>\n        fixed_hash_set<br>\n        fixed_hash_map<br></td>\n      <td>hash tables in EASTL are implemented as an array of singly-linked lists. The array is the mpBucketArray member. </td>\n    </tr>\n    <tr>\n      <td>basic_string<br>\n        fixed_string<br>\n        fixed_substring</td>\n      <td>View the string mpBegin value in the debugger. If the string is long, use &quot;, N&quot; to limit the view length, as with someString.mpBegin, 32</td>\n    </tr>\n    <tr>\n      <td style=\"vertical-align: top;\">heap<br></td>\n      <td style=\"vertical-align: top;\">A heap is an array of data (e.g. EASTL vector) which is organized in a tree whereby the highest priority item is array[0], The next two highest priority items are array[1] and [2]. Underneath [1] in priority are items [3] and [4], and underneath item [2] in priority are items [5] and [6]. etc.</td>\n    </tr>\n    <tr>\n      <td style=\"vertical-align: top;\">stack<br></td>\n      <td style=\"vertical-align: top;\">View the stack member c value in the debugger. That member will typically be a list or deque. </td>\n    </tr>\n    <tr>\n      <td style=\"vertical-align: top;\">queue<br></td>\n      <td style=\"vertical-align: top;\">View the queue member c value in the debugger. That member will typically be a list or deque. </td>\n    </tr>\n    <tr>\n      <td style=\"vertical-align: top;\">priority_queue<br></td>\n      <td style=\"vertical-align: top;\">View the priority_queue member c value in the debugger. That member will typically be a vector or deque which is organized as a heap. See the heap section above for how to view a heap. </td>\n    </tr>\n    <tr>\n      <td>smart_ptr</td>\n      <td>View the mpValue member.</td>\n    </tr>\n  </tbody>\n</table>\n</blockquote>\n<p class=\"faq-question\"><a name=\"Debug.3\"></a>Debug.3\nThe EASTL source code is sometimes rather complicated looking. Why is that?</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Short answer</span><br>\nMaximum performance.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Long answer</span><br>\n  EASTL uses templates, type_traits, iterator categories, redundancy reduction, and branch reduction in order to achieve optimal performance. A side effect of this is that there are sometimes a lot of template parameters and multiple levels of function calls due to template specialization. The ironic thing about this is that this makes the code (an optimized build, at least) go faster, not slower. In an optimized build the compiler will see through the calls and template parameters and generate a direct optimized inline version.</p>\n<p class=\"faq-answer\">As an example of this, take a look at the implementation of the <span style=\"font-style: italic;\">copy</span> implementation in algorithm.h. If you are copying an array of scalar values or other trivially copyable values, the compiler will see how the code directs this to the memcpy function and will generate nothing but a memcpy in the final code. For non-memcpyable data types the compiler will automatically understand that in do the right thing.</p>\n<p class=\"faq-answer\">EASTL's primary objective is maximal performance, and it has been deemed worthwhile to make the code a little less obvious in order to achieve this goal. Every case where EASTL does something in an indirect way is by design and usually this is for the purpose of achieving the highest possible performance.</p>\n<p class=\"faq-question\"><a name=\"Debug.4\"></a>Debug.4\nWhen I get compilation errors, they are very long and complicated looking. What do I do?</p>\n<p class=\"faq-answer\">Assuming the bugs are all worked out of EASTL, these errors really do indicate that you have something wrong. EASTL is intentionally very strict about types, as it tries to minimize the chance of users errors. Unfortunately, there is no simple resolution to the problem of long compiler errors other than to deal with them. On the other hand, once you've dealt with them a few times, you tend to realize that most of time they are the same kinds of errors and<br>\n<br>\nTop five approaches to dealing with long compilation errors:</p>\n<ol>\n  <li>Look at the line where the compilation error occurred and ignore the text of the error and just look at obvious things that might be wrong.</li>\n  <li>Consider the most common typical causes of templated compilation errors and consider if any of these might be your problem. Usually one of them are.</li>\n  <li>Either read through the error (it's not as hard as it may look on the surface) or copy the error to a text file and remove the extraneous</li>\n  <li>Compile the code under GCC instead of MSVC, as GCC warnings and errors tend to be more helpful than MSVC's. Possibly also consider compiling an isolated version under Comeau C++'s free online compiler at www.comeaucomputing.com or the Dinkumware online compiler at http://dinkumware.com/exam/.&nbsp;</li>\n  <li>Try using an STL filter (http://www.bdsoft.com/tools/stlfilt.html) which automatically boils down template errors to simpler forms. We haven't tried this yet with EASTL. Also there is the more generic TextFilt (http://textfilt.sourceforge.net/).</li>\n</ol>\n<p class=\"faq-answer\">Top five causes of EASTL compilation errors:</p>\n<ol>\n  <li>const-correctness. Perhaps a quarter of container template errors are due to the user not specifying const correctly.</li>\n  <li>Missing hash function. hash_map, hash_set, etc. require that you either specify a hash function or one exists for your class. See functional.h for examples of declarations of hash functions for common data types.</li>\n  <li>Missing operators. Various containers and algorithms require that certain operators exist for your contained classes. For example, list requires that you can test contained objects for equivalence (i.e. operator==), while map requires that you can test contained objects for \"less-ness\" (operator &lt;). If you define a Widget class and don't have a way to compare two Widgets, you will get errors when trying to put them into a map.</li>\n  <li>Specifying the wrong data type. For example, it is a common mistake to forget that when you insert into a map, you need to insert a pair of objects and not just your key or value type.</li>\n  <li>Incorrect template parameters. When declaring a template instantiation (e.g. map&lt;int, int, less&lt;int&gt; &gt;) you simply need to get the template parameters correct. Also note that when you have \"<span style=\"font-family: Courier New;\">&gt;&gt;</span>\" next to each other that you need to separate them by one space (e.g. \"<span style=\"font-family: Courier New;\">&gt; &gt;</span>\").</li>\n</ol>\n<p class=\"faq-question\"><a name=\"Debug.5\"></a>Debug.5\nHow do I measure hash table balancing?</p>\n<p class=\"faq-answer\">The following functionality lets you spelunk hash container layout.</p>\n<ul>\n  <li>There is the load_factor function which tells you the overall hashtable load, but doesn't tell you if a load is unevenly distributed.</li>\n  <li>You can control the load factor and thus the automated bucket redistribution with set_load_factor.</li>\n  <li>The local_iterator begin(size_type n) and local_iterator end(size_type) functions lets you iterate each bucket individually. You can use this to examine the elements in a bucket.</li>\n  <li>You can use the above to get the size of any bucket, but there is also simply the bucket_size(size_type n) function.</li>\n  <li>The bucket_count function tells you the count of buckets. So with this you can completely visualize the layout of the hash table.</li>\n  <li>There is also iterator find_by_hash(hash_code_t c), for what it's worth.</li>\n</ul>\n<p class=\"faq-answer\">The following function draws an ASCII bar graph of the hash table for easy visualization of bucket distribution:</p>\n<blockquote>\n  <p><font face=\"Courier New\" size=\"1\">#include &lt;EASTL/hash_map.h&gt;<br>\n    #include &lt;EASTL/algorithm.h&gt;<br>\n    #include &lt;stdio.h&gt;<br>\n    <br>\n    template &lt;typename HashTable&gt;<br>\n    void VisualizeHashTableBuckets(const HashTable&amp; h)<br>\n    {<br>\n&nbsp;&nbsp;&nbsp; eastl_size_t bucketCount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = h.bucket_count();<br>\n&nbsp;&nbsp;&nbsp; eastl_size_t largestBucketSize = 0;<br>\n    <br>\n&nbsp;&nbsp;&nbsp; for(eastl_size_t i = 0; i &lt; bucketCount; i++)<br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; largestBucketSize = eastl::max_alt(largestBucketSize, h.bucket_size(i));<br>\n    <br>\n&nbsp;&nbsp;&nbsp; YourPrintFunction(&quot;\\n --------------------------------------------------------------------------------\\n&quot;);<br>\n     <br>\n&nbsp;&nbsp;&nbsp; for(eastl_size_t i = 0; i &lt; bucketCount; i++)<br>\n&nbsp;&nbsp;&nbsp; {<br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const eastl_size_t k = h.bucket_size(i) * 80 / largestBucketSize;<br>\n    <br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char buffer[16];<br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(buffer, &quot;%3u|&quot;, (unsigned)i);<br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; YourPrintFunction(buffer);<br>\n    <br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(eastl_size_t j = 0; j &lt; k; j++)<br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; YourPrintFunction(&quot;*&quot;);<br>\n    <br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; YourPrintFunction(&quot;\\n&quot;);<br>\n&nbsp;&nbsp;&nbsp; }<br>\n    <br>\n&nbsp;&nbsp;&nbsp; YourPrintFunction(&quot; --------------------------------------------------------------------------------\\n&quot;);<br>\n    }</font></p>\n</blockquote>\n<p class=\"faq-answer\"> This results in a graph that looks like the following (with one horizontal bar per bucket). This hashtable has a large number of collisions in each of its 10 buckets.\n<blockquote>\n  <p><font face=\"Courier New\" size=\"2\">&nbsp;&nbsp; ------------------------------------------------------<br>\n&nbsp;0|********************************************<br>\n&nbsp;1|************************************************<br>\n&nbsp;2|***************************************<br>\n&nbsp;3|********************************************<br>\n&nbsp;4|*****************************************************<br>\n&nbsp;5|*************************************************<br>\n&nbsp;6|****************************************<br>\n&nbsp;7|***********************************************<br>\n&nbsp;8|********************************************<br>\n&nbsp;9|**************************************<br>\n    10|********************************************<br>\n&nbsp;&nbsp; -----------------------------------------------------</font>\n</blockquote>\n<h2>  Containers</h2>\n<p class=\"faq-question\"><a name=\"Cont.1\"></a>Cont.1\nWhy do some containers have \"fixed\" versions (e.g. fixed_list) but others(e.g. deque) don't have fixed versions?</p>\n<p class=\"faq-answer\">Recall that fixed containers are those that are implemented via a single contiguous block of memory and don't use a general purpose heap to allocate memory from. For example, fixed_list is a list container that implements its list by a user-configurable fixed block of memory. Such containers have an upper limit to how many items they can hold, but have the advantage of being more efficient with memory use and memory access coherency.</p>\n<p class=\"faq-answer\">The reason why some containers don't have fixed versions is that such functionality doesn't make sense with these containers. Containers which don't have fixed versions include:</p>\n<pre class=\"code-example\">array, deque, bitset, stack, queue, priority_queue,\nintrusive_list, intrusive_hash_map, intrusive_hash_set,\nintrusive_hash_multimap, intrusive_hash_multimap,\nvector_map, vector_multimap, vector_set, vector_multiset.</pre>\n<p class=\"faq-answer\">Some of these containers are adapters which wrap other containers and thus there is no need for a fixed version because you can just wrap a fixed container. In the case of intrusive containers, the user is doing the allocation and so there are no memory allocations. In the case of array, the container is a primitive type which doesn't allocate memory. In the case of deque, it's primary purpose for being is to dynamically resize and thus the user would likely be better of using a fixed_vector.</p>\n<p class=\"faq-question\">  <a name=\"Cont.2\"></a>Cont.2\nCan I mix EASTL with standard C++ STL?</p>\n<p class=\"faq-answer\">This is possible to some degree, though the extent depends on the implementation of C++ STL. One of things that makes interoperability is something called iterator categories. Containers and algorithms recognize iterator types via their category and STL iterator categories are not recognized by EASTL and vice versa.</p>\n<p class=\"faq-answer\">Things that you definitely can do:</p>\n<ul>\n  <li>#include both EASTL and standard STL headers from the same .cpp file.</li>\n  <li>Use EASTL containers to hold STL containers.</li>\n  <li>Construct an STL reverse_iterator from an EASTL&nbsp;iterator.</li>\n  <li>Construct an EASTL reverse_iterator from an&nbsp;STL&nbsp;iterator.</li>\n</ul>\n<p class=\"faq-answer\">Things that you probably will be able to do, though a given std STL implementation may prevent it:\n</p>\n<ul>\n  <li>Use STL containers in EASTL algorithms.</li>\n  <li>Use EASTL containers in STL algorithms.</li>\n  <li>Construct or assign to an STL container via iterators into an EASTL container.</li>\n  <li>Construct or assign to an EASTL container via iterators into an&nbsp;STL container.</li>\n</ul>\n<p class=\"faq-answer\">Things that you would be able to do if the given std STL implementation is bug-free:\n</p>\n<ul>\n  <li>Use STL containers to hold EASTL containers. Unfortunately, VC7.x STL has a confirmed bug that prevents this. Similarly, STLPort versions prior to v5 have a similar but.</li>\n</ul>\n<p class=\"faq-answer\">Things that you definitely can't do:\n</p>\n<ul>\n  <li>Use an STL allocator directly with an EASTL container (though you can use one indirectly).</li>\n  <li>Use an EASTL allocator directly with an STL container (though you can use one indirectly).</li>\n</ul>\n<p class=\"faq-question\">  <a name=\"Cont.3\"></a>Cont.3\nWhy are there so many containers?</p>\n<p class=\"faq-answer\">EASTL has a large number of container types (e.g vector, list, set) and often has a number of variations of given types (list, slist, intrusive_list, fixed_list). The reason for this is that each container is tuned and to a specific need and there is no single container that works for all needs. The more the user is concerned about squeezing the most performance out of their system, the more the individual container variations become significant. It's important to note that having additional container types generally does not mean generating additional code or code bloat. Templates result in generated code regardless of what templated class they come from, and so for the most part you get optimal performance by choosing the optimal container for your needs.</p>\n<p class=\"faq-question\">  <a name=\"Cont.4\"></a>Cont.4\nDon't STL and EASTL containers fragment memory?</p>\n<p class=\"faq-answer\">They only fragment memory if you use them in a way that does so. This is no different from any other type of container used in a dynamic way. There are various solutions to this problem, and EASTL provides additional help as well:</p>\n<ul>\n  <li>For vectors, use the reserve function (or the equivalent constructor) to set aside a block of memory for the container. The container will not reallocate memory unless you try grow beyond the capacity you reserve.</li>\n  <li>EASTL has \"fixed\" variations of containers which allow you to specify a fixed block of memory which the container uses for its memory. The container will not allocate any memory with these types of containers and all memory will be cache-friendly due to its locality.</li>\n  <li>You can assign custom allocators to containers instead of using the default global allocator. You would typically use an allocator that has its own private pool of memory.</li>\n  <li>Where possible, add all a container's elements to it at once up front instead of adding them over time. This avoids memory fragmentation and increase cache coherency.</li>\n</ul>\n<p class=\"faq-question\"><a name=\"Cont.5\"></a>Cont.5\n  I don't see container optimizations for equivalent scalar types such\nas pointer types. Why?</p>\n<p>Metrowerks (and no other, as of this writing) STL has some container specializations for type T* which maps them to type void*. The idea is that a user who declares a list of Widget* and a list of Gadget* will generate only one container: a list of void*. As a result, code generation will be smaller. Often this is done only in optimized builds, as such containers are harder to view in debug builds due to type information being lost.<br>\n<br>\nThe addition of this optimization is under consideration for EASTL, though it might be noted that optimizing compilers such as VC++ are already capable of recognizing duplicate generated code and folding it automatically as part of link-time code generation (LTCG) (a.k.a. \"whole program optimization\"). This has been verified with VC++, as the following code and resulting disassembly demonstrate:</p>\n<pre class=\"code-example\">eastl::list&lt;int*&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intPtrList;\neastl::list&lt;TestObject*&gt; toPtrList;\n\neastl_size_t n1 = intPtrList.size();\neastl_size_t n2 = toPtrList.size();\n\n0042D288&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edx,[esp+14h]\n0042D28C&nbsp; <span style=\"color: rgb(51, 51, 255);\">call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eastl::list&lt;TestObject&gt;::size (414180h)</span>\n0042D291&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax&nbsp;\n0042D292&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edx,[esp+24h]\n0042D296&nbsp; <span style=\"color: rgb(51, 51, 255);\">call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eastl::list&lt;TestObject&gt;::size (414180h)</span></pre>\nNote that in the above case the compiler folded the two implementations of size() into a single implementation.<br>\n<p class=\"faq-question\"><a name=\"Cont.6\"></a>Cont.6\nWhat about alternative container and algorithm implementations (e.g. treaps, skip lists, avl trees)?</p>\n<p class=\"faq-answer\">EASTL chooses to implement some alternative containers and algorithms and not others. It's a matter of whether or not the alternative provides truly complementary or improved functionality over existing containers. The following is a list of some implemented and non-implemented alternatives and the rationale behind each:</p>\n<p class=\"faq-answer\">Implemented:</p>\n<ul>\n  <li>intrusive_list, etc. -- Saves memory and improves cache locality.</li>\n  <li>vector_map, etc. -- Saves memory and improves cache locality.</li>\n  <li>ring_buffer -- Useful for some types of operations and has no alternative.</li>\n  <li>shell_sort -- Useful sorting algorithm.</li>\n  <li>sparse_matrix -- Useful for some types of operations and has no alternative.</li>\n</ul>\n<p class=\"faq-answer\">Not implemented:\n</p>\n<ul>\n  <li>skip lists (alternative to red-black tree) -- These use more memory and usually perform worse than rbtrees.</li>\n  <li>treap (alternative to red-black tree) -- These are easier and smaller than rbtrees, but perform worse.</li>\n  <li>avl tree (alternative to red-black tree) -- These have slightly better search performance than rbtrees, but significantly worse insert/remove performance.</li>\n  <li>btree (alternative to red-black tree) --&nbsp; These are no better than rbtrees.</li>\n</ul>\n<p class=\"faq-answer\">If you have an idea of something that should be implemented, please suggest it or even provide at least a prototypical implementation.</p>\n<p class=\"faq-question\"><a name=\"Cont.7\"></a>Cont.7\nWhy are tree-based EASTL containers hard to read with a debugger?</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Short answer<br>\n</span> Maximum performance and design mandates.</p>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Long answer</span><br>\nYou may notice that when you have a tree-based container (e.g. set, map)&nbsp; in the debugger that it isn't automatically able to recognize the tree nodes as containing instances of your contained object. You can get the debugger to do what you want with casting statements in the debug watch window, but this is not an ideal solution. The reason this is happening is that node-based containers always use an anonymous node type as the base class for container nodes. This is primarily done for performance, as it allows the node manipulation code to exist as a single non-templated library of functions and it saves memory because containers will have one or two base nodes as container 'anchors' and you don't want to allocate a node of the size of the user data when you can just use a base node. See list.h for an example of this and some additional in-code documentation on this.</p>\n<p class=\"faq-answer\">Additionally, EASTL has the design mandate that an empty container constructs no user objects. This is both for performance reasons and because it doing so would skew the user's tracking of object counts and might possibly break some expectation the user has about object lifetimes.</p>\n<p class=\"faq-answer\">Currently this debug issue exists only with tree-based containers. Other node-based containers such as list and slist use a trick to get around this problem in debug builds.</p>\n<p class=\"faq-question\"><a name=\"Cont.8\"></a>Cont.8\nHow do I assign a custom allocator to an EASTL container?</p>\n<p class=\"faq-answer\">There are two ways of doing this:</p>\n<ol>\n  <li>Use the set_allocator function that is present in each container.</li>\n  <li>Specify a new allocator type via the Allocator template parameter that is present in each container.</li>\n</ol>\n<p class=\"faq-answer\">For item #1, EASTL expects that you provide an instance of an allocator of the type that EASTL recognizes. This is simple but has the disadvantage that all such allocators must be of the same class. The class would need to have C++ virtual functions in order to allow a given instance to act differently from another instance.</p>\n<p class=\"faq-answer\">For item #2, you specify that the container use your own allocator class. The advantage of this is that your class can be implemented any way you want and doesn't require virtual functions for differentiation from other instances. Due to the way C++ works your class would necessarily have to use the same member function names as the default allocator class type. In order to make things easier, we provide a skeleton allocator here which you can copy and fill in with your own implementation.</p>\n<pre class=\"code-example\">class custom_allocator\n{\npublic:\n&nbsp;&nbsp;&nbsp; custom_allocator(const char* pName = EASTL_NAME_VAL(\"custom allocator\"))\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #if EASTL_NAME_ENABLED\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Possibly do something here.\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; custom_allocator(const allocator&amp; x, const char* pName = EASTL_NAME_VAL(\"custom allocator\"));\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #if EASTL_NAME_ENABLED\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Possibly copy from x here.\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; ~custom_allocator();\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Possibly do something here.\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; custom_allocator&amp; operator=(const custom_allocator&amp; x)\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Possibly copy from x here.\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; void* allocate(size_t n, int flags = 0)\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Implement the allocation here.\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0)\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Implement the allocation here.\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; void deallocate(void* p, size_t n)\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Implement the deallocation here.\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; const char* get_name() const\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #if EASTL_NAME_ENABLED\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return mpName;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #else\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return \"custom allocator\";\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; void set_name(const char* pName)\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #if EASTL_NAME_ENABLED\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mpName = pName;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif\n&nbsp;&nbsp;&nbsp; }\n\nprotected:\n&nbsp;&nbsp;&nbsp; // Possibly place instance data here.\n\n&nbsp;&nbsp;&nbsp; #if EASTL_NAME_ENABLED\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const char* mpName; // Debug name, used to track memory.\n&nbsp;&nbsp;&nbsp; #endif\n};\n\n\ninline bool operator==(const allocator&amp; a, const allocator&amp; b)\n{\n&nbsp;&nbsp;&nbsp; // Provide a comparison here.\n}\n\ninline bool operator!=(const allocator&amp; a, const allocator&amp; b)\n{\n&nbsp;&nbsp;&nbsp; // Provide a negative comparison here.\n}</pre>\n<p class=\"faq-answer\">  Here's an example of how to use the above custom allocator:</p>\n<pre class=\"code-example\">// Declare a Widget list and have it default construct.\nlist&lt;Widget, custom_allocator&gt; widgetList;\n\n// Declare a Widget list and have it construct with a copy of some global allocator.\nlist&lt;Widget, custom_allocator&gt; widgetList2(gSomeGlobalAllocator);\n\n// Declare a Widget list and have it default construct, but assign\n// an underlying implementation after construction.\nlist&lt;Widget, custom_allocator&gt; widgetList;\nwidgetList.get_allocator().mpIAllocator = new WidgetAllocatorImpl;</pre>\n\n<p class=\"faq-question\"><a name=\"Cont.9\"></a>Cont.9 How do I set the VC++ debugger to display EASTL container data with tooltips?</p>\n<p class=\"faq-answer\">Visual Studio supports this via the AutoExp.dat file, an example of which is <a href=\"AutoExp.dat\">present</a> with this documentation. </p>\n<p class=\"faq-answer\">Sometimes the AutoExp.dat doesn't seem to work. Avery Lee's explanation:</p>\n<blockquote>\n  <p class=\"faq-answer style5\"> If I had to take a guess, the problem is most likely in the cast to the concrete node type. These are always tricky because, for some strange reason, the debugger is whitespace sensitive with regard to specifying template types. You might try manually checking one of the routines of the specific map instantiation and checking that the placement of whitespace and const within the template expression still matches exactly. In some cases the compiler uses different whitespace rules depending on the value type which makes it impossible to correctly specify a single visualizer &ndash; this was the case for eastl::list&lt;&gt;, for which I was forced to include sections for both cases. The downside is that you have a bunch of (error) entries either way. </p>\n</blockquote>\n<p class=\"faq-question\">  <a name=\"Cont.10\"></a>Cont.10\nHow do I use a memory pool with a container?</p>\n<p class=\"faq-answer\">Using custom memory pools is a common technique for decreasing memory fragmentation and increasing memory cache locality. EASTL gives you the flexibility of defining your own memory pool systems for containers. There are two primary ways of doing this:</p>\n<ul>\n  <li>Assign a custom allocator to a container. eastl::fixed_pool provides an implementation.</li>\n  <li>Use one of the EASTL fixed containers, such as fixed_list.</li>\n</ul>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Custom Allocator</span><br>\nIn the custom allocator case, you will want to create a memory pool and assign it to the container. For purely node-based containers such as list, slist, map, set, multimap, and multiset, your pool simply needs to be able to allocate list nodes. Each of these containers has a member typedef called node_type which defines the type of node allocated by the container.&nbsp;So if you have a memory pool that has a constructor that takes the size of pool items and the count of pool items, you would do this (assuming that MemoryPool implements the Allocator interface):</p>\n<pre class=\"code-example\">typedef list&lt;Widget, MemoryPool&gt; WidgetList;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Declare your WidgetList type.\n\nMemoryPool myPool(sizeof(WidgetList::node_type), 100); // Make a pool of 100 Widget nodes.\nWidgetList myList(&amp;myPool);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create a list that uses the pool.</pre>\n<p class=\"faq-answer\">In the case of containers that are array-based, such as vector and basic_string, memory pools don't work very well as these containers work on a realloc-basis instead of by adding incremental nodes. What we want to do with these containers is assign a sufficient block of memory to them and&nbsp;reserve() the container's capacity to the size of the memory.</p>\n<p class=\"faq-answer\">In the case of mixed containers which are partly array-based and partly node-based, such as hash containers and deque, you can use a memory pool for the nodes but will need a single array block to supply for the buckets (hash containers and deque both use a bucket-like system).</p>\n<p class=\"faq-answer\">You might consider using eastl::fixed_pool as such an allocator, as it provides such functionality and allows the user to provide the actual memory used for the pool. Here is some example code:</p>\n<pre class=\"code-example\">char buffer[256];\n\nlist&lt;Widget, fixed_pool&gt;&nbsp;myList;\nmyList.get_allocator().init(buffer, 256);</pre>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">Fixed Container</span><br>\nIn the fixed container case, the container does all the work for you. To use a list which implements a private pool of memory, just declare it like so:</p>\n<pre class=\"code-example\">fixed_list&lt;Widget, 100&gt; fixedList; // Declare a fixed_list that can hold 100 Widgets</pre>\n<p class=\"faq-question\"><a name=\"Cont.11\"></a>Cont.11\nHow do I write a comparison (operator&lt;()) for a struct that contains two or more members?&nbsp;</p>\n<p class=\"faq-answer\">See <a href=\"#Algo.2\">Algo.2</a></p>\n<p class=\"faq-question\">  <a name=\"Cont.12\"></a>Cont.12\nWhy doesn't container X have member function Y?</p>\n<p class=\"faq-answer\">Why don't the list or vector containers have a find() function? Why doesn't the vector container have a sort() function? Why doesn't the string container have a mid() function? These are common examples of such questions.</p>\n<p class=\"faq-answer\">The answer usually boils down to two reasons:</p>\n<ul>\n  <li>The functionality exists in a more centralized location elsewhere, such as the algorithms.</li>\n  <li>The functionality can be had by using other member functions.</li>\n</ul>\n<p class=\"faq-answer\">In the case of find and sort functions not being part of containers, the find algorithm and sort algorithm are centralized versions that apply to <span style=\"font-style: italic;\">any</span> container. Additionally, the algorithms allow you to specify a sub-range of the container on which to apply the algorithm. So in order to find an element in a list, you would do this:<br>\n</p>\n<div class=\"code-example\">list&lt;int&gt;::iterator i =&nbsp;find(list.begin(), list.end(), 3);</div>\n<p class=\"faq-answer\">And in order to sort a vector, you would do this:<br>\n</p>\n<div class=\"code-example\">quick_sort(v.begin(), v.end()); &nbsp; // Sort the entire array.\n  <br>\nquick_sort(&amp;v[3], &amp;v[8]); &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Sort the items at the indexes in the range of [3, 8).</div>\n<p class=\"faq-answer\">In the case of functionality that can be had by using other member functions, \nnote that EASTL follows the philosophy that duplicated functionality should not exist in a container, \nwith exceptions being made for cases where mistakes and unsafe practices commonly happen if the given \nfunction isn't present. In the case of string not having a mid function, this is because there is a \nstring constructor that takes a sub-range of another string. So to make a string out of the middle of \nanother, you would do this:</p>\n<pre class=\"code-example\">string strMid(str, 3, 5); // Make a new string of the characters from the source range of [3, 3+5).</pre>\n<p class=\"faq-answer\">  It might be noted that the EASTL string class is unique among EASTL containers in that it sometimes violates the minimum functionality rule. This is so because the std C++ string class similarly does so and EASTL aims to be compatible.</p>\n<p class=\"faq-question\"><a name=\"Cont.13\"></a>Cont.13\nHow do I search a hash_map of strings via a char pointer efficiently? If I use map.find(\"hello\") it creates a temporary string, which is inefficient.</p>\n<p class=\"faq-answer\">The problem is illustrated with this example:</p>\n<pre class=\"code-example\">map&lt;string, Widget&gt; swMap;\n  ...\nmap&lt;string, Widget&gt;::iterator it = swMap.find(\"blue\"); // A temporary string object is created here.</pre>\n<p class=\"faq-answer\">In this example, the find function expects a string object and not a string literal and so (silently!) creates a temporary string object for the duration of the find. There are two solutions to this problem:\n</p>\n<ul>\n  <li>Make the map a map of char pointers instead of string objects. Don't forget to write a custom compare or else the default comparison function will compare pointer values instead of string contents.</li>\n  <li>Use the EASTL hash_map::find_as function, which allows you to find an item in a hash container via an alternative key than the one the hash table uses.</li>\n</ul>\n<p class=\"faq-question\"><a name=\"Cont.14\"></a>Cont.14\nWhy are set and hash_set iterators const (i.e. const_iterator)?</p>\n<p class=\"faq-answer\">The situation is illustrated with this example:</p>\n<pre class=\"code-example\">set&lt;int&gt; intSet;\n\nintSet.insert(1);\nset&lt;int&gt;::iterator i = intSet.begin();\n*i = 2; // Error: iterator i is const.</pre>\n<p class=\"faq-answer\">In this example, the iterator is a regular iterator and not a const_iterator, yet the compiler gives an error when trying to change the iterator value. The reason this is so is that a set is an ordered container and changing the value would make it out of order. Thus, set and multiset iterators are always const_iterators. If you need to change the value and are sure the change will not alter the container order, use const_cast or declare mutable member variables for your contained object. This resolution is the one blessed by the C++ standardization committee.</p>\n\n<p class=\"faq-question\"><a name=\"Cont.15\"></a>Cont.15\nHow do I prevent my hash container from re-hashing?</p>\n<p class=\"faq-answer\">If you want to make a hashtable never re-hash (i.e. increase/reallocate its bucket count), \ncall set_max_load_factor with a very high value such as 100000.f.</p>\n<p class=\"faq-answer\">Similarly, you can control the bucket growth factor with the rehash_policy function. \nBy default, when buckets reallocate, they reallocate to about twice their previous count. \nYou can control that value as with the example code here:</p>\n<pre class=\"code-example\">hash_set&lt;int&gt; hashSet;\nhashSet.rehash_policy().mfGrowthFactor = 1.5f</pre>\n\n<p class=\"faq-question\">\n  <a name=\"Cont.16\"></a>Cont.16\nWhich uses less memory, a map or a hash_map?\n</p>\n<p class=\"faq-answer\">A hash_map will virtually always use less memory. A hash_map will use an average of two pointers per stored element, while a map uses three pointers per stored element.</p>\n<p class=\"faq-question\">  <a name=\"Cont.17\"></a>Cont.17\nHow do I write a custom hash function?</p>\n<p class=\"faq-answer\">You can look at the existing hash functions in functional.h, but we provide a couple examples here.</p>\n<p class=\"faq-answer\">To write a specific hash function for a Widget class, you would do this:</p>\n<pre class=\"code-example\">struct WidgetHash {\n&nbsp; &nbsp; size_t operator()(const Widget&amp; w) const\n&nbsp; &nbsp; &nbsp; &nbsp; { return w.id; }\n};\n\nhash_set&lt;Widget, WidgetHash&gt; widgetHashSet;</pre>\n<p class=\"faq-answer\">To write a generic (templated) hash function for a set of similar classes (in this case that have an id member), you would do this:<br>\n</p>\n<pre class=\"code-example\">template &lt;typename T&gt;\nstruct GeneralHash {\n&nbsp; &nbsp; size_t operator()(const T&amp; t) const\n&nbsp; &nbsp; &nbsp; &nbsp; { return t.id; }\n};\n\nhash_set&lt;Widget,&nbsp;GeneralHash&lt;Widget&gt; &gt; widgetHashSet;\nhash_set&lt;Dogget,&nbsp;GeneralHash&lt;Dogget&gt; &gt; doggetHashSet;</pre>\n\n<p class=\"faq-question\">  <a name=\"Cont.18\"></a>Cont.18\nHow do I write a custom compare function for a map or set?</p>\n<p class=\"faq-answer\">  The sorted containers require that an operator&lt; exist for the stored values or that the user provide a suitable custom comparison function. A custom can be implemented like so:<br>\n</p>\n<div class=\"code-example\">struct WidgetLess {\n&nbsp; &nbsp; bool operator()(const Widget&amp; w1, const Widget&amp; w2) const\n&nbsp; &nbsp; &nbsp; &nbsp; { return w.id &lt; w2.id; }\n};\n\nset&lt;Widget, WidgetLess&gt; wSet;</div>\n<p class=\"faq-answer\">It's important that your comparison function must be consistent in its behaviour, else the container will either be unsorted or a crash will occur. This concept is called \"strict weak ordering.\"</p>\n<p class=\"faq-question\"><a name=\"Cont.19\"></a>Cont.19\nHow do I force my vector or string capacity down to the size of the container?</p>\n<p class=\"faq-answer\">You can simply use the set_capacity() member function which is present in both vector and string. This is a function that is not present in std STL vector and string functions.</p>\n<pre class=\"code-example\">eastl::vector&lt;Widget&gt; x;\nx.set_capacity(); &nbsp; // Shrink x's capacity to be equal to its size.\n\neastl::vector&lt;Widget&gt; x;\nx.set_capacity(0); &nbsp;// Completely clear x.</pre>\n<p>  To compact your vector or string in a way that would also work with std STL you need to do the following.</p>\n<p> How to shrink a vector's capacity to be equal to its size:</p>\n<pre class=\"code-example\">std::vector&lt;Widget&gt; x;\nstd::vector&lt;Widget&gt;(x).swap(x); // Shrink x's capacity.</pre>\nHow to completely clear a std::vector (size = 0, capacity = 0, no allocation):<br>\n<pre class=\"code-example\">std::vector&lt;Widget&gt; x;\nstd::vector&lt;Widget&gt;().swap(x); // Completely clear x.\n</pre>\n<p class=\"faq-question\">    <a name=\"Cont.20\"></a>Cont.20\nHow do I iterate a container while (selectively) removing items from it?</p>\n<p class=\"faq-answer\">All EASTL containers have an erase function which takes an iterator as an argument and returns an iterator to the next item. Thus, you can erase items from a container while iterating it like so:</p>\n<pre class=\"code-example\">set&lt;int&gt; intSet;<br>\nset&lt;int&gt;::iterator i = intSet.begin();<br>\nwhile(i != intSet.end())\n{\n    if(*i &amp; 1) &nbsp;<span class=\"code-example-comment\">// Erase all odd integers from the container.</span>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i = intSet.erase(i);\n&nbsp;&nbsp;&nbsp; else\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++i;\n}</pre>\n<p class=\"faq-question\"><a name=\"Cont.21\"></a>Cont.21\nHow do I store a pointer in a container?</p>\n<p class=\"faq-answer\">    The problem with storing pointers in containers is that clearing the container will not\nfree the pointers automatically. There are two conventional resolutions to this problem:</p>\n<ul>\n  <li>Manually free pointers when removing them from containers.&nbsp;</li>\n  <li>Store the pointer as a smart pointer instead of a \"raw\"pointer.</li>\n</ul>\n<p class=\"faq-answer\">The advantage of the former is that it makes the user's intent obvious and prevents the possibility of smart pointer \"thrashing\" with some containers. The disadvantage of the former is that it is more tedicous and error-prone.</p>\n<p class=\"faq-answer\">The advantage of the latter is that your code will be cleaner and will always be error-free. The disadvantage is that it is perhaps slightly obfuscating and with some uses of some containers it can cause smart pointer thrashing, whereby a resize of a linear container (e.g. vector) can cause shared pointers to be repeatedly incremented and decremented with no net effect.</p>\n<p class=\"faq-answer\">It's important that you use a shared smart pointer and not an unshared one such as C++ auto_ptr, as the latter will result in crashes upon linear container resizes. Here we provide an example of how to create a list of smart pointers:</p>\n<pre class=\"code-example\">list&lt; shared_ptr&lt;Widget&gt; &gt; wList;\n\nwList.push_back(shared_ptr&lt;Widget&gt;(new Widget));\nwList.pop_back(); // The Widget will be freed.</pre>\n<p class=\"faq-question\"><a name=\"Cont.22\"></a>Cont.22\nHow do I make a union of two containers? difference? intersection?</p>\n<p class=\"faq-answer\">The best way to accomplish this is to sort your container (or use a sorted container such as set) and then apply the set_union, set_difference, or set_intersection algorithms.</p>\n<p class=\"faq-question\"><a name=\"Cont.23\"></a>Cont.23\nHow do I override the default global allocator?&nbsp;</p>\n<p class=\"faq-answer\">There are multiple ways to accomplish this. The allocation mechanism is defined in EASTL/internal/config.h and in allocator.h/cpp. Overriding the default global allocator means overriding these files, overriding what these files refer to, or changing these files outright. Here is a list of things you can do, starting with the simplest:</p>\n<ul>\n  <li>Simply provide the following versions of operator new (which EASTL requires, actually):<br>\n      <small><span style=\"font-family: Helvetica,Arial,sans-serif;\">&nbsp;&nbsp;&nbsp; void* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);</span><br style=\n\"font-family: Helvetica,Arial,sans-serif;\">\n    <span style=\"font-family: Helvetica,Arial,sans-serif;\">&nbsp;&nbsp;&nbsp; void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);</span></small></li>\n  <li>Predefine the config.h macros for EASTLAlloc, EASTLFree, etc.&nbsp;See config.h for this.</li>\n  <li>Override config.h entirely via EASTL_USER_CONFIG_HEADER. See config.h for this.</li>\n  <li>Provide your own version of allocator.h/cpp</li>\n  <li>Provide your own version of config.h.&nbsp;</li>\n</ul>\n<p class=\"faq-answer\">If you redefine the allocator class, you can make it work however you want.</p>\n<p class=\"faq-answer\">Note that config.h defines EASTLAllocatorDefault, which returns the default allocator instance. As documented in config.h, this is not a global allocator which implements all container allocations but is the allocator that is used when EASTL needs to allocate memory internally. There are very few cases where EASTL allocates memory internally, and in each of these it is for a sensible reason that is documented to behave as such.</p>\n<p class=\"faq-question\">  <a name=\"Cont.24\"></a>Cont.24\nHow do I do trick X with the string container?</p>\n<p class=\"faq-answer\">There seem to be many things users want to do with strings. Perhaps the most commonly requested EASTL container extensions are string class shortcut functions. While some of these requests are being considered, we provide some shortcut functions here.<br>\n<br>\n<span style=\"font-weight: bold;\">find_and_replace</span></p>\n<pre class=\"code-example\">template &lt;typename String&gt;\nvoid find_and_replace(String&amp; s, const typename String::value_type* pFind,&nbsp;const typename String::value_type* pReplace)&nbsp;&nbsp;&nbsp;&nbsp;\n{\n    for(size_t i; (i = source.find(pFind)) != T::npos; )\n    &nbsp;&nbsp;&nbsp; s.replace(i, eastl::CharStrlen(pFind),&nbsp;pReplace);\n}\n\nExample:<span class=\"style1\">\n</span>    find_and_replace(s, \"hello\", \"hola\");</pre>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">trim front</span> (multiple chars)</p>\n<pre class=\"code-example\">template &lt;typename String&gt;\nvoid trim_front(String&amp; s, const typename String::value_type* pValues)\n{\n&nbsp; &nbsp; s.erase(0, s.find_first_not_of(pValues));\n}\n\nExample:\n    trim_front(s, \" \\t\\n\\r\");</pre>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">trim back</span> (multiple chars)</p>\n<pre class=\"code-example\">template &lt;typename String&gt;\nvoid trim_front(String&amp; s, const typename String::value_type* pValues)\n{\n&nbsp; &nbsp; s.resize(s.find_last_not_of(pValues) + 1);\n}\n\nExample:\n    trim_back(s, \" \\t\\n\\r\");</pre>\n<p class=\"faq-answer\">prepend</p>\n<pre class=\"code-example\">template &lt;typename String&gt;\nvoid prepend(String&amp; s, const typename String::value_type* p)\n{\n&nbsp;&nbsp;&nbsp; s.insert(0,&nbsp;p);\n}\n\nExample:\n    prepend(s, \"log: \");</pre>\n<p><span class=\"faq-answer\" style=\"font-weight: bold;\">begins_with</span>\n</p>\n<pre class=\"code-example\">template &lt;typename String&gt;\nbool begins_with(const String&amp; s, const typename String::value_type* p)\n{\n&nbsp; &nbsp; return&nbsp;s.compare(0,&nbsp;eastl::CharStrlen(p), p) == 0;\n}\n\nExample:\n    if(begins_with(s, \"log: \")) ...</pre>\n<p class=\"faq-answer\">ends_with</p>\n<pre class=\"code-example\">template &lt;typename String&gt;\nbool ends_with(const String&amp; s, const typename String::value_type* p)\n{\n&nbsp; &nbsp; const typename String::size_type n1 = s.size();\n&nbsp; &nbsp; const typename String::size_type n2 = eastl::CharStrlen(p);\n&nbsp;&nbsp;&nbsp; return ((n1 &gt;= n2) &amp;&amp; s.compare(n1 - n2, n2, p) == 0);\n}\n\nExample:\n    if(ends_with(s, \"test.\")) ...</pre>\n<p class=\"faq-answer\"><span style=\"font-weight: bold;\">tokenize</span><br>\nHere is a simple tokenization function that acts very much like the C strtok function.&nbsp;</p>\n<pre class=\"code-example\">template &lt;typename String&gt;\nsize_t tokenize(const String&amp; s, const typename String::value_type* pDelimiters,\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String* resultArray, size_t resultArraySize)\n{\n&nbsp;&nbsp;&nbsp; size_t n = 0;\n&nbsp;&nbsp;&nbsp; typename String::size_type lastPos = s.find_first_not_of(pDelimiters, 0);\n&nbsp;&nbsp;&nbsp; typename String::size_type pos &nbsp; &nbsp; = s.find_first_of(pDelimiters, lastPos);\n\n&nbsp;&nbsp;&nbsp; while((n &lt; resultArraySize) &amp;&amp; (pos != String::npos) || (lastPos != String::npos))\n&nbsp;&nbsp;&nbsp; {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resultArray[n++].assign(s, lastPos, pos - lastPos);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastPos = s.find_first_not_of(pDelimiters, pos);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos &nbsp; &nbsp; = s.find_first_of(pDelimiters, lastPos);\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp;&nbsp;return n;\n}\n\nExample:\n   string resultArray[32];\ntokenize(s, \" \\t\", resultArray, 32));</pre>\n   \n<p class=\"faq-question\"><a name=\"Cont.25\"></a>Cont.25 How do EASTL smart pointers compare to Boost smart pointers?&nbsp;</p>\n<p class=\"faq-answer\">EASTL's smart pointers are nearly identical to Boost (including all that crazy member template and dynamic cast functionality in shared_ptr), but are not using the Boost source code. EA legal has already stated that it is fine to have smart pointer classes with the same names and functionality as those present in Boost. EA legal specifically looked at the smart pointer classes in EASTL for this. There are two differences between EASTL smart pointers and Boost smart pointers:</p>\n<ul>\n  <li>EASTL smart pointers don't have thread safety built-in. It was deemed that this is too much overhead and that thread safety is something best done at a higher level. By coincidence the C++ library proposal to add shared_ptr also omits the thread safety feature. FWIW, I put a thread-safe shared_ptr in EAThread, though it doesn't attempt to do all the fancy member template things that Boost shared_ptr does. Maybe I'll add that some day if people care.</li>\n</ul>\n<ul>\n  <li>EASTL shared_ptr object deletion goes through a deletion object instead of through a virtual function interface. 95% of the time this makes no difference (aside from being more efficient), but the primary case where it matters is when you have shared_ptr&lt;void&gt; and assign to is something like \"new Widget\". The problem is that shared_ptr&lt;void&gt; doesn't know what destructor to call and so doesn't call a destructor unless you specify a custom destructor object as part of the template specification. I don't know what to say about this one, as it is less safe, but forcing everybody to have the overhead of additional templated classes and virtual destruction functions doesn't seem to be in the spirit of high performance or lean game development.</li>\n</ul>\n<p class=\"faq-answer\">There is the possibility of making a shared_ptr_boost which is completely identical to Boost shared_ptr. So perhaps that will be done some day.</p>\n<p class=\"faq-question\"><a name=\"Cont.26\"></a>Cont.26\nHow do your forward-declare an EASTL container?</p>\n<p class=\"faq-answer\">Here is are some examples of how to do this:</p>\n<pre class=\"code-example\">namespace eastl\n{\n&nbsp;&nbsp;&nbsp; template &lt;typename T, typename Allocator&gt; class basic_string;\n    typedef basic_string&lt;char, allocator&gt; string8;   <span class=\"code-example-comment\">// Forward declare EASTL's string8 type.</span>\n\n&nbsp;&nbsp;&nbsp; template &lt;typename T, typename Allocator&gt; class vector;\n    typedef vector&lt;char, allocator&gt; CharArray;\n\n&nbsp;&nbsp;&nbsp; template &lt;typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode&gt; class hash_set;\n\n&nbsp;&nbsp;&nbsp; template &lt;typename Key, typename T, typename Compare, typename Allocator&gt; class map;\n}</pre>\n<p class=\"faq-answer\">The forward declaration can be used to declare a pointer or reference to such a class. It cannot be used to declare an instance of a class or refer to class data, static or otherwise. Nevertheless, forward declarations for pointers and references are useful for reducing the number of header files a header file needs to include.</p>\n<p class=\"faq-question\">  <a name=\"Cont.27\" id=\"Cont.27\"></a>Cont.27\nHow do I make two containers share a memory pool?</p>\n<p class=\"faq-answer\">EASTL (and std STL) allocators are specified by value semantics and not reference semantics. Value semantics is more powerful (because a value can also be a reference, but not the other way around), but is not always what people expects if they're used to writing things the other way.</p>\n<p class=\"faq-answer\">Here is some example code:</p>\n<pre class=\"code-example\">struct fixed_pool_reference<br>{<br>public:<br>    fixed_pool_reference()<br>    {<br>        mpFixedPool = NULL;<br>    }<br> <br>    fixed_pool_reference(eastl::fixed_pool&amp; fixedPool)<br>    {<br>        mpFixedPool = &amp;fixedPool;<br>    }<br> <br>    fixed_pool_reference(const fixed_pool_reference&amp; x)<br>    {<br>        mpFixedPool = x.mpFixedPool;<br>    }<br> <br>    fixed_pool_reference&amp; operator=(const fixed_pool_reference&amp; x)<br>    {<br>        mpFixedPool = x.mpFixedPool;<br>        return *this;<br>    }<br> <br>    void* allocate(size_t /*n*/, int /*flags*/ = 0)<br>    {<br>        return mpFixedPool-&gt;allocate();<br>    }<br> <br>    void* allocate(size_t /*n*/, size_t /*alignment*/, size_t /*offset*/, int /*flags*/ = 0)<br>    {<br>        return mpFixedPool-&gt;allocate();<br>    }<br> <br>    void deallocate(void* p, size_t /*n*/)<br>    {<br>        return mpFixedPool-&gt;deallocate(p);<br>    }<br> <br>    const char* get_name() const<br>    {<br>        return &quot;fixed_pool_reference&quot;;<br>    }<br> <br>    void set_name(const char* /*pName*/)<br>    {<br>    }<br> <br>protected:<br>    friend bool operator==(const fixed_pool_reference&amp; a, const fixed_pool_reference&amp; b);<br>    friend bool operator!=(const fixed_pool_reference&amp; a, const fixed_pool_reference&amp; b);<br> <br>    eastl::fixed_pool* mpFixedPool;<br>};\n\ninline bool operator==(const fixed_pool_reference&amp; a, const fixed_pool_reference&amp; b)\n{\n    return (a.mpFixedPool == b.mpFixedPool);<br>}\n\ninline bool operator!=(const fixed_pool_reference&amp; a, const fixed_pool_reference&amp; b)\n{\n    return (a.mpFixedPool != b.mpFixedPool);\n}</pre>\n  <p class=\"faq-answer\"> Example usage of the above:</p>\n<pre class=\"code-example\">typedef eastl::list&lt;int, fixed_pool_reference&gt; IntList;\n\nIntList::node_type buffer[2];\neastl::fixed_pool  myPool(buffer, sizeof(buffer), sizeof(Int::node_type), 2);\n\nIntList myList1(myPool);\nIntList myList2(myPool);\n           \nmyList1.push_back(37);\nmyList2.push_back(39);</pre>\n<p class=\"faq-question\"><a name=\"Cont.28\"></a>Cont.28\nCan I use a std (STL) allocator with EASTL?</p>\n<p class=\"faq-answer\">No. EASTL allocators are similar in interface to std STL allocators, but not 100% compatible. If it was possible to make them compatible with std STL allocators but also match the design of EASTL then compatibility would exist. The primary reasons for lack of compatibility are:</p>\n<ul>\n  <li>EASTL allocators have a different allocate function signature.</li>\n  <li>EASTL allocators have as many as four extra required functions: ctor(name), get_name(), set_name(), allocate(size, align, offset).</li>\n  <li>EASTL allocators have an additional allocate function specifically for aligned allocations, as listed directly above.</li>\n</ul>\n<p class=\"faq-question\"><a name=\"Cont.29\" id=\"Cont.29\"></a>What are the requirements of classes stored in containers?</p>\n<p class=\"faq-answer\">Class types stored in containers must have:</p>\n<ul>\n  <li>a public copy constructor</li>\n  <li>a public assignment operator</li>\n  <li>a public destructor</li>\n  <li>an operator &lt; that compares two such classes (sorted containers only).</li>\n  <li>an operator == that compares two such classes (hash containers only). </li>\n</ul>\n<p class=\"faq-answer\">Recall that the compiler generates basic versions these functions for you when you don't implement them yourself, so you can omit any of the above if the compiler-generated version is sufficient. </p>\n<p class=\"faq-answer\">For example, the following code will act incorrectly, because the user forgot to implement an assignment operator. The compiler-generated assignment operator will assign the refCount value, which the user doesn't want, and which will be called by the vector during resizing. </p>\n<pre class=\"code-example\">struct NotAPod\n{\n   NotAPod(const NotAPod&amp;) {} <span class=\"code-example-comment\">// Intentionally don't copy the refCount </span><br>\n  &nbsp;int refCount; <span class=\"code-example-comment\">// refCounts should not be copied between NotAPod instances.</span> \n}; \n \neastl::vector&lt;NotAPod&gt; v;</pre>\n<h2>Algorithms</h2>\n<p class=\"faq-question\">  <a name=\"Algo.1\"></a>Algo.1\n  I'm getting screwy behavior in sorting algorithms or sorted\ncontainers. What's wrong?</p>\n<p class=\"faq-answer\">It may possible that you are seeing floating point roundoff problems. Many STL algorithms require object comparisons to act consistently. However, floating point values sometimes compare differently between uses because in one situation a value might be in 32 bit form in system memory, whereas in anther situation that value might be in an FPU register with a different precision. These are difficult problems to track down and aren't the fault of EASTL or whatever similar library you might be using. There are various solutions to the problem, but the important thing is to find a way to force the comparisons to be consistent.</p>\n<p class=\"faq-answer\">The code below was an example of this happening, whereby the object pA-&gt;mPos was stored in system memory while pB-&gt;mPos was stored in a register and comparisons were inconsistent and a crash ensued.</p>\n<pre class=\"code-example\">class SortByDistance : public binary_function&lt;WorldTreeObject*, WorldTreeObject*, bool&gt;\n{\nprivate:\n&nbsp;&nbsp;&nbsp; Vector3 mOrigin;\n\npublic:\n&nbsp;&nbsp;&nbsp; SortByDistance(Vector3 origin) {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mOrigin = origin;\n&nbsp;&nbsp;&nbsp; }\n\n&nbsp;&nbsp;&nbsp; bool operator()(WorldTreeObject* pA, WorldTreeObject* pB) const {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((WorldObject*)pA)-&gt;mPos - mOrigin).GetLength()\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt; ((WorldObject*)pB)-&gt;mPos - mOrigin).GetLength();\n&nbsp;&nbsp;&nbsp; }\n};</pre>\n\n<p class=\"faq-question\"><a name=\"Algo.2\"></a>Algo.2\nHow do I write a comparison (operator&lt;()) for a struct that contains two or more members?&nbsp;</p>\n<p class=\"faq-answer\">For a struct with two members such as the following:</p>\n<pre class=\"code-example\">struct X {\n&nbsp;&nbsp;&nbsp; Blah m1;\n&nbsp;&nbsp;&nbsp; Blah m2;\n};</pre>\n<p class=\"faq-answer\">You would write the comparison function like this:</p>\n<pre class=\"code-example\">bool operator&lt;(const X&amp; a, const X&amp; b) {\n&nbsp;&nbsp;&nbsp; return (a.m1 == b.m1) ? (a.m2 &lt; b.m2) : (a.m1 &lt; b.m1);\n}</pre>\n<p class=\"faq-answer\">or, using only operator &lt; but more instructions:</p>\n<pre class=\"code-example\">bool operator&lt;(const X&amp; a, const X&amp; b) {\n&nbsp;&nbsp;&nbsp; return (a.m1 &lt; b.m1) || (!(b.m1 &lt; a.m1) &amp;&amp; (a.m2 &lt; b.m2));\n}</pre>\n<p class=\"faq-answer\">  For a struct with three members, you would have:</p>\n<pre class=\"code-example\">bool operator&lt;(const X&amp; a, const X&amp; b) {\n&nbsp;&nbsp;&nbsp; if(a.m1 != b.m1)\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (a.m1 &lt; b.m1);\n&nbsp;&nbsp;&nbsp; if(a.m2 != b.m2)\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (a.m2 &lt; b.m2);\n&nbsp;&nbsp;&nbsp; return (a.mType &lt; b.mType);\n}</pre>\n<p class=\"faq-answer\">And a somewhat messy implementation if you wanted to use only operator &lt;.</p>\n<p class=\"faq-answer\">Note also that you can use the above technique to implement operator &lt; for spatial types such as vectors, points, and rectangles. You would simply treat the members of the struct as an array of values and ignore the fact that they have spatial meaning. All operator &lt; cares about is that things order consistently.</p>\n<pre class=\"code-example\">bool operator&lt;(const Point2D&amp; a, const Point2D&amp; b) {\n&nbsp;&nbsp;&nbsp; return (a.x == b.x) ? (a.y &lt; b.y) : (a.x &lt; b.x);\n}</pre>\n<p class=\"faq-question\"><a name=\"Algo.3\"></a>Algo.3\nHow do I sort something in reverse order?</p>\n<p class=\"faq-answer\">Normally sorting puts the lowest value items first in the sorted range. You can change this by simply reversing the comparison. For example:<br>\n</p>\n<div class=\"code-example\">sort(intVector.begin(), intVector.end(), greater&lt;int&gt;());</div>\n<p class=\"faq-answer\">  It's important that you use operator &gt; instead of &gt;=. The comparison function must return false for every case where values are equal.</p>\n<p class=\"faq-question\"><a name=\"Algo.4\"></a>Algo.4\nI'm getting errors about min and max while compiling.</p>\n<p class=\"faq-answer\">You need to define NOMINMAX under VC++ when this occurs, as it otherwise defines min and max macros that interfere. There may be equivalent issues with other compilers. Also, VC++ has a specific &lt;minmax.h&gt; header file which defines min and max macros but which doesn't pay attention to NOMINMAX and so in that case there is nothing to do but not include that file or to undefine min and max. minmax.h is not a standard file and its min and max macros are not standard C or C++ macros or functions.</p>\n<p class=\"faq-question\"><a name=\"Algo.5\"></a>Algo.5\nWhy don't algorithms take a container as an argument instead of iterators? A container would be more convenient.</p>\n<p class=\"faq-answer\">Having algorithms that use containers instead of algorithms would reduce reduce functionality with no increase in performance. This is because the use of iterators allows for the application of algorithms to sub-ranges of containers and allows for the application of algorithms to containers aren't formal C++ objects, such as C-style arrays.</p>\n<p class=\"faq-answer\">Providing additional algorithms that use containers would introduce redundancy with respect to the existing algorithms that use iterators.</p>\n<p class=\"faq-question\"><a name=\"Algo.6\"></a>Algo.6\nGiven a container of pointers, how do I find an element by value (instead of by pointer)?</p>\n<p class=\"faq-answer\">Functions such as&nbsp;find_if help you find a T element in a container of Ts. But if you have a container of pointers such as vector&lt;Widget*&gt;, these functions will enable you to find an element that matches a given Widget* pointer, but they don't let you find an element that matches a given Widget object.</p>\n<p class=\"faq-answer\">You can write your own iterating 'for' loop and compare values, or you can use a generic function object to do the work if this is a common task:</p>\n<pre class=\"code-example\">template&lt;typename T&gt;\nstruct dereferenced_equal\n{\n&nbsp; &nbsp; const T&amp; mValue;\n\n&nbsp; &nbsp;&nbsp;dereferenced_equal(const T&amp; value) : mValue(value) { } &nbsp;&nbsp;&nbsp;&nbsp;\n&nbsp; &nbsp;&nbsp;bool operator==(const T* pValue) const { return *pValue ==&nbsp;mValue; }\n};\n\n...\n\nfind_if(container.begin(), container.end(),&nbsp;dereferenced_equal&lt;Widget&gt;(someWidget));</pre>\n\n<p class=\"faq-question\"><a name=\"Algo.7\"></a>Algo.7\nWhen do stored objects need to support <small><span style=\"font-family: Courier New;\">operator &lt;</span></small> vs. when do they need to support <small><span style=\"font-family: Courier New;\">operator ==</span></small>?</p>\n<p class=\"faq-answer\">Any object which is sorted needs to have operator &lt; defined for it, implicitly via operator &lt; or explicitly via a user-supplied Compare function. Sets and map containers require operator &lt;, while sort, binary search, and min/max algorithms require operator &lt;.</p>\n<p class=\"faq-answer\">Any object which is compared for equality needs to have operator == defined for it, implicitly via operator == or explicitly via a user-supplied BinaryPredicate function. Hash containers required operator ==, while many of the algorithms other than those mentioned above for operator &lt; require operator ==.</p>\n<p class=\"faq-answer\">Some algorithms and containers require neither &lt; nor ==. Interestingly, no algorithm or container requires both &lt; and ==.</p>\n<p class=\"faq-question\"><a name=\"Algo.8\"></a>Algo.8 How do I sort via pointers or array indexes instead of objects directly?</p>\n<p class=\"faq-answer\">Pointers </p>\n<pre class=\"code-example\"><span class=\"style4\">vector&lt;TestObject&gt;  toArray;\nvector&lt;TestObject*&gt; topArray;\n\nfor(eastl_size_t i = 0; i &lt; 32; i++)\n   toArray.push_back(TestObject(rng.RandLimit(20)));\nfor(eastl_size_t i = 0; i &lt; 32; i++) // This needs to be a second loop because the addresses might change in the first loop due to container resizing.\n   topArray.push_back(&amp;toArray[i]);\n</span>\nstruct TestObjectPtrCompare\n{\n    bool operator()(TestObject* a, TestObject* b)\n        { return a-&gt;mX &lt; a-&gt;mX; }\n};\n\nquick_sort(topArray.begin(), topArray.end(), TestObjectPtrCompare());</pre>\n<p class=\"faq-answer\">Array indexes</p>\n<pre class=\"code-example\"><span class=\"style4\">vector&lt;TestObject&gt;   toArray;\nvector&lt;eastl_size_t&gt; toiArray;\n\nfor(eastl_size_t i = 0; i < 32; i++)\n{\n    toArray.push_back(TestObject(rng.RandLimit(20)));\n    toiArray.push_back(i);\n}</span>\n\nstruct TestObjectIndexCompare\n{\n    vector<TestObject>* mpArray;\n\n    TestObjectIndexCompare(vector&lt;TestObject&gt;* pArray) : mpArray(pArray) { }\n    TestObjectIndexCompare(const TestObjectIndexCompare& x) : mpArray(x.mpArray){ }\n    TestObjectIndexCompare& operator=(const TestObjectIndexCompare& x) { mpArray = x.mpArray; return *this; }\n\n    bool operator()(eastl_size_t a, eastl_size_t b)\n       { return (*mpArray)[a] &lt; (*mpArray)[b]; }\n};\n\nquick_sort(toiArray.begin(), toiArray.end(), TestObjectIndexCompare(&toArray));\n</pre>\n<p class=\"faq-answer\">Array indexes (simpler version using toArray as a global variable) </p>\n<pre class=\"code-example\"><span class=\"style4\">vector&lt;TestObject&gt;   toArray;\nvector&lt;eastl_size_t&gt; toiArray;\n\nfor(eastl_size_t i = 0; i < 32; i++)\n{\n    toArray.push_back(TestObject(rng.RandLimit(20)));\n    toiArray.push_back(i);\n}</span>\n\nstruct TestObjectIndexCompare\n{\n    bool operator()(eastl_size_t a, eastl_size_t b)\n       { return toArray[a] &lt; toArray[b]; }\n};\n\nquick_sort(toiArray.begin(), toiArray.end(), TestObjectIndexCompare(&toArray));</pre>\n<h2>Iterators</h2>\n<p class=\"faq-question\"><a name=\"Iter.1\"></a>Iter.1\nWhat's the difference between iterator, const iterator, and const_iterator?</p>\n<p class=\"faq-answer\">An iterator can be modified and item it points to can be modified.<br>\nA const iterator cannot be modified, but the items it points to can be modified.<br>\nA const_iterator can be modified, but the items it points to cannot be modified.<br>\nA const const_iterator cannot be modified, nor can the items it points to.</p>\n<p class=\"faq-answer\">This situation is much like with char pointers:</p>\n<div style=\"margin-left: 40px;\">\n  <table style=\"text-align: left; width: 400px;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n    <tbody>\n      <tr>\n        <td>Iterator type</td>\n        <td>Pointer equivalent</td>\n      </tr>\n      <tr>\n        <td>iterator</td>\n        <td>char*</td>\n      </tr>\n      <tr>\n        <td>const iterator</td>\n        <td>char* const</td>\n      </tr>\n      <tr>\n        <td>const_iterator</td>\n        <td>const char*</td>\n      </tr>\n      <tr>\n        <td>const const_iterator</td>\n        <td>const char* const</td>\n      </tr>\n    </tbody>\n  </table>\n</div>\n<p class=\"faq-question\"><a name=\"Iter.2\"></a>Iter.2 How do I tell from an iterator what type of thing it is iterating?</p>\n<p class=\"faq-answer\">Use the value_type typedef from iterator_traits, as in this example</p>\n<pre class=\"code-example\">template &lt;typename Iterator&gt;\nvoid DoSomething(Iterator first, Iterator last)\n{\n&nbsp;&nbsp;&nbsp; typedef typename iterator_traits&lt;Iterator&gt;::value_type;\n\n&nbsp; &nbsp; // use value_type\n}</pre>\n<p class=\"faq-question\"><a name=\"Iter.3\"></a>Iter.3\nHow do I iterate a container while (selectively) removing items from it?</p>\n<p class=\"faq-answer\">All EASTL containers have an erase function which takes an iterator as an \nargument and returns an iterator to the next item. Thus, you can erase items from a container \nwhile iterating it like so:</p>\n<pre class=\"code-example\">set&lt;int&gt; intSet;\nset&lt;int&gt;::iterator i = intSet.begin();\n\nwhile(i != intSet.end())\n{\n&nbsp;&nbsp;&nbsp;&nbsp;if(*i &amp; 1) // Erase all odd integers from the container.\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i = intSet.erase(i);\n&nbsp;&nbsp;&nbsp;&nbsp;else\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++i;\n}</pre>\n<p class=\"faq-question\"><a name=\"Iter.4\"></a>Iter.4\nWhat is an insert_iterator?</p>\n<p class=\"faq-answer\">An insert_iterator is a utility class which is like an iterator except that when you assign a value to it, the insert_iterator inserts the value into the container (via insert()) and increments the iterator. Similarly, there are front_insert_iterator and back_insert_iterator, which are similar to insert_iterator except that assigning a value to them causes then to call push_front and push_back, respectively, on the container. These utilities may seem a slightly abstract, but they have uses in generic programming.<br>\n</p>\n<hr style=\"width: 100%; height: 2px;\">\nEnd of document<br>\n<br>\n<br>\n<br>\n<br>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL Glossary.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n\t<title>EASTL Glossary</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Definitions of common terms related to EASTL.\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n</head>\n<body>\n<h1>EASTL Glossary</h1>\n<p>This document provides definitions to various terms related to EASTL. Items that are capitalized are items that are\nused as template parameters.</p>\n<table style=\"width: 100%; text-align: left;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n<tbody>\n<tr>\n<td>adapter</td>\n<td>An adapter is something that encapsulates a component to provide another interface, such as a C++ class which makes\na stack out of a list.</td>\n</tr>\n<tr>\n<td style=\"width: 150px; vertical-align: top;\">algorithm<br></td>\n<td style=\"vertical-align: top;\">Algorithms are standalone functions which manipulate data which usually but not\nnecessarily comes from a container. Some algorithms change the data while others don't. Examples are reverse, sort,\nfind, and remove.<br></td>\n</tr>\n<tr>\n<td>associative container</td>\n<td>An associative container is a variable-sized container that supports efficient retrieval of elements (values) based\non keys. It supports insertion and removal of elements, but differs from a sequence in that it does not provide a\nmechanism for inserting an element at a specific position. Associative containers include map, multimap, set, multiset,\nhash_map, hash_multimap, hash_set, hash_multiset.</td>\n</tr>\n<tr>\n<td>array</td>\n<td>An array is a C++ container which directly implements a C-style fixed array but which adds STL container semantics\nto it.</td>\n</tr>\n<tr>\n<td>basic_string</td>\n<td>A templated string class which is usually used to store char or wchar_t strings.</td>\n</tr>\n<tr>\n<td>begin</td>\n<td>The function used by all conventional containers to return the first item in the container.</td>\n</tr>\n<tr>\n<td>BidirectionalIterator</td>\n<td>An input iterator which is like ForwardIterator except it can be read in a backward direction as well.</td>\n</tr>\n<tr>\n<td>BinaryOperation&nbsp;</td>\n<td>A function which takes two arguments and returns a value (which will usually be assigned to a third object).</td>\n</tr>\n<tr>\n<td>BinaryPredicate</td>\n<td>A function which takes two arguments and returns true if some criteria is met (e.g. they are equal).</td>\n</tr>\n<tr>\n<td>binder1st, binder2nd</td>\n<td>These are function objects which convert one function object into another. &nbsp;In particular, they implement a\nbinary function whereby you can specify one of the arguments.This is a somewhat abstract concept but has its uses.</td>\n</tr>\n<tr>\n<td>bit vector</td>\n<td>A specialized container that acts like vector&lt;bool&gt; but is implemented via one bit per entry. STL\nvector&lt;bool&gt; is usually implemented as a bit vector but EASTL avoids this in favor of a specific bit vector\ncontainer.</td>\n</tr>\n<tr>\n<td>bitset</td>\n<td>An extensible yet efficient implementation of bit flags. Not strictly a conventional STL container and not the same\nthing as vector&lt;bool&gt; or a bit_vector, both of which are formal iterate-able containers.</td>\n</tr>\n<tr>\n<td>capacity</td>\n<td>Refers to the amount of total storage available in an array-based container such as vector, string, and array.\nCapacity is always &gt;= container size and is &gt; size in order to provide extra space for a container to grow\ninto.</td>\n</tr>\n<tr>\n<td>const_iterator</td>\n<td>An iterator whose iterated items are cannot be modified. A const_iterator is akin to a const pointer such as 'const\nchar*'.</td>\n</tr>\n<tr>\n<td>container</td>\n<td>A container is an object that stores other objects (its elements), and that has methods for accessing its elements.\nIn particular, every type that is a model of container has an associated iterator type that can be used to iterate\nthrough the container's elements.</td>\n</tr>\n<tr>\n<td>copy constructor</td>\n<td>A constructor for a type which takes another object of that type as its argument. For a hypothetical Widget class,\nthe copy constructor is of the form Widget(const Widget&amp; src);</td>\n</tr>\n<tr>\n<td>Compare</td>\n<td>A function which takes two arguments and returns the lesser of the two.</td>\n</tr>\n<tr>\n<td>deque</td>\n<td>The name deque is pronounced \"deck\" and stands for \"double-ended queue.\"<br>\n<br>\nA deque is very much like a vector: like vector, it is a sequence that supports random access to elements, constant\ntime insertion and removal of elements at the end of the sequence, and linear time insertion and removal of elements in\nthe middle.<br>\n<br>\nThe main way in which deque differs from vector is that deque also supports constant time insertion and removal of\nelements at the beginning of the sequence. Additionally, deque does not have any member functions analogous to vector's\ncapacity() and reserve(), and does not provide the guarantees on iterator validity that are associated with those\nmember functions.</td>\n</tr>\n<tr>\n<td>difference_type</td>\n<td>The typedef'd type used by all conventional containers and iterators to define the distance between two iterators.\nIt is usually the same thing as the C/C++ ptrdiff_t data type.</td>\n</tr>\n<tr>\n<td>empty</td>\n<td>The function used by all conventional containers to tell if a container has a size of zero. In many cases empty is\nmore efficient than checking for size() == 0.</td>\n</tr>\n<tr>\n<td>element</td>\n<td>An element refers to a member of a container.</td>\n</tr>\n<tr>\n<td>end</td>\n<td>The function used by all conventional containers to return one-past the last item in the container.</td>\n</tr>\n<tr>\n<td>equal_range</td>\n<td>equal_range is a version of binary search: it attempts to find the element value in an ordered range [first, last).\nThe value returned by equal_range is essentially a combination of the values returned by lower_bound and upper_bound:\nit returns a pair of iterators i and j such that i is the first position where value could be inserted without\nviolating the ordering and j is the last position where value could be inserted without violating the ordering. It\nfollows that every element in the range [i, j) is equivalent to value, and that [i, j) is the largest subrange of\n[first, last) that has this property.</td>\n</tr>\n<tr>\n<td>explicit instantiation</td>\n<td>Explicit instantiation lets you create an instantiation of a templated class or function without actually using it\nin your code. Since this is useful when you are creating library files that use templates for distribution,\nuninstantiated template definitions are not put into object files.&nbsp;An example of the syntax for explicit\ninstantiation is:<br>\n<small><span style=\"font-family: Courier New;\">&nbsp; &nbsp;</span></small> <small><span style=\n\"font-family: Courier New;\">template class vector&lt;char&gt;;<br>\n&nbsp; &nbsp; template void min&lt;int&gt;(int, int);<br>\n&nbsp; &nbsp; template void min(int, int);</span></small></td>\n</tr>\n<tr>\n<td>ForwardIterator</td>\n<td>An input iterator which is like InputIterator except it can be reset back to the beginning.</td>\n</tr>\n<tr>\n<td>Function</td>\n<td>A function which takes one argument and applies some operation to the target.</td>\n</tr>\n<tr>\n<td>function object, functor</td>\n<td>A function object or functor is a&nbsp;class that has the function-call operator (<tt>operator()</tt>)\ndefined.</td>\n</tr>\n<tr>\n<td>Generator</td>\n<td>A function which takes no arguments and returns a value (which will usually be assigned to an object).</td>\n</tr>\n<tr>\n<td>hash_map, hash_multimap, hash_set, hash_multiset</td>\n<td>The hash containers are implementations of map, multimap, set, and multiset via a hashtable instead of via a tree.\nSearches are O(1) (fast) but the container is not sorted.</td>\n</tr>\n<tr>\n<td>heap</td>\n<td>A heap is a data structure which is not necessarily sorted but is organized such that the highest priority item is\nat the top. A heap is synonymous with a priority queue and has numerous applications in computer science.</td>\n</tr>\n<tr>\n<td>InputIterator</td>\n<td>An input iterator (iterator you read from) which allows reading each element only once and only in a forward\ndirection.</td>\n</tr>\n<tr>\n<td>intrusive_list, intrusive_hash_map, etc.</td>\n<td>Intrusive containers are containers which don't allocate memory but instead use their contained object to manage\nthe container's memory. While list allocates nodes (with mpPrev/mpNext pointers) that contain the list items,\nintrusive_list doesn't allocate nodes but instead the container items have the mpPrev/mpNext pointers.</td>\n</tr>\n<tr>\n<td>intrusive_ptr</td>\n<td>intrusive_ptr is a smart pointer which doesn't allocate memory but instead uses the contained object to manage\nlifetime via addref and release functions.</td>\n</tr>\n<tr>\n<td>iterator</td>\n<td>An iterator is the fundamental entity of reading and enumerating values in a&nbsp;container. Much like a pointer\ncan be used to walk through a character array, an iterator is used to walk through a linked list.</td>\n</tr>\n<tr>\n<td>iterator category</td>\n<td>An iterator category defines the functionality the iterator provides. The conventional iterator categories are\nInputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator, and OutputIterator. See the definitions of\neach of these for more information.Iterator category is synonymous with <span style=\n\"font-style: italic;\">iterator_tag</span>.</td>\n</tr>\n<tr>\n<td>iterator_tag</td>\n<td>See <span style=\"font-style: italic;\">iterator category</span>.</td>\n</tr>\n<tr>\n<td>key_type, Key</td>\n<td>A Key or key_type is the identifier used by associative (a.k.a. dictionary) containers (e.g. map, hash_map) to\nidentify the type used to index the mapped_type. If you have a dictionary of strings that you access by an integer id,\nthe ids are the keys and the strings are the mapped types.</td>\n</tr>\n<tr>\n<td>lexicographical compare</td>\n<td>A lexicographical compare is a comparison of two containers that compares them element by element, much like the C\nstrcmp function compares two strings.</td>\n</tr>\n<tr>\n<td>linked_ptr</td>\n<td>A linked_ptr is a shared smart pointer which implements object lifetime via a linked list of all linked_ptrs that\nare referencing the object. linked_ptr, like intrusive_ptr, is a non-memory-allocating alternative to shared_ptr.</td>\n</tr>\n<tr>\n<td>list</td>\n<td>A list is a doubly linked list. It is a sequence that supports both forward and backward traversal, and (amortized)\nconstant time insertion and removal of elements at the beginning or the end, or in the middle. Lists have the important\nproperty that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates\nonly the iterators that point to the elements that are removed. The ordering of iterators may be changed (that is,\nlist&lt;T&gt;::iterator might have a different predecessor or successor after a list operation than it did before), but\nthe iterators themselves will not be invalidated or made to point to different elements unless that invalidation or\nmutation is explicit.</td>\n</tr>\n<tr>\n<td>lower_bound</td>\n<td>lower_bound is a version of binary search: it attempts to find the element value in an ordered range [first, last).\nSpecifically, it returns the first position where value could be inserted without violating the ordering.</td>\n</tr>\n<tr>\n<td>map</td>\n<td>Map is a sorted associative container that associates objects of type Key with objects of type T. Map is a pair\nassociative container, meaning that its value type is pair&lt;const Key, T&gt;. It is also a unique associative\ncontainer, meaning that no two elements have the same key. It is implemented with a tree structure.</td>\n</tr>\n<tr>\n<td>mapped_type</td>\n<td>A mapped_type is a typedef used by associative containers to identify the container object which is accessed by a\nkey. If you have a dictionary of strings that you access by an integer id, the ids are the keys and the strings are the\nmapped types.</td>\n</tr>\n<tr>\n<td>member template</td>\n<td>A member template is a templated function of a templated class. Thus with a member template function there are two\nlevels of templating -- the class and the function.</td>\n</tr>\n<tr>\n<td>multimap,&nbsp;</td>\n<td>Multimap is a sorted associative&nbsp;container that associates objects of type Key with objects of type T.\nmultimap is a pair associative container, meaning that its value type is pair&lt;const Key, T&gt;. It is also a\nmultiple associative container, meaning that there is no limit on the number of elements with the same key.It is\nimplemented with a tree structure.</td>\n</tr>\n<tr>\n<td>multiset</td>\n<td>Multiset is a sorted associative container that stores objects of type Key. Its value type, as well as its key\ntype, is Key. It is also a multiple associative container, meaning that two or more elements may be identical.&nbsp;It\nis implemented with a tree structure.</td>\n</tr>\n<tr>\n<td>node</td>\n<td>A node is a little holder class used by many containers to hold the contained items. A linked-list, for example,\ndefines a node which has three members: mpPrev, mpNext, and T (the contained object).</td>\n</tr>\n<tr>\n<td>npos</td>\n<td>npos is used by the string class to identify a non-existent index. Some string functions return npos to indicate\nthat the function failed.</td>\n</tr>\n<tr>\n<td>rel_ops</td>\n<td>rel_ops refers to \"relational operators\" and is a set of templated functions which provide operator!= for classes\nthat&nbsp; have only operator== and provide operator &gt; for classes that have only operator &lt;, etc. Unfortunately,\nrel_ops have a habit of polluting the global operator space and creating conflicts. They must be used with\ndiscretion.</td>\n</tr>\n<tr>\n<td>reverse_iterator</td>\n<td>A reverse_iterator is an iterator which wraps a bidirectional or random access iterator and allows the iterator to\nbe read in reverse direction. The difference between using reverse_iterators and just decrementing regular iterators is\nthat reverse_iterators use operator++ to move backwards and thus work in any algorithm that calls ++ to move through a\ncontainer.</td>\n</tr>\n<tr>\n<td>OutputIterator</td>\n<td>An output iterator (iterator you write to) which allows writing each element only once in only in a forward\ndirection.</td>\n</tr>\n<tr>\n<td>POD</td>\n<td>POD means Plain Old Data. It refers to C++ classes which act like built-in types and C structs. These are useful to\ndistinguish because some algorithms can be made more efficient when they can detect that they are working with PODs\ninstead of regular classes.&nbsp;</td>\n</tr>\n<tr>\n<td>Predicate</td>\n<td>A function which takes one argument returns true if the argument meets some criteria.</td>\n</tr>\n<tr>\n<td>priority_queue</td>\n<td>A priority_queue is an adapter container which implements a heap via a random access container such as vector or\ndeque.</td>\n</tr>\n<tr>\n<td>queue</td>\n<td>A queue is an adapter container which implements a FIFO (first-in, first-out) container with which you can add\nitems to the back and get items from the front.</td>\n</tr>\n<tr>\n<td>RandomAccessIterator</td>\n<td>An input iterator which can be addressed like an array. It is a superset of all other input iterators.</td>\n</tr>\n<tr>\n<td>red-black tree</td>\n<td>A red-black tree is a binary tree which has the property of being always balanced. The colors red and black are\nsomewhat arbitrarily named monikers for nodes used to measure the balance of the tree. Red-black trees are considered\nthe best all-around data structure for sorted containers.</td>\n</tr>\n<tr>\n<td>scalar</td>\n<td>A scalar is a data type which is implemented via a numerical value. In C++ this means integers, floating point\nvalues, enumerations, and pointers.&nbsp;</td>\n</tr>\n<tr>\n<td>scoped_ptr</td>\n<td>A scoped_ptr is a smart pointer which is the same as C++ auto_ptr except that it cannot be copied.</td>\n</tr>\n<tr>\n<td>set</td>\n<td>Set is a sorted associative container that stores objects of type Key. Its value type, as well as its key type, is\nKey. It is also a unique associative container, meaning that no two elements are the same.It is implemented with a tree\nstructure.</td>\n</tr>\n<tr>\n<td>sequence</td>\n<td>A sequence is a variable-sized container whose elements are arranged in a strict linear (though not necessarily\ncontiguous) order. It supports insertion and removal of elements. Sequence containers include vector, deque, array,\nlist, slist.</td>\n</tr>\n<tr>\n<td>size</td>\n<td>All conventional containers have a size member function which returns the count of elements in the container. The\nefficiency of the size function differs between containers.</td>\n</tr>\n<tr>\n<td>size_type</td>\n<td>The type that a container uses to define its size and counts. This is similar to the C/C++ size_t type but may be\nspecialized for the container. It defaults to size_t, but it is possible to force it to be 4 bytes for 64 bit machines by defining EASTL_SIZE_T_32BIT.</td>\n</tr>\n<tr>\n<td>skip list</td>\n<td>A skip-list is a type of container which is an alternative to a binary tree for finding data.</td>\n</tr>\n<tr>\n<td>shared_ptr</td>\n<td>A shared_ptr is a smart pointer which allows multiple references (via multiple shared_ptrs) to the same object.\nWhen the last shared_ptr goes away, the pointer is freed. shared_ptr is implemented via a shared count between all\ninstances.</td>\n</tr>\n<tr>\n<td>slist</td>\n<td>An slist is like a list but is singly-linked instead of doubly-linked. It can only be iterated in a\nforward-direction.</td>\n</tr>\n<tr>\n<td>smart pointer</td>\n<td>Smart pointer is a term that identifies a family of utility classes which store pointers and free them when the\nclass instance goes out of scope. Examples of smart pointers are shared_ptr, linked_ptr, intrusive_ptr, and\nscoped_ptr.</td>\n</tr>\n<tr>\n<td>splice</td>\n<td>Splicing refers to the moving of a subsequence of one Sequence into another Sequence.</td>\n</tr>\n<tr>\n<td>stack</td>\n<td>A stack is a adapter container which implements LIFO (last-in, first, out) access via another container such as a\nlist or deque.</td>\n</tr>\n<tr>\n<td>STL</td>\n<td>Standard Template Library.&nbsp;</td>\n</tr>\n<tr>\n<td>StrictWeakOrdering</td>\n<td>A BinaryPredicate that compares two objects, returning true if the first precedes the second. Like Compare but has\nadditional requirements. Used for sorting routines.<br>\n<br>\nThis predicate must satisfy the standard mathematical definition of a strict weak ordering. A StrictWeakOrdering has to\nbehave the way that \"less than\" behaves: if a is less than b then b is not less than a, if a is less than b and b is\nless than c then a is less than c, and so on.</td>\n</tr>\n<tr>\n<td>string</td>\n<td>See basic_string.</td>\n</tr>\n<tr>\n<td>T</td>\n<td>T is the template parameter name used by most containers to identify the contained element type.&nbsp;</td>\n</tr>\n<tr>\n<td>template parameter</td>\n<td>A template parameter is the templated type used to define a template function or class. In the declaration\n'template &lt;typename T&gt; class vector{ },' &nbsp;T is a template parameter.</td>\n</tr>\n<tr>\n<td>template specialization</td>\n<td>A template specialization is a custom version of a template which overrides the default version and provides\nalternative functionality, often for the purpose of providing improved or specialized functionality.</td>\n</tr>\n<tr>\n<td>treap</td>\n<td>A tree-like structure implemented via a heap. This is an alternative to a binary tree (e.g. red-black tree),\nskip-list, and sorted array as a mechanism for a fast-access sorted container.</td>\n</tr>\n<tr>\n<td>type traits</td>\n<td>Type traits are properties of types. If you have a templated type T and you want to know if it is a pointer, you\nwould use the is_pointer type trait. If you want to know if the type is a POD, you would use the is_pod type trait.\nType traits are very useful for allowing the implementation of optimized generic algorithms and for asserting that\ntypes have properties expected by the function or class contract. For example, you can use type_traits to tell if a\ntype can be copied via memcpy instead of a slower element-by-element copy.</td>\n</tr>\n<tr>\n<td>typename</td>\n<td>Typename is a C++ keyword used in templated function implementations which identifies to the compiler that the\nfollowing expression is a type and not a value. It is used extensively in EASTL, particularly in the algorithms.</td>\n</tr>\n<tr>\n<td>UnaryOperation</td>\n<td>A function which takes one argument and returns a value (which will usually be assigned to second object).</td>\n</tr>\n<tr>\n<td>upper_bound</td>\n<td>upper_bound is a version of binary search: it attempts to find the element value in an ordered range [first, last).\nSpecifically, it returns the last position where value could be inserted without violating the ordering.</td>\n</tr>\n<tr>\n<td>value_type, Value</td>\n<td>A value_type is a typedef used by all containers to identify the elements they contain. In most cases value_type is\nsimply the same thing as the user-supplied T template parameter. The primary exception is the associative containers\nwhereby value_type is the pair of key_type and mapped_type.</td>\n</tr>\n<tr>\n<td>vector</td>\n<td>A vector is a Sequence that supports random access to elements, constant time insertion and removal of elements at\nthe end, and linear time insertion and removal of elements at the beginning or in the middle. The number of elements in\na vector may vary dynamically; memory management is automatic. Vector is the simplest of the container classes, and in\nmany cases the most efficient.</td>\n</tr>\n<tr>\n<td>vector_map,&nbsp;vector_multimap,&nbsp;vector_set,&nbsp;vector_multiset</td>\n<td>These are containers that implement the functionality of map, multimap, set, and multiset via a vector or deque\ninstead of a tree. They use less memory and find items faster, but are slower to modify and modification invalidates\niterators.</td>\n</tr>\n<tr>\n<td>weak_ptr</td>\n<td>A weak_ptr is an adjunct to shared_ptr which doesn't increment the reference on the contained object but can safely\ntell you if the object still exists and access it if so. It has uses in preventing circular references in\nshared_ptrs.</td>\n</tr>\n</tbody>\n</table>\n<br>\n\n<hr style=\"width: 100%; height: 2px;\">\nEnd of document<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL Gotchas.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n\t<title>EASTL Gotchas</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Desciptions of potential pitfalls that exist in EASTL.\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n    <style type=\"text/css\">\n<!--\n.style1 {color: #FF0000}\n.style2 {color: #009933}\n-->\n    </style>\n</head>\n<body>\n<h1>EASTL Gotchas</h1>\n<p> There are some cases where the EASTL design results in \"gotchas\" or behavior that isn't necessarily what the new user\n  would expect. These are all situations in which this behavior may be undesirable. One might ask, \"Why not change EASTL\n  to make these gotchas go away?\" The answer is that in each case making the gotchas go away would either be impossible\n  or would compromise the functionality of the library.</p>\n<h2>Summary</h2>\n<p>The descriptions here are intentionally terse; this is to make them easier to visually scan.</p>\n<table style=\"text-align: left; width: 100%;\" border=\"0\" cellpadding=\"1\" cellspacing=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 28px;\">1</td>\n<td><a href=\"#Gotchas.1\">map::operator[] can create elements.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">2</td>\n<td><a href=\"#Gotchas.2\">char* converts to string silently.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">3</td>\n<td><a href=\"#Gotchas.3\">char* is compared by ptr and not by contents.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">4</td>\n<td><a href=\"#Gotchas.4\">Iterators can be invalidated by container mutations.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">5</td>\n<td><a href=\"#Gotchas.5\">Vector resizing may cause ctor/dtor cascades.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">6</td>\n<td><a href=\"#Gotchas.6\">Vector and string insert/push_back/resize can reallocate.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">7</td>\n<td><a href=\"#Gotchas.7\">Deriving from containers may not work.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">8</td>\n<td><a href=\"#Gotchas.8\">set::iterator is const_iterator.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">9</td>\n<td><a href=\"#Gotchas.9\">Inserting elements means copying by value.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">10</td>\n<td><a href=\"#Gotchas.10\">Containers of pointers can leak if you aren't careful.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">11</td>\n<td><a href=\"#Gotchas.11\">Containers of auto_ptrs can crash.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">12</td>\n<td><a href=\"#Gotchas.12\">Remove algorithms don't actually remove elements.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">13</td>\n<td><a href=\"#Gotchas.13\">list::size() is O(n).</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">14</td>\n<td><a href=\"#Gotchas.14\">vector and deque::size() may incur integer division.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">15</td>\n<td><a href=\"#Gotchas.15\">Be careful making custom Compare functions.</a></td>\n</tr>\n<tr>\n<td style=\"width: 28px;\">16</td>\n<td><a href=\"#Gotchas.16\">Comparisons involving floating point are dangerous.</a></td>\n</tr>\n<tr>\n  <td style=\"width: 28px;\">17</td>\n  <td><a href=\"#Gotchas.17\">Writing beyond string::size and vector::size is dangerous. </a></td>\n</tr>\n<tr>\n  <td style=\"width: 28px;\">18</td>\n  <td><a href=\"#Gotchas.18\">Container operator=() doesn't copy allocators. </a></td>\n</tr>\n</tbody>\n</table>\n<h2>  Detail</h2>\n<p class=\"faq-question\"><a name=\"Gotchas.1\"></a>1\nmap::operator[] can create elements.</p>\n<p class=\"faq-answer\">By design, map operator[] creates a value for you if it isn't already present. The reason for this is that the alternative behavior would be to throw an exception, and such behavior isn't desirable. The resolution is to simply use the map::find function instead of operator[].</p>\n<p class=\"faq-question\"><a name=\"Gotchas.2\"></a>2\nchar* converts to string silently.</p>\n<p class=\"faq-answer\">The string class has a non-explicit constructor that takes char* as an argument. Thus if you pass char* to a function that takes a string object, a temporary string will be created. In some cases this is undesirable behavior but the user may not notice it right away, as the compiler gives no warnings. The reason that the string constructor from char* is not declared explicit is that doing so would prevent the user from expressions such as: string s = &quot;hello&quot;. In this example, no temporary string object is created, but the syntax is not possible if the char* constructor is declared explicit. Thus a decision to make the string char* constructor explicit involves tradeoffs.</p>\n<p class=\"faq-answer\">There is an EASTL configuration option called EASTL_STRING_EXPLICIT which makes the string char* ctor explicit and avoids the behaviour described above.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.3\"></a>3\nchar* is compared by ptr and not by contents.</p>\n<p class=\"faq-answer\">If you have a set of strings declared as set&lt;char*&gt;, the find function will compare via the pointer value and not the string contents. The workaround is to make a set of string objects or, better, to supply a custom string comparison function to the set. The workaround is not to declare a global operator&lt; for type char*, as that could cause other systems to break.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.4\"></a>4 Iterators can be invalidated by container mutations</p>\n<p class=\"faq-answer\">With some containers, modifications of them may invalidate iterators into them. With other containers, modifications of them only an iterator if the modification involves the element that iterator refers to. Containers in the former category include vector, deque, basic_string (string), vector_map, vector_multimap, vector_set, and vector_multiset. Containers in the latter category include list, slist, map, multimap, multiset, all hash containers, and all intrusive containers.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.5\"></a>5 Vector resizing may cause ctor/dtor cascades.</p>\n<p>If elements are inserted into a vector in middle of the sequence, the elements from the insertion point to the end will be copied upward. This will necessarily cause a series of element constructions and destructions as the elements are copied upward. Similarly, if an element is appended to a vector but the vector capacity is exhausted and needs to be reallocated, the entire vector will undergo a construction and destruction pass as the values are copied to the new storage. This issue exists for deque as well, though to a lesser degree. For vector, the resolution is to reserve enough space in your vector to prevent such reallocation. For deque the resolution is to set its subarray size to enough to prevent such reallocation. Another solution that can often be used is to take advantage of the has_trivial_relocate type trait, which can cause such moves to happen via memcpy instead of via ctor/dtor calls. If your class can be safely memcpy'd, you can use EASTL_DECLARE_TRIVIAL_RELOCATE to tell the compiler it can be memcpy'd. Note that built-in scalars (e.g. int) already are automatically memcpy'd by EASTL.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.6\"></a>6\nVector and string insert/push_back/resize can reallocate.</p>\n<p>If you create an empty vector and use push_back to insert 100 elements, the vector will reallocate itself at least three or four times during the operation. This can be an undesirable thing. The best thing to do if possible is to reserve the size you will need up front in the vector constructor or before you add any elements.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.7\"></a>7\nDeriving from containers may not work.</p>\n<p>EASTL containers are not designed with the guarantee that they can be arbitrarily subclassed. This is by design and is done for performance reasons, as such guarantees would likely involve making containers use virtual functions. However, some types of subclassing can be successful and EASTL does such subclassing internally to its advantage. The primary problem with subclassing results when a parent class function calls a function that the user wants to override. The parent class cannot see the overridden function and silent unpredictable behavior will likely occur. If your derived container acts strictly as a wrapper for the container then you will likely be able to successfully subclass it.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.8\"></a>8 \nset::iterator is const_iterator.</p>\n<p class=\"faq-answer\">The reason this is so is that a set is an ordered container and changing the value referred to by an iterator could make the set be out of order. Thus, set and multiset iterators are always const_iterators. If you need to change the value and are sure the change will not alter the container order, use const_cast or declare mutable member variables for your contained object. This resolution is the one blessed by the C++ standardization committee. This issue is addressed in more detail in the EASTL FAQ.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.9\"></a>9\nInserting elements means copying by value.</p>\n<p class=\"faq-answer\">When you insert an element into a (non-intrusive) container, the container makes a copy of the element. There is no provision to take over ownership of an object from the user. The exception to this is of course when you use a container of pointers instead of a container of values. See the entry below regarding containers of pointers. Intrusive containers (e.g. intrusive_list) do in fact take over the user-provided value, and thus provide another advantage over regular containers in addition to avoiding memory allocation.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.10\"></a>10\n  Containers of pointers can leak if you aren't careful.</p>\n<p class=\"faq-answer\">Containers of points don't know or care about the possibility that the pointer may have been allocated and need to be freed. Thus if you erase such elements from a container they are not freed. The resolution is to manually free the pointers when removing them or to instead use a container of smart pointers (shared smart pointers, in particular). This issue is addressed in more detail in the EASTL FAQ and the auto_ptr-related entry below.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.11\"></a>11\nContainers of auto_ptrs can crash</p>\n<p class=\"faq-answer\">We suggested above that the user can use a container of smart pointers to automatically manage contained pointers. However, you don't want to use auto_ptr, as auto_ptrs cannot be safely assigned to each other; doing so results in a stale pointer and most likely a crash.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.12\"></a>12\nRemove algorithms don't actually remove elements.</p>\n<p class=\"faq-answer\">Algorithms such as remove, remove_if, remove_heap, and unique do not erase elements from the sequences they work on. Instead, they return an iterator to the new end of the sequence and the user must call erase with that iterator in order to actually remove the elements from the container. This behavior exists because algorithms work on sequences via iterators and don't know how to work with containers. Only the container can know how to best erase its own elements. In each case, the documentation for the algorithm reminds the user of this behavior. Similarly, the copy algorithm copies elements from one sequence to another and doesn't modify the size of the destination sequence. So the destination must hold at least as many items as the source, and if it holds more items, you may want to erase the items at the end after the copy.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.13\"></a>13 \nlist::size() is O(n).</p>\n<p class=\"faq-answer\">By this we mean that calling size() on a list will iterate the list and add the size as it goes. Thus, getting the size of a list is not a fast operation, as it requires traversing the list and counting the nodes. We could make list::size() be fast by having a member mSize variable. There are reasons for having such functionality and reasons for not having such functionality. We currently choose to not have a member mSize variable as it would add four bytes to the class, add&nbsp;processing to functions such as insert and erase, and would only serve to improve the size function, but no other function. The alternative&nbsp;argument is that the C++ standard states that std::list&nbsp;should be an O(1) operation (i.e. have a member size variable), most C++ standard library list implementations do so, the size is but an integer which is quick to update, and many users expect to have a fast size function. All of this applies to slist and intrusive_list as well.</p>\n<p class=\"faq-answer\">Note that EASTL's config.h file has an option in it to cause list and slist to cache their size with an mSize variable and thus make size() O(1). This option is disabled by default.</p>\n<p class=\"faq-question\">  <a name=\"Gotchas.14\"></a>14 \n  vector and deque::size() may incur integer division.</p>\n<p class=\"faq-answer\">Some containers (vector and deque in particular) calculate their size by pointer subtraction. For example, the implementation of vector::size() is 'return mpEnd - mpBegin'. This looks like a harmless subtraction, but if the size of the contained object is not an even power of two then the compiler will likely need to do an integer division to calculate the value of the subtracted pointers. One might suggest that vector use mpBegin and mnSize as member variables instead of mpBegin and mpEnd, but that would incur costs in other vector operations. The suggested workaround is to iterate a vector instead of using a for loop and operator[] and for those cases where you do use a for loop and operator[], get the size once at the beginning of the loop instead of repeatedly during the condition test.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.15\"></a>15\n  Be careful making custom Compare functions.\n</p>\n<p class=\"faq-answer\">A Compare function compares two values and returns true if the first is less than the second. This is easy to understand for integers and strings, but harder to get right for more complex structures. Many a time have people decided to come up with a fancy mechanism for comparing values and made mistakes. The FAQ has a couple entries related to this. See http://blogs.msdn.com/oldnewthing/archive/2003/10/23/55408.aspx for a story about how this can go wrong by being overly clever.</p>\n<p class=\"faq-question\">  <a name=\"Gotchas.16\"></a>16 \n  Comparisons involving floating point are dangerous.</p>\n<p class=\"faq-answer\">Floating point comparisons between two values that are very nearly equal can result in inconsistent results. Similarly, floating point comparisons between NaN values will always generate inconsistent results, as NaNs by definition always compare as non-equal. You thus need to be careful when using comparison functions that work with floating point values. Conversions to integral values may help the problem, but not necessarily.</p>\n<p class=\"faq-question\"><a name=\"Gotchas.17\" id=\"Gotchas.17\"></a>17 Writing beyond string::size and vector::size is dangerous.</p>\n<p>A trick that often comes to mind when working with strings is to set the string capacity to some maximum value, strcpy data into it, and then resize the string when done. This can be done with EASTL, but only if you resize the string to the maximum value and not reserve the string to the maximum value. The reason is that when you resize a string from size (n) to size (n + count), the count characters are zeroed and overwrite the characters that you strcpyd. </p>\n<p class=\"faq-answer\">The following code is broken: </p>\n<p class=\"code-example\">string mDataDir;<br>\n  <br>\n  mDataDir.<span class=\"style1\">reserve</span>(kMaxPathLength);<br>\n  strcpy(&amp;mDataDir[0], &quot;blah/blah/blah&quot;);<br>\nmDataDir.resize(strlen(&amp;mDataDir[0])); // Overwrites your blah/... with 00000...</p>\n<p class=\"faq-answer\">This following code is OK: </p>\n<p class=\"code-example\">string mDataDir;<br>\n  <br>\n  mDataDir.<span class=\"style2\">resize</span>(kMaxPathLength);<br>\n  strcpy(&amp;mDataDir[0], &quot;blah/blah/blah&quot;);<br>\nmDataDir.resize(strlen(&amp;mDataDir[0]));</p>\n<p class=\"faq-question\"><a name=\"Gotchas.18\" id=\"Gotchas.18\"></a>18 Container operator=() doesn't copy allocators.\n</p>\n<p class=\"faq-answer\">EASTL container assignment (e.g. vector::operator=(const vector&amp;)) doesn't copy the allocator. There are good and bad reasons for doing this, but that's how it acts. So you need to beware that you need to assign the allocator separately or make a container subclass which overrides opeator=() and does this. </p>\n<br>\n<hr style=\"width: 100%; height: 2px;\">\nEnd of document<br>\n<br>\n<br>\n<br>\n<br>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL Introduction.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n\t<title>EASTL Introduction</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Basic introduction to EASTL.\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n</head>\n<body>\n<h1>EASTL Introduction</h1>\n<p>EASTL stands for Electronic Arts Standard Template Library. It is a C++ template library of containers, algorithms, and\n  iterators useful for runtime and tool development across multiple platforms. It is a fairly extensive and robust\n  implementation of such a library and has an emphasis on high performance above all other considerations.</p>\n<h2>Intended Audience</h2>\n<p>This is a short document intended to provide a basic introduction to EASTL for \n  those new to the concept of EASTL or STL. If you are familiar with the C++ STL \n  or have worked with other templated container/algorithm libraries, you probably \n  don't need to read this. If you have no familiarity with C++ templates at all, \n  then you probably will need more than this document to get you up to speed. In \n  this case you need to understand that templates, when used properly, are powerful \n  vehicles for the ease of creation of optimized C++ code. A description of C++ \n  templates is outside the scope of this documentation, but there is plenty of such \n  documentation on the Internet. See the <a href=\"EASTL%20FAQ.html\">EASTL FAQ.html</a> \n  document for links to information related to learning templates and STL.</p>\n<h2>EASTL Modules</h2>\n<p>EASTL consists primarily of containers, algorithms, and iterators. An example of a container is a linked list, while an\n  example of an algorithm is a sort function; iterators are the entities of traversal for containers and algorithms.\n  EASTL containers a fairly large number of containers and algorithms, each of which is a very clean, efficient, and\n  unit-tested implementation. We can say with some confidence that you are not likely to find better implementations of\n  these (commercial or otherwise), as these are the result of years of wisdom and diligent work. For a detailed list of\n  EASTL modules, see <a href=\"EASTL%20Modules.html\">EASTL Modules.html</a>.</p>\n<h2>EASTL Suitability</h2>\n<p>What uses are EASTL suitable for? Essentially any situation in tools and shipping applications where the functionality\n  of EASTL is useful. Modern compilers are capable of producing good code with templates and many people are using them\n  in both current generation and future generation applications on multiple platforms from embedded systems to servers\n  and mainframes.</p>\n<hr style=\"width: 100%; height: 2px;\">\nEnd of document<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL Maintenance.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n\t<title>EASTL Maintenance</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Information for the EASTL maintainer.\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n</head>\n<body>\n\n<h1>EASTL Maintenance</h1>\n<h2><span style=\"font-style: italic;\"><a name=\"Introduction\" id=\"Introduction\"></a></span>Introduction</h2>\n<p>The purpose of this document is to provide some necessary background for anybody who might do work on EASTL. Writing\n  generic templated systems like EASTL can be surprisingly tricky. There are numerous details of the C++ language that\n  you need to understand which don't usually come into play during the day-to-day C++ coding that many people do. It is\n  easy to make a change to some function that seems proper and works for your test case but either violates the design\n  expectations or simply breaks under other circumstances.<br>\n  <br>\n  It may be useful to start with an example. Here we provide an implementation of the count algorithm which is seems\nsimple enough. Except it is wrong and while it&nbsp;will compile in some cases it won't compile in others:</p>\n<pre class=\"code-example\">template &lt;class InputIterator, class T&gt;\nint count(InputIterator first, InputIterator last, const T&amp; value)\n{\n &nbsp;&nbsp;&nbsp; int result = 0;\n \n &nbsp;&nbsp;&nbsp; for(; first &lt; last; ++first){\n &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(*first == value)\n &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++result;\n &nbsp;&nbsp;&nbsp; }\n \n &nbsp;&nbsp;&nbsp; return result;\n } </pre>\n<p>The problem is with the comparison 'first &lt; last'. The count algorithm takes an InputIterator and operator&lt; is\nnot guaranteed to exist for any given InputIterator (and indeed while operator&lt; exists for vector::iterator, it\ndoesn't exist for list::iterator). The comparison in the above algorithm must instead be implemented as 'first !=\nlast'. If we were working with a RandomAccessIterator then 'first &lt; last' would be valid.</p>\n<p>In the following sections we cover various topics of interest regarding the development and maintentance of EASTL.\n  Unfortunately, this document can't cover every aspect of EASTL maintenance issues, but at least it should give you a\nsense of the kinds of issues.</p>\n\n<h2>  <a name=\"Language_Standard\" id=\"Language_Standard\"></a>C++ Language Standard</h2>\n<p>First and foremost, you need to be familiar with the C++ standard. In particular, the sections of the standard related\n  to containers, algorithms, and iterators are of prime significance. We'll talk about some of this in more detail below.\n  Similarly, a strong understanding of the basic data types is required. What is the difference between ptrdiff_t and\nintptr_t; unsigned int and size_t; char and signed char?</p>\n<p>In addition to the C++ language standard, you'll want to be familiar with the C++ Defect Report. This is a continuously\n  updated document which lists flaws in the original C++ language specification and the current thinking as the\nresolutions of those flaws. You will notice various references to the Defect Report in EASTL source code.</p>\n<p>Additionally, you will want to be familiar with the C++ Technical Report 1 (as of this writing there is only one). This\n  document is the evolving addendum to the C++ standard based on both the Defect Report and based on desired additions to\nthe C++ language and standard library.</p>\n<p>Additionally, you will probably want to have some familiarity with Boost. It also helps to&nbsp;keep an eye on\n  comp.std.c++ Usenet discussions. However, watch out for what people say on Usenet. They tend to defend GCC, Unix, std\n  STL, and C++&nbsp;to a sometimes&nbsp;unreasonable degree. Many discussions ignore performance implications and\nconcentrate only on correctness and sometimes academic correctness above usability.</p>\n<h2>  <a name=\"Langauge_Use\" id=\"Langauge_Use\"></a>Language Use</h2>\n<p>Macros are (almost) not allowed in EASTL.&nbsp;A prime directive of EASTL is to be easier to read by users and most of\n  the time macros are an impedence to this. So we avoid macros at all costs, even if it ends up making our development\n  and maintenance more difficult. That being said, you will notice that the EASTL config.h file uses macros to control\n  various options. This is an exception to the rule; when we talk about not using macros, we mean with the EASTL\nimplementation itself.</p>\n<p>EASTL assumes a compliant and intelligent C++ compiler, and thus all language facilities are usable. However, we\nnevertheless choose to stay away from some language functionality. The primary language features we avoid are:</p>\n<ul>\n  <li>RTTI (run-time-type-identification) (this is deemed too costly)</li>\n<li>Template export (few compilers support this)</li>\n<li>Exception specifications (most compilers ignore them)</li>\n</ul>\n<p>Use of per-platform or per-compiler code should be avoided when possible but where there is a significant advantage to\n  be gained it can and indeed should be used. An example of this is the GCC __builtin_expect feature, which allows the\n  user to give the compiler a hint about whether an expression is true or false. This allows for the generation of code\nthat executes faster due to more intelligent branch prediction.</p>\n<h2>  <a name=\"Prime_Directives\" id=\"Prime_Directives\"></a>Prime Directives</h2>\n<p>The\nimplementation of EASTL is guided foremost by the following directives which are listed in order of importance.</p>\n<ol>\n<li>Efficiency (speed and memory usage)</li>\n<li>Correctness (doesn't have bugs)</li>\n<li>Portability (works on all required platforms with minimal specialized code)</li>\n<li>Readability (code is legible and comments are present and useful)</li>\n</ol>\n<p>Note that unlike commercial STL implementations which must put correctness above all, we put a higher value on\n  efficiency. As a result, some functionality may have some usage limitation that is not present in other similar systems\nbut which allows for more efficient operation, especially on the platforms of significance to us.</p>\n<p>Portability is significant, but not critical. Yes, EASTL must compile and run on all platforms that we will ship games\n    for. But we don't take that to mean under all compilers that could be conceivably used for such platforms. For example,\n    Microsoft VC6 can be used to compile Windows programs, but VC6's C++ support is too weak for EASTL and so you simply\ncannot use EASTL under VC6.</p>\n<p>Readability is something that EASTL achieves better than many other templated libraries, particularly Microsoft STL and\n    STLPort. We make every attempt to make EASTL code clean and sensible. Sometimes our need to provide optimizations\n    (particularly related to type_traits and iterator types) results in less simple code, but efficiency happens to be our\nprime directive and so it overrides all other considerations.</p>\n\n<h2>  <a name=\"Coding_Conventions\" id=\"Coding_Conventions\"></a>Coding Conventions</h2>\n<p>Here we provide a list of coding conventions to follow when maintaining or adding to EASTL, starting with the three\nlanguage use items from above:</p>\n<ul>\n<li>No RTTI use.</li>\n<li>No use of exception specifications (e.g. appending the 'throw' declarator to a function).</li>\n<li>No use of exception handling itself except where explicitly required by the implementation (e.g. vector::at).</li>\n<li>Exception use needs to savvy to EASTL_EXCEPTIONS_ENABLED.</li>\n<li>No use of macros (outside of config.h). Macros make things more difficult for the user.</li>\n<li>No use of static or global variables.</li>\n<li>No use of global new, delete, malloc, or free. All memory must be user-specifyable via an Allocator parameter\n(default-specified or explicitly specified).</li>\n<li>Containers use protected member data and functions as opposed to private. This is because doing so allows\nsubclasses to extend the container without the creation of intermediary functions. Recall from our <a href=\"#Prime_Directives\">prime directives</a> above that performance and simplicity overrule all.</li>\n<li>No use of multithreading primitives.&nbsp;</li>\n<li>No use of the export keyword.</li>\n<li>We don't have a rule about C-style casts vs. C++ static_cast&lt;&gt;, etc. We would always use static_cast except\nthat debuggers can't evaluate them and so in practice they can get in the way of debugging and tracing. However, if the\ncast is one that users don't tend to need to view in a debugger, C++ casts are preferred.</li>\n<li>No external library dependencies whatsoever, including standard STL. EASTL is dependent&nbsp;on only EABase and the\nC++ compiler.&nbsp;</li>\n<li>All code must be const-correct. This isn't just for readability -- compilation can fail unless const-ness is used\ncorrectly everywhere.&nbsp;</li>\n<li>Algorithms do not refer to containers; they refer only to iterators.</li>\n<li>Algorithms in general do not allocate memory. If such a situation arises, there should be a version of the\nalgorithm which allows the user to provide the allocator.</li>\n<li>No inferior implementations. No facility should be added to EASTL unless it is of professional\nquality.</li>\n<li>The maintainer should emulate the EASTL style of code layout, regardless of the maintainer's personal preferences.\nWhen in Rome, do as the Romans do. EASTL uses 4 spaces for indents, which is how the large majority of code within EA\nis written.</li>\n<li>No major changes should be done without consulting a peer group.</li>\n</ul>\n\n<h2><a name=\"Compiler_Issues\" id=\"Compiler_Issues\"></a>Compiler Issues</h2>\n<p>Historically, templates are the feature of C++ that has given C++ compilers the most fits. We are still working with\n  compilers that don't completely and properly support templates. Luckily, most compilers are now good enough to handle\nwhat EASTL requires. Nevertheless, there are precautions we must take.</p>\n<p>It turns out that the biggest problem in writing portable EASTL code is that VC++ allows you to make illegal statements\n    which are not allowed by other compilers. For example, VC++ will allow you to neglect using the typename keyword in\ntemplate references, whereas GCC (especially 3.4+) requires it.</p>\n<p>In order to feel comfortable that your EASTL code is C++ correct and is portable, you must do at least these two\nthings:</p>\n<ul>\n<li>Test under at least VS2005, GCC 3.4+, GCC 4.4+, EDG, and clang. </li>\n<li>Test all functions that you write, as compilers will often skip the compilation of a template function if it isn't\nused.</li>\n</ul>\n<p>The two biggest issues to watch out for are 'typename' and a concept called \"dependent names\". In both cases VC++ will\n  accept non-conforming syntax whereas most other compilers will not. Whenever you reference a templated type (and not a templated\n  value) in a template, you need to prefix it by 'typename'. Whenever your class function refers to a base class member (data or\n  function), you need to refer to it by \"this-&gt;\", \"base_type::\", or by placing a \"using\" statement in your class to\ndeclare that you will be referencing the given base class member.</p>\n\n<h2>  <a name=\"Iterator_Issues\" id=\"Iterator_Issues\"></a>Iterator Issues</h2>\n<p>The most important thing to understand about iterators is the concept of iterator types and their designated\n    properties. In particular, we need to understand the difference between InputIterator, ForwardIterator,\n    BidirectionalIterator, RandomAccessIterator, and OutputIterator. These differences dictate both how we implement our\n    algorithms and how we implement our optimizations. Please read the C++ standard for a reasonably well-implemented\n  description of these iterator types.</p>\n<p>Here's an example from EASTL/algorithm.h which demonstrates how we use iterator types to optimize the reverse algorithm\nbased on the kind of iterator passed to it:</p>\n<pre class=\"code-example\">template &lt;class BidirectionalIterator&gt;\ninline void reverse_impl(BidirectionalIterator first, BidirectionalIterator last, bidirectional_iterator_tag)<br>{\n&nbsp;&nbsp;&nbsp; for(; (first != last) &amp;&amp; (first != --last); ++first) <span class=\"code-example-comment\">// We are not allowed to use operator &lt;, &lt;=, &gt;, &gt;= with</span>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iter_swap(first, last);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"code-example-comment\">// a generic (bidirectional or otherwise) iterator.</span>\n}<br>\n\ntemplate &lt;typename RandomAccessIterator&gt;\ninline void reverse_impl(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)\n{\n&nbsp;&nbsp;&nbsp; for(; first &lt; --last; ++first) <span class=\"code-example-comment\">// With a random access iterator, we can use operator &lt; to more efficiently implement</span>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iter_swap(first, last);&nbsp;&nbsp;&nbsp; <span class=\"code-example-comment\">// this algorithm. A generic iterator doesn't necessarily have an operator &lt; defined.</span>\n}<br><br>\ntemplate &lt;class BidirectionalIterator&gt;\ninline void reverse(BidirectionalIterator first, BidirectionalIterator last)\n{\n&nbsp;&nbsp;&nbsp; typedef typename iterator_traits&lt;BidirectionalIterator&gt;::iterator_category IC;\n&nbsp;&nbsp;&nbsp; reverse_impl(first, last, IC());\n}</pre>\n\n<h2>  <a name=\"Exception_Handling\" id=\"Exception_Handling\"></a>Exception Handling</h2>\n<p>You will notice that EASTL uses try/catch in some places (particularly in containers) and uses\n  the&nbsp;EASTL_EXCEPTIONS_ENABLED define. For starters, any EASTL code that uses try/catch should always be wrapped\n  within #if EASTL_EXCEPTIONS_ENABLED (note: #if, not #ifdef).</p>\n<p>This is simple enough, but what you may be wondering is how it is that EASTL decides to use try/catch for some sections\n  of code and not for others. EASTL follows the C++ standard library conventions with respect to exception handling, and\n  you will see similar exception handling in standard STL. The code that you need to wrap in try/catch is code that can\n  throw a C++ exception (not to be confused with CPU exception) and needs to have something unwound (or fixed) as a\n  result. The important thing is that the container be in a valid state after encountering such exceptions. In general\nthe kinds of things that require such try/catch are:</p>\n<ul>\n<li>Memory allocation failures (which throw exceptions)</li>\n<li>Constructor exceptions</li>\n</ul>\n<p>Take a look at the cases in EASTL where try/catch is used and see what it is doing.</p>\n<h2>  <a name=\"Type_Traits\" id=\"Type_Traits\"></a>Type Traits </h2>\n<p>EASTL provides a facility called type_traits which is very similar to the type_traits being proposed by the C++ TR1\n  (see above). type_traits are useful because they tell you about properties of types at compile time. This allows you to\n  do things such as assert that a data type is scalar or that a data type is const. The way we put them to use in EASTL\n  is to take advantage of them to implement different pathways for functions based on types. For example, we can copy a\n  contiguous array of scalars much faster via memcpy than we can via a for loop, though we could not safely employ the\n  for loop for a non-trivial C++ class.</p>\n<p>As mentioned in the GeneralOptimizations section below, EASTL should take advantage of type_traits information to the\nextent possible to achive maximum effiiciency.</p>\n<h2>  <a name=\"General_Optimizations\" id=\"General_Optimizations\"></a>General\nOptimizations</h2>\n<p>One of the primary goals of EASTL is to achieve the highest possible efficiency. In cases where EASTL functionality\n  overlaps standard C++ STL functionality, standard STL implementations provided by compiler vendors are a benchmark upon\n  which EASTL strives to beat. Indeed EASTL is more efficient than all other current STL implementations&nbsp;(with some\n  exception in the case of some Metrowerks STL facilities). Here we list some of the things to look for when considering\n  optimization of EASTL code These items can be considered general optimization suggestions for any code, but this\nparticular list applies to EASTL:</p>\n<ul>\n<li>Take advantage of type_traits to the extent possible (e.g. to use memcpy to move data instead of a for loop when\npossible).</li>\n<li>Take advantage of iterator types to the extent possible.</li>\n<li>Take advantage of the compiler's expectation that if statements are expected to evaluate as true and for loop\nconditions are expected to evaluate as false.</li>\n<li>Make inline-friendly code. This often means avoiding temporaries to the extent possible.</li>\n<li>Minimize branching (i.e. minimize 'if' statements). Where branching is used, make it so that 'if' statements\nexecute as true.</li>\n<li>Use EASTL_LIKELY/EASTL_UNLIKELY to give branch hints to the compiler when you are confident it will be\nbeneficial.</li>\n<li>Use&nbsp;restricted pointers (EABase's EA_RESTRICT or various compiler-specific versions of __restrict).</li>\n<li>Compare unsigned values to &lt; max instead of comparing signed values to &gt;= 0 &amp;&amp; &lt; max.</li>\n<li>Employ power of 2 integer math instead of math with any kind of integer.</li>\n<li>Use template specialization where possible to implement improved functionality.</li>\n<li>Avoid function calls when the call does something trivial. This improves debug build speed (which matters) and\nsometimes release build speed as well, though sometimes makes the code intent less clear. A comment next to the code\nsaying what call it is replacing makes the intent clear without sacrificing performance.</li>\n</ul>\n<h2><a name=\"Unit_Tests\" id=\"Unit_Tests\"></a>Unit Tests</h2>\n<p>Writing robust templated containers and algorithms is difficult or impossible without a heavy unit test suite in place.\n    EASTL has a pretty extensive set of unit tests for all containers and algorithms. While the successful automated unit\n    testing of shipping application programs may be a difficult thing to pull off, unit testing of libraries such as this\n    is of huge importance and cannot be understated. </p>\n<ul>\n<li>When making a new unit test, start by copying one of the existing unit tests and follow its conventions.</li>\n<li>Test containers of both scalars and classes.</li>\n<li>Test algorithms on both container iterators (e.g. vector.begin()) and pointer iterators (e.g. int*).</li>\n<li>Make sure that algorithm or container member functions which take iterators work with the type of iterator they\nclaim to (InputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator).&nbsp;</li>\n<li>Test for const-correctness. If a user is allowed to modify something that is supposed to be const, silent errors\ncan go undetected.</li>\n<li>Make sure that unit tests cover all functions and all pathways of the tested code. This means that in writing the\nunit test you need to look at the source code to understand all the pathways.</li>\n<li>Consider using a random number generator (one is provided in the test library) to do 'monkey' testing whereby\nunexpected input is given to a module being tested. When doing so, make sure you seed the generator in a way that\nproblems can be reproduced.</li>\n<li>While we avoid macros in EASTL user code, macros to assist in unit tests aren't considered a problem. However,\nconsider that a number of macros could be replaced by templated functions and thus be easier to work with.</li>\n<li>Unit tests don't need to be efficient; feel free to take up all the CPU power and time you need to test a module\nsufficiently.</li>\n<li>EASTL containers are not thread-safe, by design. Thus there is no need to do multithreading tests as long as you\nstay away from the usage of static and global variables.</li>\n<li>Unit tests must succeed with no memory leaks and of course no memory corruption. The heap system should be\nconfigured to test for this, and heap validation functions are available to the unit tests while in the middle of\nruns.</li>\n</ul>\n\n<h2><a name=\"Things_to_Keep_in_Mind\" id=\"Things_to_Keep_in_Mind\"></a>Things to Keep in Mind</h2>\n<ul>\n<li>When referring to EASTL functions and types from EASTL code, make sure to preface the type with the EASTL\nnamespace. If you don't do this you can get collisions due to the compiler not knowing if it should use the EASTL\nnamespace or the namespace of the templated type for the function or type.</li>\n<li>Newly constructed empty containers do no memory allocation. Some STL and other container libraries allocate an\ninitial node from the class memory allocator. EASTL containers by design never do this.&nbsp;If a container needs an\ninitial node, that node should be made part of the container itself or be a static empty node object.</li>\n<li>Empty containers (new or otherwise) contain no constructed objects, including those that might be in an 'end' node.\nSimilarly, no user object (e.g. of type T) should be constructed unless required by the design and unless documented in\nthe cotainer/algorithm contract.&nbsp;</li>\n<li>When creating a new container class, it's best to copy from an existing similar class to the extent possible. This\nhelps keep the library consistent and resolves subtle problems that can happen in the construction of containers.</li>\n<li>Be very careful about tweaking the code. It's easy to think (for example) that a &gt; could be switch to a &gt;=\nwhere instead it is a big deal. Just about every line of code in EASTL has been thought through and has a purpose. Unit\ntests may or may not currently test every bit of EASTL, so you can't necessarily rely on them to give you 100%\nconfidence in changes. If you are not sure about something, contact the original author and he will tell you for\nsure.</li>\n<li>Algorithm templates always work with iterators and not containers. A given container may of course implement an\noptimized form or an algorithm itself.</li>\n<li>Make sure everything is heavily unit tested. If somebody finds a bug, fix the bug and make a unit test to make sure\nthe bug doesn't happen again.</li>\n<li>It's easy to get iterator categories confused or forgotten while implementing algorithms and containers.</li>\n<li>Watch out for the strictness of GCC 3.4+. There is a bit of syntax &#8212; especially related to templates &#8212; that other\ncompilers accept but GCC 3.4+ will not.</li>\n<li>Don't forget to update the config.h EASTL_VERSION define before publishing.</li>\n<li>The vector and string classes define iterator to be T*. We want to always leave this so &#8212; at least in release\nbuilds &#8212; as this gives some algorithms an advantage that optimizers cannot get around.</li>\n</ul>\n<hr style=\"width: 100%; height: 2px;\">\n<br>\n<br>\n<br>\n<br>\n<br>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTL Modules.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n\t<title>EASTL Modules</title>\n\t<meta content=\"text/html; charset=us-ascii\" http-equiv=\"content-type\">\n\t<meta name=\"author\" content=\"Paul Pedriana\">\n\t<meta name=\"description\" content=\"Lists the top-level modules present in EASTL.\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"EASTLDoc.css\">\n    <style type=\"text/css\">\n<!--\n.style1 {font-size: 10pt}\n-->\n    </style>\n</head>\n<body>\n<h1><font size=\"+3\">EASTL Modules</font></h1>\n<h2>  Introduction</h2>\n<p>We provide here a list of all top-level modules present or planned for future presence in EASTL. In some cases (e.g.\n  algorithm), the module consists of many smaller submodules which are not described in detail here. In those cases you\n  should consult the source code for those modules or consult the detailed documentation for those modules. This document\nis a high level overview and not a detailed document.</p>\n<h2>Module List</h2>\n<table style=\"text-align: left; width: 100%;\" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n<tbody>\n<tr>\n<td style=\"font-weight: bold;\">&nbsp;Module</td>\n<td style=\"font-weight: bold;\">Description</td>\n</tr>\n<tr>\n<td>config</td>\n<td>Configuration header. Allows for changing some compile-time options.</td>\n</tr>\n<tr>\n<td>slist<br>\nfixed_slist</td>\n<td>Singly-linked list.<br>\nfixed_slist is a version which is implemented via a fixed block of contiguous memory.</td>\n</tr>\n<tr>\n<td>list<br>\nfixed_list</td>\n<td>Doubly-linked list.</td>\n</tr>\n<tr>\n<td>intrusive_list<br>\nintrusive_slist</td>\n<td>List whereby the contained item provides the node implementation.</td>\n</tr>\n<tr>\n<td>array</td>\n<td>Wrapper for a C-style array which extends it to act like an STL container.</td>\n</tr>\n<tr>\n<td>vector<br>\nfixed_vector</td>\n<td>Resizable array container.</td>\n</tr>\n<tr>\n<td>vector_set<br>\nvector_multiset<br></td>\n<td>Set implemented via a vector instead of a tree. Speed and memory use is improved but resizing is slower.</td>\n</tr>\n<tr>\n<td>vector_map<br>\nvector_multimap<br></td>\n<td>Map implemented via a vector instead of a tree. Speed and memory use is improved but resizing is slower.</td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">deque<br></td>\n<td style=\"vertical-align: top;\">Double-ended queue, but also with random access. Acts like a vector but insertions and\nremovals are efficient.<br></td>\n</tr>\n<tr>\n<td>bit_vector</td>\n<td>Implements a vector of bool, but the actual storage is done with one bit per bool. Not the same thing as a\nbitset.</td>\n</tr>\n<tr>\n<td>bitset</td>\n<td>Implements an efficient arbitrarily-sized bitfield. Note that this is not strictly the same thing as a vector of\nbool (bit_vector), as it is optimized to act like an arbitrary set of flags and not to be a generic container which can\nbe iterated, inserted, removed, etc.</td>\n</tr>\n<tr>\n<td>set<br>\nmultiset<br>\nfixed_set<br>\nfixed_multiset<br></td>\n<td>A set is a sorted unique collection, multiset is sorted but non-unique collection.</td>\n</tr>\n<tr>\n<td>map<br>\nmultimap<br>\nfixed_map<br>\nfixed_multimap</td>\n<td>A map is a sorted associative collection implemented via a tree. It is also known as dictionary.</td>\n</tr>\n<tr>\n<td>hash_map<br>\nhash_multimap<br>\nfixed_hash_map<br>\nfixed_hash_multimap</td>\n<td>Map implemented via a hash table.</td>\n</tr>\n<tr>\n<td>intrusive_hash_map<br>\nintrusive_hash_multimap<br>\nintrusive_hash_set<br>\nintrusive_hash_multiset</td>\n<td>hash_map whereby the contained item provides the node implementation, much like intrusive_list.</td>\n</tr>\n<tr>\n<td>hash_set<br>\nhash_multiset<br>\nfixed_hash_set<br>\nfixed_hash_map<br></td>\n<td>Set implemented via a hash table.</td>\n</tr>\n<tr>\n<td>basic_string<br>\nfixed_string<br>\nfixed_substring</td>\n<td>basic_string is a character string/array.<br>\nfixed_substring is a string which is a reference to a range within another string or character array.<br>\ncow_string is a string which implements copy-on-write.</td>\n</tr>\n<tr>\n<td>algorithm</td>\n<td>min/max, find, binary_search, random_shuffle, reverse, etc.&nbsp;</td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">sort<br></td>\n<td style=\"vertical-align: top;\">Sorting functionality, including functionality not in STL. quick_sort, heap_sort,\nmerge_sort, shell_sort, insertion_sort, etc.<br></td>\n</tr>\n<tr>\n<td>numeric</td>\n<td>Numeric algorithms: accumulate, inner_product, partial_sum, adjacent_difference, etc.</td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">heap<br></td>\n<td style=\"vertical-align: top;\">Heap structure functionality: make_heap, push_heap, pop_heap, sort_heap, is_heap,\nremove_heap, etc.<br></td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">stack<br></td>\n<td style=\"vertical-align: top;\">Adapts any container into a stack.<br></td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">queue<br></td>\n<td style=\"vertical-align: top;\">Adapts any container into a queue.<br></td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">priority_queue<br></td>\n<td style=\"vertical-align: top;\">Implements a conventional priority queue via a heap structure.<br></td>\n</tr>\n<tr>\n<td>type_traits</td>\n<td>Type information, useful for writing optimized and robust code. Also used for implementing optimized containers and\nalgorithms.</td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">utility<br></td>\n<td style=\"vertical-align: top;\">pair, make_pair, rel_ops, etc.<br></td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">functional<br></td>\n<td style=\"vertical-align: top;\">Function objects.<br></td>\n</tr>\n<tr>\n<td style=\"vertical-align: top;\">iterator<br></td>\n<td style=\"vertical-align: top;\">Iteration for containers and algorithms.<br></td>\n</tr>\n<tr>\n<td>smart_ptr</td>\n<td>Smart pointers:&nbsp;shared_ptr, shared_array, weak_ptr, scoped_ptr, scoped_array, linked_ptr, linked_array,\nintrusive_ptr.</td>\n</tr>\n</tbody>\n</table>\n<p>&nbsp;</p>\n<h2>Module Behaviour</h2>\n<p>The overhead sizes listed here refer to an optimized release build; debug builds may add some additional overhead. Some\n  of the overhead sizes may be off by a little bit (usually at most 4 bytes). This is because the values reported here\n  are those that refer to when EASTL's container optimizations have been complete. These optimizations may not have been\n  completed as you are reading this.</p>\n<table style=\"width: 100%;\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 15%; vertical-align: top; height: 13px; font-weight: bold;\">\n<p>Container</p>\n</td>\n<td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\">\n<p>Stores</p>\n</td>\n<td style=\"font-weight: bold; text-align: center;\">Container Overhead (32 bit)</td>\n<td style=\"font-weight: bold; text-align: center;\">Container Overhead (64 bit)</td>\n<td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\">\n<p>Node Overhead (32 bit)</p>\n</td>\n<td style=\"font-weight: bold; text-align: center;\">Node Overhead (64 bit)</td>\n<td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"9%\">\n<p>Iterator category</p>\n</td>\n<td style=\"text-align: center; font-weight: bold;\">size() efficiency</td>\n<td style=\"text-align: center; font-weight: bold;\">operator[] efficiency</td>\n<td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\">\n<p>Insert efficiency</p>\n</td>\n<td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\">\n<p>Erase via Iterator efficiency</p>\n</td>\n<td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"7%\">\n<p>Find efficiency</p>\n</td>\n<td style=\"font-weight: bold; text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\">\n<p>Sort efficiency</p>\n</td>\n</tr>\n<tr>\n<td>slist</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">f</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n+</td>\n</tr>\n<tr>\n<td height=\"13\" valign=\"top\" width=\"15%\">\n<p>list</p>\n</td>\n<td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\">\n<p>T</p>\n</td>\n<td style=\"text-align: center;\">12</td>\n<td style=\"text-align: center;\">24</td>\n<td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\">\n<p>8</p>\n</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"9%\">\n<p>b</p>\n</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\">\n<p>1</p>\n</td>\n<td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"16%\">\n<p>1</p>\n</td>\n<td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"7%\">\n<p>n</p>\n</td>\n<td style=\"text-align: center;\" height=\"13\" valign=\"top\" width=\"10%\">\n<p>n log(n)</p>\n</td>\n</tr>\n<tr>\n<td>intrusive_slist</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">f</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n+</td>\n</tr>\n<tr>\n<td>intrusive_list</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n log(n)</td>\n</tr>\n<tr>\n<td>array</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n log(n)</td>\n</tr>\n<tr>\n<td>vector</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">32</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n log(n)</td>\n</tr>\n<tr>\n<td>vector_set</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">32</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>vector_multiset</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">32</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>vector_map</td>\n<td style=\"text-align: center;\">Key, T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">32</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>vector_multimap</td>\n<td style=\"text-align: center;\">Key, T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">32</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>deque</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">44</td>\n<td style=\"text-align: center;\">84</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at begin or end,<br>\nelse n / 2</td>\n<td style=\"text-align: center;\">1&nbsp;at begin or end,<br>\nelse n / 2</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n log(n)</td>\n</tr>\n<tr>\n<td>bit_vector</td>\n<td style=\"text-align: center;\">bool</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n log(n)</td>\n</tr>\n<tr>\n<td>string (all types)</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">32</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">0</td>\n<td style=\"text-align: center;\">r</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">1&nbsp;at end, else n</td>\n<td style=\"text-align: center;\">n</td>\n<td style=\"text-align: center;\">n log(n)</td>\n</tr>\n<tr>\n<td>set</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">24</td>\n<td style=\"text-align: center;\">44</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">28</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>multiset</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">24</td>\n<td style=\"text-align: center;\">44</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">28</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>map</td>\n<td style=\"text-align: center;\">Key, T</td>\n<td style=\"text-align: center;\">24</td>\n<td style=\"text-align: center;\">44</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">28</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>multimap</td>\n<td style=\"text-align: center;\">Key, T</td>\n<td style=\"text-align: center;\">24</td>\n<td style=\"text-align: center;\">44</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">28</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">log(n)</td>\n<td style=\"text-align: center;\">1</td>\n</tr>\n<tr>\n<td>hash_set</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n<tr>\n<td>hash_multiset</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1<br></td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n<tr>\n<td>hash_map</td>\n<td style=\"text-align: center;\">Key, T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n<tr>\n<td>hash_multimap</td>\n<td style=\"text-align: center;\">Key, T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n<tr>\n<td>intrusive_hash_set</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n<tr>\n<td>intrusive_hash_multiset</td>\n<td style=\"text-align: center;\">T</td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n<tr>\n<td>intrusive_hash_map</td>\n<td style=\"text-align: center;\">T <small>(Key == T)</small></td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n<tr>\n<td>intrusive_hash_multimap</td>\n<td style=\"text-align: center;\">T <small>(Key == T)&nbsp;</small></td>\n<td style=\"text-align: center;\">16</td>\n<td style=\"text-align: center;\">20</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: center;\">8</td>\n<td style=\"text-align: center;\">b</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: center;\">-</td>\n</tr>\n</tbody>\n</table>\n<ul>\n<li>- means that the operation does not exist.</li>\n<li>1 means amortized constant time. Also known as O(1)</li>\n<li>n means time proportional to the container size. Also known as O(n)</li>\n<li>log(n) means time proportional to the natural logarithm of the container size. Also known as O(log(n))</li>\n<li>n log(n) means time proportional to log(n) times the size of the container. Also known as O(n log(n))</li>\n<li>n+ means that the time is at least n, and possibly higher.</li>\n<li>Iterator meanings are: f = forward iterator; b = bidirectional iterator, r = random iterator.</li>\n<li>Overhead indicates approximate per-element overhead memory required in bytes. Overhead doesn't include possible\nadditional overhead that may be imposed by the memory heap used to allocate nodes. General heaps tend to have between 4\nand 16 bytes of overhead per allocation, depending on the heap.</li>\n<li>Some overhead values are dependent on the structure alignment characteristics in effect. The values reported here\nare those that would be in effect for a system that requires pointers to be aligned on boundaries of their size and\nallocations with a minimum of 4 bytes (thus one byte values get rounded up to 4).</li>\n<li>Some overhead values are dependent on the size_type used by containers. size_type defaults to size_t, but it is possible to force it to be 4 bytes for 64 bit machines by defining EASTL_SIZE_T_32BIT.</li>\n<li>Inserting at the end of a vector may cause the vector to be resized; resizing a vector is O(n). However, the\namortized time complexity for vector insertions at the end is constant.</li>\n<li>Sort assumes the usage of the best possible sort for a large container of random data. Some sort algorithms (e.g.\nquick_sort) require random access iterators and so the sorting of some containers requires a different sort algorithm.\nWe do not include bucket or radix sorts, as they are always O(n).</li>\n<li>Some containers (e.g. deque, hash*) have unusual data structures that make per-container and per-node overhead\ncalculations not quite account for all memory.</li>\n</ul>\n<hr style=\"width: 100%; height: 2px;\">\nEnd of document<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n<br>\n</body>\n</html>\n"
  },
  {
    "path": "doc/html/EASTLDoc.css",
    "content": "body \n{\n\tfont-family: Georgia, \"Times New Roman\", Times, serif;\n\tfont-size: 12pt;\n}\n\nh1\n{\n\tfont-family: Verdana, Arial, Helvetica, sans-serif;\n\tdisplay: block;\n\tbackground-color: #BBCCDD;\n\tborder: 2px solid #000000;\n\tfont-size: 16pt;\n\tfont-weight: bold;\n\tpadding: 6px;\n}\n\nh2 \n{\n\tfont-size: 14pt;\n\tfont-family: Verdana;\n\tborder-bottom: 2px solid black;\n}\n\nh3\n{\n\tfont-family: Verdana;\n\tfont-size: 13pt;\n\tfont-weight: bold;\n}\n\n.code-example \n{\n\tdisplay: block;\n\tbackground-color: #D1DDE9;\n\tmargin-left: 3em;\n\tmargin-right: 3em;\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n\tpadding: 8px;\n\tborder: 2px solid #7993C8;\n\tfont-family: \"Courier New\", Courier, mono;\n\tfont-size: 10pt;\n\twhite-space: pre;\n}\n\n.code-example-span \n{\n\tfont-family: \"Courier New\", Courier, mono;\n\tfont-size: 10pt;\n\twhite-space: pre;\n}\n\n.code-example-comment\n{\n\tbackground-color: #e0e0f0; \n\tpadding: 0px 0px; \n\tfont-family: \"Courier New\", Courier, mono; \n\tfont-size: 10pt; \n\twhite-space: pre; \n\tcolor: #999999; \n\tmargin: auto auto; \n}\n\n\n.faq-question\n{\n\tbackground-color: #D9E2EC;\n\tfont-size: 12pt;\n\tfont-weight: bold;\n\tmargin-top: 0em;\n\tpadding-left:5px;\n\tpadding-right:8px;\n\tpadding-top:2px;\n\tpadding-bottom:3px;\n\tmargin-bottom: 0.5em;\n}\n\n.faq-answer\n{\n\tdisplay: block;\n\tmargin: 4pt 1em 0.8em;\n}\n.indented {\n\tmargin-left: 50px;\n}\n"
  },
  {
    "path": "include/EASTL/algorithm.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements some of the primary algorithms from the C++ STL\n// algorithm library. These versions are just like that STL versions and so\n// are redundant. They are provided solely for the purpose of projects that\n// either cannot use standard C++ STL or want algorithms that have guaranteed\n// identical behaviour across platforms.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Definitions\n//\n// You will notice that we are very particular about the templated typenames\n// we use here. You will notice that we follow the C++ standard closely in\n// these respects. Each of these typenames have a specific meaning;\n// this is why we don't just label templated arguments with just letters\n// such as T, U, V, A, B. Here we provide a quick reference for the typenames\n// we use. See the C++ standard, section 25-8 for more details.\n//    --------------------------------------------------------------\n//    typename                     Meaning\n//    --------------------------------------------------------------\n//    T                            The value type.\n//    Compare                      A function which takes two arguments and returns the lesser of the two.\n//    Predicate                    A function which takes one argument returns true if the argument meets some criteria.\n//    BinaryPredicate              A function which takes two arguments and returns true if some criteria is met (e.g. they are equal).\n//    StrickWeakOrdering           A BinaryPredicate that compares two objects, returning true if the first precedes the second. Like Compare but has additional requirements. Used for sorting routines.\n//    Function                     A function which takes one argument and applies some operation to the target.\n//    Size                         A count or size.\n//    Generator                    A function which takes no arguments and returns a value (which will usually be assigned to an object).\n//    UnaryOperation               A function which takes one argument and returns a value (which will usually be assigned to second object).\n//    BinaryOperation              A function which takes two arguments and returns a value (which will usually be assigned to a third object).\n//    InputIterator                An input iterator (iterator you read from) which allows reading each element only once and only in a forward direction.\n//    ForwardIterator              An input iterator which is like InputIterator except it can be reset back to the beginning.\n//    BidirectionalIterator        An input iterator which is like ForwardIterator except it can be read in a backward direction as well.\n//    RandomAccessIterator         An input iterator which can be addressed like an array. It is a superset of all other input iterators.\n//    OutputIterator               An output iterator (iterator you write to) which allows writing each element only once in only in a forward direction.\n//\n// Note that with iterators that a function which takes an InputIterator will\n// also work with a ForwardIterator, BidirectionalIterator, or RandomAccessIterator.\n// The given iterator type is merely the -minimum- supported functionality the\n// iterator must support.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Optimizations\n//\n// There are a number of opportunities for optimizations that we take here\n// in this library. The most obvious kinds are those that subsitute memcpy\n// in the place of a conventional loop for data types with which this is\n// possible. The algorithms here are optimized to a higher level than currently\n// available C++ STL algorithms from vendors such as Microsoft. This is especially\n// so for game programming on console devices, as we do things such as reduce\n// branching relative to other STL algorithm implementations. However, the\n// proper implementation of these algorithm optimizations is a fairly tricky\n// thing.\n//\n// The various things we look to take advantage of in order to implement\n// optimizations include:\n//    - Taking advantage of random access iterators.\n//    - Taking advantage of trivially copyable data types (types for which it is safe to memcpy or memmove).\n//    - Taking advantage of type_traits in general.\n//    - Reducing branching and taking advantage of likely branch predictions.\n//    - Taking advantage of issues related to pointer and reference aliasing.\n//    - Improving cache coherency during memory accesses.\n//    - Making code more likely to be inlinable by the compiler.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Supported Algorithms\n//\n// Algorithms that we implement are listed here. Note that these items are not\n// all within this header file, as we split up the header files in order to\n// improve compilation performance. Items marked with '+' are items that are\n// extensions which don't exist in the C++ standard.\n//\n//    -------------------------------------------------------------------------------\n//      Algorithm                                   Notes\n//    -------------------------------------------------------------------------------\n//      adjacent_find\n//      adjacent_find<Compare>\n//      all_of                                      C++11\n//      any_of                                      C++11\n//      none_of                                     C++11\n//      binary_search\n//      binary_search<Compare>\n//     +binary_search_i\n//     +binary_search_i<Compare>\n//     +change_heap                                 Found in heap.h\n//     +change_heap<Compare>                        Found in heap.h\n//      clamp\n//      copy\n//      copy_if                                     C++11\n//      copy_n                                      C++11\n//      copy_backward\n//      count\n//      count_if\n//      equal\n//      equal<Compare>\n//      equal_range\n//      equal_range<Compare>\n//      fill\n//      fill_n\n//      find\n//      find_end\n//      find_end<Compare>\n//      find_first_of\n//      find_first_of<Compare>\n//     +find_first_not_of\n//     +find_first_not_of<Compare>\n//     +find_last_of\n//     +find_last_of<Compare>\n//     +find_last_not_of\n//     +find_last_not_of<Compare>\n//      find_if\n//      find_if_not\n//      for_each\n//      generate\n//      generate_n\n//     +identical\n//     +identical<Compare>\n//      iter_swap\n//      lexicographical_compare\n//      lexicographical_compare<Compare>\n//      lexicographical_compare_three_way\n//      lower_bound\n//      lower_bound<Compare>\n//      make_heap                                   Found in heap.h\n//      make_heap<Compare>                          Found in heap.h\n//      min\n//      min<Compare>\n//      max\n//      max<Compare>\n//     +min_alt                                     Exists to work around the problem of conflicts with min/max #defines on some systems.\n//     +min_alt<Compare>\n//     +max_alt\n//     +max_alt<Compare>\n//     +median\n//     +median<Compare>\n//      merge                                       Found in sort.h\n//      merge<Compare>                              Found in sort.h\n//      min_element\n//      min_element<Compare>\n//      max_element\n//      max_element<Compare>\n//      mismatch\n//      mismatch<Compare>\n//      move\n//      move_backward\n//      nth_element                                 Found in sort.h\n//      nth_element<Compare>                        Found in sort.h\n//      partial_sort                                Found in sort.h\n//      partial_sort<Compare>                       Found in sort.h\n//      push_heap                                   Found in heap.h\n//      push_heap<Compare>                          Found in heap.h\n//      pop_heap                                    Found in heap.h\n//      pop_heap<Compare>                           Found in heap.h\n//      random_shuffle<Random>\n//      remove\n//      remove_if\n//     +apply_and_remove\n//     +apply_and_remove_if\n//      remove_copy\n//      remove_copy_if\n//     +remove_heap                                 Found in heap.h\n//     +remove_heap<Compare>                        Found in heap.h\n//      replace\n//      replace_if\n//      replace_copy\n//      replace_copy_if\n//      reverse_copy\n//      reverse\n//      random_shuffle\n//      rotate\n//      rotate_copy\n//      search\n//      search<Compare>\n//      search_n\n//      set_difference\n//      set_difference<Compare>\n//      set_difference_2\n//      set_difference_2<Compare>\n//      set_decomposition\n//      set_decomposition<Compare>\n//      set_intersection\n//      set_intersection<Compare>\n//      set_symmetric_difference\n//      set_symmetric_difference<Compare>\n//      set_union\n//      set_union<Compare>\n//      sort                                        Found in sort.h\n//      sort<Compare>                               Found in sort.h\n//      sort_heap                                   Found in heap.h\n//      sort_heap<Compare>                          Found in heap.h\n//      stable_sort                                 Found in sort.h\n//      stable_sort<Compare>                        Found in sort.h\n//      partition                                   Found in sort.h\n//      stable_partition                            Found in sort.h\n//      swap\n//      swap_ranges\n//      transform\n//      transform<Operation>\n//      unique\n//      unique<Compare>\n//      upper_bound\n//      upper_bound<Compare>\n//      includes\n//      includes<Compare>\n//      is_permutation\n//      is_permutation<Predicate>\n//      next_permutation\n//      next_permutation<Compare>\n//      is_partitioned\n//      partition_point\n//\n// Algorithms from the C++ standard that we don't implement are listed here.\n// Most of these items are absent because they aren't used very often.\n// They also happen to be the more complicated than other algorithms.\n// However, we can implement any of these functions for users that might\n// need them.\n//      inplace_merge\n//      inplace_merge<Compare>\n//      partial_sort_copy\n//      partial_sort_copy<Compare>\n//      prev_permutation\n//      prev_permutation<Compare>\n//      search_n<Compare>\n//      unique_copy\n//      unique_copy<Compare>\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ALGORITHM_H\n#define EASTL_ALGORITHM_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/internal/copy_help.h>\n#include <EASTL/internal/fill_help.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/iterator.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n#include <EASTL/random.h>\n#include <EASTL/compare.h>\n\nEA_DISABLE_ALL_VC_WARNINGS();\n\n\t#if defined(EA_COMPILER_MSVC) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\t#include <intrin.h>\n\t#endif\n\n\t#include <stddef.h>\n\t#include <string.h> // memcpy, memcmp, memmove\n\nEA_RESTORE_ALL_VC_WARNINGS();\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// min/max workaround\n//\n// MSVC++ has #defines for min/max which collide with the min/max algorithm\n// declarations. The following may still not completely resolve some kinds of\n// problems with MSVC++ #defines, though it deals with most cases in production\n// game code.\n//\n#if EASTL_NOMINMAX\n\t#ifdef min\n\t\t#undef min\n\t#endif\n\t#ifdef max\n\t\t#undef max\n\t#endif\n#endif\n\n\n\n\nnamespace eastl\n{\n\t/// min_element\n\t///\n\t/// min_element finds the smallest element in the range [first, last).\n\t/// It returns the first iterator i in [first, last) such that no other\n\t/// iterator in [first, last) points to a value smaller than *i.\n\t/// The return value is last if and only if [first, last) is an empty range.\n\t///\n\t/// Returns: The first iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, last) the following corresponding\n\t/// condition holds: !(*j < *i).\n\t///\n\t/// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the\n\t/// corresponding comparisons.\n\t///\n\ttemplate <typename ForwardIterator>\n\tForwardIterator min_element(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator currentMin = first;\n\n\t\t\twhile(++first != last)\n\t\t\t{\n\t\t\t\tif(*first < *currentMin)\n\t\t\t\t\tcurrentMin = first;\n\t\t\t}\n\t\t\treturn currentMin;\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// min_element\n\t///\n\t/// min_element finds the smallest element in the range [first, last).\n\t/// It returns the first iterator i in [first, last) such that no other\n\t/// iterator in [first, last) points to a value smaller than *i.\n\t/// The return value is last if and only if [first, last) is an empty range.\n\t///\n\t/// Returns: The first iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, last) the following corresponding\n\t/// conditions hold: compare(*j, *i) == false.\n\t///\n\t/// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the\n\t/// corresponding comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename Compare>\n\tForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare compare)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator currentMin = first;\n\n\t\t\twhile(++first != last)\n\t\t\t{\n\t\t\t\tif(compare(*first, *currentMin))\n\t\t\t\t\tcurrentMin = first;\n\t\t\t}\n\t\t\treturn currentMin;\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// max_element\n\t///\n\t/// max_element finds the largest element in the range [first, last).\n\t/// It returns the first iterator i in [first, last) such that no other\n\t/// iterator in [first, last) points to a value greater than *i.\n\t/// The return value is last if and only if [first, last) is an empty range.\n\t///\n\t/// Returns: The first iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, last) the following corresponding\n\t/// condition holds: !(*i < *j).\n\t///\n\t/// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the\n\t/// corresponding comparisons.\n\t///\n\ttemplate <typename ForwardIterator>\n\tForwardIterator max_element(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator currentMax = first;\n\n\t\t\twhile(++first != last)\n\t\t\t{\n\t\t\t\tif(*currentMax < *first)\n\t\t\t\t\tcurrentMax = first;\n\t\t\t}\n\t\t\treturn currentMax;\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// max_element\n\t///\n\t/// max_element finds the largest element in the range [first, last).\n\t/// It returns the first iterator i in [first, last) such that no other\n\t/// iterator in [first, last) points to a value greater than *i.\n\t/// The return value is last if and only if [first, last) is an empty range.\n\t///\n\t/// Returns: The first iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, last) the following corresponding\n\t/// condition holds: compare(*i, *j) == false.\n\t///\n\t/// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the\n\t/// corresponding comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename Compare>\n\tForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare compare)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator currentMax = first;\n\n\t\t\twhile(++first != last)\n\t\t\t{\n\t\t\t\tif(compare(*currentMax, *first))\n\t\t\t\t\tcurrentMax = first;\n\t\t\t}\n\t\t\treturn currentMax;\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t#if EASTL_MINMAX_ENABLED\n\n\t\t/// min\n\t\t///\n\t\t/// Min returns the lesser of its two arguments; it returns the first\n\t\t/// argument if neither is less than the other. The two arguments are\n\t\t/// compared with operator <.\n\t\t///\n\t\t/// This min and our other min implementations are defined as returning:\n\t\t///     b < a ? b : a\n\t\t/// which for example may in practice result in something different than:\n\t\t///     b <= a ? b : a\n\t\t/// in the case where b is different from a (though they compare as equal).\n\t\t/// We choose the specific ordering here because that's the ordering\n\t\t/// done by other STL implementations.\n\t\t///\n\t\t/// Some compilers (e.g. VS20003 - VS2013) generate poor code for the case of\n\t\t/// scalars returned by reference, so we provide a specialization for those cases.\n\t\t/// The specialization returns T by value instead of reference, which is\n\t\t/// not that the Standard specifies. The Standard allows you to use\n\t\t/// an expression like &max(x, y), which would be impossible in this case.\n\t\t/// However, we have found no actual code that uses min or max like this and\n\t\t/// this specialization causes no problems in practice. Microsoft has acknowledged\n\t\t/// the problem and may fix it for a future VS version.\n\t\t///\n\t\ttemplate <typename T>\n\t\tinline EA_CONSTEXPR typename eastl::enable_if<eastl::is_scalar<T>::value, T>::type\n\t\tmin(T a, T b)\n\t\t{\n\t\t\treturn b < a ? b : a;\n\t\t}\n\n\t\ttemplate <typename T>\n\t\tinline EA_CONSTEXPR typename eastl::enable_if<!eastl::is_scalar<T>::value, const T&>::type\n\t\tmin(const T& a, const T& b)\n\t\t{\n\t\t\treturn b < a ? b : a;\n\t\t}\n\n\t\tinline EA_CONSTEXPR float       min(float  a, float   b)           { return b < a ? b : a; }\n\t\tinline EA_CONSTEXPR double      min(double a, double  b)           { return b < a ? b : a; }\n\t\tinline EA_CONSTEXPR long double min(long double a, long double  b) { return b < a ? b : a; }\n\n\t#endif // EASTL_MINMAX_ENABLED\n\n\n\t/// min_alt\n\t///\n\t/// This is an alternative version of min that avoids any possible\n\t/// collisions with Microsoft #defines of min and max.\n\t///\n\t/// See min(a, b) for detailed specifications.\n\t///\n\ttemplate <typename T>\n\tinline EA_CONSTEXPR typename eastl::enable_if<eastl::is_scalar<T>::value, T>::type\n\tmin_alt(T a, T b)\n\t{\n\t\treturn b < a ? b : a;\n\t}\n\n\ttemplate <typename T>\n\tinline typename eastl::enable_if<!eastl::is_scalar<T>::value, const T&>::type\n\tmin_alt(const T& a, const T& b)\n\t{\n\t\treturn b < a ? b : a;\n\t}\n\n\tinline EA_CONSTEXPR float       min_alt(float  a, float   b)           { return b < a ? b : a; }\n\tinline EA_CONSTEXPR double      min_alt(double a, double  b)           { return b < a ? b : a; }\n\tinline EA_CONSTEXPR long double min_alt(long double a, long double  b) { return b < a ? b : a; }\n\n\n\t#if EASTL_MINMAX_ENABLED\n\n\t\t/// min\n\t\t///\n\t\t/// Min returns the lesser of its two arguments; it returns the first\n\t\t/// argument if neither is less than the other. The two arguments are\n\t\t/// compared with the Compare function (or function object), which\n\t\t/// takes two arguments and returns true if the first is less than\n\t\t/// the second.\n\t\t///\n\t\t/// See min(a, b) for detailed specifications.\n\t\t///\n\t\t/// Example usage:\n\t\t///    struct A{ int a; };\n\t\t///    struct Struct{ bool operator()(const A& a1, const A& a2){ return a1.a < a2.a; } };\n\t\t///\n\t\t///    A a1, a2, a3;\n\t\t///    a3 = min(a1, a2, Struct());\n\t\t///\n\t\t/// Example usage:\n\t\t///    struct B{ int b; };\n\t\t///    inline bool Function(const B& b1, const B& b2){ return b1.b < b2.b; }\n\t\t///\n\t\t///    B b1, b2, b3;\n\t\t///    b3 = min(b1, b2, Function);\n\t\t///\n\t\ttemplate <typename T, typename Compare>\n\t\tinline const T&\n\t\tmin(const T& a, const T& b, Compare compare)\n\t\t{\n\t\t\treturn compare(b, a) ? b : a;\n\t\t}\n\n\t#endif // EASTL_MINMAX_ENABLED\n\n\n\t/// min_alt\n\t///\n\t/// This is an alternative version of min that avoids any possible\n\t/// collisions with Microsoft #defines of min and max.\n\t///\n\t/// See min(a, b) for detailed specifications.\n\t///\n\ttemplate <typename T, typename Compare>\n\tinline const T&\n\tmin_alt(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn compare(b, a) ? b : a;\n\t}\n\n\n\t#if EASTL_MINMAX_ENABLED\n\n\t\t/// max\n\t\t///\n\t\t/// Max returns the greater of its two arguments; it returns the first\n\t\t/// argument if neither is greater than the other. The two arguments are\n\t\t/// compared with operator < (and not operator >).\n\t\t///\n\t\t/// This min and our other min implementations are defined as returning:\n\t\t///     a < b ? b : a\n\t\t/// which for example may in practice result in something different than:\n\t\t///     a <= b ? b : a\n\t\t/// in the case where b is different from a (though they compare as equal).\n\t\t/// We choose the specific ordering here because that's the ordering\n\t\t/// done by other STL implementations.\n\t\t///\n\t\ttemplate <typename T>\n\t\tinline EA_CONSTEXPR typename eastl::enable_if<eastl::is_scalar<T>::value, T>::type\n\t\tmax(T a, T b)\n\t\t{\n\t\t\treturn a < b ? b : a;\n\t\t}\n\n\t\ttemplate <typename T>\n\t\tinline EA_CONSTEXPR typename eastl::enable_if<!eastl::is_scalar<T>::value, const T&>::type\n\t\tmax(const T& a, const T& b)\n\t\t{\n\t\t\treturn a < b ? b : a;\n\t\t}\n\n\t\tinline EA_CONSTEXPR float       max(float       a, float       b) { return a < b ? b : a; }\n\t\tinline EA_CONSTEXPR double      max(double      a, double      b) { return a < b ? b : a; }\n\t\tinline EA_CONSTEXPR long double max(long double a, long double b) { return a < b ? b : a; }\n\n\t#endif // EASTL_MINMAX_ENABLED\n\n\n\t/// max_alt\n\t///\n\t/// This is an alternative version of max that avoids any possible\n\t/// collisions with Microsoft #defines of min and max.\n\t///\n\ttemplate <typename T>\n\tinline EA_CONSTEXPR typename eastl::enable_if<eastl::is_scalar<T>::value, T>::type\n\tmax_alt(T a, T b)\n\t{\n\t\treturn a < b ? b : a;\n\t}\n\n\ttemplate <typename T>\n\tinline EA_CONSTEXPR typename eastl::enable_if<!eastl::is_scalar<T>::value, const T&>::type\n\tmax_alt(const T& a, const T& b)\n\t{\n\t\treturn a < b ? b : a;\n\t}\n\n\tinline EA_CONSTEXPR float       max_alt(float       a, float       b) { return a < b ? b : a; }\n\tinline EA_CONSTEXPR double      max_alt(double      a, double      b) { return a < b ? b : a; }\n\tinline EA_CONSTEXPR long double max_alt(long double a, long double b) { return a < b ? b : a; }\n\n\n\t#if EASTL_MINMAX_ENABLED\n\t\t/// max\n\t\t///\n\t\t/// Min returns the lesser of its two arguments; it returns the first\n\t\t/// argument if neither is less than the other. The two arguments are\n\t\t/// compared with the Compare function (or function object), which\n\t\t/// takes two arguments and returns true if the first is less than\n\t\t/// the second.\n\t\t///\n\t\ttemplate <typename T, typename Compare>\n\t\tinline const T&\n\t\tmax(const T& a, const T& b, Compare compare)\n\t\t{\n\t\t\treturn compare(a, b) ? b : a;\n\t\t}\n\t#endif\n\n\n\t/// max_alt\n\t///\n\t/// This is an alternative version of max that avoids any possible\n\t/// collisions with Microsoft #defines of min and max.\n\t///\n\ttemplate <typename T, typename Compare>\n\tinline const T&\n\tmax_alt(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn compare(a, b) ? b : a;\n\t}\n\n\n\t/// min(std::initializer_list)\n\t///\n\ttemplate <typename T >\n\tT min(std::initializer_list<T> ilist)\n\t{\n\t\treturn *eastl::min_element(ilist.begin(), ilist.end());\n\t}\n\n\t/// min(std::initializer_list, Compare)\n\t///\n\ttemplate <typename T, typename Compare>\n\tT min(std::initializer_list<T> ilist, Compare compare)\n\t{\n\t\treturn *eastl::min_element(ilist.begin(), ilist.end(), compare);\n\t}\n\n\n\t/// max(std::initializer_list)\n\t///\n\ttemplate <typename T >\n\tT max(std::initializer_list<T> ilist)\n\t{\n\t\treturn *eastl::max_element(ilist.begin(), ilist.end());\n\t}\n\n\t/// max(std::initializer_list, Compare)\n\t///\n\ttemplate <typename T, typename Compare>\n\tT max(std::initializer_list<T> ilist, Compare compare)\n\t{\n\t\treturn *eastl::max_element(ilist.begin(), ilist.end(), compare);\n\t}\n\n\n\t/// minmax_element\n\t///\n\t/// Returns: make_pair(first, first) if [first, last) is empty, otherwise make_pair(m, M),\n\t/// where m is the first iterator in [first,last) such that no iterator in the range\n\t/// refers to a smaller element, and where M is the last iterator in [first,last) such\n\t/// that no iterator in the range refers to a larger element.\n\t///\n\t/// Complexity: At most max([(3/2)*(N - 1)], 0) applications of the corresponding predicate,\n\t/// where N is distance(first, last).\n\t///\n\ttemplate <typename ForwardIterator, typename Compare>\n\teastl::pair<ForwardIterator, ForwardIterator>\n\tminmax_element(ForwardIterator first, ForwardIterator last, Compare compare)\n\t{\n\t\teastl::pair<ForwardIterator, ForwardIterator> result(first, first);\n\n\t\tif(!(first == last) && !(++first == last))\n\t\t{\n\t\t\tif(compare(*first, *result.first))\n\t\t\t{\n\t\t\t\tresult.second = result.first;\n\t\t\t\tresult.first = first;\n\t\t\t}\n\t\t\telse\n\t\t\t\tresult.second = first;\n\n\t\t\twhile(++first != last)\n\t\t\t{\n\t\t\t\tForwardIterator i = first;\n\n\t\t\t\tif(++first == last)\n\t\t\t\t{\n\t\t\t\t\tif(compare(*i, *result.first))\n\t\t\t\t\t\tresult.first = i;\n\t\t\t\t\telse if(!compare(*i, *result.second))\n\t\t\t\t\t\tresult.second = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(compare(*first, *i))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(compare(*first, *result.first))\n\t\t\t\t\t\t\tresult.first = first;\n\n\t\t\t\t\t\tif(!compare(*i, *result.second))\n\t\t\t\t\t\t\tresult.second = i;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif(compare(*i, *result.first))\n\t\t\t\t\t\t\tresult.first = i;\n\n\t\t\t\t\t\tif(!compare(*first, *result.second))\n\t\t\t\t\t\t\tresult.second = first;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename ForwardIterator>\n\teastl::pair<ForwardIterator, ForwardIterator>\n\tminmax_element(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\n\t\treturn eastl::minmax_element(first, last, eastl::less<value_type>());\n\t}\n\n\n\n\t/// minmax\n\t///\n\t/// Requires: Type T shall be LessThanComparable.\n\t/// Returns: pair<const T&, const T&>(b, a) if b is smaller than a, and pair<const T&, const T&>(a, b) otherwise.\n\t/// Remarks: Returns pair<const T&, const T&>(a, b) when the arguments are equivalent.\n\t/// Complexity: Exactly one comparison.\n\t///\n\n\t// The following optimization is a problem because it changes the return value in a way that would break\n\t// users unless they used auto (e.g. auto result = minmax(17, 33); )\n\t//\n\t// template <typename T>\n\t// inline EA_CONSTEXPR typename eastl::enable_if<eastl::is_scalar<T>::value, eastl::pair<T, T> >::type\n\t// minmax(T a, T b)\n\t// {\n\t//     return (b < a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);\n\t// }\n\t//\n\t// template <typename T>\n\t// inline typename eastl::enable_if<!eastl::is_scalar<T>::value, eastl::pair<const T&, const T&> >::type\n\t// minmax(const T& a, const T& b)\n\t// {\n\t//     return (b < a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);\n\t// }\n\n\t// It turns out that the following conforming definition of minmax generates a warning when used with VC++ up\n\t// to at least VS2012. The VS2012 version of minmax is a broken and non-conforming definition, and we don't\n\t// want to do that. We could do it for scalars alone, though we'd have to decide if we are going to do that\n\t// for all compilers, because it changes the return value from a pair of references to a pair of values.\n\ttemplate <typename T>\n\tinline eastl::pair<const T&, const T&>\n\tminmax(const T& a, const T& b)\n\t{\n\t\treturn (b < a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);\n\t}\n\n\n\ttemplate <typename T, typename Compare>\n\teastl::pair<const T&, const T&>\n\tminmax(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn compare(b, a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);\n\t}\n\n\n\n\ttemplate <typename T>\n\teastl::pair<T, T>\n\tminmax(std::initializer_list<T> ilist)\n\t{\n\t\ttypedef typename std::initializer_list<T>::iterator iterator_type;\n\t\teastl::pair<iterator_type, iterator_type> iteratorPair = eastl::minmax_element(ilist.begin(), ilist.end());\n\t\treturn eastl::make_pair(*iteratorPair.first, *iteratorPair.second);\n\t}\n\n\ttemplate <typename T, class Compare>\n\teastl::pair<T, T>\n\tminmax(std::initializer_list<T> ilist, Compare compare)\n\t{\n\t\ttypedef typename std::initializer_list<T>::iterator iterator_type;\n\t\teastl::pair<iterator_type, iterator_type> iteratorPair = eastl::minmax_element(ilist.begin(), ilist.end(), compare);\n\t\treturn eastl::make_pair(*iteratorPair.first, *iteratorPair.second);\n\t}\n\n\ttemplate <typename T>\n\tinline T&& median_impl(T&& a, T&& b, T&& c)\n\t{\n\t\tif(a < b)\n\t\t{\n\t\t\tif(b < c)\n\t\t\t\treturn eastl::forward<T>(b);\n\t\t\telse if(a < c)\n\t\t\t\treturn eastl::forward<T>(c);\n\t\t\telse\n\t\t\t\treturn eastl::forward<T>(a);\n\t\t}\n\t\telse if(a < c)\n\t\t\treturn eastl::forward<T>(a);\n\t\telse if(b < c)\n\t\t\treturn eastl::forward<T>(c);\n\t\treturn eastl::forward<T>(b);\n\t}\n\n\t/// median\n\t///\n\t/// median finds which element of three (a, b, d) is in-between the other two.\n\t/// If two or more elements are equal, the first (e.g. a before b) is chosen.\n\t///\n\t/// Complexity: Either two or three comparisons will be required, depending\n\t/// on the values.\n\t///\n\ttemplate <typename T>\n\tinline const T& median(const T& a, const T& b, const T& c)\n\t{\n\t\treturn median_impl(a, b, c);\n\t}\n\n\t/// median\n\t///\n\t/// median finds which element of three (a, b, d) is in-between the other two.\n\t/// If two or more elements are equal, the first (e.g. a before b) is chosen.\n\t///\n\t/// Complexity: Either two or three comparisons will be required, depending\n\t/// on the values.\n\t///\n\ttemplate <typename T>\n\tinline T&& median(T&& a, T&& b, T&& c)\n\t{\n\t\treturn eastl::forward<T>(median_impl(eastl::forward<T>(a), eastl::forward<T>(b), eastl::forward<T>(c)));\n\t}\n\n\n\ttemplate <typename T, typename Compare>\n\tinline T&& median_impl(T&& a, T&& b, T&& c, Compare compare)\n\t{\n\t\tif(compare(a, b))\n\t\t{\n\t\t\tif(compare(b, c))\n\t\t\t\treturn eastl::forward<T>(b);\n\t\t\telse if(compare(a, c))\n\t\t\t\treturn eastl::forward<T>(c);\n\t\t\telse\n\t\t\t\treturn eastl::forward<T>(a);\n\t\t}\n\t\telse if(compare(a, c))\n\t\t\treturn eastl::forward<T>(a);\n\t\telse if(compare(b, c))\n\t\t\treturn eastl::forward<T>(c);\n\t\treturn eastl::forward<T>(b);\n\t}\n\n\n\t/// median\n\t///\n\t/// median finds which element of three (a, b, d) is in-between the other two.\n\t/// If two or more elements are equal, the first (e.g. a before b) is chosen.\n\t///\n\t/// Complexity: Either two or three comparisons will be required, depending\n\t/// on the values.\n\t///\n\ttemplate <typename T, typename Compare>\n\tinline const T& median(const T& a, const T& b, const T& c, Compare compare)\n\t{\n\t\treturn median_impl<const T&, Compare>(a, b, c, compare);\n\t}\n\n\t/// median\n\t///\n\t/// median finds which element of three (a, b, d) is in-between the other two.\n\t/// If two or more elements are equal, the first (e.g. a before b) is chosen.\n\t///\n\t/// Complexity: Either two or three comparisons will be required, depending\n\t/// on the values.\n\t///\n\ttemplate <typename T, typename Compare>\n\tinline T&& median(T&& a, T&& b, T&& c, Compare compare)\n\t{\n\t\treturn eastl::forward<T>(median_impl<T&&, Compare>(eastl::forward<T>(a), eastl::forward<T>(b), eastl::forward<T>(c), compare));\n\t}\n\n\n\n\n\t/// all_of\n\t///\n\t/// Returns: true if the unary predicate p returns true for all elements in the range [first, last)\n\t///\n\ttemplate <typename InputIterator, typename Predicate>\n\tinline bool all_of(InputIterator first, InputIterator last, Predicate p)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(!p(*first))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\n\t/// any_of\n\t///\n\t/// Returns: true if the unary predicate p returns true for any of the elements in the range [first, last)\n\t///\n\ttemplate <typename InputIterator, typename Predicate>\n\tinline bool any_of(InputIterator first, InputIterator last, Predicate p)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(p(*first))\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\n\t/// none_of\n\t///\n\t/// Returns: true if the unary predicate p returns true for none of the elements in the range [first, last)\n\t///\n\ttemplate <typename InputIterator, typename Predicate>\n\tinline bool none_of(InputIterator first, InputIterator last, Predicate p)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(p(*first))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\n\t/// adjacent_find\n\t///\n\t/// Returns: The first iterator i such that both i and i + 1 are in the range\n\t/// [first, last) for which the following corresponding conditions hold: *i == *(i + 1).\n\t/// Returns last if no such iterator is found.\n\t///\n\t/// Complexity: Exactly 'find(first, last, value) - first' applications of the corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator>\n\tinline ForwardIterator\n\tadjacent_find(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator i = first;\n\n\t\t\tfor(++i; i != last; ++i)\n\t\t\t{\n\t\t\t\tif(*first == *i)\n\t\t\t\t\treturn first;\n\t\t\t\tfirst = i;\n\t\t\t}\n\t\t}\n\t\treturn last;\n\t}\n\n\n\n\t/// adjacent_find\n\t///\n\t/// Returns: The first iterator i such that both i and i + 1 are in the range\n\t/// [first, last) for which the following corresponding conditions hold: predicate(*i, *(i + 1)) != false.\n\t/// Returns last if no such iterator is found.\n\t///\n\t/// Complexity: Exactly 'find(first, last, value) - first' applications of the corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator, typename BinaryPredicate>\n\tinline ForwardIterator\n\tadjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate predicate)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator i = first;\n\n\t\t\tfor(++i; i != last; ++i)\n\t\t\t{\n\t\t\t\tif(predicate(*first, *i))\n\t\t\t\t\treturn first;\n\t\t\t\tfirst = i;\n\t\t\t}\n\t\t}\n\t\treturn last;\n\t}\n\n\n\t/// shuffle\n\t///\n\t/// New for C++11\n\t/// Randomizes a sequence of values via a user-supplied UniformRandomNumberGenerator.\n\t/// The difference between this and the original random_shuffle function is that this uses the more\n\t/// advanced and flexible UniformRandomNumberGenerator interface as opposed to the more\n\t/// limited RandomNumberGenerator interface of random_shuffle.\n\t///\n\t/// Effects: Shuffles the elements in the range [first, last) with uniform distribution.\n\t///\n\t/// Complexity: Exactly '(last - first) - 1' swaps.\n\t///\n\t/// Example usage:\n\t///     struct Rand{ eastl_size_t operator()(eastl_size_t n) { return (eastl_size_t)(rand() % n); } }; // Note: The C rand function is poor and slow.\n\t///     Rand randInstance;\n\t///     shuffle(pArrayBegin, pArrayEnd, randInstance);\n\t///\n\t// See the C++11 Standard, 26.5.1.3, Uniform random number generator requirements.\n\t// Also http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution\n\n\ttemplate <typename RandomAccessIterator, typename UniformRandomNumberGenerator>\n\tvoid shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& urng)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\t\ttypedef typename eastl::make_unsigned<difference_type>::type                   unsigned_difference_type;\n\t\t\ttypedef typename eastl::uniform_int_distribution<unsigned_difference_type>     uniform_int_distribution;\n\t\t\ttypedef typename uniform_int_distribution::param_type                          uniform_int_distribution_param_type;\n\n\t\t\tuniform_int_distribution uid;\n\n\t\t\tfor(RandomAccessIterator i = first + 1; i != last; ++i)\n\t\t\t\titer_swap(i, first + uid(urng, uniform_int_distribution_param_type(0, i - first)));\n\t\t}\n\t}\n\n\n\t/// random_shuffle\n\t///\n\t/// Randomizes a sequence of values.\n\t///\n\t/// Effects: Shuffles the elements in the range [first, last) with uniform distribution.\n\t///\n\t/// Complexity: Exactly '(last - first) - 1' swaps.\n\t///\n\t/// Example usage:\n\t///     eastl_size_t Rand(eastl_size_t n) { return (eastl_size_t)(rand() % n); } // Note: The C rand function is poor and slow.\n\t///     random_shuffle(pArrayBegin, pArrayEnd, Rand);\n\t///\n\t/// Example usage:\n\t///     struct Rand{ eastl_size_t operator()(eastl_size_t n) { return (eastl_size_t)(rand() % n); } }; // Note: The C rand function is poor and slow.\n\t///     Rand randInstance;\n\t///     random_shuffle(pArrayBegin, pArrayEnd, randInstance);\n\t///\n\ttemplate <typename RandomAccessIterator, typename RandomNumberGenerator>\n\tinline void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator&& rng)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\n\t\t// We must do 'rand((i - first) + 1)' here and cannot do 'rand(last - first)',\n\t\t// as it turns out that the latter results in unequal distribution probabilities.\n\t\t// http://www.cigital.com/papers/download/developer_gambling.php\n\n\t\tconst difference_type swapMax = eastl::distance(first, last);\n\n\t\t// deliberately start at 1.\n\t\tfor (difference_type swapIter = 1; swapIter < swapMax; ++swapIter)\n\t\t{\n\t\t\tRandomAccessIterator i = first + swapIter;\n\t\t\titer_swap(i, first + (difference_type)rng((eastl_size_t)((i - first) + 1)));\n\t\t}\n\t}\n\n\n\t/// random_shuffle\n\t///\n\t/// Randomizes a sequence of values.\n\t///\n\t/// Effects: Shuffles the elements in the range [first, last) with uniform distribution.\n\t///\n\t/// Complexity: Exactly '(last - first) - 1' swaps.\n\t///\n\t/// Example usage:\n\t///     random_shuffle(pArrayBegin, pArrayEnd);\n\t///\n\t/// *** Disabled until we decide if we want to get into the business of writing random number generators. ***\n\t///\n\t/// template <typename RandomAccessIterator>\n\t/// inline void random_shuffle(RandomAccessIterator first, RandomAccessIterator last)\n\t/// {\n\t///     for(RandomAccessIterator i = first + 1; i < last; ++i)\n\t///         iter_swap(i, first + SomeRangedRandomNumberGenerator((i - first) + 1));\n\t/// }\n\n\n\n\n\n\n\t/// move_n\n\t///\n\t/// Same as move(InputIterator, InputIterator, OutputIterator) except based on count instead of iterator range.\n\t///\n\ttemplate <typename InputIterator, typename Size, typename OutputIterator>\n\tinline OutputIterator\n\tmove_n_impl(InputIterator first, Size n, OutputIterator result, eastl::input_iterator_tag)\n\t{\n\t\tfor(; n > 0; --n)\n\t\t\t*result++ = eastl::move(*first++);\n\t\treturn result;\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename Size, typename OutputIterator>\n\tinline OutputIterator\n\tmove_n_impl(RandomAccessIterator first, Size n, OutputIterator result, eastl::random_access_iterator_tag)\n\t{\n\t\treturn eastl::move(first, first + n, result); // Take advantage of the optimizations present in the move algorithm.\n\t}\n\n\n\ttemplate <typename InputIterator, typename Size, typename OutputIterator>\n\tinline OutputIterator\n\tmove_n(InputIterator first, Size n, OutputIterator result)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\treturn eastl::move_n_impl(first, n, result, IC());\n\t}\n\n\n\n\t/// copy_n\n\t///\n\t/// Same as copy(InputIterator, InputIterator, OutputIterator) except based on count instead of iterator range.\n\t/// Effects: Copies exactly count values from the range beginning at first to the range beginning at result, if count > 0. Does nothing otherwise.\n\t/// Returns: Iterator in the destination range, pointing past the last element copied if count>0 or first otherwise.\n\t/// Complexity: Exactly count assignments, if count > 0.\n\t///\n\ttemplate <typename InputIterator, typename Size, typename OutputIterator>\n\tinline OutputIterator\n\tcopy_n_impl(InputIterator first, Size n, OutputIterator result, eastl::input_iterator_tag)\n\t{\n\t\tfor(; n > 0; --n)\n\t\t\t*result++ = *first++;\n\t\treturn result;\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename Size, typename OutputIterator>\n\tinline OutputIterator\n\tcopy_n_impl(RandomAccessIterator first, Size n, OutputIterator result, eastl::random_access_iterator_tag)\n\t{\n\t\treturn eastl::copy(first, first + n, result); // Take advantage of the optimizations present in the copy algorithm.\n\t}\n\n\n\ttemplate <typename InputIterator, typename Size, typename OutputIterator>\n\tinline OutputIterator\n\tcopy_n(InputIterator first, Size n, OutputIterator result)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\treturn eastl::copy_n_impl(first, n, result, IC());\n\t}\n\n\n\t/// copy_if\n\t///\n\t/// Effects: Assigns to the result iterator only if the predicate is true.\n\t///\n\ttemplate <typename InputIterator, typename OutputIterator, typename Predicate>\n\tinline OutputIterator\n\tcopy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate)\n\t{\n\t\t// This implementation's performance could be improved by taking a more complicated approach like with the copy algorithm.\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(predicate(*first))\n\t\t\t\t*result++ = *first;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\n\n\t// Implementation moving copying both trivial and non-trivial data via a lesser iterator than random-access.\n\ttemplate <typename /*BidirectionalIterator1Category*/, bool /*isMove*/, bool /*canMemmove*/>\n\tstruct move_and_copy_backward_helper\n\t{\n\t\ttemplate <typename BidirectionalIterator1, typename BidirectionalIterator2>\n\t\tstatic BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t\t{\n\t\t\twhile(first != last)\n\t\t\t\t*--resultEnd = *--last;\n\t\t\treturn resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.\n\t\t}\n\t};\n\n\t// Specialization for moving non-trivial data via a lesser iterator than random-access.\n\ttemplate <typename BidirectionalIterator1Category>\n\tstruct move_and_copy_backward_helper<BidirectionalIterator1Category, true, false>\n\t{\n\t\ttemplate <typename BidirectionalIterator1, typename BidirectionalIterator2>\n\t\tstatic BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t\t{\n\t\t\twhile(first != last)\n\t\t\t\t*--resultEnd = eastl::move(*--last);\n\t\t\treturn resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.\n\t\t}\n\t};\n\n\t// Specialization for moving non-trivial data via a random-access iterator. It's theoretically faster because the compiler can see the count when its a compile-time const.\n\ttemplate<>\n\tstruct move_and_copy_backward_helper<eastl::random_access_iterator_tag, true, false>\n\t{\n\t\ttemplate<typename BidirectionalIterator1, typename BidirectionalIterator2>\n\t\tstatic BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator1>::difference_type difference_type;\n\n\t\t\tfor(difference_type n = (last - first); n > 0; --n)\n\t\t\t\t*--resultEnd = eastl::move(*--last);\n\t\t\treturn resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.\n\t\t}\n\t};\n\n\t// Specialization for copying non-trivial data via a random-access iterator. It's theoretically faster because the compiler can see the count when its a compile-time const.\n\t// This specialization converts the random access BidirectionalIterator1 last-first to an integral type. There's simple way for us to take advantage of a random access output iterator,\n\t// as the range is specified by the input instead of the output, and distance(first, last) for a non-random-access iterator is potentially slow.\n\ttemplate <>\n\tstruct move_and_copy_backward_helper<eastl::random_access_iterator_tag, false, false>\n\t{\n\t\ttemplate <typename BidirectionalIterator1, typename BidirectionalIterator2>\n\t\tstatic BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator1>::difference_type difference_type;\n\n\t\t\tfor(difference_type n = (last - first); n > 0; --n)\n\t\t\t\t*--resultEnd = *--last;\n\t\t\treturn resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.\n\t\t}\n\t};\n\n\t// Specialization for when we can use memmove/memcpy. See the notes above for what conditions allow this.\n\ttemplate <bool isMove>\n\tstruct move_and_copy_backward_helper<eastl::random_access_iterator_tag, isMove, true>\n\t{\n\t\ttemplate <typename T>\n\t\tstatic T* move_or_copy_backward(const T* first, const T* last, T* resultEnd)\n\t\t{\n\t\t\tconst size_t n = (size_t)((uintptr_t)last - (uintptr_t)first);\n\t\t\t// We could use memcpy here if there's no range overlap, but memcpy is rarely much faster than memmove.\n\t\t\tif (n > 0)\n\t\t\t\treturn (T*)memmove(resultEnd - (last - first), first, n);\n\t\t\telse\n\t\t\t\treturn resultEnd;\n\t\t}\n\t};\n\n\ttemplate <bool isMove, typename BidirectionalIterator1, typename BidirectionalIterator2>\n\tinline BidirectionalIterator2 move_and_copy_backward_chooser(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t{\n\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator1>::iterator_category IIC;\n\n\t\tconst bool canBeMemmoved = internal::can_be_memmoved_helper<BidirectionalIterator1, BidirectionalIterator2>::value;\n\n\t\treturn eastl::move_and_copy_backward_helper<IIC, isMove, canBeMemmoved>::move_or_copy_backward(first, last, resultEnd); // Need to chose based on the input iterator tag and not the output iterator tag, because containers accept input ranges of iterator types different than self.\n\t}\n\n\n\ttemplate <bool isMove, typename BidirectionalIterator1, typename BidirectionalIterator2>\n\tEASTL_REMOVE_AT_2024_SEPT inline BidirectionalIterator2 move_and_copy_backward_unwrapper(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t{\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED() // 'unwrap_iterator': was declared deprecated\n\t\treturn BidirectionalIterator2(eastl::move_and_copy_backward_chooser<isMove>(eastl::unwrap_iterator(first), eastl::unwrap_iterator(last), eastl::unwrap_iterator(resultEnd))); // Have to convert to BidirectionalIterator2 because result.base() could be a T*\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t}\n\n\n\t/// move_backward\n\t///\n\t/// The elements are moved in reverse order (the last element is moved first), but their relative order is preserved.\n\t/// After this operation the elements in the moved-from range will still contain valid values of the\n\t/// appropriate type, but not necessarily the same values as before the move.\n\t/// Returns the beginning of the result range.\n\t/// Note: When moving between containers, the dest range must be valid; this function doesn't resize containers.\n\t/// Note: If result is within [first, last), move must be used instead of move_backward.\n\t///\n\t/// Example usage:\n\t///     eastl::move_backward(myArray.begin(), myArray.end(), myDestArray.end());\n\t///\n\t/// Reference implementation:\n\t///     template <typename BidirectionalIterator1, typename BidirectionalIterator2>\n\t///     BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t///     {\n\t///         while(last != first)\n\t///             *--resultEnd = eastl::move(*--last);\n\t///         return resultEnd;\n\t///     }\n\t///\n\ttemplate <typename BidirectionalIterator1, typename BidirectionalIterator2>\n\tinline BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t{\n\t\treturn eastl::move_and_copy_backward_chooser<true>(first, last, resultEnd);\n\t}\n\n\n\t/// copy_backward\n\t///\n\t/// copies memory in the range of [first, last) to the range *ending* with result.\n\t///\n\t/// Effects: Copies elements in the range [first, last) into the range\n\t/// [result - (last - first), result) starting from last 1 and proceeding to first.\n\t/// For each positive integer n <= (last - first), performs *(result n) = *(last - n).\n\t///\n\t/// Requires: result shall not be in the range [first, last).\n\t///\n\t/// Returns: result - (last - first). That is, returns the beginning of the result range.\n\t///\n\t/// Complexity: Exactly 'last - first' assignments.\n\t///\n\ttemplate <typename BidirectionalIterator1, typename BidirectionalIterator2>\n\tinline BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)\n\t{\n\t\treturn eastl::move_and_copy_backward_chooser<false>(first, last, resultEnd);\n\t}\n\n\n\t/// count\n\t///\n\t/// Counts the number of items in the range of [first, last) which equal the input value.\n\t///\n\t/// Effects: Returns the number of iterators i in the range [first, last) for which the\n\t/// following corresponding conditions hold: *i == value.\n\t///\n\t/// Complexity: At most 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The predicate version of count is count_if and not another variation of count.\n\t/// This is because both versions would have three parameters and there could be ambiguity.\n\t///\n\ttemplate <typename InputIterator, typename T>\n\tinline typename eastl::iterator_traits<InputIterator>::difference_type\n\tcount(InputIterator first, InputIterator last, const T& value)\n\t{\n\t\ttypename eastl::iterator_traits<InputIterator>::difference_type result = 0;\n\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(*first == value)\n\t\t\t\t++result;\n\t\t}\n\t\treturn result;\n\t}\n\n\n\t// C++ doesn't define a count with predicate, as it can effectively be synthesized via count_if\n\t// with an appropriate predicate. However, it's often simpler to just have count with a predicate.\n\ttemplate <typename InputIterator, typename T, typename Predicate>\n\tinline typename eastl::iterator_traits<InputIterator>::difference_type\n\tcount(InputIterator first, InputIterator last, const T& value, Predicate predicate)\n\t{\n\t\ttypename eastl::iterator_traits<InputIterator>::difference_type result = 0;\n\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(predicate(*first, value))\n\t\t\t\t++result;\n\t\t}\n\t\treturn result;\n\t}\n\n\n\t/// count_if\n\t///\n\t/// Counts the number of items in the range of [first, last) which match\n\t/// the input value as defined by the input predicate function.\n\t///\n\t/// Effects: Returns the number of iterators i in the range [first, last) for which the\n\t/// following corresponding conditions hold: predicate(*i) != false.\n\t///\n\t/// Complexity: At most 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The non-predicate version of count_if is count and not another variation of count_if.\n\t/// This is because both versions would have three parameters and there could be ambiguity.\n\t///\n\ttemplate <typename InputIterator, typename Predicate>\n\tinline typename eastl::iterator_traits<InputIterator>::difference_type\n\tcount_if(InputIterator first, InputIterator last, Predicate predicate)\n\t{\n\t\ttypename eastl::iterator_traits<InputIterator>::difference_type result = 0;\n\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(predicate(*first))\n\t\t\t\t++result;\n\t\t}\n\t\treturn result;\n\t}\n\n\n\t/// find\n\t///\n\t/// finds the value within the unsorted range of [first, last).\n\t///\n\t/// Returns: The first iterator i in the range [first, last) for which\n\t/// the following corresponding conditions hold: *i == value.\n\t/// Returns last if no such iterator is found.\n\t///\n\t/// Complexity: At most 'last - first' applications of the corresponding predicate.\n\t/// This is a linear search and not a binary one.\n\t///\n\t/// Note: The predicate version of find is find_if and not another variation of find.\n\t/// This is because both versions would have three parameters and there could be ambiguity.\n\t///\n\ttemplate <typename InputIterator, typename T>\n\tinline InputIterator\n\tfind(InputIterator first, InputIterator last, const T& value)\n\t{\n\t\twhile((first != last) && !(*first == value)) // Note that we always express value comparisons in terms of < or ==.\n\t\t\t++first;\n\t\treturn first;\n\t}\n\n\n\t// C++ doesn't define a find with predicate, as it can effectively be synthesized via find_if\n\t// with an appropriate predicate. However, it's often simpler to just have find with a predicate.\n\ttemplate <typename InputIterator, typename T, typename Predicate>\n\tinline InputIterator\n\tfind(InputIterator first, InputIterator last, const T& value, Predicate predicate)\n\t{\n\t\twhile((first != last) && !predicate(*first, value))\n\t\t\t++first;\n\t\treturn first;\n\t}\n\n\n\n\t/// find_if\n\t///\n\t/// finds the value within the unsorted range of [first, last).\n\t///\n\t/// Returns: The first iterator i in the range [first, last) for which\n\t/// the following corresponding conditions hold: pred(*i) != false.\n\t/// Returns last if no such iterator is found.\n\t/// If the sequence of elements to search for (i.e. first2 - last2) is empty,\n\t/// the find always fails and last1 will be returned.\n\t///\n\t/// Complexity: At most 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The non-predicate version of find_if is find and not another variation of find_if.\n\t/// This is because both versions would have three parameters and there could be ambiguity.\n\t///\n\ttemplate <typename InputIterator, typename Predicate>\n\tinline InputIterator\n\tfind_if(InputIterator first, InputIterator last, Predicate predicate)\n\t{\n\t\twhile((first != last) && !predicate(*first))\n\t\t\t++first;\n\t\treturn first;\n\t}\n\n\n\n\t/// find_if_not\n\t///\n\t/// find_if_not works the same as find_if except it tests for if the predicate\n\t/// returns false for the elements instead of true.\n\t///\n\ttemplate <typename InputIterator, typename Predicate>\n\tinline InputIterator\n\tfind_if_not(InputIterator first, InputIterator last, Predicate predicate)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(!predicate(*first))\n\t\t\t\treturn first;\n\t\t}\n\t\treturn last;\n\t}\n\n\n\n\n\t/// find_first_of\n\t///\n\t/// find_first_of is similar to find in that it performs linear search through\n\t/// a range of ForwardIterators. The difference is that while find searches\n\t/// for one particular value, find_first_of searches for any of several values.\n\t/// Specifically, find_first_of searches for the first occurrance in the\n\t/// range [first1, last1) of any of the elements in [first2, last2).\n\t/// This function is thus similar to the strpbrk standard C string function.\n\t/// If the sequence of elements to search for (i.e. first2-last2) is empty,\n\t/// the find always fails and last1 will be returned.\n\t///\n\t/// Effects: Finds an element that matches one of a set of values.\n\t///\n\t/// Returns: The first iterator i in the range [first1, last1) such that for some\n\t/// integer j in the range [first2, last2) the following conditions hold: *i == *j.\n\t/// Returns last1 if no such iterator is found.\n\t///\n\t/// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the\n\t/// corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\tForwardIterator1\n\tfind_first_of(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t\t  ForwardIterator2 first2, ForwardIterator2 last2)\n\t{\n\t\tfor(; first1 != last1; ++first1)\n\t\t{\n\t\t\tfor(ForwardIterator2 i = first2; i != last2; ++i)\n\t\t\t{\n\t\t\t\tif(*first1 == *i)\n\t\t\t\t\treturn first1;\n\t\t\t}\n\t\t}\n\t\treturn last1;\n\t}\n\n\n\t/// find_first_of\n\t///\n\t/// find_first_of is similar to find in that it performs linear search through\n\t/// a range of ForwardIterators. The difference is that while find searches\n\t/// for one particular value, find_first_of searches for any of several values.\n\t/// Specifically, find_first_of searches for the first occurrance in the\n\t/// range [first1, last1) of any of the elements in [first2, last2).\n\t/// This function is thus similar to the strpbrk standard C string function.\n\t///\n\t/// Effects: Finds an element that matches one of a set of values.\n\t///\n\t/// Returns: The first iterator i in the range [first1, last1) such that for some\n\t/// integer j in the range [first2, last2) the following conditions hold: pred(*i, *j) != false.\n\t/// Returns last1 if no such iterator is found.\n\t///\n\t/// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the\n\t/// corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>\n\tForwardIterator1\n\tfind_first_of(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t\t  ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t\t\t  BinaryPredicate predicate)\n\t{\n\t\tfor(; first1 != last1; ++first1)\n\t\t{\n\t\t\tfor(ForwardIterator2 i = first2; i != last2; ++i)\n\t\t\t{\n\t\t\t\tif(predicate(*first1, *i))\n\t\t\t\t\treturn first1;\n\t\t\t}\n\t\t}\n\t\treturn last1;\n\t}\n\n\n\t/// find_first_not_of\n\t///\n\t/// Searches through first range for the first element that does not belong the second input range.\n\t/// This is very much like the C++ string find_first_not_of function.\n\t///\n\t/// Returns: The first iterator i in the range [first1, last1) such that for some\n\t/// integer j in the range [first2, last2) the following conditions hold: !(*i == *j).\n\t/// Returns last1 if no such iterator is found.\n\t///\n\t/// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the\n\t/// corresponding predicate.\n\t///\n\ttemplate <class ForwardIterator1, class ForwardIterator2>\n\tForwardIterator1\n\tfind_first_not_of(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t\t\t  ForwardIterator2 first2, ForwardIterator2 last2)\n\t{\n\t\tfor(; first1 != last1; ++first1)\n\t\t{\n\t\t\tif(eastl::find(first2, last2, *first1) == last2)\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn first1;\n\t}\n\n\n\n\t/// find_first_not_of\n\t///\n\t/// Searches through first range for the first element that does not belong the second input range.\n\t/// This is very much like the C++ string find_first_not_of function.\n\t///\n\t/// Returns: The first iterator i in the range [first1, last1) such that for some\n\t/// integer j in the range [first2, last2) the following conditions hold: pred(*i, *j) == false.\n\t/// Returns last1 if no such iterator is found.\n\t///\n\t/// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the\n\t/// corresponding predicate.\n\t///\n\ttemplate <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>\n\tinline ForwardIterator1\n\tfind_first_not_of(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t\t\t  ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t\t\t\t  BinaryPredicate predicate)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::value_type value_type;\n\n\t\tfor(; first1 != last1; ++first1)\n\t\t{\n\t\t\tif(eastl::find_if(first2, last2, [&predicate, first1](value_type& rhs) { return predicate(*first1, rhs); }) == last2)\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn first1;\n\t}\n\n\n\ttemplate <class BidirectionalIterator1, class ForwardIterator2>\n\tinline BidirectionalIterator1\n\tfind_last_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,\n\t\t\t\t ForwardIterator2 first2, ForwardIterator2 last2)\n\t{\n\t\tif((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tBidirectionalIterator1 it1(last1);\n\n\t\t\twhile((--it1 != first1) && (eastl::find(first2, last2, *it1) == last2))\n\t\t\t\t; // Do nothing\n\n\t\t\tif((it1 != first1) || (eastl::find(first2, last2, *it1) != last2))\n\t\t\t\treturn it1;\n\t\t}\n\n\t\treturn last1;\n\t}\n\n\n\ttemplate <class BidirectionalIterator1, class ForwardIterator2, class BinaryPredicate>\n\tBidirectionalIterator1\n\tfind_last_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,\n\t\t\t\t ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t\t\t BinaryPredicate predicate)\n\t{\n\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator1>::value_type value_type;\n\n\t\tif((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tBidirectionalIterator1 it1(last1);\n\n\t\t\twhile((--it1 != first1) && (eastl::find_if(first2, last2, [&predicate, it1](value_type& rhs) { return predicate(*it1, rhs); }) == last2))\n\t\t\t\t; // Do nothing\n\n\t\t\tif((it1 != first1) || (eastl::find_if(first2, last2, [&predicate, it1](value_type& rhs) { return predicate(*it1, rhs); }) != last2))\n\t\t\t\treturn it1;\n\t\t}\n\n\t\treturn last1;\n\t}\n\n\n\ttemplate <class BidirectionalIterator1, class ForwardIterator2>\n\tinline BidirectionalIterator1\n\tfind_last_not_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,\n\t\t\t\t\t ForwardIterator2 first2, ForwardIterator2 last2)\n\t{\n\t\tif((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tBidirectionalIterator1 it1(last1);\n\n\t\t\twhile((--it1 != first1) && (eastl::find(first2, last2, *it1) != last2))\n\t\t\t\t; // Do nothing\n\n\t\t\tif((it1 != first1) || (eastl::find( first2, last2, *it1) == last2))\n\t\t\t\treturn it1;\n\t\t}\n\n\t\treturn last1;\n\t}\n\n\n\ttemplate <class BidirectionalIterator1, class ForwardIterator2, class BinaryPredicate>\n\tinline BidirectionalIterator1\n\tfind_last_not_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,\n\t\t\t\t\t ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t\t\t\t BinaryPredicate predicate)\n\t{\n\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator1>::value_type value_type;\n\n\t\tif((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tBidirectionalIterator1 it1(last1);\n\n\t\t\twhile((--it1 != first1) && (eastl::find_if(first2, last2, [&predicate, it1](value_type& rhs) { return predicate(*it1, rhs); }) != last2))\n\t\t\t\t; // Do nothing\n\n\t\t\tif((it1 != first1) || (eastl::find_if(first2, last2, [&predicate, it1](value_type& rhs) { return predicate(*it1, rhs); })) != last2)\n\t\t\t\treturn it1;\n\t\t}\n\n\t\treturn last1;\n\t}\n\n\n\n\n\t/// for_each\n\t///\n\t/// Calls the Function function for each value in the range [first, last).\n\t/// Function takes a single parameter: the current value.\n\t///\n\t/// Effects: Applies function to the result of dereferencing every iterator in\n\t/// the range [first, last), starting from first and proceeding to last 1.\n\t///\n\t/// Returns: function.\n\t///\n\t/// Complexity: Applies function exactly 'last - first' times.\n\t///\n\t/// Note: If function returns a result, the result is ignored.\n\t///\n\ttemplate <typename InputIterator, typename Function>\n\tinline Function\n\tfor_each(InputIterator first, InputIterator last, Function function)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t\tfunction(*first);\n\t\treturn function;\n\t}\n\n\t/// for_each_n\n\t///\n\t/// Calls the Function function for each value in the range [first, first + n).\n\t/// Function takes a single parameter: the current value.\n\t///\n\t/// Effects: Applies function to the result of dereferencing every iterator in\n\t/// the range [first, first + n), starting from first and proceeding to last 1.\n\t///\n\t/// Returns: first + n.\n\t///\n\t/// Complexity: Applies function exactly 'first + n' times.\n\t///\n\t/// Note:\n\t////  * If function returns a result, the result is ignored.\n\t////  * If n < 0, behaviour is undefined.\n\t///\n\ttemplate <typename InputIterator, typename Size, typename Function>\n\tEA_CPP14_CONSTEXPR inline InputIterator\n\tfor_each_n(InputIterator first, Size n, Function function)\n\t{\n\t\tfor (Size i = 0; i < n; ++first, i++)\n\t\t\tfunction(*first);\n\t\treturn first;\n\t}\n\n\n\t/// generate\n\t///\n\t/// Iterates the range of [first, last) and assigns to each element the\n\t/// result of the function generator. Generator is a function which takes\n\t/// no arguments.\n\t///\n\t/// Complexity: Exactly 'last - first' invocations of generator and assignments.\n\t///\n\ttemplate <typename ForwardIterator, typename Generator>\n\tinline void\n\tgenerate(ForwardIterator first, ForwardIterator last, Generator generator)\n\t{\n\t\tfor(; first != last; ++first) // We cannot call generate_n(first, last-first, generator)\n\t\t\t*first = generator();     // because the 'last-first' might not be supported by the\n\t}                                 // given iterator.\n\n\n\t/// generate_n\n\t///\n\t/// Iterates an interator n times and assigns the result of generator\n\t/// to each succeeding element. Generator is a function which takes\n\t/// no arguments.\n\t///\n\t/// Complexity: Exactly n invocations of generator and assignments.\n\t///\n\ttemplate <typename OutputIterator, typename Size, typename Generator>\n\tinline OutputIterator\n\tgenerate_n(OutputIterator first, Size n, Generator generator)\n\t{\n\t\tfor(; n > 0; --n, ++first)\n\t\t\t*first = generator();\n\t\treturn first;\n\t}\n\n\n\t/// transform\n\t///\n\t/// Iterates the input range of [first, last) and the output iterator result\n\t/// and assigns the result of unaryOperation(input) to result.\n\t///\n\t/// Effects: Assigns through every iterator i in the range [result, result + (last1 - first1))\n\t/// a new corresponding value equal to unaryOperation(*(first1 + (i - result)).\n\t///\n\t/// Requires: op shall not have any side effects.\n\t///\n\t/// Returns: result + (last1 - first1). That is, returns the end of the output range.\n\t///\n\t/// Complexity: Exactly 'last1 - first1' applications of unaryOperation.\n\t///\n\t/// Note: result may be equal to first.\n\t///\n\ttemplate <typename InputIterator, typename OutputIterator, typename UnaryOperation>\n\tinline OutputIterator\n\ttransform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unaryOperation)\n\t{\n\t\tfor(; first != last; ++first, ++result)\n\t\t\t*result = unaryOperation(*first);\n\t\treturn result;\n\t}\n\n\n\t/// transform\n\t///\n\t/// Iterates the input range of [first, last) and the output iterator result\n\t/// and assigns the result of binaryOperation(input1, input2) to result.\n\t///\n\t/// Effects: Assigns through every iterator i in the range [result, result + (last1 - first1))\n\t/// a new corresponding value equal to binaryOperation(*(first1 + (i - result), *(first2 + (i - result))).\n\t///\n\t/// Requires: binaryOperation shall not have any side effects.\n\t///\n\t/// Returns: result + (last1 - first1). That is, returns the end of the output range.\n\t///\n\t/// Complexity: Exactly 'last1 - first1' applications of binaryOperation.\n\t///\n\t/// Note: result may be equal to first1 or first2.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename BinaryOperation>\n\tinline OutputIterator\n\ttransform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binaryOperation)\n\t{\n\t\tfor(; first1 != last1; ++first1, ++first2, ++result)\n\t\t\t*result = binaryOperation(*first1, *first2);\n\t\treturn result;\n\t}\n\n\n\t/// equal\n\t///\n\t/// Returns: true if for every iterator i in the range [first1, last1) the\n\t/// following corresponding conditions hold: predicate(*i, *(first2 + (i - first1))) != false.\n\t/// Otherwise, returns false.\n\t///\n\t/// Complexity: At most last1 first1 applications of the corresponding predicate.\n\t///\n\t/// To consider: Make specializations of this for scalar types and random access\n\t/// iterators that uses memcmp or some trick memory comparison function.\n\t/// We should verify that such a thing results in an improvement.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2>\n\tEA_CPP14_CONSTEXPR inline bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)\n\t{\n\t\tfor(; first1 != last1; ++first1, ++first2)\n\t\t{\n\t\t\tif(!(*first1 == *first2)) // Note that we always express value comparisons in terms of < or ==.\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/* Enable the following if there was shown to be some benefit. A glance and Microsoft VC++ memcmp\n\t\tshows that it is not optimized in any way, much less one that would benefit us here.\n\n\tinline bool equal(const bool* first1, const bool* last1, const bool* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const char* first1, const char* last1, const char* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const unsigned char* first1, const unsigned char* last1, const unsigned char* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const signed char* first1, const signed char* last1, const signed char* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\t#ifndef EA_WCHAR_T_NON_NATIVE\n\t\tinline bool equal(const wchar_t* first1, const wchar_t* last1, const wchar_t* first2)\n\t\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\t#endif\n\n\tinline bool equal(const int16_t* first1, const int16_t* last1, const int16_t* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const uint16_t* first1, const uint16_t* last1, const uint16_t* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const int32_t* first1, const int32_t* last1, const int32_t* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const uint32_t* first1, const uint32_t* last1, const uint32_t* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const int64_t* first1, const int64_t* last1, const int64_t* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\n\tinline bool equal(const uint64_t* first1, const uint64_t* last1, const uint64_t* first2)\n\t\t{ return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }\n\t*/\n\n\n\n\t/// equal\n\t///\n\t/// Returns: true if for every iterator i in the range [first1, last1) the\n\t/// following corresponding conditions hold: pred(*i, *(first2 + (i first1))) != false.\n\t/// Otherwise, returns false.\n\t///\n\t/// Complexity: At most last1 first1 applications of the corresponding predicate.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename BinaryPredicate>\n\tinline bool\n\tequal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate predicate)\n\t{\n\t\tfor(; first1 != last1; ++first1, ++first2)\n\t\t{\n\t\t\tif(!predicate(*first1, *first2))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\n\n\t/// identical\n\t///\n\t/// Returns true if the two input ranges are equivalent.\n\t/// There is a subtle difference between this algorithm and\n\t/// the 'equal' algorithm. The equal algorithm assumes the\n\t/// two ranges are of equal length. This algorithm efficiently\n\t/// compares two ranges for both length equality and for\n\t/// element equality. There is no other standard algorithm\n\t/// that can do this.\n\t///\n\t/// Returns: true if the sequence of elements defined by the range\n\t/// [first1, last1) is of the same length as the sequence of\n\t/// elements defined by the range of [first2, last2) and if\n\t/// the elements in these ranges are equal as per the\n\t/// equal algorithm.\n\t///\n\t/// Complexity: At most 'min((last1 - first1), (last2 - first2))' applications\n\t/// of the corresponding comparison.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2>\n\tbool identical(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t   InputIterator2 first2, InputIterator2 last2)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2) && (*first1 == *first2))\n\t\t{\n\t\t\t++first1;\n\t\t\t++first2;\n\t\t}\n\t\treturn (first1 == last1) && (first2 == last2);\n\t}\n\n\n\t/// identical\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename BinaryPredicate>\n\tbool identical(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t   InputIterator2 first2, InputIterator2 last2, BinaryPredicate predicate)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2) && predicate(*first1, *first2))\n\t\t{\n\t\t\t++first1;\n\t\t\t++first2;\n\t\t}\n\t\treturn (first1 == last1) && (first2 == last2);\n\t}\n\n\n\n\t/// lexicographical_compare\n\t///\n\t/// Returns: true if the sequence of elements defined by the range\n\t/// [first1, last1) is lexicographically less than the sequence of\n\t/// elements defined by the range [first2, last2). Returns false otherwise.\n\t///\n\t/// Complexity: At most 'min((last1 - first1), (last2 - first2))' applications\n\t/// of the corresponding comparison.\n\t///\n\t/// Note: If two sequences have the same number of elements and their\n\t/// corresponding elements are equivalent, then neither sequence is\n\t/// lexicographically less than the other. If one sequence is a prefix\n\t/// of the other, then the shorter sequence is lexicographically less\n\t/// than the longer sequence. Otherwise, the lexicographical comparison\n\t/// of the sequences yields the same result as the comparison of the first\n\t/// corresponding pair of elements that are not equivalent.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2>\n\tinline bool\n\tlexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)\n\t{\n\t\tfor(; (first1 != last1) && (first2 != last2); ++first1, ++first2)\n\t\t{\n\t\t\tif(*first1 < *first2)\n\t\t\t\treturn true;\n\t\t\tif(*first2 < *first1)\n\t\t\t\treturn false;\n\t\t}\n\t\treturn (first1 == last1) && (first2 != last2);\n\t}\n\n\tinline bool     // Specialization for const char*.\n\tlexicographical_compare(const char* first1, const char* last1, const char* first2, const char* last2)\n\t{\n\t\tconst ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\tconst size_t n = (size_t)eastl::min_alt(n1, n2);\n\t\tif (n == 0) // don't call memcmp with n == 0\n\t\t\treturn false;\n\t\tconst int result = memcmp(first1, first2, n);\n\t\treturn result ? (result < 0) : (n1 < n2);\n\t}\n\n\tinline bool     // Specialization for char*.\n\tlexicographical_compare(char* first1, char* last1, char* first2, char* last2)\n\t{\n\t\tconst ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\tconst size_t n = (size_t)eastl::min_alt(n1, n2);\n\t\tif (n == 0) // don't call memcmp with n == 0\n\t\t\treturn false;\n\t\tconst int result = memcmp(first1, first2, n);\n\t\treturn result ? (result < 0) : (n1 < n2);\n\t}\n\n\tinline bool     // Specialization for const unsigned char*.\n\tlexicographical_compare(const unsigned char* first1, const unsigned char* last1, const unsigned char* first2, const unsigned char* last2)\n\t{\n\t\tconst ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\tconst size_t n = (size_t)eastl::min_alt(n1, n2);\n\t\tif (n == 0) // don't call memcmp with n == 0\n\t\t\treturn false;\n\t\tconst int result = memcmp(first1, first2, n);\n\t\treturn result ? (result < 0) : (n1 < n2);\n\t}\n\n\tinline bool     // Specialization for unsigned char*.\n\tlexicographical_compare(unsigned char* first1, unsigned char* last1, unsigned char* first2, unsigned char* last2)\n\t{\n\t\tconst ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\tconst size_t n = (size_t)eastl::min_alt(n1, n2);\n\t\tif (n == 0) // don't call memcmp with n == 0\n\t\t\treturn false;\n\t\tconst int result = memcmp(first1, first2, n);\n\t\treturn result ? (result < 0) : (n1 < n2);\n\t}\n\n\tinline bool     // Specialization for const signed char*.\n\tlexicographical_compare(const signed char* first1, const signed char* last1, const signed char* first2, const signed char* last2)\n\t{\n\t\tconst ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\tconst size_t n = (size_t)eastl::min_alt(n1, n2);\n\t\tif (n == 0) // don't call memcmp with n == 0\n\t\t\treturn false;\n\t\tconst int result = memcmp(first1, first2, n);\n\t\treturn result ? (result < 0) : (n1 < n2);\n\t}\n\n\tinline bool     // Specialization for signed char*.\n\tlexicographical_compare(signed char* first1, signed char* last1, signed char* first2, signed char* last2)\n\t{\n\t\tconst ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\tconst size_t n = (size_t)eastl::min_alt(n1, n2);\n\t\tif (n == 0) // don't call memcmp with n == 0\n\t\t\treturn false;\n\t\tconst int result = memcmp(first1, first2, n);\n\t\treturn result ? (result < 0) : (n1 < n2);\n\t}\n\n\t#if defined(_MSC_VER) // If using the VC++ compiler (and thus bool is known to be a single byte)...\n\t\t//Not sure if this is a good idea.\n\t\t//inline bool     // Specialization for const bool*.\n\t\t//lexicographical_compare(const bool* first1, const bool* last1, const bool* first2, const bool* last2)\n\t\t//{\n\t\t//    const ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\t//    const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));\n\t\t//    return result ? (result < 0) : (n1 < n2);\n\t\t//}\n\t\t//\n\t\t//inline bool     // Specialization for bool*.\n\t\t//lexicographical_compare(bool* first1, bool* last1, bool* first2, bool* last2)\n\t\t//{\n\t\t//    const ptrdiff_t n1(last1 - first1), n2(last2 - first2);\n\t\t//    const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));\n\t\t//    return result ? (result < 0) : (n1 < n2);\n\t\t//}\n\t#endif\n\n\n\n\t/// lexicographical_compare\n\t///\n\t/// Returns: true if the sequence of elements defined by the range\n\t/// [first1, last1) is lexicographically less than the sequence of\n\t/// elements defined by the range [first2, last2). Returns false otherwise.\n\t///\n\t/// Complexity: At most 'min((last1 -first1), (last2 - first2))' applications\n\t/// of the corresponding comparison.\n\t///\n\t/// Note: If two sequences have the same number of elements and their\n\t/// corresponding elements are equivalent, then neither sequence is\n\t/// lexicographically less than the other. If one sequence is a prefix\n\t/// of the other, then the shorter sequence is lexicographically less\n\t/// than the longer sequence. Otherwise, the lexicographical comparison\n\t/// of the sequences yields the same result as the comparison of the first\n\t/// corresponding pair of elements that are not equivalent.\n\t///\n\t/// Note: False is always returned if range 1 is exhausted before range 2.\n\t/// The result of this is that you can't do a successful reverse compare\n\t/// (e.g. use greater<> as the comparison instead of less<>) unless the\n\t/// two sequences are of identical length. What you want to do is reverse\n\t/// the order of the arguments in order to get the desired effect.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename Compare>\n\tinline bool\n\tlexicographical_compare(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\tInputIterator2 first2, InputIterator2 last2, Compare compare)\n\t{\n\t\tfor(; (first1 != last1) && (first2 != last2); ++first1, ++first2)\n\t\t{\n\t\t\tif(compare(*first1, *first2))\n\t\t\t\treturn true;\n\t\t\tif(compare(*first2, *first1))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn (first1 == last1) && (first2 != last2);\n\t}\n\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\n\t/// lexicographical_compare_three_way\n\t///\n\t/// Returns: The comparison category ordering between both ranges. For the first non-equivalent pair in the ranges,\n\t/// the comparison will be returned. Else if the first range is a subset (superset) of the second range, then the\n\t/// less (greater) ordering will be returned.\n\t///\n\t/// Complexity: At most N iterations, where N = min(last1-first1, last2-first2) of the applications\n\t/// of the corresponding comparison.\n\t///\n\t/// Note: If two sequences have the same number of elements and their\n\t/// corresponding elements are equivalent, then neither sequence is\n\t/// lexicographically less than the other. If one sequence is a prefix\n\t/// of the other, then the shorter sequence is lexicographically less\n\t/// than the longer sequence. Otherwise, the lexicographical comparison\n\t/// of the sequences yields the same result as the comparison of the first\n\t/// corresponding pair of elements that are not equivalent.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename Compare>\n\tconstexpr auto lexicographical_compare_three_way(InputIterator1 first1, InputIterator1 last1,\n\t                                                 InputIterator2 first2, InputIterator2 last2,\n\t                                                 Compare compare) -> decltype(compare(*first1, *first2))\n\t{\n\t\tfor (; (first1 != last1) && (first2 != last2); ++first1, ++first2)\n\t\t{\n\t\t\tif (auto c = compare(*first1, *first2); c != 0)\n\t\t\t\treturn c;\n\t\t}\n\n\t\treturn (first1 != last1) ? std::strong_ordering::greater :\n\t\t       (first2 != last2) ? std::strong_ordering::less :\n\t\t\t\tstd::strong_ordering::equal;\n\t}\n#endif\n\n\t/// mismatch\n\t///\n\t/// Finds the first position where the two ranges [first1, last1) and\n\t/// [first2, first2 + (last1 - first1)) differ. The two versions of\n\t/// mismatch use different tests for whether elements differ.\n\t///\n\t/// Returns: A pair of iterators i and j such that j == first2 + (i - first1)\n\t/// and i is the first iterator in the range [first1, last1) for which the\n\t/// following corresponding condition holds: !(*i == *(first2 + (i - first1))).\n\t/// Returns the pair last1 and first2 + (last1 - first1) if such an iterator\n\t/// i is not found.\n\t///\n\t/// Complexity: At most last1 first1 applications of the corresponding predicate.\n\t///\n\ttemplate <class InputIterator1, class InputIterator2>\n\tinline eastl::pair<InputIterator1, InputIterator2>\n\tmismatch(InputIterator1 first1, InputIterator1 last1,\n\t\t\t InputIterator2 first2) // , InputIterator2 last2)\n\t{\n\t\twhile((first1 != last1) && (*first1 == *first2)) // && (first2 != last2) <- C++ standard mismatch function doesn't check first2/last2.\n\t\t{\n\t\t\t++first1;\n\t\t\t++first2;\n\t\t}\n\n\t\treturn eastl::pair<InputIterator1, InputIterator2>(first1, first2);\n\t}\n\n\n\t/// mismatch\n\t///\n\t/// Finds the first position where the two ranges [first1, last1) and\n\t/// [first2, first2 + (last1 - first1)) differ. The two versions of\n\t/// mismatch use different tests for whether elements differ.\n\t///\n\t/// Returns: A pair of iterators i and j such that j == first2 + (i - first1)\n\t/// and i is the first iterator in the range [first1, last1) for which the\n\t/// following corresponding condition holds: pred(*i, *(first2 + (i - first1))) == false.\n\t/// Returns the pair last1 and first2 + (last1 - first1) if such an iterator\n\t/// i is not found.\n\t///\n\t/// Complexity: At most last1 first1 applications of the corresponding predicate.\n\t///\n\ttemplate <class InputIterator1, class InputIterator2, class BinaryPredicate>\n\tinline eastl::pair<InputIterator1, InputIterator2>\n\tmismatch(InputIterator1 first1, InputIterator1 last1,\n\t\t\t InputIterator2 first2, // InputIterator2 last2,\n\t\t\t BinaryPredicate predicate)\n\t{\n\t\twhile((first1 != last1) && predicate(*first1, *first2)) // && (first2 != last2) <- C++ standard mismatch function doesn't check first2/last2.\n\t\t{\n\t\t\t++first1;\n\t\t\t++first2;\n\t\t}\n\n\t\treturn eastl::pair<InputIterator1, InputIterator2>(first1, first2);\n\t}\n\n\n\t/// lower_bound\n\t///\n\t/// Finds the position of the first element in a sorted range that has a value\n\t/// greater than or equivalent to a specified value.\n\t///\n\t/// Effects: Finds the first position into which value can be inserted without\n\t/// violating the ordering.\n\t///\n\t/// Returns: The furthermost iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, i) the following corresponding\n\t/// condition holds: *j < value.\n\t///\n\t/// Complexity: At most 'log(last - first) + 1' comparisons.\n\t///\n\t/// Optimizations: We have no need to specialize this implementation for random\n\t/// access iterators (e.g. contiguous array), as the code below will already\n\t/// take advantage of them.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tForwardIterator\n\tlower_bound(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::difference_type DifferenceType;\n\n\t\tDifferenceType d = eastl::distance(first, last); // This will be efficient for a random access iterator such as an array.\n\n\t\twhile(d > 0)\n\t\t{\n\t\t\tForwardIterator i  = first;\n\t\t\tDifferenceType  d2 = d >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.\n\n\t\t\teastl::advance(i, d2); // This will be efficient for a random access iterator such as an array.\n\n\t\t\tif(*i < value)\n\t\t\t{\n\t\t\t\t// Disabled because std::lower_bound doesn't specify (23.3.3.3, p3) this can be done: EASTL_VALIDATE_COMPARE(!(value < *i)); // Validate that the compare function is sane.\n\t\t\t\tfirst = ++i;\n\t\t\t\td    -= d2 + 1;\n\t\t\t}\n\t\t\telse\n\t\t\t\td = d2;\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// lower_bound\n\t///\n\t/// Finds the position of the first element in a sorted range that has a value\n\t/// greater than or equivalent to a specified value. The input Compare function\n\t/// takes two arguments and returns true if the first argument is less than\n\t/// the second argument.\n\t///\n\t/// Effects: Finds the first position into which value can be inserted without\n\t/// violating the ordering.\n\t///\n\t/// Returns: The furthermost iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, i) the following corresponding\n\t/// condition holds: compare(*j, value) != false.\n\t///\n\t/// Complexity: At most 'log(last - first) + 1' comparisons.\n\t///\n\t/// Optimizations: We have no need to specialize this implementation for random\n\t/// access iterators (e.g. contiguous array), as the code below will already\n\t/// take advantage of them.\n\t///\n\ttemplate <typename ForwardIterator, typename T, typename Compare>\n\tForwardIterator\n\tlower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::difference_type DifferenceType;\n\n\t\tDifferenceType d = eastl::distance(first, last); // This will be efficient for a random access iterator such as an array.\n\n\t\twhile(d > 0)\n\t\t{\n\t\t\tForwardIterator i  = first;\n\t\t\tDifferenceType  d2 = d >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.\n\n\t\t\teastl::advance(i, d2); // This will be efficient for a random access iterator such as an array.\n\n\t\t\tif(compare(*i, value))\n\t\t\t{\n\t\t\t\t// Disabled because std::lower_bound doesn't specify (23.3.3.1, p3) this can be done: EASTL_VALIDATE_COMPARE(!compare(value, *i)); // Validate that the compare function is sane.\n\t\t\t\tfirst = ++i;\n\t\t\t\td    -= d2 + 1;\n\t\t\t}\n\t\t\telse\n\t\t\t\td = d2;\n\t\t}\n\t\treturn first;\n\t}\n\n\n\n\t/// upper_bound\n\t///\n\t/// Finds the position of the first element in a sorted range that has a\n\t/// value that is greater than a specified value.\n\t///\n\t/// Effects: Finds the furthermost position into which value can be inserted\n\t/// without violating the ordering.\n\t///\n\t/// Returns: The furthermost iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, i) the following corresponding\n\t/// condition holds: !(value < *j).\n\t///\n\t/// Complexity: At most 'log(last - first) + 1' comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tForwardIterator\n\tupper_bound(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::difference_type DifferenceType;\n\n\t\tDifferenceType len = eastl::distance(first, last);\n\n\t\twhile(len > 0)\n\t\t{\n\t\t\tForwardIterator i    = first;\n\t\t\tDifferenceType  len2 = len >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.\n\n\t\t\teastl::advance(i, len2);\n\n\t\t\tif(!(value < *i)) // Note that we always express value comparisons in terms of < or ==.\n\t\t\t{\n\t\t\t\tfirst = ++i;\n\t\t\t\tlen -= len2 + 1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Disabled because std::upper_bound doesn't specify (23.3.3.2, p3) this can be done: EASTL_VALIDATE_COMPARE(!(*i < value)); // Validate that the compare function is sane.\n\t\t\t\tlen = len2;\n\t\t\t}\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// upper_bound\n\t///\n\t/// Finds the position of the first element in a sorted range that has a\n\t/// value that is greater than a specified value. The input Compare function\n\t/// takes two arguments and returns true if the first argument is less than\n\t/// the second argument.\n\t///\n\t/// Effects: Finds the furthermost position into which value can be inserted\n\t/// without violating the ordering.\n\t///\n\t/// Returns: The furthermost iterator i in the range [first, last) such that\n\t/// for any iterator j in the range [first, i) the following corresponding\n\t/// condition holds: compare(value, *j) == false.\n\t///\n\t/// Complexity: At most 'log(last - first) + 1' comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename T, typename Compare>\n\tForwardIterator\n\tupper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::difference_type DifferenceType;\n\n\t\tDifferenceType len = eastl::distance(first, last);\n\n\t\twhile(len > 0)\n\t\t{\n\t\t\tForwardIterator i    = first;\n\t\t\tDifferenceType  len2 = len >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.\n\n\t\t\teastl::advance(i, len2);\n\n\t\t\tif(!compare(value, *i))\n\t\t\t{\n\t\t\t\tfirst = ++i;\n\t\t\t\tlen -= len2 + 1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Disabled because std::upper_bound doesn't specify (23.3.3.2, p3) this can be done: EASTL_VALIDATE_COMPARE(!compare(*i, value)); // Validate that the compare function is sane.\n\t\t\t\tlen = len2;\n\t\t\t}\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// equal_range\n\t///\n\t/// Effects: Finds the largest subrange [i, j) such that the value can be inserted\n\t/// at any iterator k in it without violating the ordering. k satisfies the\n\t/// corresponding conditions: !(*k < value) && !(value < *k).\n\t///\n\t/// Complexity: At most '2 * log(last - first) + 1' comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tpair<ForwardIterator, ForwardIterator>\n\tequal_range(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\treturn equal_range(first, last, value, eastl::less<>{});\n\t}\n\n\n\t/// equal_range\n\t///\n\t/// Effects: Finds the largest subrange [i, j) such that the value can be inserted\n\t/// at any iterator k in it without violating the ordering. k satisfies the\n\t/// corresponding conditions: compare(*k, value) == false && compare(value, *k) == false.\n\t///\n\t/// Complexity: At most '2 * log(last - first) + 1' comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename T, typename Compare>\n\tpair<ForwardIterator, ForwardIterator>\n\tequal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\t{\n\t\ttypedef pair<ForwardIterator, ForwardIterator> ResultType;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::difference_type DifferenceType;\n\n\t\tDifferenceType d = eastl::distance(first, last);\n\n\t\twhile(d > 0)\n\t\t{\n\t\t\tForwardIterator i(first);\n\t\t\tDifferenceType  d2 = d >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.\n\n\t\t\teastl::advance(i, d2);\n\n\t\t\tif(compare(*i, value))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(value, *i)); // Validate that the compare function is sane.\n\t\t\t\tfirst = ++i;\n\t\t\t\td    -= d2 + 1;\n\t\t\t}\n\t\t\telse if(compare(value, *i))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*i, value)); // Validate that the compare function is sane.\n\t\t\t\td    = d2;\n\t\t\t\tlast = i;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tForwardIterator j(i);\n\n\t\t\t\treturn ResultType(eastl::lower_bound(first, i, value, compare),\n\t\t\t\t\t\t\t\t  eastl::upper_bound(++j, last, value, compare));\n\t\t\t}\n\t\t}\n\t\treturn ResultType(first, first);\n\t}\n\n\n\t/// replace\n\t///\n\t/// Effects: Substitutes elements referred by the iterator i in the range [first, last)\n\t/// with new_value, when the following corresponding conditions hold: *i == old_value.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The predicate version of replace is replace_if and not another variation of replace.\n\t/// This is because both versions would have the same parameter count and there could be ambiguity.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tinline void\n\treplace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(*first == old_value)\n\t\t\t\t*first = new_value;\n\t\t}\n\t}\n\n\n\t/// replace_if\n\t///\n\t/// Effects: Substitutes elements referred by the iterator i in the range [first, last)\n\t/// with new_value, when the following corresponding conditions hold: predicate(*i) != false.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The predicate version of replace_if is replace and not another variation of replace_if.\n\t/// This is because both versions would have the same parameter count and there could be ambiguity.\n\t///\n\ttemplate <typename ForwardIterator, typename Predicate, typename T>\n\tinline void\n\treplace_if(ForwardIterator first, ForwardIterator last, Predicate predicate, const T& new_value)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(predicate(*first))\n\t\t\t\t*first = new_value;\n\t\t}\n\t}\n\n\t/// remove_copy\n\t///\n\t/// Effects: Copies all the elements referred to by the iterator i in the range\n\t/// [first, last) for which the following corresponding condition does not hold:\n\t/// *i == value.\n\t///\n\t/// Requires: The ranges [first, last) and [result, result + (last - first)) shall not overlap.\n\t///\n\t/// Returns: The end of the resulting range.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\ttemplate <typename InputIterator, typename OutputIterator, typename T>\n\tinline OutputIterator\n\tremove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(!(*first == value)) // Note that we always express value comparisons in terms of < or ==.\n\t\t\t{\n\t\t\t\t*result = *first;\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t/// remove_copy_if\n\t///\n\t/// Effects: Copies all the elements referred to by the iterator i in the range\n\t/// [first, last) for which the following corresponding condition does not hold:\n\t/// predicate(*i) != false.\n\t///\n\t/// Requires: The ranges [first, last) and [result, result + (last - first)) shall not overlap.\n\t///\n\t/// Returns: The end of the resulting range.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\ttemplate <typename InputIterator, typename OutputIterator, typename Predicate>\n\tinline OutputIterator\n\tremove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tif(!predicate(*first))\n\t\t\t{\n\t\t\t\t*result = *first;\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\n\t/// remove\n\t///\n\t/// Effects: Eliminates all the elements referred to by iterator i in the\n\t/// range [first, last) for which the following corresponding condition\n\t/// holds: *i == value.\n\t///\n\t/// Returns: The end of the resulting range.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The predicate version of remove is remove_if and not another variation of remove.\n\t/// This is because both versions would have the same parameter count and there could be ambiguity.\n\t///\n\t/// Note: Since this function moves the element to the back of the heap and\n\t/// doesn't actually remove it from the given container, the user must call\n\t/// the container erase function if the user wants to erase the element\n\t/// from the container.\n\t///\n\t/// Example usage:\n\t///    vector<int> intArray;\n\t///    ...\n\t///    intArray.erase(remove(intArray.begin(), intArray.end(), 4), intArray.end()); // Erase all elements of value 4.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tinline ForwardIterator\n\tremove(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\tfirst = eastl::find(first, last, value);\n\t\tif(first != last)\n\t\t{\n\t\t\tfor (ForwardIterator i = first; ++i != last;)\n\t\t\t{\n\t\t\t\tif (!(*i == value))\n\t\t\t\t{\n\t\t\t\t\t*first++ = eastl::move(*i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn first;\n\t}\n\n\t/// remove_if\n\t///\n\t/// Effects: Eliminates all the elements referred to by iterator i in the\n\t/// range [first, last) for which the following corresponding condition\n\t/// holds: predicate(*i) != false.\n\t///\n\t/// Returns: The end of the resulting range.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The predicate version of remove_if is remove and not another variation of remove_if.\n\t/// This is because both versions would have the same parameter count and there could be ambiguity.\n\t///\n\t/// Note: Since this function moves the element to the back of the heap and\n\t/// doesn't actually remove it from the given container, the user must call\n\t/// the container erase function if the user wants to erase the element\n\t/// from the container.\n\t///\n\t/// Example usage:\n\t///    vector<int> intArray;\n\t///    ...\n\t///    intArray.erase(remove(intArray.begin(), intArray.end(), bind(less<int>(), (int)3)), intArray.end()); // Erase all elements less than 3.\n\t///\n\ttemplate <typename ForwardIterator, typename Predicate>\n\tinline ForwardIterator\n\tremove_if(ForwardIterator first, ForwardIterator last, Predicate predicate)\n\t{\n\t\tfirst = eastl::find_if(first, last, predicate);\n\t\tif(first != last)\n\t\t{\n\t\t\tfor (ForwardIterator i = first; ++i != last;)\n\t\t\t{\n\t\t\t\tif (!predicate(*i))\n\t\t\t\t{\n\t\t\t\t\t*first++ = eastl::move(*i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn first;\n\t}\n\n\t/// apply_and_remove_if\n\t///\n\t/// Calls the Function function for all elements referred to  my iterator i in the range\n\t/// [first, last) for which the following corresponding condition holds:\n\t/// predicate(*i) == true\n\t/// and then left shift moves potential non-matching elements over it.\n\t///\n\t/// Returns: a past-the-end iterator for the new end of the range.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate + applies\n\t/// function once for every time the condition holds.\n\t///\n\t/// Note: Since removing is done by shifting (by means of copy move assignment) the elements\n\t/// in the range in such a way that the elements that are not to be removed appear in the\n\t/// beginning of the range doesn't actually remove it from the given container, the user must call\n\t/// the container erase function if the user wants to erase the element\n\t/// from the container. I.e. in the same they as for remove_if the excess elements\n\t/// are left in a valid but possibly moved from state.\n\t///\n\ttemplate <typename ForwardIterator, typename Function, typename Predicate>\n\tinline ForwardIterator apply_and_remove_if(ForwardIterator first,\n\t                                           ForwardIterator last,\n\t                                           Function function,\n\t                                           Predicate predicate)\n\t{\n\t\tfirst = eastl::find_if(first, last, predicate);\n\t\tif (first != last)\n\t\t{\n\t\t\tfunction(*first);\n\t\t\tfor (auto i = next(first); i != last; ++i)\n\t\t\t{\n\t\t\t\tif (predicate(*i))\n\t\t\t\t{\n\t\t\t\t\tfunction(*i);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t*first = eastl::move(*i);\n\t\t\t\t++first;\n\t\t\t}\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// apply_and_remove\n\t///\n\t/// Calls the Function function for all elements referred to my iterator i in the range\n\t/// [first, last) for which the following corresponding condition holds:\n\t/// value == *i\n\t/// and then left shift moves potential non-matching elements over it.\n\t///\n\t/// Returns: a past-the-end iterator for the new end of the range.\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding equality test\n\t/// + applies function once for every time the condition holds.\n\t///\n\t/// Note: Since removing is done by shifting (by means of copy move assignment) the elements\n\t/// in the range in such a way that the elements that are not to be removed appear in the\n\t/// beginning of the range doesn't actually remove it from the given container, the user must call\n\t/// the container erase function if the user wants to erase the element\n\t/// from the container. I.e. in the same they as for remove_if the excess elements\n\t/// are left in a valid but possibly moved from state.\n\t///\n\ttemplate <typename ForwardIterator, typename Function, typename T>\n\tinline ForwardIterator apply_and_remove(ForwardIterator first,\n\t                                        ForwardIterator last,\n\t                                        Function function,\n\t                                        const T& value)\n\t{\n\t\tfirst = eastl::find(first, last, value);\n\t\tif (first != last)\n\t\t{\n\t\t\tfunction(*first);\n\t\t\tfor (auto i = next(first); i != last; ++i)\n\t\t\t{\n\t\t\t\tif (value == *i)\n\t\t\t\t{\n\t\t\t\t\tfunction(*i);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t*first = eastl::move(*i);\n\t\t\t\t++first;\n\t\t\t}\n\t\t}\n\t\treturn first;\n\t}\n\n\n\t/// replace_copy\n\t///\n\t/// Effects: Assigns to every iterator i in the range [result, result + (last - first))\n\t/// either new_value or *(first + (i - result)) depending on whether the following\n\t/// corresponding conditions hold: *(first + (i - result)) == old_value.\n\t///\n\t/// Requires: The ranges [first, last) and [result, result + (last - first)) shall not overlap.\n\t///\n\t/// Returns: result + (last - first).\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The predicate version of replace_copy is replace_copy_if and not another variation of replace_copy.\n\t/// This is because both versions would have the same parameter count and there could be ambiguity.\n\t///\n\ttemplate <typename InputIterator, typename OutputIterator, typename T>\n\tinline OutputIterator\n\treplace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)\n\t{\n\t\tfor(; first != last; ++first, ++result)\n\t\t\t*result = (*first == old_value) ? new_value : *first;\n\t\treturn result;\n\t}\n\n\n\t/// replace_copy_if\n\t///\n\t/// Effects: Assigns to every iterator i in the range [result, result + (last - first))\n\t/// either new_value or *(first + (i - result)) depending on whether the following\n\t/// corresponding conditions hold: predicate(*(first + (i - result))) != false.\n\t///\n\t/// Requires: The ranges [first, last) and [result, result+(lastfirst)) shall not overlap.\n\t///\n\t/// Returns: result + (last - first).\n\t///\n\t/// Complexity: Exactly 'last - first' applications of the corresponding predicate.\n\t///\n\t/// Note: The predicate version of replace_copy_if is replace_copy and not another variation of replace_copy_if.\n\t/// This is because both versions would have the same parameter count and there could be ambiguity.\n\t///\n\ttemplate <typename InputIterator, typename OutputIterator, typename Predicate, typename T>\n\tinline OutputIterator\n\treplace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate, const T& new_value)\n\t{\n\t\tfor(; first != last; ++first, ++result)\n\t\t\t*result = predicate(*first) ? new_value : *first;\n\t\treturn result;\n\t}\n\n\n\n\n\t// reverse\n\t//\n\t// We provide helper functions which allow reverse to be implemented more\n\t// efficiently for some types of iterators and types.\n\t//\n\ttemplate <typename BidirectionalIterator>\n\tinline void reverse_impl(BidirectionalIterator first, BidirectionalIterator last, eastl::bidirectional_iterator_tag)\n\t{\n\t\tfor(; (first != last) && (first != --last); ++first) // We are not allowed to use operator <, <=, >, >= with a\n\t\t\teastl::iter_swap(first, last);                   // generic (bidirectional or otherwise) iterator.\n\t}\n\n\ttemplate <typename RandomAccessIterator>\n\tinline void reverse_impl(RandomAccessIterator first, RandomAccessIterator last, eastl::random_access_iterator_tag)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tfor(; first < --last; ++first)      // With a random access iterator, we can use operator < to more efficiently implement\n\t\t\t\teastl::iter_swap(first, last);  // this algorithm. A generic iterator doesn't necessarily have an operator < defined.\n\t\t}\n\t}\n\n\t/// reverse\n\t///\n\t/// Reverses the values within the range [first, last).\n\t///\n\t/// Effects: For each nonnegative integer i <= (last - first) / 2,\n\t/// applies swap to all pairs of iterators first + i, (last i) - 1.\n\t///\n\t/// Complexity: Exactly '(last - first) / 2' swaps.\n\t///\n\ttemplate <typename BidirectionalIterator>\n\tinline void reverse(BidirectionalIterator first, BidirectionalIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator>::iterator_category IC;\n\t\teastl::reverse_impl(first, last, IC());\n\t}\n\n\n\n\t/// reverse_copy\n\t///\n\t/// Copies the range [first, last) in reverse order to the result.\n\t///\n\t/// Effects: Copies the range [first, last) to the range\n\t/// [result, result + (last - first)) such that for any nonnegative\n\t/// integer i < (last - first) the following assignment takes place:\n\t/// *(result + (last - first) - i) = *(first + i)\n\t///\n\t/// Requires: The ranges [first, last) and [result, result + (last - first))\n\t/// shall not overlap.\n\t///\n\t/// Returns: result + (last - first). That is, returns the end of the output range.\n\t///\n\t/// Complexity: Exactly 'last - first' assignments.\n\t///\n\ttemplate <typename BidirectionalIterator, typename OutputIterator>\n\tinline OutputIterator\n\treverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result)\n\t{\n\t\tfor(; first != last; ++result)\n\t\t\t*result = *--last;\n\t\treturn result;\n\t}\n\n\n\n\t/// search\n\t///\n\t/// Search finds a subsequence within the range [first1, last1) that is identical to [first2, last2)\n\t/// when compared element-by-element. It returns an iterator pointing to the beginning of that\n\t/// subsequence, or else last1 if no such subsequence exists. As such, it is very much like\n\t/// the C strstr function, with the primary difference being that strstr uses 0-terminated strings\n\t/// whereas search uses an end iterator to specify the end of a string.\n\t///\n\t/// Returns: The first iterator i in the range [first1, last1 - (last2 - first2)) such that for\n\t/// any nonnegative integer n less than 'last2 - first2' the following corresponding condition holds:\n\t/// *(i + n) == *(first2 + n). Returns last1 if no such iterator is found.\n\t///\n\t/// Complexity: At most (last1 first1) * (last2 first2) applications of the corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\tForwardIterator1\n\tsearch(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t   ForwardIterator2 first2, ForwardIterator2 last2)\n\t{\n\t\tif(first2 != last2) // If there is anything to search for...\n\t\t{\n\t\t\t// We need to make a special case for a pattern of one element,\n\t\t\t// as the logic below prevents one element patterns from working.\n\t\t\tForwardIterator2 temp2(first2);\n\t\t\t++temp2;\n\n\t\t\tif(temp2 != last2) // If what we are searching for has a length > 1...\n\t\t\t{\n\t\t\t\tForwardIterator1 cur1(first1);\n\t\t\t\tForwardIterator2 p2;\n\n\t\t\t\twhile(first1 != last1)\n\t\t\t\t{\n\t\t\t\t\t// The following loop is the equivalent of eastl::find(first1, last1, *first2)\n\t\t\t\t\twhile((first1 != last1) && !(*first1 == *first2))\n\t\t\t\t\t\t++first1;\n\n\t\t\t\t\tif(first1 != last1)\n\t\t\t\t\t{\n\t\t\t\t\t\tp2   = temp2;\n\t\t\t\t\t\tcur1 = first1;\n\n\t\t\t\t\t\tif(++cur1 != last1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twhile(*cur1 == *p2)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(++p2 == last2)\n\t\t\t\t\t\t\t\t\treturn first1;\n\n\t\t\t\t\t\t\t\tif(++cur1 == last1)\n\t\t\t\t\t\t\t\t\treturn last1;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t++first1;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn last1;\n\t\t\t\t}\n\n\t\t\t\t// Fall through to the end.\n\t\t\t}\n\t\t\telse\n\t\t\t\treturn eastl::find(first1, last1, *first2);\n\t\t}\n\n\t\treturn first1;\n\n\n\t\t#if 0\n\t\t/*  Another implementation which is a little more simpler but executes a little slower on average.\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::difference_type difference_type_1;\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator2>::difference_type difference_type_2;\n\n\t\t\tconst difference_type_2 d2 = eastl::distance(first2, last2);\n\n\t\t\tfor(difference_type_1 d1 = eastl::distance(first1, last1); d1 >= d2; ++first1, --d1)\n\t\t\t{\n\t\t\t\tForwardIterator1 temp1 = first1;\n\n\t\t\t\tfor(ForwardIterator2 temp2 = first2; ; ++temp1, ++temp2)\n\t\t\t\t{\n\t\t\t\t\tif(temp2 == last2)\n\t\t\t\t\t\treturn first1;\n\t\t\t\t\tif(!(*temp1 == *temp2))\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn last1;\n\t\t*/\n\t\t#endif\n\t}\n\n\n\t/// search\n\t///\n\t/// Search finds a subsequence within the range [first1, last1) that is identical to [first2, last2)\n\t/// when compared element-by-element. It returns an iterator pointing to the beginning of that\n\t/// subsequence, or else last1 if no such subsequence exists. As such, it is very much like\n\t/// the C strstr function, with the only difference being that strstr uses 0-terminated strings\n\t/// whereas search uses an end iterator to specify the end of a string.\n\t///\n\t/// Returns: The first iterator i in the range [first1, last1 - (last2 - first2)) such that for\n\t/// any nonnegative integer n less than 'last2 - first2' the following corresponding condition holds:\n\t/// predicate(*(i + n), *(first2 + n)) != false. Returns last1 if no such iterator is found.\n\t///\n\t/// Complexity: At most (last1 first1) * (last2 first2) applications of the corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>\n\tForwardIterator1\n\tsearch(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t   ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t   BinaryPredicate predicate)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::difference_type difference_type_1;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator2>::difference_type difference_type_2;\n\n\t\tdifference_type_2 d2 = eastl::distance(first2, last2);\n\n\t\tif(d2 != 0)\n\t\t{\n\t\t\tForwardIterator1 i(first1);\n\t\t\teastl::advance(i, d2);\n\n\t\t\tfor(difference_type_1 d1 = eastl::distance(first1, last1); d1 >= d2; --d1)\n\t\t\t{\n\t\t\t\tif(eastl::equal<ForwardIterator1, ForwardIterator2, BinaryPredicate>(first1, i, first2, predicate))\n\t\t\t\t\treturn first1;\n\t\t\t\tif(d1 > d2) // To do: Find a way to make the algorithm more elegant.\n\t\t\t\t{\n\t\t\t\t\t++first1;\n\t\t\t\t\t++i;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn last1;\n\t\t}\n\t\treturn first1; // Just like with strstr, we return first1 if the match string is empty.\n\t}\n\n\n\n\t// search_n helper functions\n\t//\n\ttemplate <typename ForwardIterator, typename Size, typename T>\n\tForwardIterator     // Generic implementation.\n\tsearch_n_impl(ForwardIterator first, ForwardIterator last, Size count, const T& value, eastl::forward_iterator_tag)\n\t{\n\t\tif(count <= 0)\n\t\t\treturn first;\n\n\t\tSize d1 = (Size)eastl::distance(first, last); // Should d1 be of type Size, ptrdiff_t, or iterator_traits<ForwardIterator>::difference_type?\n\t\t\t\t\t\t\t\t\t\t\t\t\t  // The problem with using iterator_traits<ForwardIterator>::difference_type is that\n\t\tif(count > d1)                                // ForwardIterator may not be a true iterator but instead something like a pointer.\n\t\t\treturn last;\n\n\t\tfor(; d1 >= count; ++first, --d1)\n\t\t{\n\t\t\tForwardIterator i(first);\n\n\t\t\tfor(Size n = 0; n < count; ++n, ++i, --d1)\n\t\t\t{\n\t\t\t\tif(!(*i == value)) // Note that we always express value comparisons in terms of < or ==.\n\t\t\t\t\tgoto not_found;\n\t\t\t}\n\t\t\treturn first;\n\n\t\t\tnot_found:\n\t\t\tfirst = i;\n\t\t}\n\t\treturn last;\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename Size, typename T> inline\n\tRandomAccessIterator    // Random access iterator implementation. Much faster than generic implementation.\n\tsearch_n_impl(RandomAccessIterator first, RandomAccessIterator last, Size count, const T& value, eastl::random_access_iterator_tag)\n\t{\n\t\tif(count <= 0)\n\t\t\treturn first;\n\t\telse if(count == 1)\n\t\t\treturn eastl::find(first, last, value);\n\t\telse if(last > first)\n\t\t{\n\t\t\tRandomAccessIterator lookAhead;\n\t\t\tRandomAccessIterator backTrack;\n\n\t\t\tSize skipOffset = (count - 1);\n\t\t\tSize tailSize = (Size)(last - first);\n\t\t\tSize remainder;\n\t\t\tSize prevRemainder;\n\n\t\t\tfor(lookAhead = first + skipOffset; tailSize >= count; lookAhead += count)\n\t\t\t{\n\t\t\t\ttailSize -= count;\n\n\t\t\t\tif(*lookAhead == value)\n\t\t\t\t{\n\t\t\t\t\tremainder = skipOffset;\n\n\t\t\t\t\tfor(backTrack = lookAhead - 1; *backTrack == value; --backTrack)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(--remainder == 0)\n\t\t\t\t\t\t\treturn (lookAhead - skipOffset); // success\n\t\t\t\t\t}\n\n\t\t\t\t\tif(remainder <= tailSize)\n\t\t\t\t\t{\n\t\t\t\t\t\tprevRemainder = remainder;\n\n\t\t\t\t\t\twhile(*(++lookAhead) == value)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(--remainder == 0)\n\t\t\t\t\t\t\t\treturn (backTrack + 1); // success\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttailSize -= (prevRemainder - remainder);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\treturn last; // failure\n\t\t\t\t}\n\n\t\t\t\t// lookAhead here is always pointing to the element of the last mismatch.\n\t\t\t}\n\t\t}\n\n\t\treturn last; // failure\n\t}\n\n\n\t/// search_n\n\t///\n\t/// Returns: The first iterator i in the range [first, last count) such that\n\t/// for any nonnegative integer n less than count the following corresponding\n\t/// conditions hold: *(i + n) == value, pred(*(i + n),value) != false.\n\t/// Returns last if no such iterator is found.\n\t///\n\t/// Complexity: At most '(last1 - first1) * count' applications of the corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator, typename Size, typename T>\n\tForwardIterator\n\tsearch_n(ForwardIterator first, ForwardIterator last, Size count, const T& value)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;\n\t\treturn eastl::search_n_impl(first, last, count, value, IC());\n\t}\n\n\n\t/// binary_search\n\t///\n\t/// Returns: true if there is an iterator i in the range [first last) that\n\t/// satisfies the corresponding conditions: !(*i < value) && !(value < *i).\n\t///\n\t/// Complexity: At most 'log(last - first) + 2' comparisons.\n\t///\n\t/// Note: The reason binary_search returns bool instead of an iterator is\n\t/// that search_n, lower_bound, or equal_range already return an iterator.\n\t/// However, there are arguments that binary_search should return an iterator.\n\t/// Note that we provide binary_search_i (STL extension) to return an iterator.\n\t///\n\t/// To use search_n to find an item, do this:\n\t///     iterator i = search_n(begin, end, 1, value);\n\t/// To use lower_bound to find an item, do this:\n\t///     iterator i = lower_bound(begin, end, value);\n\t///     if((i != last) && !(value < *i))\n\t///         <use the iterator>\n\t/// It turns out that the above lower_bound method is as fast as binary_search\n\t/// would be if it returned an iterator.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tinline bool\n\tbinary_search(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\t// To do: This can be made slightly faster by not using lower_bound.\n\t\tForwardIterator i(eastl::lower_bound<ForwardIterator, T>(first, last, value));\n\t\treturn ((i != last) && !(value < *i)); // Note that we always express value comparisons in terms of < or ==.\n\t}\n\n\n\t/// binary_search\n\t///\n\t/// Returns: true if there is an iterator i in the range [first last) that\n\t/// satisfies the corresponding conditions: compare(*i, value) == false &&\n\t/// compare(value, *i) == false.\n\t///\n\t/// Complexity: At most 'log(last - first) + 2' comparisons.\n\t///\n\t/// Note: See comments above regarding the bool return value of binary_search.\n\t///\n\ttemplate <typename ForwardIterator, typename T, typename Compare>\n\tinline bool\n\tbinary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\t{\n\t\t// To do: This can be made slightly faster by not using lower_bound.\n\t\tForwardIterator i(eastl::lower_bound<ForwardIterator, T, Compare>(first, last, value, compare));\n\t\treturn ((i != last) && !compare(value, *i));\n\t}\n\n\n\t/// binary_search_i\n\t///\n\t/// Returns: iterator if there is an iterator i in the range [first last) that\n\t/// satisfies the corresponding conditions: !(*i < value) && !(value < *i).\n\t/// Returns last if the value is not found.\n\t///\n\t/// Complexity: At most 'log(last - first) + 2' comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tinline ForwardIterator\n\tbinary_search_i(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\t// To do: This can be made slightly faster by not using lower_bound.\n\t\tForwardIterator i(eastl::lower_bound<ForwardIterator, T>(first, last, value));\n\t\tif((i != last) && !(value < *i)) // Note that we always express value comparisons in terms of < or ==.\n\t\t\treturn i;\n\t\treturn last;\n\t}\n\n\n\t/// binary_search_i\n\t///\n\t/// Returns: iterator if there is an iterator i in the range [first last) that\n\t/// satisfies the corresponding conditions: !(*i < value) && !(value < *i).\n\t/// Returns last if the value is not found.\n\t///\n\t/// Complexity: At most 'log(last - first) + 2' comparisons.\n\t///\n\ttemplate <typename ForwardIterator, typename T, typename Compare>\n\tinline ForwardIterator\n\tbinary_search_i(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\t{\n\t\t// To do: This can be made slightly faster by not using lower_bound.\n\t\tForwardIterator i(eastl::lower_bound<ForwardIterator, T, Compare>(first, last, value, compare));\n\t\tif((i != last) && !compare(value, *i))\n\t\t\treturn i;\n\t\treturn last;\n\t}\n\n\n\t/// unique\n\t///\n\t/// Given a sorted range, this function removes duplicated items.\n\t/// Note that if you have a container then you will probably want\n\t/// to call erase on the container with the return value if your\n\t/// goal is to remove the duplicated items from the container.\n\t///\n\t/// Effects: Eliminates all but the first element from every consecutive\n\t/// group of equal elements referred to by the iterator i in the range\n\t/// [first, last) for which the following corresponding condition holds:\n\t/// *i == *(i - 1).\n\t///\n\t/// Returns: The end of the resulting range.\n\t///\n\t/// Complexity: If the range (last - first) is not empty, exactly (last - first)\n\t/// applications of the corresponding predicate, otherwise no applications of the predicate.\n\t///\n\t/// Example usage:\n\t///    vector<int> intArray;\n\t///    ...\n\t///    intArray.erase(unique(intArray.begin(), intArray.end()), intArray.end());\n\t///\n\ttemplate <typename ForwardIterator>\n\tForwardIterator unique(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tfirst = eastl::adjacent_find<ForwardIterator>(first, last);\n\n\t\tif(first != last) // We expect that there are duplicated items, else the user wouldn't be calling this function.\n\t\t{\n\t\t\tForwardIterator dest(first);\n\n\t\t\tfor(++first; first != last; ++first)\n\t\t\t{\n\t\t\t\tif(!(*dest == *first)) // Note that we always express value comparisons in terms of < or ==.\n\t\t\t\t\t*++dest = *first;\n\t\t\t}\n\t\t\treturn ++dest;\n\t\t}\n\t\treturn last;\n\t}\n\n\n\t/// unique\n\t///\n\t/// Given a sorted range, this function removes duplicated items.\n\t/// Note that if you have a container then you will probably want\n\t/// to call erase on the container with the return value if your\n\t/// goal is to remove the duplicated items from the container.\n\t///\n\t/// Effects: Eliminates all but the first element from every consecutive\n\t/// group of equal elements referred to by the iterator i in the range\n\t/// [first, last) for which the following corresponding condition holds:\n\t/// predicate(*i, *(i - 1)) != false.\n\t///\n\t/// Returns: The end of the resulting range.\n\t///\n\t/// Complexity: If the range (last - first) is not empty, exactly (last - first)\n\t/// applications of the corresponding predicate, otherwise no applications of the predicate.\n\t///\n\ttemplate <typename ForwardIterator, typename BinaryPredicate>\n\tForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate predicate)\n\t{\n\t\tfirst = eastl::adjacent_find<ForwardIterator, BinaryPredicate>(first, last, predicate);\n\n\t\tif(first != last) // We expect that there are duplicated items, else the user wouldn't be calling this function.\n\t\t{\n\t\t\tForwardIterator dest(first);\n\n\t\t\tfor(++first; first != last; ++first)\n\t\t\t{\n\t\t\t\tif(!predicate(*dest, *first))\n\t\t\t\t\t*++dest = *first;\n\t\t\t}\n\t\t\treturn ++dest;\n\t\t}\n\t\treturn last;\n\t}\n\n\n\n\t// find_end\n\t//\n\t// We provide two versions here, one for a bidirectional iterators and one for\n\t// regular forward iterators. Given that we are searching backward, it's a bit\n\t// more efficient if we can use backwards iteration to implement our search,\n\t// though this requires an iterator that can be reversed.\n\t//\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\tForwardIterator1\n\tfind_end_impl(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t\t  ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t\t\t  eastl::forward_iterator_tag, eastl::forward_iterator_tag)\n\t{\n\t\tif(first2 != last2) // We have to do this check because the search algorithm below will return first1 (and not last1) if the first2/last2 range is empty.\n\t\t{\n\t\t\tfor(ForwardIterator1 result(last1); ; )\n\t\t\t{\n\t\t\t\tconst ForwardIterator1 resultNext(eastl::search(first1, last1, first2, last2));\n\n\t\t\t\tif(resultNext != last1) // If another sequence was found...\n\t\t\t\t{\n\t\t\t\t\tfirst1 = result = resultNext;\n\t\t\t\t\t++first1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\treturn last1;\n\t}\n\n\ttemplate <typename BidirectionalIterator1, typename BidirectionalIterator2>\n\tBidirectionalIterator1\n\tfind_end_impl(BidirectionalIterator1 first1, BidirectionalIterator1 last1,\n\t\t\t\t  BidirectionalIterator2 first2, BidirectionalIterator2 last2,\n\t\t\t\t  eastl::bidirectional_iterator_tag, eastl::bidirectional_iterator_tag)\n\t{\n\t\ttypedef eastl::reverse_iterator<BidirectionalIterator1> reverse_iterator1;\n\t\ttypedef eastl::reverse_iterator<BidirectionalIterator2> reverse_iterator2;\n\n\t\treverse_iterator1 rresult(eastl::search(reverse_iterator1(last1), reverse_iterator1(first1),\n\t\t\t\t\t\t\t\t\t\t\t\treverse_iterator2(last2), reverse_iterator2(first2)));\n\t\tif(rresult.base() != first1) // If we found something...\n\t\t{\n\t\t\tBidirectionalIterator1 result(rresult.base());\n\n\t\t\teastl::advance(result, -eastl::distance(first2, last2)); // We have an opportunity to optimize this, as the\n\t\t\treturn result;                                           // search function already calculates this distance.\n\t\t}\n\t\treturn last1;\n\t}\n\n\t/// find_end\n\t///\n\t/// Finds the last occurrence of the second sequence in the first sequence.\n\t/// As such, this function is much like the C string function strrstr and it\n\t/// is also the same as a reversed version of 'search'. It is called find_end\n\t/// instead of the possibly more consistent search_end simply because the C++\n\t/// standard algorithms have such naming.\n\t///\n\t/// Returns an iterator between first1 and last1 if the sequence is found.\n\t/// returns last1 (the end of the first seqence) if the sequence is not found.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\tinline ForwardIterator1\n\tfind_end(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t ForwardIterator2 first2, ForwardIterator2 last2)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::iterator_category IC1;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator2>::iterator_category IC2;\n\n\t\treturn eastl::find_end_impl(first1, last1, first2, last2, IC1(), IC2());\n\t}\n\n\n\n\n\t// To consider: Fold the predicate and non-predicate versions of\n\t//              this algorithm into a single function.\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>\n\tForwardIterator1\n\tfind_end_impl(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t\t  ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t\t\t  BinaryPredicate predicate,\n\t\t\t\t  eastl::forward_iterator_tag, eastl::forward_iterator_tag)\n\t{\n\t\tif(first2 != last2) // We have to do this check because the search algorithm below will return first1 (and not last1) if the first2/last2 range is empty.\n\t\t{\n\t\t\tfor(ForwardIterator1 result = last1; ; )\n\t\t\t{\n\t\t\t\tconst ForwardIterator1 resultNext(eastl::search<ForwardIterator1, ForwardIterator2, BinaryPredicate>(first1, last1, first2, last2, predicate));\n\n\t\t\t\tif(resultNext != last1) // If another sequence was found...\n\t\t\t\t{\n\t\t\t\t\tfirst1 = result = resultNext;\n\t\t\t\t\t++first1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\treturn last1;\n\t}\n\n\ttemplate <typename BidirectionalIterator1, typename BidirectionalIterator2, typename BinaryPredicate>\n\tBidirectionalIterator1\n\tfind_end_impl(BidirectionalIterator1 first1, BidirectionalIterator1 last1,\n\t\t\t\t  BidirectionalIterator2 first2, BidirectionalIterator2 last2,\n\t\t\t\t  BinaryPredicate predicate,\n\t\t\t\t  eastl::bidirectional_iterator_tag, eastl::bidirectional_iterator_tag)\n\t{\n\t\ttypedef eastl::reverse_iterator<BidirectionalIterator1> reverse_iterator1;\n\t\ttypedef eastl::reverse_iterator<BidirectionalIterator2> reverse_iterator2;\n\n\t\treverse_iterator1 rresult(eastl::search<reverse_iterator1, reverse_iterator2, BinaryPredicate>\n\t\t\t\t\t\t\t\t\t\t\t   (reverse_iterator1(last1), reverse_iterator1(first1),\n\t\t\t\t\t\t\t\t\t\t\t\treverse_iterator2(last2), reverse_iterator2(first2),\n\t\t\t\t\t\t\t\t\t\t\t\tpredicate));\n\t\tif(rresult.base() != first1) // If we found something...\n\t\t{\n\t\t\tBidirectionalIterator1 result(rresult.base());\n\t\t\teastl::advance(result, -eastl::distance(first2, last2));\n\t\t\treturn result;\n\t\t}\n\t\treturn last1;\n\t}\n\n\n\t/// find_end\n\t///\n\t/// Effects: Finds a subsequence of equal values in a sequence.\n\t///\n\t/// Returns: The last iterator i in the range [first1, last1 - (last2 - first2))\n\t/// such that for any nonnegative integer n < (last2 - first2), the following\n\t/// corresponding conditions hold: pred(*(i+n),*(first2+n)) != false. Returns\n\t/// last1 if no such iterator is found.\n\t///\n\t/// Complexity: At most (last2 - first2) * (last1 - first1 - (last2 - first2) + 1)\n\t/// applications of the corresponding predicate.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>\n\tinline ForwardIterator1\n\tfind_end(ForwardIterator1 first1, ForwardIterator1 last1,\n\t\t\t ForwardIterator2 first2, ForwardIterator2 last2,\n\t\t\t BinaryPredicate predicate)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::iterator_category IC1;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator2>::iterator_category IC2;\n\n\t\treturn eastl::find_end_impl<ForwardIterator1, ForwardIterator2, BinaryPredicate>\n\t\t\t\t\t\t\t\t   (first1, last1, first2, last2, predicate, IC1(), IC2());\n\t}\n\n\n\t/// set_difference\n\t///\n\t/// set_difference iterates over both input ranges and copies elements present\n\t/// in the first range but not the second to the output range.\n\t///\n\t/// Effects: Copies the elements of the range [first1, last1) which are not\n\t/// present in the range [first2, last2) to the range beginning at result.\n\t/// The elements in the constructed range are sorted.\n\t///\n\t/// Requires: The input ranges must be sorted.\n\t/// Requires: The output range shall not overlap with either of the original ranges.\n\t///\n\t/// Returns: The end of the output range.\n\t///\n\t/// Complexity: At most (2 * ((last1 - first1) + (last2 - first2)) - 1) comparisons.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator>\n\tOutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t\t  InputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t\t  OutputIterator result)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(*first1 < *first2)\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++result;\n\t\t\t}\n\t\t\telse if(*first2 < *first1)\n\t\t\t\t++first2;\n\t\t\telse\n\t\t\t{\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t}\n\n\t\treturn eastl::copy(first1, last1, result);\n\t}\n\n\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>\n\tOutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t\t  InputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t\t  OutputIterator result, Compare compare)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(compare(*first1, *first2))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first2, *first1)); // Validate that the compare function is sane.\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++result;\n\t\t\t}\n\t\t\telse if(compare(*first2, *first1))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.\n\t\t\t\t++first2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t}\n\n\t\treturn eastl::copy(first1, last1, result);\n\t}\n\n\n\t/// set_difference_2\n\t///\n\t/// set_difference_2 iterates over both input ranges and copies elements present\n\t/// in the first range but not the second to the first output range and copies\n\t/// elements present in the second range but not in the first to the second output\n\t/// range.\n\t///\n\t/// Effects: Copies the elements of the range [first1, last1) which are not\n\t/// present in the range [first2, last2) to the first output range beginning at\n\t/// result1 AND copies the element of range [first2, last2) which are not present\n\t/// in the range [first1, last) to the second output range beginning at result2.\n\t/// The elements in the constructed range are sorted.\n\t///\n\t/// Requires: The input ranges must be sorted.\n\t/// Requires: The output ranges shall not overlap with either of the original ranges.\n\t///\n\t/// Returns:  Nothing.\n\t///\n\t/// Complexity: At most (2 * ((last1 - first1) + (last2 - first2)) - 1) comparisons.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>\n\tvoid set_difference_2(InputIterator1 first1, InputIterator1 last1,\n\t                      InputIterator2 first2, InputIterator2 last2,\n\t                      OutputIterator result1, OutputIterator result2, Compare compare)\n\t{\n\t\twhile ((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif (compare(*first1, *first2))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first2, *first1)); // Validate that the compare function is sane.\n\t\t\t\t*result1++ = *first1++;\n\t\t\t}\n\t\t\telse if (compare(*first2, *first1))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.\n\t\t\t\t*result2++ = *first2++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t}\n\n\t\teastl::copy(first2, last2, result2);\n\t\teastl::copy(first1, last1, result1);\n\t}\n\n\t/// set_difference_2\n\t///\n\t///  set_difference_2 with the default comparison object is eastl::less<>.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator>\n\tvoid set_difference_2(InputIterator1 first1, InputIterator1 last1,\n\t                      InputIterator2 first2, InputIterator2 last2,\n\t                      OutputIterator result1, OutputIterator result2)\n\t{\n\t\teastl::set_difference_2(first1, last1, first2, last2, result1, result2, eastl::less<>{});\n\t}\n\n\n\t/// set_symmetric_difference\n\t///\n\t/// set_difference iterates over both input ranges and copies elements present\n\t/// in the either range but not the other to the output range.\n\t///\n\t/// Effects: Copies the elements of the range [first1, last1) which are not\n\t/// present in the range [first2, last2), and the elements of the range [first2, last2)\n\t/// which are not present in the range [first1, last1) to the range beginning at result.\n\t/// The elements in the constructed range are sorted.\n\t///\n\t/// Requires: The input ranges must be sorted.\n\t/// Requires: The resulting range shall not overlap with either of the original ranges.\n\t///\n\t/// Returns: The end of the constructed range.\n\t///\n\t/// Complexity: At most (2 * ((last1 - first1) + (last2 - first2)) - 1) comparisons.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator>\n\tOutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t\t\t\t\tInputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t\t\t\t\tOutputIterator result)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(*first1 < *first2)\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++result;\n\t\t\t}\n\t\t\telse if(*first2 < *first1)\n\t\t\t{\n\t\t\t\t*result = *first2;\n\t\t\t\t++first2;\n\t\t\t\t++result;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t}\n\n\t\treturn eastl::copy(first2, last2, eastl::copy(first1, last1, result));\n\t}\n\n\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>\n\tOutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t\t\t\t\tInputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t\t\t\t\tOutputIterator result, Compare compare)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(compare(*first1, *first2))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first2, *first1)); // Validate that the compare function is sane.\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++result;\n\t\t\t}\n\t\t\telse if(compare(*first2, *first1))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.\n\t\t\t\t*result = *first2;\n\t\t\t\t++first2;\n\t\t\t\t++result;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t}\n\n\t\treturn eastl::copy(first2, last2, eastl::copy(first1, last1, result));\n\t}\n\n\n\t/// set_intersection\n\t///\n\t/// set_intersection over both ranges and copies elements present in\n\t/// both ranges to the output range.\n\t///\n\t/// Effects: Constructs a sorted intersection of the elements from the\n\t/// two ranges; that is, the set of elements that are present in both of the ranges.\n\t///\n\t/// Requires: The input ranges must be sorted.\n\t/// Requires: The resulting range shall not overlap with either of the original ranges.\n\t///\n\t/// Returns: The end of the constructed range.\n\t///\n\t/// Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1)  comparisons.\n\t///\n\t/// Note: The copying operation is stable; if an element is present in both ranges,\n\t/// the one from the first range is copied.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator>\n\tOutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t\t\tInputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t\t\tOutputIterator result)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(*first1 < *first2)\n\t\t\t\t++first1;\n\t\t\telse if(*first2 < *first1)\n\t\t\t\t++first2;\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>\n\tOutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t\t\tInputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t\t\tOutputIterator result, Compare compare)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(compare(*first1, *first2))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first2, *first1)); // Validate that the compare function is sane.\n\t\t\t\t++first1;\n\t\t\t}\n\t\t\telse if(compare(*first2, *first1))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.\n\t\t\t\t++first2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t\t++result;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\n\t/// set_union\n\t///\n\t/// set_union iterates over both ranges and copies elements present in\n\t/// both ranges to the output range.\n\t///\n\t/// Effects: Constructs a sorted union of the elements from the two ranges;\n\t/// that is, the set of elements that are present in one or both of the ranges.\n\t///\n\t/// Requires: The input ranges must be sorted.\n\t/// Requires: The resulting range shall not overlap with either of the original ranges.\n\t///\n\t/// Returns: The end of the constructed range.\n\t///\n\t/// Complexity: At most (2 * ((last1 - first1) + (last2 - first2)) - 1) comparisons.\n\t///\n\t/// Note: The copying operation is stable; if an element is present in both ranges,\n\t/// the one from the first range is copied.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator>\n\tOutputIterator set_union(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t InputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t OutputIterator result)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(*first1 < *first2)\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t}\n\t\t\telse if(*first2 < *first1)\n\t\t\t{\n\t\t\t\t*result = *first2;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t\t++result;\n\t\t}\n\n\t\treturn eastl::copy(first2, last2, eastl::copy(first1, last1, result));\n\t}\n\n\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>\n\tOutputIterator set_union(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\t InputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t OutputIterator result, Compare compare)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(compare(*first1, *first2))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first2, *first1)); // Validate that the compare function is sane.\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t}\n\t\t\telse if(compare(*first2, *first1))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.\n\t\t\t\t*result = *first2;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t\t++result;\n\t\t}\n\n\t\treturn eastl::copy(first2, last2, eastl::copy(first1, last1, result));\n\t}\n\n\n\t/// set_decomposition\n\t///\n\t/// set_decomposition iterates over both ranges and copies elements to one of the three\n\t/// categories of output ranges.\n\t///\n\t/// Effects: Constructs three sorted containers of the elements from the two ranges.\n\t///             * OutputIterator1 is elements only in Container1.\n\t///             * OutputIterator2 is elements only in Container2.\n\t///             * OutputIterator3 is elements that are in both Container1 and Container2.\n\t///\n\t/// Requires: The input ranges must be sorted.\n\t/// Requires: The resulting ranges shall not overlap with either of the original ranges.\n\t///\n\t/// Returns: The end of the constructed range of elements in both Container1 and Container2.\n\t///\n\t/// Complexity: At most (2 * ((last1 - first1) + (last2 - first2)) - 1) comparisons.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2,\n\t          typename OutputIterator1, typename OutputIterator2, typename OutputIterator3, typename Compare>\n\tOutputIterator3 set_decomposition(InputIterator1 first1, InputIterator1 last1,\n\t                                  InputIterator2 first2, InputIterator2 last2,\n\t                                  OutputIterator1 result1, OutputIterator2 result2, OutputIterator3 result3, Compare compare)\n\t{\n\t\twhile ((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif (compare(*first1, *first2))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first2, *first1)); // Validate that the compare function is sane.\n\t\t\t\t*result1++ = *first1++;\n\t\t\t}\n\t\t\telse if (compare(*first2, *first1))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.\n\t\t\t\t*result2++ = *first2++;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result3++ = *first1++;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t}\n\n\t\teastl::copy(first1, last1, result1);\n\t\teastl::copy(first2, last2, result2);\n\n\t\treturn result3;\n\t}\n\n\t/// set_decomposition\n\t///\n\t///  set_decomposition with the default comparison object is eastl::less<>.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2,\n\t\t\t  typename OutputIterator1, typename OutputIterator2, typename OutputIterator3>\n\tOutputIterator3 set_decomposition(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\t  OutputIterator1 result1, OutputIterator2 result2, OutputIterator3 result3)\n\t{\n\t\treturn eastl::set_decomposition(first1, last1, first2, last2, result1, result2, result3, eastl::less<>{});\n\t}\n\n\t/// includes\n\t///\n\t/// Returns true if the sorted range [first2, last2) is a subsequence of the sorted range [first1, last1).\n\t/// Note: a subsequence need not be contiguous!.\n\t/// If [first1, last1) or [first2, last2) is not sorted with respect to comp, the behavior is undefined.\n\ttemplate<class InputIt1, class InputIt2, class Compare>\n\tbool includes(InputIt1 first1, InputIt1 last1,\n\t\t\t\t  InputIt2 first2, InputIt2 last2, Compare comp)\n\t{\n\t\tfor (; first2 != last2; ++first1)\n\t\t{\n\t\t\tif (first1 == last1 || comp(*first2, *first1))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!comp(*first1, *first2))\n\t\t\t{\n\t\t\t\t++first2;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/// includes\n\t///\n\t/// Returns true if the sorted range [first2, last2) is a subsequence of the sorted range [first1, last1).\n\t/// Note: a subsequence need not be contiguous!.\n\t/// If [first1, last1) or [first2, last2) is not sorted with respect to eastl::less, the behavior is undefined.\n\ttemplate<class InputIt1, class InputIt2>\n\tbool includes(InputIt1 first1, InputIt1 last1,\n\t\t\t\t  InputIt2 first2, InputIt2 last2)\n\t{\n\t\treturn eastl::includes(first1, last1, first2, last2, eastl::less<>{});\n\t}\n\n\t/// is_permutation\n\t///\n\ttemplate<typename ForwardIterator1, typename ForwardIterator2>\n\tbool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::difference_type difference_type;\n\n\t\t// Skip past any equivalent initial elements.\n\t\twhile((first1 != last1) && (*first1 == *first2))\n\t\t{\n\t\t\t++first1;\n\t\t\t++first2;\n\t\t}\n\n\t\tif(first1 != last1)\n\t\t{\n\t\t\tconst difference_type first1Size = eastl::distance(first1, last1);\n\t\t\tForwardIterator2 last2 = first2;\n\t\t\teastl::advance(last2, first1Size);\n\n\t\t\tfor(ForwardIterator1 i = first1; i != last1; ++i)\n\t\t\t{\n\t\t\t\tif(i == eastl::find(first1, i, *i))\n\t\t\t\t{\n\t\t\t\t\tconst difference_type c = eastl::count(first2, last2, *i);\n\n\t\t\t\t\tif((c == 0) || (c != eastl::count(i, last1, *i)))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/// is_permutation\n\t///\n\ttemplate<typename ForwardIterator1, typename ForwardIterator2, class BinaryPredicate>\n\tbool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate predicate)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::difference_type difference_type;\n\n\t\t// Skip past any equivalent initial elements.\n\t\twhile((first1 != last1) && predicate(*first1, *first2))\n\t\t{\n\t\t\t++first1;\n\t\t\t++first2;\n\t\t}\n\n\t\tif(first1 != last1)\n\t\t{\n\t\t\tconst difference_type first1Size = eastl::distance(first1, last1);\n\t\t\tForwardIterator2 last2 = first2;\n\t\t\teastl::advance(last2, first1Size);\n\n\t\t\tfor(ForwardIterator1 i = first1; i != last1; ++i)\n\t\t\t{\n\t\t\t\tif(i == eastl::find(first1, i, *i, predicate))\n\t\t\t\t{\n\t\t\t\t\tconst difference_type c = eastl::count(first2, last2, *i, predicate);\n\n\t\t\t\t\tif((c == 0) || (c != eastl::count(i, last1, *i, predicate)))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\n\t/// next_permutation\n\t///\n\t/// mutates the range [first, last) to the next permutation. Returns true if the\n\t/// new range is not the final permutation (sorted like the starting permutation).\n\t/// Permutations start with a sorted range, and false is returned when next_permutation\n\t/// results in the initial sorted range, or if the range has <= 1 element.\n\t/// Note that elements are compared by operator < (as usual) and that elements deemed\n\t/// equal via this are not rearranged.\n\t///\n\t/// http://marknelson.us/2002/03/01/next-permutation/\n\t/// Basically we start with an ordered range and reverse it's order one specifically\n\t/// chosen swap and reverse at a time. It happens that this require going through every\n\t/// permutation of the range. We use the same variable names as the document above.\n\t///\n\t/// To consider: Significantly improved permutation/combination functionality:\n\t///    http://home.roadrunner.com/~hinnant/combinations.html\n\t///\n\t/// Example usage:\n\t///     vector<int> intArray;\n\t///     // <populate intArray>\n\t///     sort(intArray.begin(), intArray.end());\n\t///     do {\n\t///         // <do something with intArray>\n\t///     } while(next_permutation(intArray.begin(), intArray.end()));\n\t///\n\n\ttemplate<typename BidirectionalIterator, typename Compare>\n\tbool next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare compare)\n\t{\n\t\tif(first != last) // If there is anything in the range...\n\t\t{\n\t\t\tBidirectionalIterator i = last;\n\n\t\t\tif(first != --i) // If the range has more than one item...\n\t\t\t{\n\t\t\t\tfor(;;)\n\t\t\t\t{\n\t\t\t\t\tBidirectionalIterator ii(i), j;\n\n\t\t\t\t\tif(compare(*--i, *ii)) // Find two consecutive values where the first is less than the second.\n\t\t\t\t\t{\n\t\t\t\t\t\tj = last;\n\t\t\t\t\t\twhile(!compare(*i, *--j)) // Find the final value that's greater than the first (it may be equal to the second).\n\t\t\t\t\t\t\t{}\n\t\t\t\t\t\teastl::iter_swap(i, j);     // Swap the first and the final.\n\t\t\t\t\t\teastl::reverse(ii, last);   // Reverse the ranget from second to last.\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(i == first) // There are no two consecutive values where the first is less than the second, meaning the range is in reverse order. The reverse ordered range is always the last permutation.\n\t\t\t\t\t{\n\t\t\t\t\t\teastl::reverse(first, last);\n\t\t\t\t\t\tbreak; // We are done.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\ttemplate<typename BidirectionalIterator>\n\tbool next_permutation(BidirectionalIterator first, BidirectionalIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator>::value_type value_type;\n\n\t\treturn eastl::next_permutation(first, last, eastl::less<value_type>());\n\t}\n\n\n\n\t/// rotate\n\t///\n\t/// Effects: For each non-negative integer i < (last - first), places the element from the\n\t/// position first + i into position first + (i + (last - middle)) % (last - first).\n\t///\n\t/// Returns: first + (last - middle). That is, returns where first went to.\n\t///\n\t/// Remarks: This is a left rotate.\n\t///\n\t/// Requires: [first,middle) and [middle,last) shall be valid ranges. ForwardIterator shall\n\t/// satisfy the requirements of ValueSwappable (17.6.3.2). The type of *first shall satisfy\n\t/// the requirements of MoveConstructible (Table 20) and the requirements of MoveAssignable.\n\t///\n\t/// Complexity: At most last - first swaps.\n\t///\n\t/// Note: While rotate works on ForwardIterators (e.g. slist) and BidirectionalIterators (e.g. list),\n\t/// you can get much better performance (O(1) instead of O(n)) with slist and list rotation by\n\t/// doing splice operations on those lists instead of calling this rotate function.\n\t///\n\t/// http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf / http://books.google.com/books?id=kse_7qbWbjsC&pg=PA14&lpg=PA14&dq=Programming+Pearls+flipping+hands\n\t/// http://books.google.com/books?id=tjOlkl7ecVQC&pg=PA189&lpg=PA189&dq=stepanov+Elements+of+Programming+rotate\n\t/// http://stackoverflow.com/questions/21160875/why-is-stdrotate-so-fast\n\t///\n\t/// Strategy:\n\t///     - We handle the special case of (middle == first) and (middle == last) no-ops\n\t///       up front in the main rotate entry point.\n\t///     - There's a basic ForwardIterator implementation (rotate_general_impl) which is\n\t///       a fallback implementation that's not as fast as others but works for all cases.\n\t///     - There's a slightly better BidirectionalIterator implementation.\n\t///     - We have specialized versions for rotating elements that are trivially copyable.\n\t///       These versions will use memmove for when we have a RandomAccessIterator.\n\t///     - We have a specialized version for rotating by only a single position, as that allows us\n\t///       (with any iterator type) to avoid a lot of logic involved with algorithms like \"flipping hands\"\n\t///       and achieve near optimal O(n) behavior. it turns out that rotate-by-one is a common use\n\t///       case in practice.\n\t///\n\tnamespace Internal\n\t{\n\t\ttemplate<typename ForwardIterator>\n\t\tForwardIterator rotate_general_impl(ForwardIterator first, ForwardIterator middle, ForwardIterator last)\n\t\t{\n\t\t\tusing eastl::swap;\n\n\t\t\tForwardIterator current = middle;\n\n\t\t\tdo {\n\t\t\t\tswap(*first++, *current++);\n\n\t\t\t\tif(first == middle)\n\t\t\t\t\tmiddle = current;\n\t\t\t} while(current != last);\n\n\t\t\tForwardIterator result = first;\n\t\t\tcurrent = middle;\n\n\t\t\twhile(current != last)\n\t\t\t{\n\t\t\t\tswap(*first++, *current++);\n\n\t\t\t\tif(first == middle)\n\t\t\t\t\tmiddle = current;\n\t\t\t\telse if(current == last)\n\t\t\t\t\tcurrent = middle;\n\t\t\t}\n\n\t\t\treturn result; // result points to first + (last - middle).\n\t\t}\n\n\n\t\ttemplate <typename ForwardIterator>\n\t\tForwardIterator move_rotate_left_by_one(ForwardIterator first, ForwardIterator last)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\n\t\t\tvalue_type temp(eastl::move(*first));\n\t\t\tForwardIterator result = eastl::move(eastl::next(first), last, first); // Note that while our template type is BidirectionalIterator, if the actual\n\t\t\t*result = eastl::move(temp);                                           // iterator is a RandomAccessIterator then this move will be a memmove for trivially copyable types.\n\n\t\t\treturn result; // result points to the final element in the range.\n\t\t}\n\n\n\t\ttemplate <typename BidirectionalIterator>\n\t\tBidirectionalIterator move_rotate_right_by_one(BidirectionalIterator first, BidirectionalIterator last)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator>::value_type value_type;\n\n\t\t\tBidirectionalIterator beforeLast = eastl::prev(last);\n\t\t\tvalue_type temp(eastl::move(*beforeLast));\n\t\t\tBidirectionalIterator result = eastl::move_backward(first, beforeLast, last); // Note that while our template type is BidirectionalIterator, if the actual\n\t\t\t*first = eastl::move(temp);                                                   // iterator is a RandomAccessIterator then this move will be a memmove for trivially copyable types.\n\n\t\t\treturn result; // result points to the first element in the range.\n\t\t}\n\n\t\ttemplate <typename /*IteratorCategory*/, bool /*is_trivially_copyable*/>\n\t\tstruct rotate_helper\n\t\t{\n\t\t\ttemplate <typename ForwardIterator>\n\t\t\tstatic ForwardIterator rotate_impl(ForwardIterator first, ForwardIterator middle, ForwardIterator last)\n\t\t\t\t{ return Internal::rotate_general_impl(first, middle, last); }\n\t\t};\n\n\t\ttemplate <>\n\t\tstruct rotate_helper<eastl::forward_iterator_tag, true>\n\t\t{\n\t\t\ttemplate <typename ForwardIterator>\n\t\t\tstatic ForwardIterator rotate_impl(ForwardIterator first, ForwardIterator middle, ForwardIterator last)\n\t\t\t{\n\t\t\t\tif(eastl::next(first) == middle) // If moving trivial types by a single element, memcpy is fast for that case.\n\t\t\t\t\treturn Internal::move_rotate_left_by_one(first, last);\n\t\t\t\treturn Internal::rotate_general_impl(first, middle, last);\n\t\t\t}\n\t\t};\n\n\t\ttemplate <>\n\t\tstruct rotate_helper<eastl::bidirectional_iterator_tag, false>\n\t\t{\n\t\t\ttemplate <typename BidirectionalIterator>\n\t\t\tstatic BidirectionalIterator rotate_impl(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last)\n\t\t\t\t{ return Internal::rotate_general_impl(first, middle, last); } // rotate_general_impl outperforms the flipping hands algorithm.\n\n\t\t\t/*\n\t\t\t// Simplest \"flipping hands\" implementation. Disabled because it's slower on average than rotate_general_impl.\n\t\t\ttemplate <typename BidirectionalIterator>\n\t\t\tstatic BidirectionalIterator rotate_impl(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last)\n\t\t\t{\n\t\t\t\teastl::reverse(first, middle);\n\t\t\t\teastl::reverse(middle, last);\n\t\t\t\teastl::reverse(first, last);\n\t\t\t\treturn first + (last - middle); // This can be slow for large ranges because operator + and - are O(n).\n\t\t\t}\n\n\t\t\t// Smarter \"flipping hands\" implementation, but still disabled because benchmarks are showing it to be slower than rotate_general_impl.\n\t\t\ttemplate <typename BidirectionalIterator>\n\t\t\tstatic BidirectionalIterator rotate_impl(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last)\n\t\t\t{\n\t\t\t\t// This is the \"flipping hands\" algorithm.\n\t\t\t\teastl::reverse_impl(first,  middle, eastl::bidirectional_iterator_tag()); // Reverse the left side.\n\t\t\t\teastl::reverse_impl(middle, last,   eastl::bidirectional_iterator_tag()); // Reverse the right side.\n\n\t\t\t\t// Reverse the entire range.\n\t\t\t\twhile((first != middle) && (middle != last))\n\t\t\t\t{\n\t\t\t\t\teastl::iter_swap(first, --last);\n\t\t\t\t\t++first;\n\t\t\t\t}\n\n\t\t\t\tif(first == middle) // Finish reversing the entire range.\n\t\t\t\t{\n\t\t\t\t\teastl::reverse_impl(middle, last, bidirectional_iterator_tag());\n\t\t\t\t\treturn last;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teastl::reverse_impl(first, middle, bidirectional_iterator_tag());\n\t\t\t\t\treturn first;\n\t\t\t\t}\n\t\t\t}\n\t\t\t*/\n\t\t};\n\n\t\ttemplate <>\n\t\tstruct rotate_helper<eastl::bidirectional_iterator_tag, true>\n\t\t{\n\t\t\ttemplate <typename BidirectionalIterator>\n\t\t\tstatic BidirectionalIterator rotate_impl(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last)\n\t\t\t{\n\t\t\t\tif(eastl::next(first) == middle) // If moving trivial types by a single element, memcpy is fast for that case.\n\t\t\t\t\treturn Internal::move_rotate_left_by_one(first, last);\n\t\t\t\tif(eastl::next(middle) == last)\n\t\t\t\t\treturn Internal::move_rotate_right_by_one(first, last);\n\t\t\t\treturn Internal::rotate_general_impl(first, middle, last);\n\t\t\t}\n\t\t};\n\n\t\ttemplate <typename Integer>\n\t\tinline Integer greatest_common_divisor(Integer x, Integer y)\n\t\t{\n\t\t\tdo {\n\t\t\t\tInteger t = (x % y);\n\t\t\t\tx = y;\n\t\t\t\ty = t;\n\t\t\t} while(y);\n\n\t\t\treturn x;\n\t\t}\n\n\t\ttemplate <>\n\t\tstruct rotate_helper<eastl::random_access_iterator_tag, false>\n\t\t{\n\t\t\t// This is the juggling algorithm, using move operations.\n\t\t\t// In practice this implementation is about 25% faster than rotate_general_impl. We may want to\n\t\t\t// consider sticking with just rotate_general_impl and avoid the code generation of this function.\n\t\t\ttemplate <typename RandomAccessIterator>\n\t\t\tstatic RandomAccessIterator rotate_impl(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)\n\t\t\t{\n\t\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t\tconst difference_type m1 = (middle - first);\n\t\t\t\tconst difference_type m2 = (last - middle);\n\t\t\t\tconst difference_type g  = Internal::greatest_common_divisor(m1, m2);\n\t\t\t\tvalue_type temp;\n\n\t\t\t\tfor(RandomAccessIterator p = first + g; p != first;)\n\t\t\t\t{\n\t\t\t\t\ttemp = eastl::move(*--p);\n\t\t\t\t\tRandomAccessIterator p1 = p;\n\t\t\t\t\tRandomAccessIterator p2 = p + m1;\n\t\t\t\t\tdo\n\t\t\t\t\t{\n\t\t\t\t\t\t*p1 = eastl::move(*p2);\n\t\t\t\t\t\tp1 = p2;\n\t\t\t\t\t\tconst difference_type d = (last - p2);\n\n\t\t\t\t\t\tif(m1 < d)\n\t\t\t\t\t\t\tp2 += m1;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tp2 = first + (m1 - d);\n\t\t\t\t\t} while(p2 != p);\n\n\t\t\t\t\t*p1 = eastl::move(temp);\n\t\t\t\t}\n\n\t\t\t\treturn first + m2;\n\t\t\t}\n\t\t};\n\n\t\ttemplate <>\n\t\tstruct rotate_helper<eastl::random_access_iterator_tag, true>\n\t\t{\n\t\t\t// Experiments were done which tested the performance of using an intermediate buffer\n\t\t\t// to do memcpy's to as opposed to executing a swapping algorithm. It turns out this is\n\t\t\t// actually slower than even rotate_general_impl, partly because the average case involves\n\t\t\t// memcpy'ing a quarter of the element range twice. Experiments were done with various kinds\n\t\t\t// of PODs with various element counts.\n\n\t\t\ttemplate <typename RandomAccessIterator>\n\t\t\tstatic RandomAccessIterator rotate_impl(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)\n\t\t\t{\n\t\t\t\tif(eastl::next(first) == middle) // If moving trivial types by a single element, memcpy is fast for that case.\n\t\t\t\t\treturn Internal::move_rotate_left_by_one(first, last);\n\t\t\t\tif(eastl::next(middle) == last)\n\t\t\t\t\treturn Internal::move_rotate_right_by_one(first, last);\n\t\t\t\tif((last - first) < 32) // For small ranges rotate_general_impl is faster.\n\t\t\t\t\treturn Internal::rotate_general_impl(first, middle, last);\n\t\t\t\treturn Internal::rotate_helper<eastl::random_access_iterator_tag, false>::rotate_impl(first, middle, last);\n\t\t\t}\n\t\t};\n\n\t} // namespace Internal\n\n\n\ttemplate <typename ForwardIterator>\n\tForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)\n\t{\n\t\tif(middle != first)\n\t\t{\n\t\t\tif(middle != last)\n\t\t\t{\n\t\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;\n\t\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type        value_type;\n\n\t\t\t\t// the implementations for is_trivially_copyable types simply check whether we have a single element to rotate and if so,\n\t\t\t\t// defer to either move_rotate_left_by_one or move_rotate_right_by_one, which are optimized for trivially copyable types.\n\t\t\t\t// otherwise, use the same implementation as non-trivially copyable types.\n\t\t\t\treturn Internal::rotate_helper<IC, eastl::is_trivially_copyable<value_type>::value>::rotate_impl(first, middle, last);\n\t\t\t}\n\n\t\t\treturn first;\n\t\t}\n\n\t\treturn last;\n\t}\n\n\n\n\t/// rotate_copy\n\t///\n\t/// Similar to rotate except writes the output to the OutputIterator and\n\t/// returns an OutputIterator to the element past the last element copied\n\t/// (i.e. result + (last - first))\n\t///\n\ttemplate <typename ForwardIterator, typename OutputIterator>\n\tOutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result)\n\t{\n\t\treturn eastl::copy(first, middle, eastl::copy(middle, last, result));\n\t}\n\n\n\n\t/// clamp\n\t///\n\t/// Returns a reference to a clamped value within the range of [lo, hi].\n\t///\n\t/// http://en.cppreference.com/w/cpp/algorithm/clamp\n\t///\n\ttemplate <class T, class Compare>\n\tEA_CONSTEXPR const T& clamp(const T& v, const T& lo, const T& hi, Compare comp)\n\t{\n\t\tEASTL_ASSERT(!comp(hi, lo));\n\t\treturn comp(v, lo) ? lo : comp(hi, v) ? hi : v;\n\t}\n\n\ttemplate <class T>\n\tEA_CONSTEXPR const T& clamp(const T& v, const T& lo, const T& hi)\n\t{\n\t\treturn eastl::clamp(v, lo, hi, eastl::less<>());\n\t}\n\n\n\t/// is_partitioned\n\t///\n\t/// Returns true if all the elements in the range [first, last) is empty, or is\n\t/// partitioned by predicate. Being partitioned means that all elements v for which\n\t/// predicate(v) evaluates to true appear before any elements for which predicate(v)\n\t/// is false.\n\t///\n\ttemplate <class InputIterator, class UnaryPredicate>\n\tEA_CONSTEXPR bool is_partitioned(InputIterator first, InputIterator last, UnaryPredicate predicate)\n\t{\n\t\tfor (; first != last; ++first)\n\t\t{\n\t\t\tif (!predicate(*first))\n\t\t\t{\n\t\t\t\t// advance the iterator, we don't need to call the predicate on this item\n\t\t\t\t// again in the \"false\" loop below.\n\t\t\t\t++first;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor (; first != last; ++first)\n\t\t{\n\t\t\tif (predicate(*first))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/// partition_point\n\t///\n\t/// Precondition: for this function to work correctly the input range [first, last)\n\t/// must be partitioned by the predicate. i.e. all values for which predicate(v) is\n\t/// true should precede any value in the range for which predicate(v) is false.\n\t///\n\t/// Returns: the iterator past the end of the first partition within [first, last) or\n\t/// last if all elements satisfy the predicate.\n\t///\n\t/// Note: this is a more general version of lower_bound.\n\ttemplate <class ForwardIterator, class UnaryPredicate>\n\tEA_CONSTEXPR ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, UnaryPredicate predicate)\n\t{\n\t\t// Just binary chop our way to the first one where predicate(x) is false\n\t\tfor (auto length = eastl::distance(first, last); 0 < length;)\n\t\t{\n\t\t\tconst auto half = length / 2;\n\t\t\tconst auto middle = eastl::next(first, half);\n\t\t\tif (predicate(*middle))\n\t\t\t{\n\t\t\t\tfirst = eastl::next(middle);\n\t\t\t\tlength -= (half + 1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlength = half;\n\t\t\t}\n\t\t}\n\n\t\treturn first;\n\t}\n\n} // namespace eastl\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/allocator.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ALLOCATOR_H\n#define EASTL_ALLOCATOR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EABase/nullptr.h>\n#include <stddef.h>\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// alloc_flags\n\t///\n\t/// Defines allocation flags.\n\t///\n\tenum alloc_flags \n\t{\n\t\tMEM_TEMP = 0, // Low memory, not necessarily actually temporary.\n\t\tMEM_PERM = 1  // High memory, for things that won't be unloaded.\n\t};\n\n\n\t/// allocator\n\t///\n\t/// In this allocator class, note that it is not templated on any type and\n\t/// instead it simply allocates blocks of memory much like the C malloc and\n\t/// free functions. It can be thought of as similar to C++ std::allocator<char>.\n\t/// The flags parameter has meaning that is specific to the allocation \n\t///\n\t/// C++11's std::allocator (20.6.9) doesn't have a move constructor or assignment \n\t/// operator. This is possibly because std::allocators are associated with types\n\t/// instead of as instances. The potential non-equivalance of C++ std::allocator\n\t/// instances has been a source of some acknowledged design problems.\n\t/// We don't implement support for move construction or assignment in eastl::allocator,\n\t/// but users can define their own allocators which do have move functions and \n\t/// the eastl containers are compatible with such allocators (i.e. nothing unexpected\n\t/// will happen).\n\t///\n\tclass EASTL_API allocator\n\t{\n\tpublic:\n\t\tEASTL_ALLOCATOR_EXPLICIT allocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME));\n\t\tallocator(const allocator& x);\n\t\tallocator(const allocator& x, const char* pName);\n\n\t\tallocator& operator=(const allocator& x);\n\n\t\tvoid* allocate(size_t n, int flags = 0);\n\t\tvoid* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);\n\t\tvoid  deallocate(void* p, size_t n);\n\n\t\tconst char* get_name() const;\n\t\tvoid        set_name(const char* pName);\n\n\tprotected:\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tconst char* mpName; // Debug name, used to track memory.\n\t\t#endif\n\t};\n\n\tbool operator==(const allocator& a, const allocator& b);\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\tbool operator!=(const allocator& a, const allocator& b);\n#endif\n\n\n\t/// dummy_allocator\n\t///\n\t/// Defines an allocator which does nothing. It returns NULL from allocate calls.\n\t///\n\tclass EASTL_API dummy_allocator\n\t{\n\tpublic:\n\t\tEASTL_ALLOCATOR_EXPLICIT dummy_allocator(const char* = NULL) { }\n\t\tdummy_allocator(const dummy_allocator&) { }\n\t\tdummy_allocator(const dummy_allocator&, const char*) { }\n\n\t\tdummy_allocator& operator=(const dummy_allocator&) { return *this; }\n\n\t\tvoid* allocate(size_t, int = 0)                 { return NULL; }\n\t\tvoid* allocate(size_t, size_t, size_t, int = 0) { return NULL; }\n\t\tvoid  deallocate(void*, size_t)                 { }\n\n\t\tconst char* get_name() const      { return \"\"; }\n\t\tvoid        set_name(const char*) { }\n\t};\n\n\tinline bool operator==(const dummy_allocator&, const dummy_allocator&) { return true;  }\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\tinline bool operator!=(const dummy_allocator&, const dummy_allocator&) { return false; }\n#endif\n\n\n\t/// Defines a static default allocator which is constant across all types.\n\t/// This is different from get_default_allocator, which is is bound at\n\t/// compile-time and expected to differ per allocator type.\n\t/// Currently this Default Allocator applies only to CoreAllocatorAdapter.\n\t/// To consider: This naming of this function is too similar to get_default_allocator\n\t/// and instead should be named something like GetStaticDefaultAllocator.\n\tEASTL_API allocator* GetDefaultAllocator();\n\tEASTL_API allocator* SetDefaultAllocator(allocator* pAllocator);\n\n\n\t/// get_default_allocator\n\t///\n\t/// This templated function allows the user to implement a default allocator\n\t/// retrieval function that any part of EASTL can use. EASTL containers take\n\t/// an Allocator parameter which identifies an Allocator class to use. But \n\t/// different kinds of allocators have different mechanisms for retrieving \n\t/// a default allocator instance, and some don't even intrinsically support\n\t/// such functionality. The user can override this get_default_allocator \n\t/// function in order to provide the glue between EASTL and whatever their\n\t/// system's default allocator happens to be.\n\t///\n\t/// Example usage:\n\t///     MyAllocatorType* gpSystemAllocator;\n\t///     \n\t///     MyAllocatorType* get_default_allocator(const MyAllocatorType*)\n\t///         { return gpSystemAllocator; }\n\t///\n\ttemplate <typename Allocator>\n\tAllocator* get_default_allocator(const Allocator*);\n\n\tEASTLAllocatorType* get_default_allocator(const EASTLAllocatorType*);\n\n\n\t/// default_allocfreemethod\n\t///\n\t/// Implements a default allocfreemethod which uses the default global allocator.\n\t/// This version supports only default alignment.\n\t///\n\tvoid* default_allocfreemethod(size_t n, void* pBuffer, void* /*pContext*/);\n\n\n\t/// allocate_memory\n\t///\n\t/// This is a memory allocation dispatching function.\n\t/// To do: Make aligned and unaligned specializations.\n\t///        Note that to do this we will need to use a class with a static\n\t///        function instead of a standalone function like below.\n\t///\n\ttemplate <typename Allocator>\n\tvoid* allocate_memory(Allocator& a, size_t n, size_t alignment, size_t alignmentOffset);\n\n\n} // namespace eastl\n\n\n\n\n\n\n#ifndef EASTL_USER_DEFINED_ALLOCATOR // If the user hasn't declared that he has defined a different allocator implementation elsewhere...\n\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <new>\n\tEA_RESTORE_ALL_VC_WARNINGS()\n\n\t#if !EASTL_DLL // If building a regular library and not building EASTL as a DLL...\n\t\t// It is expected that the application define the following\n\t\t// versions of operator new for the application. Either that or the\n\t\t// user needs to override the implementation of the allocator class.\n\t\tvoid* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\n\t\tvoid* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\n\t#endif\n\n\tnamespace eastl\n\t{\n\t\tinline allocator::allocator(const char* EASTL_NAME(pName))\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n\t\t\t#endif\n\t\t}\n\n\n\t\tinline allocator::allocator(const allocator& EASTL_NAME(alloc))\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = alloc.mpName;\n\t\t\t#endif\n\t\t}\n\n\n\t\tinline allocator::allocator(const allocator&, const char* EASTL_NAME(pName))\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n\t\t\t#endif\n\t\t}\n\n\n\t\tinline allocator& allocator::operator=(const allocator& EASTL_NAME(alloc))\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = alloc.mpName;\n\t\t\t#endif\n\t\t\treturn *this;\n\t\t}\n\n\n\t\tinline const char* allocator::get_name() const\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\treturn mpName;\n\t\t\t#else\n\t\t\t\treturn EASTL_ALLOCATOR_DEFAULT_NAME;\n\t\t\t#endif\n\t\t}\n\n\n\t\tinline void allocator::set_name(const char* EASTL_NAME(pName))\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = pName;\n\t\t\t#endif\n\t\t}\n\n\n\t\tinline void* allocator::allocate(size_t n, int flags)\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\t#define pName mpName\n\t\t\t#else\n\t\t\t\t#define pName EASTL_ALLOCATOR_DEFAULT_NAME\n\t\t\t#endif\n\n\t\t\t#if EASTL_DLL\n\t\t\t\treturn allocate(n, EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT, 0, flags);\n\t\t\t#elif (EASTL_DEBUGPARAMS_LEVEL <= 0)\n\t\t\t\treturn ::new((char*)0, flags, 0, (char*)0,        0) char[n];\n\t\t\t#elif (EASTL_DEBUGPARAMS_LEVEL == 1)\n\t\t\t\treturn ::new(   pName, flags, 0, (char*)0,        0) char[n];\n\t\t\t#else\n\t\t\t\treturn ::new(   pName, flags, 0, __FILE__, __LINE__) char[n];\n\t\t\t#endif\n\t\t}\n\n\n\t\tinline void* allocator::allocate(size_t n, size_t alignment, size_t offset, int flags)\n\t\t{\n\t\t\t#if EASTL_DLL\n\t\t\t\t// We currently have no support for implementing flags when \n\t\t\t\t// using the C runtime library operator new function. The user \n\t\t\t\t// can use SetDefaultAllocator to override the default allocator.\n\t\t\t\tEA_UNUSED(offset); EA_UNUSED(flags);\n\n\t\t\t\tsize_t adjustedAlignment = (alignment > EA_PLATFORM_PTR_SIZE) ? alignment : EA_PLATFORM_PTR_SIZE;\n\n\t\t\t\tvoid* p = new char[n + adjustedAlignment + EA_PLATFORM_PTR_SIZE];\n\t\t\t\tvoid* pPlusPointerSize = (void*)((uintptr_t)p + EA_PLATFORM_PTR_SIZE);\n\t\t\t\tvoid* pAligned = (void*)(((uintptr_t)pPlusPointerSize + adjustedAlignment - 1) & ~(adjustedAlignment - 1));\n\n\t\t\t\tvoid** pStoredPtr = (void**)pAligned - 1;\n\t\t\t\tEASTL_ASSERT(pStoredPtr >= p);\n\t\t\t\t*(pStoredPtr) = p;\n\n\t\t\t\tEASTL_ASSERT(((size_t)pAligned & ~(alignment - 1)) == (size_t)pAligned);\n\n\t\t\t\treturn pAligned;\n\t\t\t#elif (EASTL_DEBUGPARAMS_LEVEL <= 0)\n\t\t\t\treturn ::new(alignment, offset, (char*)0, flags, 0, (char*)0,        0) char[n];\n\t\t\t#elif (EASTL_DEBUGPARAMS_LEVEL == 1)\n\t\t\t\treturn ::new(alignment, offset,    pName, flags, 0, (char*)0,        0) char[n];\n\t\t\t#else\n\t\t\t\treturn ::new(alignment, offset,    pName, flags, 0, __FILE__, __LINE__) char[n];\n\t\t\t#endif\n\n\t\t\t#undef pName  // See above for the definition of this.\n\t\t}\n\n\n\t\tinline void allocator::deallocate(void* p, size_t)\n\t\t{\n\t\t\t#if EASTL_DLL\n\t\t\t\tif (p != nullptr)\n\t\t\t\t{\n\t\t\t\t\tvoid* pOriginalAllocation = *((void**)p - 1);\n\t\t\t\t\tdelete[](char*)pOriginalAllocation;\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tdelete[](char*)p;\n\t\t\t#endif\n\t\t}\n\n\n\t\tinline bool operator==(const allocator&, const allocator&)\n\t\t{\n\t\t\treturn true; // All allocators are considered equal, as they merely use global new/delete.\n\t\t}\n\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\tinline bool operator!=(const allocator&, const allocator&)\n\t\t{\n\t\t\treturn false; // All allocators are considered equal, as they merely use global new/delete.\n\t\t}\n#endif\n\n\t} // namespace eastl\n\n\n#endif // EASTL_USER_DEFINED_ALLOCATOR\n\n\n\nnamespace eastl\n{\n\n\ttemplate <typename Allocator>\n\tinline Allocator* get_default_allocator(const Allocator*)\n\t{\n\t\treturn NULL; // By default we return NULL; the user must make specialization of this function in order to provide their own implementation.\n\t}\n\n\n\tinline EASTLAllocatorType* get_default_allocator(const EASTLAllocatorType*)\n\t{\n\t\treturn EASTLAllocatorDefault(); // For the built-in allocator EASTLAllocatorType, we happen to already have a function for returning the default allocator instance, so we provide it.\n\t}\n\n\n\tinline void* default_allocfreemethod(size_t n, void* pBuffer, void* /*pContext*/)\n\t{\n\t\tEASTLAllocatorType* const pAllocator = EASTLAllocatorDefault();\n\n\t\tif(pBuffer) // If freeing...\n\t\t{\n\t\t\tEASTLFree(*pAllocator, pBuffer, n);\n\t\t\treturn NULL;  // The return value is meaningless for the free.\n\t\t}\n\t\telse // allocating\n\t\t\treturn EASTLAlloc(*pAllocator, n);\n\t}\n\n\n\t/// allocate_memory\n\t///\n\t/// This is a memory allocation dispatching function.\n\t/// To do: Make aligned and unaligned specializations.\n\t///        Note that to do this we will need to use a class with a static\n\t///        function instead of a standalone function like below.\n\t///\n\ttemplate <typename Allocator>\n\tinline void* allocate_memory(Allocator& a, size_t n, size_t alignment, size_t alignmentOffset)\n\t{\n\t\tvoid *result;\n\t\tif (alignment <= EASTL_ALLOCATOR_MIN_ALIGNMENT)\n\t\t{\n\t\t\tresult = EASTLAlloc(a, n);\n\t\t\t// Ensure the result is correctly aligned.  An assertion likely indicates a mismatch between EASTL_ALLOCATOR_MIN_ALIGNMENT and the minimum alignment\n\t\t\t// of EASTLAlloc.  If there is a mismatch it may be necessary to define EASTL_ALLOCATOR_MIN_ALIGNMENT to be the minimum alignment of EASTLAlloc, or\n\t\t\t// to increase the alignment of EASTLAlloc to match EASTL_ALLOCATOR_MIN_ALIGNMENT.\n\t\t\tEASTL_ASSERT((reinterpret_cast<size_t>(result)& ~(alignment - 1)) == reinterpret_cast<size_t>(result));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tresult = EASTLAllocAligned(a, n, alignment, alignmentOffset);\n\t\t\t// Ensure the result is correctly aligned.  An assertion here may indicate a bug in the allocator.\n\t\t\tauto resultMinusOffset = (char*)result - alignmentOffset;\n\t\t\tEA_UNUSED(resultMinusOffset);\n\t\t\tEASTL_ASSERT((reinterpret_cast<size_t>(resultMinusOffset)& ~(alignment - 1)) == reinterpret_cast<size_t>(resultMinusOffset));\n\t\t}\n\t\treturn result;\n\t}\n\n}\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/allocator_malloc.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ALLOCATOR_MALLOC_H\n#define EASTL_ALLOCATOR_MALLOC_H\n\n\n#include <EABase/eahave.h>\n#include <EASTL/allocator.h>\n#include <stddef.h>\n\n\n// EASTL_ALIGNED_MALLOC_AVAILABLE\n//\n// Identifies if the standard library provides a built-in aligned version of malloc.\n// Defined as 0 or 1, depending on the standard library or platform availability.\n// None of the viable C functions provides for an aligned malloc with offset, so we \n// don't consider that supported in any case.\n//\n// Options for aligned allocations:\n// C11   aligned_alloc   http://linux.die.net/man/3/aligned_alloc\n// glibc memalign        http://linux.die.net/man/3/posix_memalign\n// Posix posix_memalign  http://pubs.opengroup.org/onlinepubs/000095399/functions/posix_memalign.html\n// VC++ _aligned_malloc  http://msdn.microsoft.com/en-us/library/8z34s9c6%28VS.80%29.aspx This is not suitable, since it has a limitation that you need to free via _aligned_free.\n//\n#if !defined EASTL_ALIGNED_MALLOC_AVAILABLE\n\t#if defined(EA_PLATFORM_POSIX) && !defined(EA_PLATFORM_APPLE)\n\t\t// memalign is more consistently available than posix_memalign, though its location isn't consistent across \n\t\t// platforms and compiler libraries. Typically it's declared in one of three headers: stdlib.h, malloc.h, or malloc/malloc.h\n\t\t#include <stdlib.h> // memalign, posix_memalign. \n\t\t#define EASTL_ALIGNED_MALLOC_AVAILABLE 1\n\n\t\t#if EA_HAS_INCLUDE_AVAILABLE\n\t\t\t#if EA_HAS_INCLUDE(<malloc/malloc.h>)\n\t\t\t\t#include <malloc/malloc.h>\n\t\t\t#elif EA_HAS_INCLUDE(<malloc.h>)\n\t\t\t\t#include <malloc.h>\n\t\t\t#endif\n\t\t#elif defined(EA_PLATFORM_BSD)\n\t\t\t#include <malloc/malloc.h>\n\t\t#elif defined(__clang__)\n\t\t\t#if __has_include(<malloc/malloc.h>)\n\t\t\t\t#include <malloc/malloc.h>\n\t\t\t#elif __has_include(<malloc.h>)\n\t\t\t\t#include <malloc.h>\n\t\t\t#endif\n\t\t#else\n\t\t\t#include <malloc.h>\n\t\t#endif\n\t#else\n\t\t#define EASTL_ALIGNED_MALLOC_AVAILABLE 0\n\t#endif\n#endif\n\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// allocator_malloc\n\t//\n\t// Implements an EASTL allocator that uses malloc/free as opposed to \n\t// new/delete or PPMalloc Malloc/Free. \n\t//\n\t// Example usage:\n\t//      vector<int, allocator_malloc> intVector;\n\t// \n\tclass allocator_malloc\n\t{\n\tpublic:\n\t\tallocator_malloc(const char* = NULL)\n\t\t\t{ }\n\n\t\tallocator_malloc(const allocator_malloc&)\n\t\t\t{ }\n\n\t\tallocator_malloc(const allocator_malloc&, const char*)\n\t\t\t{ }\n\n\t\tallocator_malloc& operator=(const allocator_malloc&)\n\t\t\t{ return *this; }\n\n\t\tbool operator==(const allocator_malloc&)\n\t\t\t{ return true; }\n\n\t\tbool operator!=(const allocator_malloc&)\n\t\t\t{ return false; }\n\n\t\tvoid* allocate(size_t n, int /*flags*/ = 0)\n\t\t\t{ return malloc(n); }\n\n\t\tvoid* allocate(size_t n, size_t alignment, size_t alignmentOffset, int /*flags*/ = 0)\n\t\t{ \n\t\t\t#if EASTL_ALIGNED_MALLOC_AVAILABLE\n\t\t\t\tif((alignmentOffset % alignment) == 0) // We check for (offset % alignmnent == 0) instead of (offset == 0) because any block which is aligned on e.g. 64 also is aligned at an offset of 64 by definition. \n\t\t\t\t\treturn memalign(alignment, n); // memalign is more consistently available than posix_memalign.\n\t\t\t#else\n\t\t\t\tif((alignment <= EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT) && ((alignmentOffset % alignment) == 0))\n\t\t\t\t\treturn malloc(n);\n\t\t\t#endif\n\t\t\treturn NULL;\n\t\t}\n\n\t\tvoid deallocate(void* p, size_t /*n*/)\n\t\t\t{ free(p); }\n\n\t\tconst char* get_name() const\n\t\t\t{ return \"allocator_malloc\"; }\n\n\t\tvoid set_name(const char*)\n\t\t\t{ }\n\t};\n\n\n} // namespace eastl\n\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/any.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the eastl::any which is part of the C++ standard STL\n// library specification.  \n//\n// eastl::any is a type-safe container for single values of any type.  Our\n// implementation makes use of the \"small local buffer\" optimization to avoid\n// unnecessary dynamic memory allocation if the specified type is eligible to\n// be stored in its local buffer.  The user type must satisfy the size\n// requirements and must be no-throw move-constructible to qualify for the local\n// buffer optimization.\n//\n// To consider:  Implement a fixed_any<SIZE> variant to allow users to customize\n// the size of the \"small local buffer\" optimization.\n//\n// http://en.cppreference.com/w/cpp/utility/any\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ANY_H\n#define EASTL_ANY_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/in_place_t.h>\n#if EASTL_RTTI_ENABLED\n\t#include <typeinfo>\n#endif\n#if EASTL_EXCEPTIONS_ENABLED\n\t#include <exception>\n#endif\n\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////////\n\t// bad_any_cast\n\t// \n\t// The type thrown by any_cast on failure.\n\t//\n\t// http://en.cppreference.com/w/cpp/utility/any/bad_any_cast\n\t//\n\t#if EASTL_EXCEPTIONS_ENABLED\n\tstruct bad_cast : std::exception\n\t{\n\t\tconst char* what() const EA_NOEXCEPT EA_OVERRIDE\n\t\t\t{ return \"bad cast\"; }\n\t};\n\n\tstruct bad_any_cast : public bad_cast \n\t{\n\t\tconst char* what() const EA_NOEXCEPT EA_OVERRIDE\n\t\t\t{ return \"bad_any_cast\"; }\n\t};\n    #endif\n\n\tnamespace Internal\n\t{\n\t\t// utility to switch between exceptions and asserts\n\t\tinline void DoBadAnyCast()\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow bad_any_cast();\n\t\t\t#else\n\t\t\t\tEASTL_ASSERT_MSG(false, \"bad_any_cast\\n\");\n\n\t\t\t\t// NOTE(rparolin): CRASH!\n\t\t\t\t// You crashed here because you requested a type that was not contained in the object.\n\t\t\t\t// We choose to intentionally crash here instead of returning invalid data to the calling \n\t\t\t\t// code which could cause hard to track down bugs. \n\t\t\t\t*((volatile int*)0) = 0xDEADC0DE;\n\t\t\t#endif\n\t\t}\n\n\t\ttemplate<typename T, typename... Args>\n\t\tvoid* DefaultConstruct(Args&&... args)\n\t\t{\n\t\t\tauto* pMem = EASTLAllocatorDefault()->allocate(sizeof(T), alignof(T), 0);\n\n\t\t\treturn ::new(pMem) T(eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate<typename T>\n\t\tvoid DefaultDestroy(T* p)\n\t\t{\n\t\t\tp->~T();\n\n\t\t\tEASTLAllocatorDefault()->deallocate(static_cast<void*>(p), sizeof(T));\n\t\t}\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.7.3, class any\n\t//\n\tclass any\n\t{\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// storage_operation \n\t\t//\n\t\t// operations supported by the storage handler \n\t\t//\n\t\tenum class storage_operation\n\t\t{\n\t\t\tGET,\n\t\t\tDESTROY,\n\t\t\tCOPY,\n\t\t\tMOVE,\n\t\t\tTYPE_INFO\n\t\t};\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// storage \n\t\t//\n\t\t// the underlying storage type which enables the switching between objects stored in\n\t\t// the heap and objects stored within the any type.\n\t\t//\n\t\tunion storage\n\t\t{\n\t\t\ttypedef aligned_storage_t<4 * sizeof(void*), alignment_of<void*>::value> internal_storage_t;\n\n\t\t\tvoid* external_storage = nullptr;\n\t\t\tinternal_storage_t internal_storage;\n\t\t};\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// use_internal_storage \n\t\t//\n\t\t// determines when the \"local buffer optimization\" is used \n\t\t//\n\t\ttemplate <typename T>\n\t\tusing use_internal_storage = bool_constant\n\t\t<\n\t\t\tis_nothrow_move_constructible<T>::value \n\t\t\t&& (sizeof(T) <= sizeof(storage)) &&\n\t\t\t(alignment_of<storage>::value % alignment_of<T>::value == 0)  \n\t\t>;\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// non-member friend functions\t\n\t\t//\n    \ttemplate <class ValueType> friend const ValueType* any_cast(const any* pAny) EA_NOEXCEPT;\n\t\ttemplate <class ValueType> friend ValueType* any_cast(any* pAny) EA_NOEXCEPT; \n\t\ttemplate <class ValueType> friend ValueType any_cast(const any& operand);\n\t\ttemplate <class ValueType> friend ValueType any_cast(any& operand);\n\t\ttemplate <class ValueType> friend ValueType any_cast(any&& operand);\n\n\t\t//Adding Unsafe any cast operations\n\t\ttemplate <class ValueType> friend const ValueType* unsafe_any_cast(const any* pAny) EA_NOEXCEPT;\n\t\ttemplate <class ValueType> friend ValueType* unsafe_any_cast(any* pAny) EA_NOEXCEPT;\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// internal storage handler\n\t\t//\n\t\ttemplate <typename T>\n\t\tstruct storage_handler_internal\n\t\t{\n\t\t\ttemplate <typename V>\n\t\t\tstatic void construct(storage& s, V&& v)\n\t\t\t{\n\t\t\t\t::new(&s.internal_storage) T(eastl::forward<V>(v));\n\t\t\t}\n\n\t\t\ttemplate <typename... Args>\n\t\t\tstatic void construct_inplace(storage& s, Args... args)\n\t\t\t{\n\t\t\t\t::new(&s.internal_storage) T(eastl::forward<Args>(args)...);\n\t\t\t}\n\n\t\t\ttemplate <class NT, class U, class... Args>\n\t\t\tstatic void construct_inplace(storage& s, std::initializer_list<U> il, Args&&... args)\n\t\t\t{\n\t\t\t\t::new(&s.internal_storage) NT(il, eastl::forward<Args>(args)...);\n\t\t\t}\n\n\t\t\tstatic inline void destroy(any& refAny)\n\t\t\t{\n\t\t\t\tT& t = *static_cast<T*>(static_cast<void*>(&refAny.m_storage.internal_storage));\n\t\t\t\tEA_UNUSED(t);\n\t\t\t\tt.~T();\n\n\t\t\t\trefAny.m_handler = nullptr;\n\t\t\t}\n\n\t\t\tstatic void* get(const any* pThis)\n\t\t\t{\n\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\treturn (void*)(&pThis->m_storage.internal_storage);\n\t\t\t}\n\n\t\t\tstatic void* handler_func(storage_operation op, const any* pThis, any* pOther)\n\t\t\t{\n\t\t\t\tswitch (op)\n\t\t\t\t{\n\t\t\t\t\tcase storage_operation::GET:\n\t\t\t\t\t{\n\t\t\t\t\t\treturn get(pThis);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::DESTROY:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\t\t\tdestroy(const_cast<any&>(*pThis));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::COPY:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\t\t\tEASTL_ASSERT(pOther);\n\t\t\t\t\t\tconstruct(pOther->m_storage, *(T*)(&pThis->m_storage.internal_storage));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::MOVE:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\t\t\tEASTL_ASSERT(pOther);\n\t\t\t\t\t\tconstruct(pOther->m_storage, eastl::move(*(T*)(&pThis->m_storage.internal_storage)));\n\t\t\t\t\t\tdestroy(const_cast<any&>(*pThis));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::TYPE_INFO:\n\t\t\t\t\t{\n\t\t\t\t\t#if EASTL_RTTI_ENABLED\n\t\t\t\t\t\treturn (void*)&typeid(T);\n\t\t\t\t\t#endif\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT_MSG(false, \"unknown storage operation\\n\");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t};\n\n\t\t\t\treturn nullptr;\n\t\t\t}\n\t\t};\n\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// external storage handler\n\t\t//\n\t\ttemplate <typename T>\n\t\tstruct storage_handler_external\n\t\t{\n\t\t\ttemplate <typename V>\n\t\t\tstatic inline void construct(storage& s, V&& v) \n\t\t\t{\n\t\t\t\ts.external_storage = Internal::DefaultConstruct<T>(eastl::forward<V>(v));\n\t\t\t}\n\n\t\t\ttemplate <typename... Args>\n\t\t\tstatic inline void construct_inplace(storage& s, Args... args)\n\t\t\t{\n\t\t\t\ts.external_storage = Internal::DefaultConstruct<T>(eastl::forward<Args>(args)...);\n\t\t\t}\n\n\t\t\ttemplate <class NT, class U, class... Args>\n\t\t\tstatic inline void construct_inplace(storage& s, std::initializer_list<U> il, Args&&... args)\n\t\t\t{\n\t\t\t\ts.external_storage = Internal::DefaultConstruct<NT>(il, eastl::forward<Args>(args)...);\n\t\t\t}\n\n\t\t\tstatic inline void destroy(any& refAny)\n\t\t\t{\n\t\t\t\tInternal::DefaultDestroy(static_cast<T*>(refAny.m_storage.external_storage));\n\n\t\t\t\trefAny.m_handler = nullptr;\n\t\t\t}\n\n\t\t\tstatic void* get(const any* pThis)\n\t\t\t{\n\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\tEASTL_ASSERT(pThis->m_storage.external_storage);\n\t\t\t\treturn static_cast<void*>(pThis->m_storage.external_storage);\n\t\t\t}\n\n\t\t\tstatic void* handler_func(storage_operation op, const any* pThis, any* pOther)\n\t\t\t{\n\t\t\t\tswitch (op)\n\t\t\t\t{\n\t\t\t\t\tcase storage_operation::GET:\n\t\t\t\t\t{\n\t\t\t\t\t\treturn get(pThis);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::DESTROY:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\t\t\tdestroy(*const_cast<any*>(pThis));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::COPY:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\t\t\tEASTL_ASSERT(pOther);\n\t\t\t\t\t\tconstruct(pOther->m_storage, *static_cast<T*>(pThis->m_storage.external_storage));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::MOVE:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT(pThis);\n\t\t\t\t\t\tEASTL_ASSERT(pOther);\n\t\t\t\t\t\tconstruct(pOther->m_storage, eastl::move(*(T*)(pThis->m_storage.external_storage)));\n\t\t\t\t\t\tdestroy(const_cast<any&>(*pThis));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase storage_operation::TYPE_INFO:\n\t\t\t\t\t{\n\t\t\t\t\t#if EASTL_RTTI_ENABLED\n\t\t\t\t\t\treturn (void*)&typeid(T);\n\t\t\t\t\t#endif\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_ASSERT_MSG(false, \"unknown storage operation\\n\");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t};\n\n\t\t\t\treturn nullptr;\n\t\t\t}\n\t\t};\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// storage_handler_ptr \n\t\t//\n\t\t// defines the function signature of the storage handler that both the internal and\n\t\t// external storage handlers must implement to retrieve the underlying type of the any\n\t\t// object.\n\t\t//\n\t\tusing storage_handler_ptr = void* (*)(storage_operation, const any*, any*);\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// storage_handler \n\t\t//\n\t\t// based on the specified type T we select the appropriate underlying storage handler\n\t\t// based on the 'use_internal_storage' trait.\n\t\t//\n\t\ttemplate <typename T>\n\t\tusing storage_handler = typename conditional<use_internal_storage<T>::value,\n\t\t                                             storage_handler_internal<T>,\n\t\t                                             storage_handler_external<T>>::type;\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////////////\n\t\t// data layout\n\t\t//\n\t\tstorage m_storage;\n\t\tstorage_handler_ptr m_handler;\n\n\tpublic:\n\t\t\t#ifndef EA_COMPILER_GNUC\n\t\t\t\t// TODO(rparolin):  renable constexpr for GCC\n\t\t\t\tEA_CONSTEXPR \n\t\t\t#endif\n\t\t\tany() EA_NOEXCEPT \n\t\t\t: m_storage(), m_handler(nullptr) {}\n\n\t\tany(const any& other) : m_handler(nullptr)\n\t\t{\n\t\t\tif (other.m_handler)\n\t\t\t{\n\t\t\t\t// NOTE(rparolin): You can not simply copy the underlying\n\t\t\t\t// storage because it could hold a pointer to an object on the\n\t\t\t\t// heap which breaks the copy semantics of the language. \n\t\t\t\tother.m_handler(storage_operation::COPY, &other, this);\n\t\t\t\tm_handler = other.m_handler;\n\t\t\t}\n\t\t}\n\n\t\tany(any&& other) EA_NOEXCEPT : m_handler(nullptr)\n\t\t{ \n\t\t\tif(other.m_handler)\n\t\t\t{\n\t\t\t\t// NOTE(rparolin): You can not simply move the underlying\n\t\t\t\t// storage because because the storage class has effectively\n\t\t\t\t// type erased user type so we have to defer to the handler\n\t\t\t\t// function to get the type back and pass on the move request.\n\t\t\t\tm_handler = eastl::move(other.m_handler);\n\t\t\t\tother.m_handler(storage_operation::MOVE, &other, this);\n\t\t\t}\n\t\t}\n\n\t\t~any() { reset(); }\n\n\t\ttemplate <class ValueType>\n\t\tany(ValueType&& value,\n\t\t    typename eastl::enable_if<!eastl::is_same<typename eastl::decay<ValueType>::type, any>::value>::type* = 0)\n\t\t{\n\t\t\ttypedef decay_t<ValueType> DecayedValueType;\n\t\t\tstatic_assert(is_copy_constructible<DecayedValueType>::value, \"ValueType must be copy-constructible\");\n\t\t\tstorage_handler<DecayedValueType>::construct(m_storage, eastl::forward<ValueType>(value));\n\t\t\tm_handler = &storage_handler<DecayedValueType>::handler_func;\n\t\t}\n\n\t\ttemplate <class T, class... Args>\n\t\texplicit any(in_place_type_t<T>, Args&&... args) \n\t\t{\n\t\t\ttypedef storage_handler<decay_t<T>> StorageHandlerT;\n\t\t\tstatic_assert(eastl::is_constructible<T, Args...>::value, \"T must be constructible with Args...\");\n\n\t\t\tStorageHandlerT::construct_inplace(m_storage, eastl::forward<Args>(args)...);\n\t\t\tm_handler = &StorageHandlerT::handler_func;\n\t\t}\n\n\t\ttemplate <class T, class U, class... Args>\n\t\texplicit any(in_place_type_t<T>,\n\t\t             std::initializer_list<U> il,\n\t\t             Args&&... args,\n\t\t             typename eastl::enable_if<eastl::is_constructible<T, std::initializer_list<U>&, Args...>::value,\n\t\t                                       void>::type* = 0)\n\t\t{\n\t\t\ttypedef storage_handler<decay_t<T>> StorageHandlerT;\n\n\t\t\tStorageHandlerT::construct_inplace(m_storage, il, eastl::forward<Args>(args)...);\n\t\t\tm_handler = &StorageHandlerT::handler_func;\n\t\t}\n\n\t\t// 20.7.3.2, assignments\n\t\ttemplate <class ValueType>\n\t\tany& operator=(ValueType&& value)\n\t\t{\n\t\t\tstatic_assert(is_copy_constructible<decay_t<ValueType>>::value, \"ValueType must be copy-constructible\");\n\t\t\tany(eastl::forward<ValueType>(value)).swap(*this);\n\t\t\treturn *this;\n\t\t}\n\n\t\tany& operator=(const any& other) \n\t\t{ \n\t\t\tany(other).swap(*this);\n\t\t\treturn *this; \n\t\t}\n\n\t\tany& operator=(any&& other) EA_NOEXCEPT \n\t\t{ \n\t\t\tany(eastl::move(other)).swap(*this);\n\t\t\treturn *this; \n\t\t}\n\n        // 20.7.3.3, modifiers\n\t\t#if EASTL_VARIADIC_TEMPLATES_ENABLED\n\t\t\ttemplate <class T, class... Args>\n\t\t\ttypename eastl::enable_if<eastl::is_constructible_v<eastl::decay_t<T>, Args...> && eastl::is_copy_constructible_v<eastl::decay_t<T>>, eastl::decay_t<T>&>::type\n\t\t\templace(Args&&... args)\n\t\t\t{\n\t\t\t    typedef storage_handler<decay_t<T>> StorageHandlerT;\n\n\t\t\t    reset();\n\t\t\t\tStorageHandlerT::construct_inplace(m_storage, eastl::forward<Args>(args)...);\n\t\t\t\tm_handler = &StorageHandlerT::handler_func;\n\t\t\t\treturn *static_cast<decay_t<T>*>(StorageHandlerT::get(this));\n\t\t\t}\n\n\t\t\ttemplate <class NT, class U, class... Args>\n\t\t    typename eastl::enable_if<eastl::is_constructible_v<eastl::decay_t<NT>, std::initializer_list<U>&, Args...> && eastl::is_copy_constructible_v<eastl::decay_t<NT>>, eastl::decay_t<NT>&>::type\n\t\t\templace(std::initializer_list<U> il, Args&&... args)\n\t\t\t{\n\t\t\t    typedef storage_handler<decay_t<NT>> StorageHandlerT;\n\n\t\t\t\treset();\n\t\t\t\tStorageHandlerT::construct_inplace(m_storage, il, eastl::forward<Args>(args)...);\n\t\t\t\tm_handler = &StorageHandlerT::handler_func;\n\t\t\t\treturn *static_cast<decay_t<NT>*>(StorageHandlerT::get(this));\n\t\t\t}\n        #endif\n\n\t\tvoid reset() EA_NOEXCEPT \n\t\t{\n\t\t\tif(m_handler)\n\t\t\t\tm_handler(storage_operation::DESTROY, this, nullptr);\n\t\t}\n\n\t\tvoid swap(any& other) EA_NOEXCEPT \n\t\t{\n\t\t\tif(this == &other)\n\t\t\t\treturn;\n\n\t\t\tif(m_handler && other.m_handler)\n\t\t\t{\n\t\t\t\tany tmp;\n\t\t\t\ttmp.m_handler = other.m_handler;\n\t\t\t\tother.m_handler(storage_operation::MOVE, &other, &tmp);\n\n\t\t\t\tother.m_handler = m_handler;\n\t\t\t\tm_handler(storage_operation::MOVE, this, &other);\n\n\t\t\t\tm_handler = tmp.m_handler;\n\t\t\t\ttmp.m_handler(storage_operation::MOVE, &tmp, this);\n\t\t\t}\n\t\t\telse if (m_handler == nullptr && other.m_handler)\n\t\t\t{\n\t\t\t\teastl::swap(m_handler, other.m_handler);\n\t\t\t\tm_handler(storage_operation::MOVE, &other, this);\n\t\t\t}\n\t\t\telse if(m_handler && other.m_handler == nullptr)\n\t\t\t{\n\t\t\t\teastl::swap(m_handler, other.m_handler);\n\t\t\t\tother.m_handler(storage_operation::MOVE, this, &other);\n\t\t\t}\n\t\t\t//else if (m_handler == nullptr && other.m_handler == nullptr)\n\t\t\t//{\n\t\t\t//     // nothing to swap \n\t\t\t//}\n\t\t}\n\n\t    // 20.7.3.4, observers\n\t\tbool has_value() const EA_NOEXCEPT { return m_handler != nullptr; }\n\n        #if EASTL_RTTI_ENABLED\n\t\t\tinline const std::type_info& type() const EA_NOEXCEPT \n\t\t\t{\n\t\t\t\tif(m_handler)\n\t\t\t\t{\n\t\t\t\t\tauto* pTypeInfo = m_handler(storage_operation::TYPE_INFO, this, nullptr);\n\t\t\t\t\treturn *static_cast<const std::type_info*>(pTypeInfo);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn typeid(void);\n\t\t\t\t}\n\t\t\t}\n\t\t#endif\n\t};\n\n\n\n\t//////////////////////////////////////////////////////////////////////////////////////////\n\t// 20.7.4, non-member functions\n\t//\n\tinline void swap(any& rhs, any& lhs) EA_NOEXCEPT { rhs.swap(lhs); }\n\n\n\t//////////////////////////////////////////////////////////////////////////////////////////\n\t// 20.7.4, The non-member any_cast functions provide type-safe access to the contained object.\n\t//\n\ttemplate <class ValueType>\n\tinline ValueType any_cast(const any& operand)\n\t{\n\t\tstatic_assert(eastl::is_reference<ValueType>::value || eastl::is_copy_constructible<ValueType>::value,\n\t\t              \"ValueType must be a reference or copy constructible\");\n\n\t\tauto* p = any_cast<typename add_const<typename remove_reference<ValueType>::type>::type>(&operand);\n\n\t\tif(p == nullptr)\n\t\t\tInternal::DoBadAnyCast();\n\n\t\treturn *p;\n\t}\n\n\ttemplate <class ValueType>\n    inline ValueType any_cast(any& operand)\n    {\n\t\tstatic_assert(eastl::is_reference<ValueType>::value || eastl::is_copy_constructible<ValueType>::value,\n\t\t              \"ValueType must be a reference or copy constructible\");\n\n\t\tauto* p = any_cast<typename remove_reference<ValueType>::type>(&operand);\n\n\t\tif(p == nullptr)\n\t\t\tInternal::DoBadAnyCast();\n\n\t\treturn *p;\n    }\n\n\ttemplate <class ValueType>\n\tinline ValueType any_cast(any&& operand)\n\t{\n\t\tstatic_assert(eastl::is_reference<ValueType>::value || eastl::is_copy_constructible<ValueType>::value,\n\t\t              \"ValueType must be a reference or copy constructible\");\n\n\t\tauto* p = any_cast<typename remove_reference<ValueType>::type>(&operand);\n\n\t\tif (p == nullptr)\n\t\t\tInternal::DoBadAnyCast();\n\n\t\treturn *p;\n\t}\n\n\t// NOTE(rparolin): The runtime type check was commented out because in DLL builds the templated function pointer\n\t// value will be different -- completely breaking the validation mechanism.  Due to the fact that eastl::any uses\n\t// type erasure we can't refresh (on copy/move) the cached function pointer to the internal handler function because\n\t// we don't statically know the type.\n\ttemplate <class ValueType>\n\tinline const ValueType* any_cast(const any* pAny) EA_NOEXCEPT\n\t{\n\t\treturn (pAny && pAny->m_handler EASTL_IF_NOT_DLL(== &any::storage_handler<decay_t<ValueType>>::handler_func)\n\t\t\t\t#if EASTL_RTTI_ENABLED\n\t\t\t\t\t&& pAny->type() == typeid(typename remove_reference<ValueType>::type)\n\t\t\t\t#endif\n\t\t\t\t) ?\n\t\t           static_cast<const ValueType*>(pAny->m_handler(any::storage_operation::GET, pAny, nullptr)) :\n\t\t           nullptr;\n\t}\n\n\ttemplate <class ValueType>\n\tinline ValueType* any_cast(any* pAny) EA_NOEXCEPT\n\t{\n\t\treturn (pAny && pAny->m_handler EASTL_IF_NOT_DLL(== &any::storage_handler<decay_t<ValueType>>::handler_func)\n\t\t\t\t#if EASTL_RTTI_ENABLED\n\t\t\t\t\t&& pAny->type() == typeid(typename remove_reference<ValueType>::type)\n\t\t\t\t#endif\n\t\t\t\t) ?\n\t\t           static_cast<ValueType*>(pAny->m_handler(any::storage_operation::GET, pAny, nullptr)) :\n\t\t           nullptr;\n\t}\n\n\t//Unsafe operations - use with caution\n\ttemplate <class ValueType>\n\tinline const ValueType* unsafe_any_cast(const any* pAny) EA_NOEXCEPT\n\t{\n\t\treturn unsafe_any_cast<ValueType>(const_cast<any*>(pAny));\n\t}\n\n\ttemplate <class ValueType>\n\tinline ValueType* unsafe_any_cast(any* pAny) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<ValueType*>(pAny->m_handler(any::storage_operation::GET, pAny, nullptr));\n\t}\n\n\t//////////////////////////////////////////////////////////////////////////////////////////\n\t// make_any\n\t//\n\t#if EASTL_VARIADIC_TEMPLATES_ENABLED\n\t\ttemplate <class T, class... Args>\n\t\tinline any make_any(Args&&... args)\n\t\t{\n\t\t\treturn any(eastl::in_place_type<T>, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <class T, class U, class... Args>\n\t\tinline any make_any(std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\treturn any(eastl::in_place_type<T>, il, eastl::forward<Args>(args)...);\n\t\t}\n    #endif\n\n} // namespace eastl\n\n#endif // EASTL_ANY_H\n"
  },
  {
    "path": "include/EASTL/array.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Implements a templated array class as per the C++ standard TR1 (technical\n// report 1, which is a list of proposed C++ library amendments).\n// The primary distinctions between this array and TR1 array are:\n//    - array::size_type is defined as eastl_size_t instead of size_t in order\n//      to save memory and run faster on 64 bit systems.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ARRAY_H\n#define EASTL_ARRAY_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/tuple_fwd_decls.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/utility.h>\n#include <stddef.h>\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <stdexcept> // std::out_of_range, std::length_error.\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4512 4626);\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////\n\t/// array\n\t///\n\t/// Implements a templated array class as per the C++ standard TR1.\n\t/// This class allows you to use a built-in C style array like an STL vector.\n\t/// It does not let you change its size, as it is just like a C built-in array.\n\t/// Our implementation here strives to remove function call nesting, as that\n\t/// makes it hard for us to profile debug builds due to function call overhead.\n\t/// Note that this is intentionally a struct with public data, as per the\n\t/// C++ standard update proposal requirements.\n\t///\n\t/// Example usage:\n\t///    array<int, 5> a = { { 0, 1, 2, 3, 4 } }; // Strict compilers such as GCC require the double brackets.\n\t///    a[2] = 4;\n\t///    for(array<int, 5>::iterator i = a.begin(); i < a.end(); ++i)\n\t///       *i = 0;\n\t///\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT)\n\ttemplate <typename T, size_t N>\n#else\n\ttemplate <typename T, size_t N = 1>\n#endif\n\tstruct array\n\t{\n\tpublic:\n\t\ttypedef array<T, N>                                   this_type;\n\t\ttypedef T                                             value_type;\n\t\ttypedef value_type&                                   reference;\n\t\ttypedef const value_type&                             const_reference;\n\t\ttypedef value_type*                                   iterator;\n\t\ttypedef const value_type*                             const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>             reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>       const_reverse_iterator;\n\t\ttypedef eastl_size_t                                  size_type;        // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                     difference_type;\n\n\t\t// Note that the member data is intentionally public.\n\t\t// This allows for aggregate initialization of the\n\t\t// object (e.g. array<int, 5> a = { 0, 3, 2, 4 }; )\n\t\t// do not use this member directly (use data() instead).\n\t\tvalue_type mValue[N];\n\n\t\t// We intentionally provide no constructor, destructor, or assignment operator.\n\n\t\tvoid fill(const value_type& value);\n\n\t\t// Unlike the swap function for other containers, array::swap takes linear time,\n\t\t// may exit via an exception, and does not cause iterators to become associated with the other container.\n\t\tvoid swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<value_type>::value);\n\n\t\tEA_CPP14_CONSTEXPR iterator       begin() EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_iterator begin() const EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT;\n\n\t\tEA_CPP14_CONSTEXPR iterator       end() EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_iterator end() const EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_iterator cend() const EA_NOEXCEPT;\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator       rbegin() EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT;\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator       rend() EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator rend() const EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT;\n\n\t\tEA_CPP14_CONSTEXPR bool empty() const EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR size_type size() const EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR size_type max_size() const EA_NOEXCEPT;\n\n\t\tEA_CPP14_CONSTEXPR T*       data() EA_NOEXCEPT;\n\t\tEA_CPP14_CONSTEXPR const T* data() const EA_NOEXCEPT;\n\n\t\tEA_CPP14_CONSTEXPR reference       operator[](size_type i);\n\t\tEA_CPP14_CONSTEXPR const_reference operator[](size_type i) const;\n\t\tEA_CPP14_CONSTEXPR const_reference at(size_type i) const;\n\t\tEA_CPP14_CONSTEXPR reference       at(size_type i);\n\n\t\tEA_CPP14_CONSTEXPR reference       front();\n\t\tEA_CPP14_CONSTEXPR const_reference front() const;\n\n\t\tEA_CPP14_CONSTEXPR reference       back();\n\t\tEA_CPP14_CONSTEXPR const_reference back() const;\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\t}; // class array\n\n\t// declaring a C-style array of size 0 is not valid C++.\n\t// thus, we have to declare this partial specialization:\n\ttemplate <typename T>\n\tstruct array<T, 0>\n\t{\n\tpublic:\n\t\ttypedef array<T, 0>                                   this_type;\n\t\ttypedef T                                             value_type;\n\t\ttypedef value_type& reference;\n\t\ttypedef const value_type& const_reference;\n\t\ttypedef value_type* iterator;\n\t\ttypedef const value_type* const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>             reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>       const_reverse_iterator;\n\t\ttypedef eastl_size_t                                  size_type;        // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                     difference_type;\n\n\t\t// We intentionally provide no constructor, destructor, or assignment operator.\n\n\t\tvoid fill(const value_type&) {}\n\n\t\t// Unlike the swap function for other containers, array::swap takes linear time,\n\t\t// may exit via an exception, and does not cause iterators to become associated with the other container.\n\t\tvoid swap(this_type&) EA_NOEXCEPT {}\n\n\t\tEA_CPP14_CONSTEXPR iterator       begin() EA_NOEXCEPT { return nullptr; }\n\t\tEA_CPP14_CONSTEXPR const_iterator begin() const EA_NOEXCEPT { return nullptr; }\n\t\tEA_CPP14_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT { return nullptr; }\n\n\t\tEA_CPP14_CONSTEXPR iterator       end() EA_NOEXCEPT { return nullptr; }\n\t\tEA_CPP14_CONSTEXPR const_iterator end() const EA_NOEXCEPT { return nullptr; }\n\t\tEA_CPP14_CONSTEXPR const_iterator cend() const EA_NOEXCEPT { return nullptr; }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator       rbegin() EA_NOEXCEPT { return reverse_iterator(nullptr); }\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator rbegin() const EA_NOEXCEPT { return const_reverse_iterator(nullptr); }\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT { return const_reverse_iterator(nullptr); }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator       rend() EA_NOEXCEPT { return reverse_iterator(nullptr); }\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator rend() const EA_NOEXCEPT { return const_reverse_iterator(nullptr); }\n\t\tEA_CPP14_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT { return const_reverse_iterator(nullptr); }\n\n\t\tEA_CPP14_CONSTEXPR bool empty() const EA_NOEXCEPT { return true; }\n\t\tEA_CPP14_CONSTEXPR size_type size() const EA_NOEXCEPT { return 0; }\n\t\tEA_CPP14_CONSTEXPR size_type max_size() const EA_NOEXCEPT { return 0; }\n\n\t\tEA_CPP14_CONSTEXPR T* data() EA_NOEXCEPT { return nullptr; }\n\t\tEA_CPP14_CONSTEXPR const T* data() const EA_NOEXCEPT { return nullptr; }\n\n\t\tEA_CPP14_CONSTEXPR reference       operator[](size_type) { return *data(); }\n\t\tEA_CPP14_CONSTEXPR const_reference operator[](size_type) const { return *data(); }\n\n\t\tEA_DISABLE_VC_WARNING(4702); // unreachable code\n\t\tEA_CPP14_CONSTEXPR const_reference at(size_type) const\n\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tthrow std::out_of_range(\"array::at -- out of range\");\n#elif EASTL_ASSERT_ENABLED\n\t\t\tEASTL_FAIL_MSG(\"array::at -- out of range\");\n#endif\n\t\t\treturn *data();\n\t\t}\n\t\tEA_RESTORE_VC_WARNING();\n\n\t\tEA_DISABLE_VC_WARNING(4702); // unreachable code\n\t\tEA_CPP14_CONSTEXPR reference       at(size_type)\n\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tthrow std::out_of_range(\"array::at -- out of range\");\n#elif EASTL_ASSERT_ENABLED\n\t\t\tEASTL_FAIL_MSG(\"array::at -- out of range\");\n#endif\n\t\t\treturn *data();\n\t\t}\n\t\tEA_RESTORE_VC_WARNING();\n\n\t\tEA_CPP14_CONSTEXPR reference       front() { return *data(); }\n\t\tEA_CPP14_CONSTEXPR const_reference front() const { return *data(); }\n\n\t\tEA_CPP14_CONSTEXPR reference       back() { return *data(); }\n\t\tEA_CPP14_CONSTEXPR const_reference back() const { return *data(); }\n\n\t\tbool validate() const { return true; }\n\t\tint  validate_iterator(const_iterator) const { return isf_none; }\n\n\t}; // class array\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// template deduction guides\n\t///////////////////////////////////////////////////////////////////////////\n\t#ifdef __cpp_deduction_guides\n\t\ttemplate <class T, class... U> array(T, U...) -> array<T, 1 + sizeof...(U)>;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// array\n\t///////////////////////////////////////////////////////////////////////\n\n\n\ttemplate <typename T, size_t N>\n\tinline void array<T, N>::fill(const value_type& value)\n\t{\n\t\teastl::fill_n(&mValue[0], N, value);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tinline void array<T, N>::swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<value_type>::value)\n\t{\n\t\teastl::swap_ranges(&mValue[0], &mValue[N], &x.mValue[0]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::iterator\n\tarray<T, N>::begin() EA_NOEXCEPT\n\t{\n\t\treturn &mValue[0];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator\n\tarray<T, N>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn &mValue[0];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator\n\tarray<T, N>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn &mValue[0];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::iterator\n\tarray<T, N>::end() EA_NOEXCEPT\n\t{\n\t\treturn &mValue[N];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator\n\tarray<T, N>::end() const EA_NOEXCEPT\n\t{\n\t\treturn &mValue[N];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_iterator\n\tarray<T, N>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn &mValue[N];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::reverse_iterator\n\tarray<T, N>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(&mValue[N]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator\n\tarray<T, N>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(&mValue[N]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator\n\tarray<T, N>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(&mValue[N]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::reverse_iterator\n\tarray<T, N>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(&mValue[0]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator\n\tarray<T, N>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(static_cast<const_iterator>(&mValue[0]));\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reverse_iterator\n\tarray<T, N>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(static_cast<const_iterator>(&mValue[0]));\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::size_type\n\tarray<T, N>::size() const EA_NOEXCEPT\n\t{\n\t\treturn (size_type)N;\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::size_type\n\tarray<T, N>::max_size() const EA_NOEXCEPT\n\t{\n\t\treturn (size_type)N;\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline bool array<T, N>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn (N == 0);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::reference\n\tarray<T, N>::operator[](size_type i)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(i >= N))\n\t\t\t\tEASTL_FAIL_MSG(\"array::operator[] -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t// We allow taking a reference to arr[0]\n\t\t\tif (EASTL_UNLIKELY((i != 0) && i >= N))\n\t\t\t\tEASTL_FAIL_MSG(\"array::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn mValue[i];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference\n\tarray<T, N>::operator[](size_type i) const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(i >= N))\n\t\t\t\tEASTL_FAIL_MSG(\"array::operator[] -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t// We allow taking a reference to arr[0]\n\t\t\tif (EASTL_UNLIKELY((i != 0) && i >= N))\n\t\t\t\tEASTL_FAIL_MSG(\"array::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn mValue[i];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::reference\n\tarray<T, N>::front()\n\t{\n\t\treturn mValue[0];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference\n\tarray<T, N>::front() const\n\t{\n\t\treturn mValue[0];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::reference\n\tarray<T, N>::back()\n\t{\n\t\treturn mValue[N - 1];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference\n\tarray<T, N>::back() const\n\t{\n\t\treturn mValue[N - 1];\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline T* array<T, N>::data() EA_NOEXCEPT\n\t{\n\t\treturn mValue;\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline const T* array<T, N>::data() const EA_NOEXCEPT\n\t{\n\t\treturn mValue;\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::const_reference array<T, N>::at(size_type i) const\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(EASTL_UNLIKELY(i >= N))\n\t\t\t\tthrow std::out_of_range(\"array::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(i >= N))\n\t\t\t\tEASTL_FAIL_MSG(\"array::at -- out of range\");\n\t\t#endif\n\n\t\treturn static_cast<const_reference>(mValue[i]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline typename array<T, N>::reference array<T, N>::at(size_type i)\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(EASTL_UNLIKELY(i >= N))\n\t\t\t\tthrow std::out_of_range(\"array::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(i >= N))\n\t\t\t\tEASTL_FAIL_MSG(\"array::at -- out of range\");\n\t\t#endif\n\n\t\treturn static_cast<reference>(mValue[i]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tinline bool array<T, N>::validate() const\n\t{\n\t\treturn true; // There is nothing to do.\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tinline int array<T, N>::validate_iterator(const_iterator i) const\n\t{\n\t\tif(i >= mValue)\n\t\t{\n\t\t\tif(i < (mValue + N))\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\n\t\t\tif(i <= (mValue + N))\n\t\t\t\treturn (isf_valid | isf_current);\n\t\t}\n\n\t\treturn isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline bool operator==(const array<T, N>& a, const array<T, N>& b)\n\t{\n\t\treturn eastl::equal(&a.mValue[0], &a.mValue[N], &b.mValue[0]);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, size_t N>\n\tinline synth_three_way_result<T> operator<=>(const array<T, N>& a, const array<T,N>& b)\n\t{\n\t    return eastl::lexicographical_compare_three_way(&a.mValue[0], &a.mValue[N], &b.mValue[0], &b.mValue[N], synth_three_way{});\n\t}\n#else\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline bool operator<(const array<T, N>& a, const array<T, N>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(&a.mValue[0], &a.mValue[N], &b.mValue[0], &b.mValue[N]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline bool operator!=(const array<T, N>& a, const array<T, N>& b)\n\t{\n\t\treturn !eastl::equal(&a.mValue[0], &a.mValue[N], &b.mValue[0]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline bool operator>(const array<T, N>& a, const array<T, N>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(&b.mValue[0], &b.mValue[N], &a.mValue[0], &a.mValue[N]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline bool operator<=(const array<T, N>& a, const array<T, N>& b)\n\t{\n\t\treturn !eastl::lexicographical_compare(&b.mValue[0], &b.mValue[N], &a.mValue[0], &a.mValue[N]);\n\t}\n\n\n\ttemplate <typename T, size_t N>\n\tEA_CPP14_CONSTEXPR inline bool operator>=(const array<T, N>& a, const array<T, N>& b)\n\t{\n\t\treturn !eastl::lexicographical_compare(&a.mValue[0], &a.mValue[N], &b.mValue[0], &b.mValue[N]);\n\t}\n#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// non-member functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate<size_t I, typename T, size_t N>\n\tEA_NODISCARD EA_CONSTEXPR T& get(array<T, N>& value) EA_NOEXCEPT\n\t{\n\t\tstatic_assert(I < N, \"array index out of bounds\");\n\t\treturn value.mValue[I];\n\t}\n\n\ttemplate<size_t I, typename T, size_t N>\n\tEA_NODISCARD EA_CONSTEXPR T&& get(array<T, N>&& value) EA_NOEXCEPT\n\t{\n\t\tstatic_assert(I < N, \"array index out of bounds\");\n\t\treturn move(value.mValue[I]);\n\t}\n\n\ttemplate<size_t I, typename T, size_t N>\n\tEA_NODISCARD EA_CONSTEXPR const T& get(const array<T, N>& value) EA_NOEXCEPT\n\t{\n\t\tstatic_assert(I < N, \"array index out of bounds\");\n\t\treturn value.mValue[I];\n\t}\n\n\ttemplate<size_t I, typename T, size_t N>\n\tEA_NODISCARD EA_CONSTEXPR const T&& get(const array<T, N>&& value) EA_NOEXCEPT\n\t{\n\t\tstatic_assert(I < N, \"array index out of bounds\");\n\t\treturn move(value.mValue[I]);\n\t}\n\n\ttemplate <typename T, size_t N>\n\tinline void swap(array<T, N>& a, array<T, N>& b)\n\t{\n\t\teastl::swap_ranges(&a.mValue[0], &a.mValue[N], &b.mValue[0]);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// to_array\n\t///////////////////////////////////////////////////////////////////////\n\tnamespace internal\n\t{\n\t\ttemplate<class T, size_t N, size_t... I>\n\t\tEA_CONSTEXPR auto to_array(T (&a)[N], index_sequence<I...>)\n\t\t{\n\t\t\treturn eastl::array<eastl::remove_cv_t<T>, N>{{a[I]...}};\n\t\t}\n\n\t\ttemplate<class T, size_t N, size_t... I>\n\t\tEA_CONSTEXPR auto to_array(T (&&a)[N], index_sequence<I...>)\n\t\t{\n\t\t\treturn eastl::array<eastl::remove_cv_t<T>, N>{{eastl::move(a[I])...}};\n\t\t}\n\t}\n\n\ttemplate<class T, size_t N>\n\tEA_CONSTEXPR eastl::array<eastl::remove_cv_t<T>, N> to_array(T (&a)[N])\n\t{\n\t\tstatic_assert(eastl::is_constructible_v<T, T&>, \"element type T must be copy-initializable\");\n\t\tstatic_assert(!eastl::is_array_v<T>, \"passing multidimensional arrays to to_array is ill-formed\");\n\t\treturn internal::to_array(a, eastl::make_index_sequence<N>{});\n\t}\n\n\ttemplate<class T, size_t N>\n\tEA_CONSTEXPR eastl::array<eastl::remove_cv_t<T>, N> to_array(T (&&a)[N])\n\t{\n\t\tstatic_assert(eastl::is_move_constructible_v<T>, \"element type T must be move-constructible\");\n\t\tstatic_assert(!eastl::is_array_v<T>, \"passing multidimensional arrays to to_array is ill-formed\");\n\t\treturn internal::to_array(eastl::move(a), eastl::make_index_sequence<N>{});\n\t}\n\n#if EASTL_TUPLE_ENABLED\n\n\t///////////////////////////////////////////////////////////////////////\n\t// helper classes\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate<typename T, size_t N>\n\tstruct tuple_size<array<T, N>> : public eastl::integral_constant<size_t, N> {};\n\n\tnamespace internal {\n\ttemplate<size_t I, typename T, size_t N, typename = void>\n\tstruct tuple_element {};\n\n\ttemplate<size_t I, typename T, size_t N>\n\tstruct tuple_element<I, T, N, eastl::enable_if_t<(I < N)>> {\n\t\tusing type = T;\n\t};\n\t}\n\n\ttemplate<size_t I, typename T, size_t N>\n\tstruct tuple_element<I, array<T, N>> : internal::tuple_element<I, T, N> {};\n\n#endif  // EASTL_TUPLE_ENABLED\n} // namespace eastl\n\n///////////////////////////////////////////////////////////////////////\n// C++17 structured bindings support for eastl::array\n///////////////////////////////////////////////////////////////////////\n\n#ifndef EA_COMPILER_NO_STRUCTURED_BINDING\n// we can't forward declare tuple_size and tuple_element because some std implementations\n// don't declare it in the std namespace, but instead alias it.\n#include <array>\n\nnamespace std\n{\n\ntemplate<typename T, size_t N>\nstruct tuple_size<eastl::array<T, N>> : public eastl::integral_constant<size_t, N> {};\n\ntemplate<size_t I, typename T, size_t N>\nstruct tuple_element<I, eastl::array<T, N>> : public eastl::tuple_element<I, eastl::array<T, N>> {};\n}\n#endif\n\n\nEA_RESTORE_VC_WARNING();\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/atomic.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_H\n#define EASTL_ATOMIC_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n//  Below is the documentation of the API of the eastl::atomic<T> library.\n//  This includes class and free functions.\n//  Anything marked with a '+' in front of the name is an extension to the std API.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// eastl::atomic<T> memory_order API\n//\n//  See below for full explanations on the memory orders and their guarantees.\n//\n//  - eastl::memory_order_relaxed\n//  - eastl::memory_order_acquire\n//  - eastl::memory_order_release\n//  - eastl::memory_order_acq_rel\n//  - eastl::memory_order_seq_cst\n//  - +eastl::memory_order_read_depends\n//\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// eastl::atomic<T> class API\n//\n//   All jargon and prerequisite knowledge is explained below.\n//\n//   Unless otherwise specified all orders except read_depends is a valid order\n//   on the given operation.\n//   Unless otherwise specified all operations are valid on all types T.\n//   If no order is provided, seq_cst memory ordering is used for the operation.\n//\n//   - atomic()        : Value-initializes the underlying object as T{}.\n//\n//   - atomic(T)       : Initializes the underlying object with a copy of T.\n//\n//   - T operator=(T)  : Atomically assigns T as store(T, seq_cst).\n//\n//   - is_lock_free()  : true if the operations are lockfree. Always true for eastl.\n//\n//   - store(T, order) : Atomically stores T affecting memory according to order.\n//                     : Valid orders are relaxed, release, and seq_cst.\n//\n//   - T load(order)   : Atomically loads T affecting memory according to order.\n//                     : Valid orders are relaxed, acquire, and seq_cst.\n//                     : If T is a pointer type, read_depends is another valid order.\n//\n//   - operator T()    : Atomically loads T as load(T, seq_cst).\n//\n//   - T exchange(T, order) : Atomically performs a RMW that replaces the current value with T.\n//                          : Memory is affected according to order.\n//                          : Returns the previous value stored before the RMW operation.\n//\n//   - bool compare_exchange_weak(T&, T, successOrder, failOrder)\n//        : Atomically compares the value stored with that of T& and if equal replaces it with T.\n//        : This is a RMW operation.\n//        : If the comparison fails, loads the observed value into T&. This is a load operation.\n//        : Memory is affected in the RMW operation according to successOrder.\n//        : Memory is affected in the load operation according to failOrder.\n//        : failOrder cannot be a stronger order than successOrder.\n//        : Returns true or false if the comparison succeeded and T was stored into the atomic object.\n//        :\n//        : The weak variant may fail even if the observed value of the atomic object equals T&.\n//        : This can yield performance gains on platforms with ld/str exclusive pair instructions especially\n//        : when the compare_exchange operation is done in a loop.\n//        : Only the bool return value can be used to determine if the operation was successful.\n//\n//   - bool compare_exchange_weak(T&, T, order)\n//        : Same as the above except that order is used for both the RMW and the load operation.\n//        : If order == acq_rel then the order of the load operation equals acquire.\n//        : If order == release then the order of the load operation equals relaxed.\n//\n//   - bool compare_exchange_strong(T&, T, successOrder, failOrder)\n//   - bool compare_exchange_strong(T&, T, order)\n//        : This operation is the same as the above weak variants\n//        : expect that it will not fail spuriously if the value stored equals T&.\n//\n//   The below operations are only valid for Integral types.\n//\n//   - T fetch_add(T, order)\n//        : Atomically performs a RMW that increments the value stored with T.\n//        : Returns the previous value stored before the RMW operation.\n//   - T fetch_sub(T, order)\n//        : Atomically performs a RMW that decrements the value stored with T.\n//        : Returns the previous value stored before the RMW operation.\n//   - T fetch_and(T, order)\n//        : Atomically performs a RMW that bit-wise and's the value stored with T.\n//        : Returns the previous value stored before the RMW operation.\n//   - T fetch_or(T, order)\n//        : Atomically performs a RMW that bit-wise or's the value stored with T.\n//        : Returns the previous value stored before the RMW operation.\n//   - T fetch_xor(T, order)\n//        : Atomically performs a RMW that bit-wise xor's the value stored with T.\n//        : Returns the previous value stored before the RMW operation.\n//\n//   - +T add_fetch(T, order)\n//        : Atomically performs a RMW that increments the value stored with T.\n//        : Returns the new updated value after the operation.\n//   - +T sub_fetch(T, order)\n//        : Atomically performs a RMW that decrements the value stored with T.\n//        : Returns the new updated value after the operation.\n//   - +T and_fetch(T, order)\n//        : Atomically performs a RMW that bit-wise and's the value stored with T.\n//        : Returns the new updated value after the operation.\n//   - +T or_fetch(T, order)\n//        : Atomically performs a RMW that bit-wise or's the value stored with T.\n//        : Returns the new updated value after the operation.\n//   - +T xor_fetch(T, order)\n//        : Atomically performs a RMW that bit-wise xor's the value stored with T.\n//        : Returns the new updated value after the operation.\n//\n//   - T operator++/--()\n//        : Atomically increments or decrements the atomic value by one.\n//        : Returns the previous value stored before the RMW operation.\n//        : Memory is affected according to seq_cst ordering.\n//\n//   - T ++/--operator()\n//        : Atomically increments or decrements the atomic value by one.\n//        : Returns the new updated value after the RMW operation.\n//        : Memory is affected according to seq_cst ordering.\n//\n//   - T operator+=/-=/&=/|=/^=(T)\n//        : Atomically adds, subtracts, bitwise and/or/xor the atomic object with T.\n//        : Returns the new updated value after the operation.\n//        : Memory is affected according to seq_cst ordering.\n//\n//\n//   The below operations are only valid for Pointer types\n//\n//   - T* fetch_add(ptrdiff_t val, order)\n//        : Atomically performs a RMW that increments the value store with sizeof(T) * val\n//        : Returns the previous value stored before the RMW operation.\n//   - T* fetch_sub(ptrdiff_t val, order)\n//        : Atomically performs a RMW that decrements the value store with sizeof(T) * val\n//        : Returns the previous value stored before the RMW operation.\n//\n//   - +T* add_fetch(ptrdiff_t val, order)\n//        : Atomically performs a RMW that increments the value store with sizeof(T) * val\n//        : Returns the new updated value after the operation.\n//   - +T* sub_fetch(ptrdiff_t val, order)\n//        : Atomically performs a RMW that decrements the value store with sizeof(T) * val\n//        : Returns the new updated value after the operation.\n//\n//   - T* operator++/--()\n//        : Atomically increments or decrements the atomic value by sizeof(T) * 1.\n//        : Returns the previous value stored before the RMW operation.\n//        : Memory is affected according to seq_cst ordering.\n//\n//   - T* ++/--operator()\n//        : Atomically increments or decrements the atomic value by sizeof(T) * 1.\n//        : Returns the new updated value after the RMW operation.\n//        : Memory is affected according to seq_cst ordering.\n//\n//\n//   - +EASTL_ATOMIC_HAS_[len]BIT Macro Definitions\n//        These macros provide the ability to compile-time switch on the availability of support for the specific\n//        bit width of an atomic object.\n//   Example:\n//\n//   #if defined(EASTL_ATOMIC_HAS_128BIT)\n//   #endif\n//\n//   Indicates the support for 128-bit atomic operations on an eastl::atomic<T> object.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// eastl::atomic_flag class API\n//\n//   Unless otherwise specified all orders except read_depends is a valid order\n//   on the given operation.\n//\n//   - atomic_flag()     : Initializes the flag to false.\n//\n//   - clear(order)\n//       : Atomically stores the value false to the flag.\n//       : Valid orders are relaxed, release, and seq_cst.\n//\n//   - bool test_and_set(order)\n//       : Atomically exchanges flag with true and returns the previous value that was held.\n//\n//   - bool test(order)\n//       : Atomically loads the flag value.\n//       : Valid orders are relaxed, acquire, and seq_cst.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// eastl::atomic standalone free function API\n//\n//   All class methods have a standalone free function that takes a pointer to the\n//   atomic object as the first argument. These functions just call the correct method\n//   on the atomic object for the given operation.\n//   These functions come in two variants, a non-explicit and an explicit variant\n//   that take on the form atomic_op() and atomic_op_explicit() respectively.\n//   The non-explicit variants take no order arguments and thus are all seq_cst.\n//   The explicit variants take an order argument.\n//   Only the standalone functions that do not have a class method equivalent pair will be\n//   documented here which includes all new extensions to the std API.\n//\n//   - +compiler_barrier()\n//        : Read-Write Compiler Barrier.\n//   - +compiler_barrier_data_dependency(const T&)\n//        : Read-Write Compiler Barrier.\n//        : Applies a fake input dependency on const T& so the compiler believes said variable is used.\n//        : Useful for example when writing benchmark or testing code with local variables that must not get dead-store eliminated.\n//   - +cpu_pause()\n//        : Prevents speculative memory order violations in spin-wait loops.\n//        : Allows giving up core resources, execution units, to other threads while in spin-wait loops.\n//   - atomic_thread_fence(order)\n//        : Read docs below.\n//   - atomic_signal_fence(order)\n//        : Prevents reordering with a signal handler.\n//   - +atomic_load_cond(const eastl::atomic<T>*, Predicate)\n//        : continuously loads the atomic object until Predicate is true\n//        : will properly ensure the spin-wait loop is optimal\n//        : very useful when needing to spin-wait for some condition to be true which is common is many lock-free algorithms\n//        : Memory is affected according to seq_cst ordering.\n//   - +atomic_load_cond_explicit(const eastl::atomic<T>*, Predicate, Order)\n//        : Same as above but takes an order for how memory is affected\n//\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n//   Deviations from the standard. This does not include new features added:\n//\n// 1.\n//   Description: Atomics are always lock free\n//   Reasoning  : We don't want people to fall into performance traps where implicit locking\n//                is done. If your user defined type is large enough to not support atomic\n//                instructions then your user code should do the locking.\n//\n// 2.\n//   Description: Atomic objects can not be volatile\n//   Reasoning  : Volatile objects do not make sense in the context of eastl::atomic<T>.\n//                Use the given memory orders to get the ordering you need.\n//                Atomic objects have to become visible on the bus. See below for details.\n//\n// 3.\n//   Description: Consume memory order is not supported\n//   Reasoning  : See below for the reasoning.\n//\n// 4.\n//   Description: ATOMIC_INIT() macros and the ATOMIC_LOCK_FREE macros are not implemented\n//   Reasoning  : Use the is_lock_free() method instead of the macros.\n//                ATOMIC_INIT() macros aren't needed since the default constructor value initializes.\n//\n// 5.\n//   Description: compare_exchange failure memory order cannot be stronger than success memory order\n//   Reasoning  : Besides the argument that it ideologically does not make sense that a failure\n//                of the atomic operation shouldn't have a stricter ordering guarantee than the\n//                success of it; if that is required then just make the whole operation stronger.\n//                This ability was added and allowed in C++17 only which makes supporting multiple\n//                C++ versions harder when using the compiler provided intrinsics since their behaviour\n//                is reliant on the C++ version being compiled. Also makes it harder to reason about code\n//                using these atomic ops since C++ versions vary the behaviour. We have also noticed\n//                that versions of compilers that say they support C++17 do not properly adhere to this\n//                new requirement in their intrinsics. Thus we will not support this.\n//\n// 6.\n//   Description: All memory orders are distinct types instead of enum values\n//   Reasoning  : This will not affect how the API is used in user code.\n//                It allows us to statically assert on invalid memory orders since they are compile-time types\n//                instead of potentially runtime enum values.\n//                Allows for more efficient code gen without the use of switch statements or if-else conditionals\n//                on the memory order enum values on compilers that do not provide intrinsics that take in a\n//                memory order, such as MSVC, especially in debug and debug-opt builds.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n//   ******** DISCLAIMER ********\n//\n//   This documentation is not meant to provide rigorous proofs on the memory models\n//   of specific architectures or the C++ memory model introduced in C++11. It is not\n//   meant to provide formal mathematical definitions and logic that shows that a given\n//   implementation adheres to the C++ memory model. This isn't meant to be some infallible\n//   oracle on memory models, barriers, observers, and architecture implementation details.\n//   What I do hope a reader gets out of this is the following. An understanding of the C++\n//   memory model and how that relates to implementations on various architectures. Various\n//   phenomena and ways that compilers and architectures can steer away from a sequentially\n//   consistent system. To provide examples on how to use this library with common patterns\n//   that will be seen in many code bases. Lastly I would like to provide insight and\n//   further readings into the lesser known topics that aren't shared outside people\n//   who live in this space and why certain things are done the way they are\n//   such as cumulativity of memory barriers as one example. Sometimes specifying barriers\n//   as LDLD/LDST/STST/STLD doesn't actually cut it, and finer grain semantics are needed\n//   to describe cumulativity of memory barriers.\n//\n//   ******** Layout of the Documentation ********\n//\n//   This document will first go through a variety of different hardware architectures with examples of the various kinds of\n//   reordering that is allowed by these architectures. We will use the memory barriers provided by the hardware to \"fix\" these\n//   examples.\n//   Then we will introduce the C++ memory model and revisit the examples using the platform agnostic abstract memory model to \"fix\"\n//   them.\n//   The hope here is that we get a sense of the various types of architectures and weak memory consistency provided by them and thus\n//   an appreciation for the design of the C++ abstract memory model.\n//\n//   ******** REFERENCES ********\n//   [1] Dekker's mutual exclusion algorithm made RW-safe\n//   [2] Handling Memory Ordering in Multithreaded Applications with Oracle Solaris\n//   [3] Evaluating the Cost of Atomic Operations on Modern Architectures\n//   [4] A Tutorial Introduction to the ARM and POWER Relaxed Memory Models\n//   [5] Memory Barriers: a Hardware View for Software Hackers\n//   [6] Memory Model = Instruction Reordering + Store Atomicity\n//   [7] ArMOR: Defending Against Memory Consistency Model Mismatches in Heterogeneous Architectures\n//   [8] Weak Memory Models: Balancing Definitional Simplicity and Implementation Flexibility\n//   [9] Repairing Sequential Consistency in C/C++11\n//   [10] A high-level operational semantics for hardware weak memory models\n//   [11] x86-TSO: A Rigorous and Usable Programmer's Model for x86 Multiprocessors\n//   [12] Simplifying ARM Concurrency: Multicopy-Atomic Axiomatic and Operational Models for ARMv8\n//   [13] Mixed-size Concurrency: ARM, POWER, C/C++11, and SC\n//   [14] P0668R4: Revising the C++ memory model\n//   [15] Constructing a Weak Memory Model\n//   [16] The Superfluous Load Queue\n//   [17] P0190R1: Proposal for New memory_order_consume Definition\n//\n//   ******** What does it mean to be Atomic? ********\n//\n//   The word atomic has been overloaded and can mean a lot of different things depending on the context,\n//   so let's digest it.\n//\n//   The first attribute for something to be atomic is that concurrent stores and loads\n//   must not tear or shear. This means if two threads write 0x01 and 0x02 at the same time\n//   then the only values that should ever be observed is 0x01 or 0x02. We can only see\n//   the whole write of 0x01 or 0x02, not 0x03 as an example. Many algorithms rely on\n//   this property; only very few such a Dekker's algorithm for mutual exclusion don't.\n//   Well actually a recent paper, [1], showed that Dekker's isn't safe without atomic\n//   loads and stores so this property is pretty fundamental and also hard to prove that\n//   your algorithm is safe without this property on loads and stores.\n//\n//   We need to ensure the compiler emits a single load instruction.\n//   If we are doing 64-bit loads on a 32-bit platform, we need to ensure the load is one\n//   instruction instead of 2 32-bit loads into two registers.\n//   Another example is if we have this struct, struct { int32_t i; int32_t k; }, even on\n//   a 64-bit system we have to ensure the compiler does one 64-bit load and not two\n//   32-bit loads for each individual member.\n//\n//   We also need to ensure the correct instruction is emitted. A general load instruction\n//   to do a 64-bit load on a 32-bit platform may perform a 64-bit load but it may not\n//   be atomic, it may be turned into two 32-bit loads behind the scenes in the cpu.\n//   For example on ARMv7 we would have to use ldrexd not ldrd for 64-bit loads\n//   on a 32-bit ARMv7 core.\n//\n//   An operation may be considered atomic if multiple sub-operations are done as one\n//   transactional unit. This is commonly known as a Read-Modify-Write, RMW, operation.\n//   Take a simple add operation; it is actually a load from memory into a register,\n//   a modification of said register and then a store back to memory. If two threads\n//   concurrently execute this add operation on the same memory location; any interleaving\n//   of the 3 sub-operations is possible. It is possible that if the initial value is 0,\n//   the result may be 1 because each thread executed in lockstep both loading 0, adding 1\n//   and then storing 1. A RMW operation may be considered atomic if the whole sequence of\n//   sub-operations are serialized as one transactional unit.\n//\n//   Atomicity may also refer to the order in which memory operations are observed and the\n//   dependencies between memory operations to different memory locations. As a quick example\n//   into the very thing we will be deep diving into that is not very intuitive. If I do, [STORE(A, 2); STORE(B, 1);],\n//   in one thread and another thread does, [r0 = LOAD(B); r1 = LOAD(A);]; if r0 == 1, thus we observed\n//   the store to B, will we observe r1 == 2. Our intuition tells us that well A was stored\n//   first and then B, so if I read the new value of B then I must also read the new value\n//   of A since the store to A happened before B so if I can see B then I must be able to\n//   see everything before B which includes A.\n//   This highlights the ordering of memory operations and why memory barriers and memory\n//   models are so heavily attached to atomic operations because one could classify something\n//   is atomic if the dependency highlighted in the above example is allowed to be maintained.\n//\n//   This is what people mean when you hear that volatile does NOT mean atomicity of the operation.\n//   Usually people imply a lot of implicit assumptions when they mark a variable as volatile.\n//   All volatile gives us is the ability to tell the compiler it may not assume anything\n//   about the state of that memory location. This means the compiler must always emit a load\n//   or store instruction, cannot perform constant folding, dead-store elimination, or\n//   do any sort of code movement on volatile variables.\n//\n//   ******** Preliminary Basics ********\n//\n//   It is expected that the reader understands what a cache is, how it is organized and how data\n//   is chunked into cachelines. It is helpful if the reader understands basic cache coherency\n//   protocols such as MSI or MESI.\n//   It is expected the reader understands alignment, especially natural alignment\n//   of the processor and why alignment is important for data access.\n//   The reader should have some understanding of how a processor executes instructions,\n//   basics of what Out-of-Order execution means and basics of what speculative execution means.\n//   It is expected that the reader has an understanding of threading, multi-threaded programming\n//   and the use of concurrency primitives such as mutexes.\n//   Memory Barrier, Barrier, Memory Fence and Fence are all interchangeable synonyms.\n//\n//   Independent memory operations can be performed or observed, depending on your perspective,\n//   in any order as long as the local cpu thinks its execution is happening in program order.\n//   This can be a problem for inter-cpu communications and thus we need some way to enforce\n//   that the compiler does not reorder instructions and that the cpu also does not reorder\n//   instructions. This is what a barrier is, it is an enforcement of ordering on memory instructions,\n//   so as the name suggests a barrier. Barriers can be one-sided or both-sided which means\n//   the barrier enforces a partial order above or below or on both sides of said barrier.\n//\n//   Processors will use tricks such as out-of-order execution, memory instruction buffering and\n//   combining, speculative loads and speculative execution, branch prediction and many types of caching even\n//   in various interconnects from the cpu to the memory itself. One key thing to note is that cpus\n//   do not physically reorder the instruction stream. Instructions are dispatched and retired\n//   in-order but executed out-of-order. Memory barriers will prevent these tricks from happening\n//   by controlling the interaction of multiple cpus.\n//\n//   Compilers will morph your code and physically move instructions around as long as the program\n//   has the same observed behaviour. This is becoming increasingly true with more optimization techniques\n//   such as Link Time Optimization becoming the norm where once people assumed compilers couldn't assume\n//   something outside the given TU and now because they have the whole program view they know everything.\n//   This means the compiler does indeed alter the instruction stream\n//   and compiler barriers are a way to tell them to not move any memory instructions across the barrier.\n//   This does not prevent a compiler from doing optimizations such as constant folding, merging of\n//   overlapping loads, or even dead store elimination. Compiler barriers are also very cheap and\n//   have zero impact on anything that the compiler knows isn't visible in memory such as local variables\n//   whose addresses do not escape the function even if their address is taken. You can think of it\n//   in terms of a sequence point as used with \"volatile\" qualified variables to denote a place in code where\n//   things must be stable and the compiler doesn't cache any variables in registers or do any reordering.\n//\n//   Memory Barriers come in many flavours that instill a partial or full ordering on memory operations.\n//   Some memory operations themselves have implicit ordering guarantees already, for example\n//   Total-Store Order, TSO, architectures like x86 guarantee that a store operation cannot be reordered with a\n//   previous store operation thus a memory barrier that only orders stores is not needed\n//   on this architecture other than ensuring the compiler doesn't do any shenanigans.\n//   Considering we have 4 permutations of memory operations; a common way to describe an ordering\n//   is via Load-Load/LDLD, Load-Store/LDST, Store-Store/STST or Store-Load/STLD notation. You read this\n//   notation as follows; STLD memory barrier means a load cannot be reordered with a previous store.\n//   For example, on TSO architecture we can say all stores provide a STST memory barrier,\n//   since a store cannot be reordered with a previous store.\n//\n//   Memory Barriers in itself are not a magic bullet, they come with caveats that must be known.\n//   Each cpu architecture also has its own flavours and guarantees provided by said memory barriers.\n//   There is no guarantee that memory instructions specified before a memory barrier will complete,\n//   be written to memory or fully propagated throughout the rest of the system, when the memory barrier\n//   instruction completes. The memory barrier creates a point in that local cpus queue of memory instructions\n//   whereby they must not cross. There is no guarantee that using a memory barrier on one cpu will have\n//   any effect at all on another remote cpu's observed view of memory. This also implies that executing\n//   a memory barrier does not hinder, incur, stall or enforce any other cpus to serialize with each other cpu.\n//   In order for a remote cpu to observe the correct effects it must also use a matching memory barrier.\n//   This means code communicating in 2 threads through memory must both be employing the use of memory barriers.\n//   For example, a store memory barrier that only orders stores, STST, in one thread must be paired with a load memory barrier\n//   that only orders loads, LDLD, in the other thread trying to observe those stores in the correct order.\n//\n//   ******** Memory Types && Devices ********\n//\n//   eastl::atomic<T> and accompanying memory barriers ONLY ORDER MEMORY to cpu-to-cpu communication through whatever the\n//   processor designates as normal cacheable memory. It does not order memory to devices. It does not provide any DMA ordering guarantees.\n//   It does not order memory with other memory types such as Write Combining. It strictly orders memory only to shared memory that is used\n//   to communicate between cpus only.\n//\n//   ******** Sequentially Consistent Machine ********\n//\n//   The most intuitive as well as the model people naturally expect a concurrent system to have is Sequential Consistency.\n//   You may have or definitely have heard this term if you dealt with any type of distributed system. Lamport's definition\n//   articulates this consistency model the best.\n//   Leslie Lamport: \"the result of any execution is the same as if the operations of all the processors were executed in some\n//                    sequential order, and the operations of each individual processor appear in this sequence in the order\n//                    specified by its program\".\n//\n//   A Sequentially Consistent machine is modelled as follows:\n//\n//   ------------               ------------\n//   | Thread 0 |      ...      | Thread N |\n//   ------------               ------------\n//       |  |                        |  |\n//       |  |                        |  |\n//   ----------------------------------------\n//   |                                      |\n//   |           Shared Memory              |\n//   |                                      |\n//   ----------------------------------------\n//\n//   This is a sequentially consistent machine. Each thread is executing instructions in program order which does loads and stores\n//   that are serialized in some order to the shared memory. This means all communication is done through the shared memory with one cpu\n//   doing one access at a time. This system has a couple key properties.\n//\n//   1. There is no local cpu memory reordering. Each cpu executes instructions in program order and all loads and stores must complete,\n//      be visible in the shared memory or be visible in a register before starting the next instruction.\n//   2. Each memory operation becomes visible to all cpus at the same time. If a store hits the shared memory, then all subsequent loads\n//      from every other cpu will always see the latest store.\n//\n//   A Sequentially Consistent machine has, Single-Copy Store Atomicity: All stores must become visible to all cores in the system at the same time.\n//\n//   ******** Adding Caches ********\n//\n//   Caches by nature implicitly add the potential for memory reordering. A centralized shared snoopy bus that we all learned in school\n//   makes it easy to implement sequential consistency with caches. Writes and reads are all serialized in a total order via the cache bus transaction\n//   ordering. Every modern day bus is not inorder, and most certainly not a shared centralized bus. Cache coherency guarantees that all memory operations\n//   will be propagated eventually to all parties, but it doesn't guarantee in what order or in what time frame. Once you add\n//   caches, various levels of caching and various interconnects between remote cpus, you inevitably run into the issue where\n//   some cpus observe the effects of a store before other cpus. Obviously we have weakly-ordered and strongly-ordered cpus with\n//   caches so why is that? The short answer is, where is the onus put, is it on the programmer or the hardware. Does the hardware\n//   have dependency tracking, is it able to determine when a memory order violation occurs such as rolling back its speculative execution\n//   and also how far along the chain of interconnects does the hardware wait before it determines that the memory operation has\n//   been acknowledged or is considered to satisfy its memory ordering guarantees. Again this is a very high level view of the system\n//   as a whole, but the takeaway is yes; caches do add the potential for reordering but other supporting hardware determines whether\n//   that is observable by the programmer. There is also some debate whether weakly-ordered processors are actually more performant\n//   than strongly-ordered cpus eluding to the fact that the hardware has a better picture of what is a violation versus the programmer\n//   having to emit far more barriers on weakly-ordered architectures in multi-threaded code which may actually not be needed because the\n//   hardware didn't commit a violation but it may have and we as the programmer cannot rely on may haves.\n//\n//   ******** Store Buffers ********\n//\n//   Obviously having all stores serialize results in unnecessary stalls. Store buffers alleviate this issue.\n//   Store buffers are simple fixed size structures that sit between the cpu and the memory hierarchy. This allows\n//   each cpu to record its write in the store buffer and then move onto the next instruction. The store buffer will\n//   eventually be flushed to the resulting memory hierarchy in FIFO order. How and when this flushing occurs is irrelevant to the\n//   understanding of a store buffer. A read from an address will grab the most recent write to the same address in the store buffer.\n//\n//   The introduction of a store buffer is our first dive into weaker memory consistency. The addition of this hardware turns the consistency model weaker,\n//   into one that is commonly known as TSO, Total-Store Order. This is the exact model used by x86 cpus and we will see what this means\n//   and what new effects are observed with the addition of the store buffer. Below is a diagram of how the machine may now look.\n//   This type of store buffer is known as a FIFO store buffer, FIFO write buffer, or Load/Store Queue in some literature. This type of\n//   store buffer introduces STLD reordering but still prevents STST reordering. We will take a look at another type of store buffer later.\n//   Even with this store buffer, stores to the same address can still be merged so that only the latest store is written to the cache assuming\n//   no other intermediary stores happen. x86 cpus do write merging even for consecutive stores, i.e. storing to A and A+1 can be merged into one two-byte store.\n//\n//   ------------               ------------\n//   | Thread 0 |      ...      | Thread N |\n//   ------------               ------------\n//       |  |                        |  |\n//       |  |                        |  |\n//    | Store  |                  | Store  |\n//    | Buffer |                  | Buffer |\n//       |  |                        |  |\n//   ----------------------------------------\n//   |                                      |\n//   |           Shared Memory              |\n//   |                                      |\n//   ----------------------------------------\n//\n//   ---- Store-Buffering / Dekker's Example ----\n//   This is a very common litmus test that showcases the introduction of STLD reordering. It is called Store-Buffering example because it is the only weaker\n//   behaviour observed under TSO and also called Dekker's Example as it famously breaks Dekker's mutual exclusion algorithm.\n//\n//   ---------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   STORE(x, 1)  | STORE(y, 1)\n//   r0 = LOAD(y) | r1 = LOAD(x)\n//   ---------------------------\n//   Observed: r0 = 0 && r1 = 0\n//   ---------------------------\n//\n//   We would normally assume that any interleaving of the two threads cannot possibly end up with both loads reading 0. We assume that the observed outcome\n//   of r0 = 0 && r1 = 0 to be impossible, clearly that is not the case. Let's start by understanding the example with no reordering possible. Both threads\n//   run and their first instruction is to write the value 1 into either x or y, the next instruction then loads from the opposite variable. This means no\n//   matter the interleaving, one of the loads always executes after the other thread's store to that variable.\n//   We could observe r0 = 1 && r1 = 1 if both threads execute in lockstep.\n//   We could observe r0 = 0 && r1 = 1 if thread 0 executes and then thread 1 executes.\n//   We could observe r0 = 1 && r1 = 0 if thread 1 executes and then thread 0 executes.\n//   Since the stores always execute before that load in the other thread, one thread must always at least observe a store, so let's see why store buffers break this.\n//\n//   What will happen is that STORE(x, 1) is stored to the store buffer but not made globally visible yet.\n//   STORE(y, 1) is written to the store buffer and also is not made globally visible yet.\n//   Both loads now read the initial state of x and y which is 0. We got the r0 = 0 && r1 = 0 outcome and just observed a Store-Load reordering.\n//   It has appeared as if the loads have been reordered with the previous stores and thus executed before the stores.\n//   Notice even if we execute the instructions in order, a series of other hardware side effects made it appear as if the instructions have been reordered.\n//   We can solve this by placing a Store-Load barrier after the store and before the load as follows.\n//\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   STORE(x, 1)  | STORE(y, 1)\n//   STLD BARRIER | STLD BARRIER\n//   r0 = LOAD(y) | r1 = LOAD(x)\n//   ---------------------------\n//\n//   This STLD barrier effectively will flush the store buffer into the memory hierarchy ensuring all stores in the buffer are visible to all other cpus at the same time\n//   before executing the load instruction. Again nothing prevents a potential hardware from speculatively executing the load even with the STLD barrier, the hardware will have to do\n//   a proper rollback if it detected a memory order violation otherwise it can continue on with its speculative load. The barrier just delimits a stability point.\n//\n//   Most hardware does not provide granular barrier semantics such as STLD. Most provide a write memory barrier which only orders stores, STST, a read memory barrier\n//   which only orders loads, LDLD, and then a full memory barrier which is all 4 permutations. So on x86 we will have to use the mfence, memory fence, instruction\n//   which is a full memory barrier to get our desired STLD requirements.\n//\n//   TSO also has the property that we call, Multi-Copy Store Atomicity. This means a cpu sees its own stores before they become visible to other cpus,\n//   by forwarding them from the store buffer, but a store becomes visible to all other cpus at the same time when flushed from the store buffer.\n//\n//\n//   Let's look at a non-FIFO store buffer now as seen in ARM cpus as an example and we will use a standard Message Passing example to see how it manifests in even weaker consistency.\n//   A store buffer on ARM as an example allows write merging even with adjacent stores, is not a FIFO queue, any stores in the small hardware hash table may be ejected at any point\n//   due to a collision eviction or the availability of cachelines in the cache hierarchy meaning that stores may bypass the buffer entirely if that cacheline is already owned by that cpu.\n//   There is no guarantee that stores will be completed in order as in the FIFO case.\n//\n//   ---------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   STORE(x, 1)  | while(LOAD(y) == 0);\n//   STORE(y, 1)  | r0 = LOAD(x)\n//   ---------------------------\n//   Observed: r0 = 0\n//   ---------------------------\n//\n//   This is a classic Message Passing example that is very commonly used in production code. We store some values and then set a flag, STORE(y, 1) in this case.\n//   The other thread waits until the flag is observed and then reads the value out of x. If we observed the flag then we should obviously see all stores before the flag was set.\n//   Given our familiarity with TSO consistency above we know this definitely works on TSO and it is impossible to observe the load of x returning 0 under that consistency model.\n//   Let's see how this breaks with a non-FIFO store buffer.\n//\n//   Thread 0 executes the STORE(x, 1) but the cacheline for x is not in thread 0's cache so we write to the store buffer and wait for the cacheline.\n//   Thread 1 executes the LOAD(y) and it also does not have y in its cacheline so it waits before completing the load.\n//   Thread 0 moves on to STORE(y, 1). It owns this cacheline, hypothetically, so it may bypass the store buffer and store directly to the cache.\n//   Thread 0 receives a message that Thread 1 needs y's cacheline, so it transfers the now modified cacheline to Thread 1.\n//   Thread 1 completes the load with the updated value of y = 1 and branches out of the while loop since we saw the new value of y.\n//   Thread 1 executes LOAD(x) which will return 0 since Thread 0 still hasn't flushed its store buffer waiting for x's cacheline.\n//   Thread 0 receives x's cacheline and now flushes x = 1 to the cache. Thread 1 will also have invalidated its cacheline for x that it brought in via the previous load.\n//\n//   We have now fallen victim to STST reordering, allowing Thread 1 to observe a load of x returning 0. Not only does this store buffer allow STLD reordering due to the nature of\n//   buffering stores, but it also allows another reordering; that of Store-Store reordering. It was observed as if Thread 0 executed STORE(y, 1) before STORE(x, 1) which completely\n//   broke our simple message passing scenario.\n//\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   STORE(x, 1)  | while(LOAD(y) == 0);\n//   STST BARRIER |\n//   STORE(y, 1)  | r0 = LOAD(x)\n//   ---------------------------\n//\n//   The STST memory barrier effectively ensures that the cpu will flush its store buffer before executing any subsequent stores. That is not entirely true, the cpu is still allowed\n//   to continue and execute stores to the store buffer as long as it doesn't flush them to the cache before the previous stores are flushed to the cache. If nothing becomes\n//   globally visible out of order then we are good.\n//   The example above will change how the processor executes due to the STST memory barrier. Thread 0 will execute STORE(y, 1), write to the store buffer and mark all current entries. Even though it owns the cacheline\n//   it cannot write the store to the cache until all marked entries, which are all the previous stores, are flushed to the cache. We have now fixed the message passing code by adding\n//   a STST or write memory barrier and thus it is no longer possible to observe the load of x returning 0.\n//\n//   ******** Invalidation Queues ********\n//\n//   Due to the cache coherency protocol in play, a write to a cacheline will have to send invalidation messages to all other cpus that may have that cacheline as well.\n//   Immediately executing and responding to invalidation messages can cause quite a stall especially if the cache is busy at the moment with other requests.\n//   The longer we wait to invalidate the cacheline, the longer the remote cpu doing the write is stalled waiting on us. We don't like this very much.\n//   Invalidation Queues are just that, we queue up the action of actually invalidating the cacheline but immediately respond to the request saying we did it anyway.\n//   Now the remote cpu thinks we invalidated said cacheline but actually it may very well still be in our cache ready to be read from. We just got weaker again, let's\n//   see how this manifests in code by starting from the end of our previous example.\n//\n//   ---------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   STORE(x, 1)  | while(LOAD(y) == 0);\n//   STST BARRIER |\n//   STORE(y, 1)  | r0 = LOAD(x)\n//   ---------------------------\n//   Observed: r0 = 0\n//   ---------------------------\n//\n//   Thread 1 receives the invalidate x's cacheline message and queues it because it is busy.\n//   Thread 1 receives the invalidate y's cacheline message, but we don't have that cacheline so acknowledge immediately.\n//   Thread 1 executes LOAD(y), loads in y's cacheline and branches out of the loop.\n//   Thread 1 executes LOAD(x), and loads from the cache the old value of x because the invalidation message is still sitting in the invalidation queue.\n//\n//   We have just again observed the load of x returning 0 but from a different type of reordering now on the reader side.\n//   This is a form of LDLD, Load-Load, reordering as it appears as if LOAD(x) was executed before LOAD(y). This can be fixed as follows.\n//\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   STORE(x, 1)  | while(LOAD(y) == 0);\n//   STST BARRIER | LDLD BARRIER\n//   STORE(y, 1)  | r0 = LOAD(x)\n//   ---------------------------\n//\n//   The LDLD memory barrier essentially marks all entries currently in the invalidation queue. Any subsequent load must wait until all the marked entries have been\n//   processed. This ensures once we observe y = 1, we process all entries that came before y and that way we observe all the stores that happened before y.\n//   The insertion of the read memory barrier creates the required memory barrier pairing as discussed above and ensures that now our code executes as expected.\n//\n//   It must be made clear that these are not the only hardware structure additions or ways that can relax STST, STLD and LDLD orderings. These are merely\n//   2 structures that are common and ones that I choose to use as examples of how hardware can reduce ordering guarantees. Knowing how the hardware does this\n//   isn't always entirely clear but having a model that tells us what operations can be reordered is all we need to be able to reason about our code when executing on that hardware.\n//\n//   ******** Load Buffering ********\n//\n//   The analog of the Store Buffering example, this litmus test has two threads read from two different locations and then write to the other locations.\n//   The outcome of having LDST reordering is allowed and observable on many processors such as ARM.\n//\n//   ---------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   r0 = LOAD(x) | r1 = LOAD(y)\n//   STORE(y, 1)  | STORE(x, 1)\n//   ---------------------------\n//   Observed: r0 = 1 && r1 = 1\n//   ---------------------------\n//\n//   This is possible because the processor does not have to wait for the other cpu's cacheline to arrive before storing into the cache.\n//   Assume Thread 0 owns y's cacheline and Thread 1 owns x's cacheline.\n//   The processor may execute the load and thus buffer the load waiting for the cacheline to arrive.\n//   The processor may continue onto the store and since each cpu owns their respective cacheline, store the result into the cache.\n//   The cpus now receive the cachelines for x and y with the now modified value.\n//   We have just observed the loads returning 1 and thus observed LDST reordering.\n//\n//   To forbid such outcome it suffices to add any full memory barrier to both threads or a local Read-After-Write/Read-To-Write dependency or a control dependency.\n//\n//   -------------------------------\n//   Thread 0       |    Thread 1\n//   -------------------------------\n//   r0 = LOAD(x)   | r1 = LOAD(y)\n//   if (r0 == 1)   | if (r1 == 1)\n//     STORE(y, 1)  |   STORE(x, 1)\n//   -------------------------------\n//\n//   -----------------------------------------------------\n//   Thread 0                 |    Thread 1\n//   -----------------------------------------------------\n//   r0 = LOAD(x)             | r1 = LOAD(y)\n//   STORE(&(y + r0 - r1), 1) | STORE(&(x + r1 - r1), 1)\n//   -----------------------------------------------------\n//\n//   Both fixes above ensure that both writes cannot be committed, made globally visible, until their program source code order preceding reads have been fully satisfied.\n//\n//   ******** Compiler Barriers ********\n//\n//   Compiler barriers are both-sided barriers that prevent loads and stores from moving down past the compiler barrier and\n//   loads and stores from moving up above the compiler barrier. Here we will see the various ways our code may be subject\n//   to compiler optimizations and why compiler barriers are needed. Note as stated above, compiler barriers may not\n//   prevent all compiler optimizations or transformations. Compiler barriers are usually implemented by reloading all\n//   variables that are currently cached in registers and flushing all stores in registers back to memory.\n//   This list isn't exhaustive but will hopefully try to outline what compiler barriers protect against and what they don't.\n//\n//   Compiler may reorder loads.\n//   LOAD A; LOAD B; -> LOAD B; LOAD A;\n//   LOAD A; operation on A; LOAD B; operation on B; -> LOAD A; LOAD B; operation on A; operation on B\n//\n//   Insert a compiler barrier in between the two loads to guarantee that they are kept in order.\n//   LOAD A; COMPILER_BARRIER; LOAD B;\n//   LOAD A; operation on A; COMPILER_BARRIER; LOAD B; operation on B;\n//\n//   The same with stores.\n//   STORE(A, 1); STORE(B, 1); -> STORE(B, 1); STORE(A, 1);\n//   operations and STORE result into A; operations and STORE result int B; -> all operations; STORE result into B; STORE result into A;\n//\n//   Insert a compiler barrier in between the two stores to guarantee that they are kept in order.\n//   It is not required that the multiple stores to A before the barrier are not merged into one final store.\n//   It is not required that the store to B after the barrier be written to memory, it may be cached in a register for some indeterminate\n//   amount of time as an example.\n//   STORE(A, 1); COMPILER_BARRIER; STORE(B, 1);\n//\n//   The compiler is allowed to merge overlapping loads and stores.\n//   Inserting a compiler barrier here will not prevent the compiler from doing this optimization as doing one wider load/store is\n//   technically still abiding by the guarantee that the loads/stores are not reordered with each other.\n//   LOAD A[0]; LOAD A[1]; -> A single wider LOAD instruction\n//   STORE(A[0], 1); STORE(A[1], 2); -> A single wider STORE instruction\n//\n//   Compilers do not have to reload the values pointers point to. This is especially common with RISC architectures with lots\n//   of general purpose registers or even compiler optimizations such as inlining or Link-Time Optimization.\n//   int i = *ptr; Do bunch of operations; if (*ptr) { do more; }\n//   It is entirely possible the compiler may remove the last if statement because it can keep the *ptr in a register\n//   and it may infer from the operations done on i that i is never 0.\n//\n//   int i = *ptr; Do bunch of operations; COMPILER_BARRIER; if (*ptr) { do more; }\n//   Inserting a compiler barrier at that location will cause the compiler to have reload *ptr thus keeping the if statement assuming\n//   no other optimizations take place, such as the compiler knowing that *ptr is always greater than 0.\n//\n//   The compiler is within its rights to also merge and reload loads as much as it pleases.\n//\n//   while (int tmp = LOAD(A))\n//        process_tmp(tmp)\n//\n//   Will be merged and transformed to\n//\n//   if (int tmp = LOAD(A))\n//        for (;;) process_tmp(tmp)\n//\n//   Inserting a compiler barrier will ensure that LOAD(A) is always reloaded and thus the unwanted transformation is avoided.\n//\n//   while (int tmp = LOAD(A))\n//   {\n//       process_tmp(tmp)\n//       COMPILER_BARRIER\n//   }\n//\n//   Under heavy register pressure scenarios, say the loop body was larger, the compiler may reload A as follows.\n//   Compiler barriers cannot prevent this from happening, even if we put it after process_tmp as above;\n//   the compiler still kept those loads above the barrier so it satisfied its contract even though it reloaded\n//   from A more than once.\n//\n//   while (int tmp = LOAD(A))\n//       process_tmp(LOAD(A))\n//\n//   In the above transformation it is possible that another cpu stores 0 into A. When we reload A for process_tmp, we pass 0\n//   to process_tmp() which it would actually never expect to observe. Because if we observed 0, the while loop condition\n//   would never be satisfied. If the compiler under register pressure instead stored and loaded tmp from its stack slot, that is fine\n//   because we are just storing and loading the original observed value from A. Obviously that is slower than just reloading from\n//   A again so an optimizing compiler may not do the stack slot store. This is an unwanted transformation which eastl::atomic<T> prevents\n//   even on relaxed loads.\n//\n//   The compiler is allowed to do dead-store elimination if it knows that value has already been stored, or that only the last store\n//   needs to be stored. The compiler does not assume or know that these variables are shared variables.\n//\n//   STORE(A, 1);         STORE(A, 1);\n//   OPERATIONS;     ->   OPERATIONS;\n//   STORE(A, 1);\n//\n//   The compiler is well within its rights to omit the second store to A. Assuming we are doing some fancy lockfree communication\n//   with another cpu and the last store is meant to ensure the ending value is 1 even if another cpu changed A in between; that\n//   assumption will not be satisfied. A compiler barrier will not prevent the last store from being dead-store removed.\n//\n//   STORE(A, 1);\n//   OPERATIONS;\n//   STORE(A, 2);\n//\n//   Assuming these stores are meant to denote some state changes to communicate with a remote cpu. The compiler is allowed to\n//   transform this as follows without a compiler barrier. Insert a compiler barrier between the two stores to prevent the transformation.\n//   Something like this will also require memory barriers, but that is not the point of this section.\n//\n//   STORE(A, 2);\n//   OPERATIONS;\n//\n//   The compiler is also allowed to invent stores as it may please.\n//   First on many RISC architectures storing an immediate value either involves loading the immediate from the .data section\n//   or combing a variety of load upper immediate and add or or immediate instructions to get our constant in a register and then\n//   doing a single 32-bit store instruction from said register. Some ISAs have 16-bit stores with immediate value so that a store\n//   may be broken into 2 16-bit store immediate values causing shearing. To reduce instruction dependencies it may also decide\n//   to do two add immediates and then two 16-bit stores again causing shearing.\n//\n//   lui $t0, 1       # t0 == 0x00010000\n//   ori $a0, $t0, 8  # t0 == 0x00010008\n//   strw $t0, 0($a1) # store t0 into address at a1\n//   ->\n//   ori $a0, $t0, 1   # t0 == 0x00000001\n//   ori $a0, $t1, 8   # t0 == 0x00000008\n//   strhw $t0, 0($a1) # store t0 lower half at a1\n//   strhw $t1, 2($a1) # store t1 upper half at a1\n//\n//   The above shows a potential transformation that a compiler barrier cannot solve for us.\n//\n//   A compiler may also introduce stores to save on branching. Let's see.\n//\n//   if (a)\n//     STORE(X, 10);\n//   else\n//     STORE(X, 20);\n//\n//   STORE(X, 20);\n//   if (a)\n//     STORE(X, 10);\n//\n//   This is a very common optimization as it saves a potentially more expensive branch instruction but breaks multi-threaded code.\n//   This is also another case where a compiler barrier doesn't give us the granularity we need.\n//   The branches may even be completely removed with the compiler instead choosing to use conditional move operations which would\n//   actually be compliant since there would be one store only done, an extra store wouldn't have been added.\n//\n//   You are now probably thinking that compiler barriers are useful and are definitely needed to tell the compiler to calm down\n//   and guarantee our hardware guarantees are valid because the code we wrote is the instructions that were emitted.\n//   But there are definitely lots of caveats where compiler barriers do not at all provide the guarantees we still need.\n//   This where eastl::atomic<T> comes into play, and under the relaxed memory ordering section it will be explained\n//   what the standard guarantees and how we achieve those guarantees, like ensuring the compiler never does dead-store elimination or reloads.\n//\n//   ******** Control Dependencies ********\n//\n//   Control dependencies are implicit local cpu ordering of memory instructions due to branching instructions, specifically\n//   only conditional branches. The problem is compilers do not understand control dependencies, and control dependencies\n//   are incredibly hard to understand. This is meant to make the reader aware they exist and to never use them\n//   because they shouldn't be needed at all with eastl::atomic<T>. Also control dependencies are categorized as LDLD or LDST,\n//   store control dependencies inherently do not make sense since the conditional branch loads and compares two values.\n//\n//   A LDLD control dependency is an anti-pattern since it is not guaranteed that any architecture will detect the memory-order violation.\n//   r0 = LOAD(A);\n//   if (r0)\n//       r1 = LOAD(B)\n//\n//   Given those sequence of instructions, it is entirely possible that a cpu attempts to speculatively predict and load the value of B\n//   before the branch instruction has finished executing. It is entirely allowed that the cpu loads from B, assume B is in cache and A\n//   is not in cache, before A. It is allowed, that even if the cpu was correct in it's prediction that it doesn't reload B and change the\n//   fact that it speculatively got lucky.\n//\n//   This is also what the x86 pause instruction inserted into spin wait loops is meant to solve.\n//   LOOP:\n//       r0 = LOAD(A);\n//       if (!r0) pause; goto LOOP;\n//\n//   In the above spin loop, after a couple of iterations the processor will fill the pipeline with speculated cmp and load instructions.\n//   x86 will catch a memory order violation if it sees that an external store was done to A and thus must flush the entire\n//   pipeline of all the speculated load A. Pause instruction tells the cpu to not do speculative loads so that the pipeline is not\n//   filled with all said speculative load instructions. This ensures we do not incur the costly pipeline flushes from memory order\n//   violations which are likely to occur in tight spin wait loops. This also allows other threads on the same physical core to use the\n//   core's resources better since our speculative nature won't be hogging it all.\n//\n//   A LDST control dependency is a true dependency in which the cpu cannot make a store visible to the system and other cpus until it\n//   knows its prediction is correct. Thus a LDST ordering is guaranteed and can be always relied upon as in the following example.\n//\n//   r0 = LOAD(A);\n//   if (r0)\n//       STORE(B, 1);\n//\n//   The fun part comes in with how does the compiler actually break all of this.\n//   First is that if the compiler can ensure that the value of A in the LDST example is always not zero, then it is always within its\n//   rights to completely remove the if statement which would lend us with no control dependency.\n//\n//   Things get more fun when we deal with conditionals with else and else if statements where the compiler might be able to employ\n//   invariant code motion optimizations. Take this example.\n//\n//   r0 = LOAD(A);\n//   r1 = LOAD(B);\n//   if (r0)\n//       STORE(B, 1);\n//       /* MORE CODE */\n//   else if (r1)\n//       STORE(B, 1);\n//       /* MORE CODE */\n//   else\n//       STORE(B, 1);\n//       /* MORE CODE */\n//\n//   If we were trying to be smart and entirely rely on the control dependency to ensure order, ya well just don't the compiler\n//   is always smarter. The compiler is well within its rights to move all the STORE(B, 1) up and above all the conditionals breaking\n//   our reliance on the LDST control dependency.\n//\n//   Things can get even more complicated especially in C++ when values may come from constexpr, inline, inline constexpr, static const, etc,\n//   variables and thus the compiler will do all sorts of transformations to reduce, remove, augment and change all your conditional code since\n//   it knows the values of the expressions or even parts of it at compile time. Even more aggressive optimizations like LTO might break code that was being cautious.\n//   Even adding simple short circuiting logic or your classic likely/unlikely macros can alter conditionals in ways you didn't expect.\n//   In short know enough about control dependencies to know not to ever use them.\n//\n//   ******** Multi-Copy Store Atomicity && Barrier Cumulativity ********\n//\n//   Single-Copy Store Atomicity: All stores must become visible to all cores in the system at the same time.\n//\n//   Multi-Copy Store Atomicity : This means a cpu sees its own stores before they become visible to other cpus, by forwarding them from the store buffer,\n//                                but a store becomes visible to all other cpus at the same time when flushed from the store buffer.\n//\n//   Non-Atomic Store Atomicity : A store becomes visible to different cpus at different times.\n//\n//   Those are the above variations of Store Atomicity. Most processors have Non-Atomic Store Atomicity and thus you must program to that lowest common denominator.\n//   We can use barriers, with some caveats, to restore Multi-Copy Store Atomicity to a Non-Atomic system though we need to define a new granular definition for\n//   memory barriers to define this behaviour. Simple LDLD/LDST/STST/STLD definition is not enough to categorize memory barriers at this level. Let's start off\n//   with a simple example that breaks under a Non-Atomic Store Atomicity system and what potential hardware features allow this behaviour to be observed.\n//\n//   NOTE: For all the below examples we assume no compile reordering and that the processor also executes the instructions with no local reorderings to make the examples simpler,\n//         to only show off the effects of Multi-Copy Store Atomicity. This is why we don't add any address dependencies, or mark explicit LDLD/LDST memory barriers.\n//         Thus you may assume all LDLD and LDST pairs have an address dependency between them, so that they are not reordered by the compiler or the local cpu.\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Write-To-Read Causality, WRC, Litmus Test\n//   ---------------------------------------------------------------------------------------------------------\n//   Initial State:\n//   X = 0; Y = 0;\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                          | Thread 2\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(X, 1)              | r0 = LOAD(X)                      | r1 = LOAD(Y)\n//                            | STORE(Y, r0)                      | r2 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 1 && r2 = 0\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   Let's go over this example in detail and whether the outcome shown above can be observed. In this example Thread 0 stores 1 into X. If Thread 1 observes the write to X,\n//   it stores the observed value into Y. Thread 2 loads from Y then X. This means if the load from Y returns 1, then we intuitively know the global store order\n//   was 1 to X and then 1 to Y. So is it possible then that the load from X in Thread 2 can return 0 in that case? Under a Multi-Copy Store Atomicity system, that would be\n//   impossible because once 1 was stored to X all cpus see that store so if Thread 2 saw the store to Y which can only happen after the store to X was observed, then\n//   Thread 2 must also have observed the store to X and return 1. As you may well have figured out, it is possible under a Non-Atomic Store Atomicity system to still\n//   observe the load from X returning 0 even if the above load from Y returned 1 in Thread 2. This completely breaks our intuition of causality. Let's now understand what hardware may cause this.\n//\n//   This is possible on cpus that have Simultaneous Multi-Threading, SMT or HyperThreading in Intel parlance, which share resources such as store buffers or L1 cache.\n//   We are accustomed to the x86 way of SMT where each logical core shares Execution Units on the physical core but each logical core has their own statically partitioned\n//   cache and store buffer that is not visible to the other cpus. It is possible on cpus like ARMv7 or POWER, POWER9 supports 4 and even 8 threads per physical core, so\n//   to save on die space though yet enable this large number of threads per physical core it is common for these logical cores to all use the same store buffer or L1 cache\n//   per physical core on these processors. Let's take the above example and rerun it with this knowledge to get the observed behaviour outlined above.\n//\n//   Assume Thread 0, Thread 1, and Thread 2 run on cpu 0, cpu 1, and cpu 2 respectively. Assume that cpu 0 and cpu 1 are two logical cores on the same physical core so this processor\n//   has an SMT value of 2. Thread 0 will store 1 into X. This store may be in the store buffer or in the L1 cache that cpu 1 also shares with cpu 0, thus cpu 1 has early access to cpu 0's stores.\n//   Thread 1 loads X which it observed as 1 early and then stores 1 into Y. Thread 2 may see the load from Y returning 1 but now the load from X returning 0 all because cpu 1 got early\n//   access to cpu 0 store due to sharing a L1 cache or store buffer.\n//   We will come back on how to fix this example with the proper memory barriers for the Non-Atomic Store Atomicity systems, but we need to detour first.\n//\n//   We need to take a deeper dive into memory barriers to understand how to restore Multi-Copy Store Atomicity from a Non-Atomic Store Atomicity system.\n//   Let's start with a motivating example and we will be using the POWER architecture throughout this example because it encompasses all the possible observable behaviour.\n//   ARMv7 technically allows Non-Atomic Store Atomicity behaviour but no consumer ARMv7 chip actually observes this behaviour.\n//   ARMv8 reworked its model to specifically say it is a Multi-Copy Store Atomicity system.\n//   POWER is one of the last few popular consumer architectures that are guaranteed to have Non-Atomic Store Atomicity observable behaviour, thus we will be using it for the following examples.\n//\n//   To preface, POWER has two types of memory barriers called lwsync and sync. The following table lists the guarantees provided by TSO, x86, and the lwsync instruction.\n//   The table gives a hint as to why using our previous definition of LDLD/LDST/STST/STLD isn't granular enough to categorize memory barrier instructions.\n//\n//   TSO:                 |       POWER lwsync memory barrier:\n//       LDLD : YES       |                                    LDLD : YES\n//       LDST : YES       |                                    LDST : YES\n//       STST : YES       |                                    STST : YES\n//       STLD : NO        |                                    STLD : NO\n//   A cumulative : YES   |                            A cumulative : YES\n//   B cumulative : YES   |                            B cumulative : YES\n//   IRIW         : YES   |                            IRIW         : NO\n//\n//   The TSO memory model provided by x86 seems to be exactly the same as POWER if we add lwsync memory barrier instructions in between each of the memory instructions.\n//   This provides us the exact same ordering guarantees as the TSO memory model. If we just looked at the 4 permutations of reorderings we would be inclined to assume that\n//   TSO has the exact same ordering as sprinkling lwsync in our code in between every pair of memory instructions. That is not the case because memory barrier causality and cumulativity differ in subtle ways.\n//   In this case they differ by the implicit guarantees from the TSO memory model versus those provided by the POWER lwsync memory barrier.\n//   So the lwsync memory barrier prevents reordering with instructions that have causality but does not prevent reordering with instructions that are completely independent.\n//   Let's dive into these concepts a bit more.\n//\n//   Non-Atomic Store Atomicity architectures are prone to behaviours such as the non-causal outcome of the WRC test above. Architectures such as POWER defines memory barriers to enforce\n//   ordering with respect to memory accesses in remote cpus other than the cpu actually issuing the memory barrier. This is known as memory barrier cumulativity.\n//   How does the memory barrier issued on my cpu affect the view of memory accesses done by remote cpuss.\n//\n//   Cumulative memory barriers are defined as follows - Take your time this part is very non-trivial:\n//   A-Cumulative: We denote group A as the set of memory instructions in this cpu or other cpus that are ordered before the memory barrier in this cpu.\n//                 A-Cumulativity requires that memory instructions from any cpu that have performed prior to a memory load before the memory barrier on this cpu are also members of group A.\n//   B-Cumulative: We denote group B as the set of memory instructions in this cpu or other cpus that are ordered after the memory barrier in this cpu.\n//                 B-Cumulativity requires that memory instructions from any cpu that perform after a load and including the load in that cpu that returns the value of a store in group B are\n//                 also members of group B.\n//   IRIW        : enforces a global ordering even for memory instructions that have no causality. The memory instructions are completely independent.\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   WRC Litmus Test\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                          | Thread 2\n//   ---------------------------------------------------------------------------------------------------------\n//   {i} : STORE(X, 1)        | {ii}  : r0 = LOAD(X)              | {v}  : r1 = LOAD(Y)\n//                            | {iii} : lwsync                    |\n//                            | {iv}  : STORE(Y, r0)              | {vi} : r2 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//   Outcome: r0 = 1 && r1 = 1 && r2 = 1\n//\n//   Group A of {iii} : {i} && {ii}\n//\n//   Group B of {iii} : {iv} && {v} && {vi}\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   Using the WRC test again and inserting a POWER lwsync, don't concern yourself with why the memory barrier was inserted at that spot right now, we now see the distinctions of group A and group B.\n//   It demonstrates the A and B Cumulative nature of the lwsync instruction, {iii}. First group A, initially consists of {ii} and group B initially consists of {iv} from the local cpu that issued the lwsync.\n//   Since {ii} reads from {i} and assume {i} happens before {ii}, by definition of A-Cumulativity {i} is included in group A.\n//   Similarly {v} reads from {iv} and assume {iv} happens before {v}, then {v} is included in group B by definition of B-Cumulativity.\n//   {vi} is also included in group B since it happens after {v} by definition of B-Cumulativity.\n//\n//   WRC litmus test represents a scenario where only a A-Cumulative memory barrier is needed. The lwsync not only provides the needed local LDST memory barrier for the local thread but also ensures\n//   that any write Thread 1 has read from before the memory barrier is kept in order with any write Thread 1 does after the memory barrier as far as any other thread observes.\n//   In other words it ensures that any write that has propagated to Thread 1 before the memory barrier is propagated to any other thread before the second store after the memory barrier in Thread 1\n//   can propagate to other threads in the system. This is exactly the definition of A-Cumulativity and what we need to ensure that causality is maintained in the WRC Litmus Test example.\n//   With that lwsync in place it is now impossible to observe r0 = 1 && r1 = 1 && r2 = 0. The lwsync has restored causal ordering. Let's look at an example that requires B-Cumulativity.\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Example 2 from POWER manual\n//   ---------------------------------------------------------------------------------------------------------\n//   Initial State:\n//   X = 0; Y = 0; Z = 0\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                          | Thread 2\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(X, 1)              | r0 = LOAD(Y)                      | r1 = LOAD(Z)\n//   STORE(Y, 1)              | STORE(Z, r0)                      | r2 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 1 && r2 = 0\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   This example is very similar to WRC except that we kinda extended the Message Passing through an additional shared variable instead.\n//   Think of this as Thread 0 writing some data into X, setting flag Y, Thread 1 waiting for flag Y then writing flag Z, and finally Thread 2 waiting for flag Z before reading the data.\n//   Take a minute to digest the above example and think about where a memory barrier, lwsync, should be placed. Don't peek at the solution below.\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Example 2 from POWER manual\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                          | Thread 2\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(X, 1)              | r0 = LOAD(Y)                      | r1 = LOAD(Z)\n//   lwsync                   |                                   |\n//   STORE(Y, 1)              | STORE(Z, r0)                      | r2 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   First the lwsync provides the needed local STST memory barrier for the local thread, thus the lwsync here ensures that the store to X propagates to Thread 1 before the store to Y.\n//   B-Cumulativity applied to all operations after the memory barrier ensure that the store to X is\n//   kept in order with respect to the store to Z as far as all other threads participating in the dependency chain are concerned. This is the exact definition of B-Cumulativity.\n//   With this one lwsync the outcome outlined above is impossible to observe. If r0 = 1 && r1 = 1 then r2 must be properly observed to be 1.\n//\n//   We know that lwsync only provides A-Cumulativity and B-Cumulativity. Now we will look at examples that have no causality constraints thus we need to grab heavier memory barriers\n//   that ensures in short we will say makes a store become visible to all processors, even those not on the dependency chains. Let's get to the first example.\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Independent Reads of Independent Writes, IRIW, coined by Doug Lea\n//   ---------------------------------------------------------------------------------------------------------\n//   Initial State:\n//   X = 0; Y = 0;\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                       | Thread 2               | Thread 3\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(X, 1)              | r0 = LOAD(X)                   | STORE(Y, 1)            | r2 = LOAD(Y)\n//                            | r1 = LOAD(Y)                   |                        | r3 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 0 && r2 = 1 && r3 = 0\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   The IRIW example above clearly shows that writes can be propagated to different cpus in completely different orders.\n//   Thread 1 sees the store to X but not the store to Y while Thread 3 sees the store to Y but not the store to X, the complete opposite.\n//   Also to the keen eye you may have noticed this example is a slight modification of the Store Buffer example so try to guess where the memory barriers would go.\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Independent Reads of Independent Writes, IRIW, coined by Doug Lea\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                       | Thread 2               | Thread 3\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(X, 1)              | r0 = LOAD(X)                   | STORE(Y, 1)            | r2 = LOAD(Y)\n//                            | sync                           |                        | sync\n//                            | r1 = LOAD(Y)                   |                        | r3 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   To ensure that the above observation is forbidden we need to add a full sync memory barrier on both the reading threads. Think of sync as restoring sequential consistency.\n//   The sync memory barrier ensures that any writes that Thread 1 has read from before the memory barrier are fully propagated to all threads before the reads are satisfied after the memory barrier.\n//   The same can be said for Thread 3. This is why the sync memory barrier is needed because there is no partial causal ordering here or anything that can be considered for our A and  B Cumulativity definitions.\n//   We must ensure that all writes have been propagated to all cpus before proceeding. This gives way to the difference between sync and lwsync with regards to visibility of writes and cumulativity.\n//   sync guarantees that all program-order previous stores must have been propagated to all other cpus before the memory instructions after the memory barrier.\n//   lwsync does not ensure that stores before the memory barrier have actually propagated to any other cpu before memory instructions after the memory barrier, but it will keep stores before and after the\n//   lwsync in order as far as other cpus are concerned that are within the dependency chain.\n//\n//   Fun fact while ARMv7 claims to be Non-Atomic Store Atomicity no mainstream ARM implementation that I have seen has shown cases of Non-Atomic Store Atomicity.\n//   It's allowed by the ARMv7 memory model and thus you have to program to that. ARMv8 changes this and states that it has Multi-Copy Store Atomicity.\n//\n//   ******** Release-Acquire Semantics ********\n//\n//   The most useful and common cases where Release-Acquire Semantics are used in every day code is in message passing and mutexes. Let's get onto some examples and the C++ definition of Release-Acquire.\n//\n//   ACQUIRE:\n//   An Acquire operation is a one-way memory barrier whereby all loads and stores after the acquire operation cannot move up and above the acquire operation.\n//   Loads and stores before the acquire operation can move down past the acquire operation. An acquire operation should always be paired with a Release operation on the SAME atomic object.\n//\n//   RELEASE:\n//   A Release operation is a one-way memory barrier whereby all loads and stores before the release operation cannot move down and below the release operation.\n//   Loads and stores after the release operation can move up and above the release operation. A release operation should always be paired with an Acquire operation on the SAME atomic object.\n//\n//   Release-Acquire pair does not create a full memory barrier but it guarantees that all memory instructions before a Release operation on an atomic object M are visible after an Acquire\n//   operation on that same atomic object M. Thus these semantics usually are enough to preclude the need for any other memory barriers.\n//   The synchronization is established only between the threads Releasing and Acquiring the same atomic object M.\n//\n//   ---------------------------------------------------\n//   Critical Section\n//   ---------------------------------------------------\n//   Thread 0                 | Thread 1\n//   ---------------------------------------------------\n//   mtx.lock() - Acquire     | mtx.lock() - Acquire\n//   STORE(X, 1)              | r0 = LOAD(X)\n//   mtx.unlock() - Release   | mtx.unlock() - Release\n//   ---------------------------------------------------\n//\n//   A mutex only requires Release-Acquire semantics to protect the critical section. We do not care if operations above the lock leak into the critical section or that operations below the unlock leak into the\n//   critical section because they are outside the protected region of the lock()/unlock() pair. Release-Acquire semantics does guarantee that everything inside the critical section cannot leak out.\n//   Thus all accesses of all previous critical sections for the mutex are guaranteed to have completed and be visible when the mutex is handed off to the next party due to the Release-Acquire chaining.\n//   This also means that mutexes do not provide or restore Multi-Copy Store Atomicity to any memory instructions outside the mutex, like the IRIW example since it does not emit full memory barriers.\n//\n//   ------------------------------------------------------\n//   Message Passing\n//   ------------------------------------------------------\n//   Thread 0                 | Thread 1\n//   ------------------------------------------------------\n//   STORE(DATA, 1)           | while (!LOAD_ACQUIRE(FLAG))\n//                            |\n//   STORE_RELEASE(FLAG, 1)   | r0 = LOAD(DATA)\n//   ------------------------------------------------------\n//\n//   This is a common message passing idiom that also shows the use of Release-Acquire semantics. It should be obvious by the definitions outlined above why this works.\n//   An Acquire operation attached to a load needs to provide a LDLD and LDST memory barrier according to our definition of acquire. This is provided by default on x86 TSO thus no memory barrier is emitted.\n//   A Release operation attached to a store needs to provide a STST and LDST memory barrier according to our definition of release. This is provided by default on x86 TSO thus no memory barrier is emitted.\n//\n//   A couple of things of note here. One is that by attaching the semantics of a memory model directly to the memory instruction/operation itself we can take advantage of the fact the some processors\n//   already provide guarantees between memory instructions and thus we do not have to emit memory barriers. Another thing of note is that the memory model is directly attached to the operation,\n//   so you must do the Release-Acquire pairing on the SAME object which in this case is the FLAG variable. Doing an Acquire or Release on a separate object has no guarantee to observe an Acquire or Release on a different object.\n//   This better encapsulates the meaning of the code and also allows the processor to potentially do more optimizations since a stand alone memory barrier will order all memory instructions of a given type before and after the barrier.\n//   Where as the memory ordering attached to the load or store tells the processor that it only has to order memory instructions in relation to that specific load or store with the given memory order.\n//\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Release Attached to a Store VS. Standalone Fence\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(DATA, 1)               |  STORE(DATA, 1)\n//                                |  ATOMIC_THREAD_FENCE_RELEASE()\n//   STORE_RELEASE(FLAG, 1)       |  STORE_RELAXED(FLAG, 1)\n//   STORE_RELAXED(VAR, 2)        |  STORE_RELAXED(VAR, 2)\n//   ---------------------------------------------------------------------------------------------------------\n//   ARMv8 Assembly\n//   ---------------------------------------------------------------------------------------------------------\n//   str 1, DATA                  |  str 1, DATA\n//                                |  dmb ish\n//   stlr 1, FLAG                 |  str 1, FLAG\n//   str 2, VAR                   |  str 2, VAR\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   In the above example the release is attached to the FLAG variable, thus synchronization only needs to be guaranteed for that atomic variable.\n//   It is entirely possible for the VAR relaxed store to be reordered above the release store.\n//   In the fence version, since the fence is standalone, there is no notion where the release is meant to be attached to thus the fence must prevent all subsequent relaxed stores\n//   from being reordered above the fence. The fence provides a stronger guarantee whereby now the VAR relaxed store cannot be moved up and above the release operation.\n//   Also notice the ARMv8 assembly is different, the release fence must use the stronger dmb ish barrier instead of the dedicated release store instruction.\n//   We dive more into fences provided by eastl::atomic<T> below.\n//\n//   Release-Acquire semantics also have the property that it must chain through multiple dependencies which is where our knowledge from the previous section comes into play.\n//   Everything on the Release-Acquire dependency chain must be visible to the next hop in the chain.\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Example 2 from POWER manual\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                          | Thread 2\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(X, 1)              | r0 = LOAD_ACQUIRE(Y)              | r1 = LOAD_ACQUIRE(Z)\n//   STORE_RELEASE(Y, 1)      | STORE_RELEASE(Z, r0)              | r2 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   ---------------------------------------------------------------------------------------------------------\n//   Write-To-Read Causality, WRC, Litmus Test\n//   ---------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                          | Thread 2\n//   ---------------------------------------------------------------------------------------------------------\n//   STORE(X, 1)              | r0 = LOAD(X)                      | r1 = LOAD_ACQUIRE(Y)\n//                            | STORE_RELEASE(Y, r0)              | r2 = LOAD(X)\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   You may notice both of these examples from the previous section. We replaced the standalone POWER memory barrier instructions with Release-Acquire semantics attached directly to the operations where we want causality preserved.\n//   We have transformed those examples to use the eastl::atomic<T> memory model.\n//   Take a moment to digest these examples in relation to the definition of Release-Acquire semantics.\n//\n//   The Acquire chain can be satisfied by reading the value from the store release or any later stored headed by that release operation. The following examples will make this clearer.\n//\n//   ------------------------------------------------------\n//   Release Sequence Headed\n//   ------------------------------------------------------\n//   Initial State:\n//   DATA = 0; FLAG = 0;\n//   ------------------------------------------------------\n//   Thread 0                 | Thread 1\n//   ------------------------------------------------------\n//   STORE(DATA, 1)           | r0 = LOAD_ACQUIRE(FLAG)\n//                            |\n//   STORE_RELEASE(FLAG, 1)   | r1 = LOAD(DATA)\n//   STORE_RELAXED(FLAG, 3)   |\n//   ------------------------------------------------------\n//   Observed: r0 = 3 && r1 = 0\n//   ------------------------------------------------------\n//\n//   In the above example we may read the value 3 from FLAG which was not the release store, but it was headed by that release store. Thus we observed a later store and therefore it is still valid to then observe r1 = 1.\n//   The stores to FLAG from the STORE_RELEASE up to but not including the next STORE_RELEASE operation make up the release sequence headed by the first release store operation. Any store on that sequence can be used to enforce\n//   causality on the load acquire.\n//\n//   ******** Consume is currently not useful ********\n//\n//   Consume is a weaker form of an acquire barrier and creates the Release-Consume barrier pairing.\n//   Consume states that a load operation on an atomic object M cannot allow any loads or stores dependent on the value loaded by the operation to be reordered before the operation.\n//   To understand consume we must first understand dependent loads.\n//   You might encounter this being called a data dependency or an address dependency in some literature.\n//\n//   --------------------------------------------------------------\n//   Address Dependency\n//   --------------------------------------------------------------\n//   Initial State:\n//   DATA = 0; PTR = nullptr;\n//   --------------------------------------------------------------\n//   Thread 0                 | Thread 1\n//   --------------------------------------------------------------\n//   STORE(DATA, 1)           | r0 = LOAD(PTR) - typeof(r0) = int*\n//                            |\n//   STORE(PTR, &DATA)        | r1 = LOAD(r0)  - typeof(r1) = int\n//   --------------------------------------------------------------\n//\n//   There is a clear dependency here where we cannot load from *int until we actually read the int* from memory.\n//   Now it is possible for Thread 1's load from *ptr to be observed before the store to DATA, therefore it can lead to r0 = &DATA && r1 = 0.\n//   While this is a failure of causality, it is allowed by some cpus such as the DEC Alpha and I believe Blackfin as well.\n//   Thus a data dependency memory barrier must be inserted between the data dependent loads in Thread 1. Note that this would equate to a nop on any processor other than the DEC Alpha.\n//\n//   This can occur for a variety of hardware reasons. We learned about invalidation queues. It is possible that the invalidation for DATA gets buffered in Thread 1. DEC Alpha allows the Thread 1\n//   load from PTR to continue without marking the entries in its invalidation queue. Thus the subsequent load is allowed to return the old cached value of DATA instead of waiting for the\n//   marked entries in the invalidation queue to be processed. It is a design decision of the processor not to do proper dependency tracking here and instead relying on the programmer to insert memory barriers.\n//\n//   This data dependent ordering guarantee is useful because in places where we were using an Acquire memory barrier we can reduce it to this Consume memory barrier without any hardware barriers actually emitted on every modern processor.\n//   Let's take the above example, translate it to Acquire and Consume memory barriers and then translate it to the ARMv7 assembly and see the difference.\n//\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   Address Dependency - Release-Acquire                                Address Dependency - Release-Acquire - ARMv7 Assembly\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   Thread 0                  | Thread 1                                Thread 0                  | Thread 1\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   STORE(DATA, 1)            | r0 = LOAD_ACQUIRE(PTR)                  STORE(DATA, 1)            | r0 = LOAD(PTR)\n//                             |                                         dmb ish                   | dmb ish\n//   STORE_RELEASE(PTR, &DATA) | r1 = LOAD(r0)                           STORE(PTR, &DATA)         | r1 = LOAD(r0)\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//\n//   To get Release-Acquire semantics on ARMv7 we need to emit dmb ish; memory barriers.\n//\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   Address Dependency - Release-Consume                                Address Dependency - Release-Consume - ARMv7 Assembly\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   Thread 0                  | Thread 1                                Thread 0                  | Thread 1\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   STORE(DATA, 1)            | r0 = LOAD_CONSUME(PTR)                  STORE(DATA, 1)            | r0 = LOAD(PTR)\n//                             |                                         dmb ish                   |\n//   STORE_RELEASE(PTR, &DATA) | r1 = LOAD(r0)                           STORE(PTR, &DATA)         | r1 = LOAD(r0)\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//\n//   Data Dependencies can not only be created by read-after-write/RAW on registers, but also by RAW on memory locations too. Let's look at some more elaborate examples.\n//\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   Address Dependency on Registers - Release-Consume - ARMv7               Address Dependency on Memory - Release-Consume - ARMv7\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   Thread 0                  | Thread 1                                Thread 0                  | Thread 1\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//   STORE(DATA, 1)            | r0 = LOAD(PTR)                          STORE(DATA, 1)            | r0 = LOAD(PTR)\n//                             | r1 = r0 + 0                                                       | STORE(TEMP, r0)\n//   dmb ish                   | r2 = r1 - 0                             dmb ish                   | r1 = LOAD(TEMP)\n//   STORE(PTR, &DATA)         | r3 = LOAD(r2)                           STORE(PTR, &DATA)         | r2 = LOAD(r1)\n//   ---------------------------------------------------------------     ---------------------------------------------------------------\n//\n//   The above shows a more elaborate example of how data dependent dependencies flow through RAW chains either through memory or through registers.\n//\n//   Notice by identifying that this is a data dependent operation and asking for a consume ordering, we can completely eliminate the memory barrier on Thread 1 since we know ARMv7 does not reorder data dependent loads. Neat.\n//   Unfortunately every major compiler upgrades a consume to an acquire ordering, because the consume ordering in the standard has a stronger guarantee and requires the compiler to do complicated dependency tracking.\n//   Dependency chains in source code must be mapped to dependency chains at the machine instruction level until a std::kill_dependency in the source code.\n//\n//   ----------------------------------------------------------------\n//   Non-Address Dependency && Multiple Chains\n//   ----------------------------------------------------------------\n//   Initial State:\n//   std::atomic<int> FLAG; int DATA[1] = 0;\n//   ----------------------------------------------------------------\n//   Thread 0                   | Thread 1\n//   ----------------------------------------------------------------\n//   STORE(DATA[0], 1)          | int f = LOAD_CONSUME(FLAG)\n//                              | int x = f\n//                              | if (x) return Func(x);\n//                              |\n//   STORE_RELEASE(FLAG, 1)     | Func(int y) return DATA[y - y]\n//   ----------------------------------------------------------------\n//\n//   This example is really concise but there is a lot going on. Let's digest it.\n//   First is that the standard allows consume ordering even on what we will call not true machine level dependencies like a ptr load and then a load from that ptr as shown in the previous examples.\n//   Here the dependency is between two ints, and the dependency chain on Thread 1 is as follows. f -> x -> y -> DATA[y - y]. The standard requires that source code dependencies on the loaded value\n//   from consume flow thru assignments and even thru function calls. Also notice we added a dependency on the dereference of DATA with the value loaded from consume which while it does nothing actually abides by the standard\n//   by enforcing a source code data dependent load on the consume operation. You may see this referred to as artificial data dependencies in other texts.\n//   If we assume the compiler is able to track all these dependencies, the question is how do we enforce these dependencies at the machine instruction level. Let's go back to our ptr dependent load example.\n//\n//   ----------------------------------------------------------------\n//   addi r0, pc, offset;\n//   ldr r1, 0(r0);\n//   ldr r2, 0(r1);\n//   ----------------------------------------------------------------\n//\n//   The above pseudo assembly does a pc relative calculation to find the address of ptr. We then load ptr and then continue the dependency chain by loading the int from the loaded ptr.\n//   Thus r0 has type of int**, which we use to load r1 an int* which we use to load our final value of r2 which is the int.\n//   The key observation here is that most instructions provided by most architectures only allow moving from a base register + offset into a destination register.\n//   This allows for trivial capturing of data dependent loads through pointers. But how do we capture the data dependency of DATA[y - y]. We would need something like this.\n//\n//   ----------------------------------------------------------------\n//   sub r1, r0, r0; // Assume r0 holds y from the Consume Operation\n//   add r3, r1, r2; // Assume r2 holds the address of DATA[0]\n//   ldr r4, 0(r3);\n//   ----------------------------------------------------------------\n//\n//   We cannot use two registers as both arguments to the load instruction. Thus to accomplish this you noticed we had to add indirect data dependencies through registers to compute the final address from the consume\n//   load of y and then load from the final computed address. The compiler would have to recognize all these dependencies and enforce that they be maintained in the generated assembly.\n//   The compiler must ensure the entire syntactic, source code, data-dependency chain is enforced in the generated assembly, no matter how long such chain may be.\n//   Because of this and other issues, every major compiler unilaterally promotes consume to an acquire operation across the board. Read reference [15] for more information.\n//   This completely removes the actual usefulness of consume for the pointer dependent case which is used quite heavily in concurrent read heavy data structures where updates are published via pointer swaps.\n//\n//   ******** read_depends use case - Release-ReadDepends Semantics ********\n//\n//   eastl::atomic<T> provides a weaker read_depends operation that only encapsulates the pointer dependency case above. Loading from a pointer and then loading the value from the loaded pointer.\n//   The read_depends operation can be used on loads from only an eastl::atomic<T*> type. The return pointer of the load must and can only be used to then further load values. And that is it.\n//   If you are unsure, upgrade this load to an acquire operation.\n//\n//   MyStruct* ptr = gAtomicPtr.load(memory_order_read_depends);\n//   int a = ptr->a;\n//   int b = ptr->b;\n//   return a + b;\n//\n//   The loads from ptr after the gAtomicPtr load ensure that the correct values of a and b are observed. This pairs with a Release operation on the writer side by releasing gAtomicPtr.\n//\n//\n//   As said above the returned pointer from a .load(memory_order_read_depends) can only be used to then further load values.\n//   Dereferencing(*) and Arrow Dereferencing(->) are valid operations on return values from .load(memory_order_read_depends).\n//\n//   MyStruct* ptr = gAtomicPtr.load(memory_order_read_depends);\n//   int a = ptr->a;  - VALID\n//   int a = *ptr;    - VALID\n//\n//   Since dereferencing is just indexing via some offset from some base address, this also means addition and subtraction of constants is ok.\n//\n//   int* ptr = gAtomicPtr.load(memory_order_read_depends);\n//   int a = *(ptr + 1)  - VALID\n//   int a = *(ptr - 1)  - VALID\n//\n//   Casts also work correctly since casting is just offsetting a pointer depending on the inheritance hierarchy or if using intrusive containers.\n//\n//   ReadDependsIntrusive** intrusivePtr = gAtomicPtr.load(memory_order_read_depends);\n//   ReadDependsIntrusive* ptr = ((ReadDependsIntrusive*)(((char*)intrusivePtr) - offsetof(ReadDependsIntrusive, next)));\n//\n//   Base* basePtr = gAtomicPtr.load(memory_order_read_depends);\n//   Dervied* derivedPtr = static_cast<Derived*>(basePtr);\n//\n//   Both of the above castings from the result of the load are valid for this memory order.\n//\n//   You can reinterpret_cast the returned pointer value to a uintptr_t to set bits, clear bits, or xor bits but the pointer must be casted back before doing anything else.\n//\n//   int* ptr = gAtomicPtr.load(memory_order_read_depends);\n//   ptr = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(ptr) & ~3);\n//\n//   Do not use any equality or relational operator (==, !=, >, <, >=, <=) results in the computation of offsets before dereferencing.\n//   As we learned above in the Control Dependencies section, CPUs will not order Load-Load Control Dependencies. Relational and equality operators are often compiled using branches.\n//   It doesn't have to be compiled to branched, condition instructions could be used. Or some architectures provide comparison instructions such as set less than which do not need\n//   branches when using the result of the relational operator in arithmetic statements. Then again short circuiting may need to introduct branches since C++ guarantees the\n//   rest of the expression must not be evaluated.\n//   The following odd code is forbidden.\n//\n//   int* ptr = gAtomicPtr.load(memory_order_read_depends);\n//   int* ptr2 = ptr + (ptr >= 0);\n//   int a = *ptr2;\n//\n//   Only equality comparisons against nullptr are allowed. This is becase the compiler cannot assume that the address of the loaded value is some known address and substitute our loaded value.\n//   int* ptr = gAtomicPtr.load(memory_order_read_depends);\n//   if (ptr == nullptr);  - VALID\n//   if (ptr != nullptr);  - VALID\n//\n//   Thus the above sentence that states:\n//   The return pointer of the load must and can only be used to then further load values. And that is it.\n//   must be respected by the programmer. This memory order is an optimization added for efficient read heavy pointer swapping data structures. IF you are unsure, use memory_order_acquire.\n//\n//   ******** Relaxed && eastl::atomic<T> guarantees ********\n//\n//   We saw various ways that compiler barriers do not help us and that we need something more granular to make sure accesses are not mangled by the compiler to be considered atomic.\n//   Ensuring these guarantees like preventing dead-store elimination or the splitting of stores into smaller sub stores is where the C/C++11\n//   standard comes into play to define what it means to operate on an atomic object.\n//   These basic guarantees are provided via new compiler intrinsics on gcc/clang that provide explicit indication to the compiler.\n//   Or on msvc by casting the underlying atomic T to a volatile T*, providing stronger compiler guarantees than the standard requires.\n//   Essentially volatile turns off all possible optimizations on that variable access and ensures all volatile variables cannot be\n//   reordered across sequence points. Again we are not using volatile here to guarantee atomicity, we are using it in its very intended purpose\n//   to tell the compiler it cannot assume anything about the contents of that variable. Now let's dive into the base guarantees of eastl::atomic<T>.\n//\n//   The standard defines the following for all operations on an atomic object M.\n//\n//   Write-Write Coherence:\n//   If an operation A modifies an atomic object M(store), happens before an operation B that modifies M(store), then A shall be earlier than B in the modification order of M.\n//\n//   Read-Read Coherence:\n//   If a value computation A on an atomic object M(load), happens before a value computation B on M(load), and A takes its value from a side effect X on M(from a previous store to M), then the value\n//   computed by B shall either be the value stored by X or some later side effect Y on M, where Y follows X in the modification order of M.\n//\n//   Read-Write Coherence:\n//   If a value computation A on an atomic object M(load), happens before an operation B that modifies M(store), then A shall take its value from a side effect X on M, where X precedes B in the modification\n//   order of M.\n//\n//   Write-Read Coherence:\n//   If a side effect X on an atomic object M(store), happens before a value computation B on M(load), then the evaluation of B must take its value from X or from some side effect Y that follows X in the\n//   modification order of M.\n//\n//   What does all this mean. This is just a pedantic way of saying that the preceding coherence requirements disallow compiler reordering of atomic operations to a single atomic object.\n//   This means all operations must be emitted by the compiler. Stores cannot be dead-store eliminated even if they are the only stores.\n//   Loads cannot have common subexpression elimination performed on them even if they are the only loads.\n//   Loads and Stores to the same atomic object cannot be reordered by the compiler.\n//   Compiler cannot introduce extra loads or stores to the atomic object.\n//   Compiler also cannot reload from an atomic object, it must save and store to a stack slot.\n//   Essentially this provides all the necessary guarantees needed when treating an object as atomic from the compilers point of view.\n//\n//   ******** Same Address LoadLoad Reordering ********\n//\n//   It is expected that same address operations cannot and are not reordered with each other. It is expected that operations to the same address have sequential consistency because\n//   they are to the same address. If you picture a cpu executing instructions, how is it possible to reorder instructions to the same address and yet keep program behaviour the same.\n//   Same Address LoadLoad Reordering is one weakening that is possible to do and keep observed program behaviour for a single-threaded program.\n//   More formally, A and B are two memory instructions onto the same address P, where A is program ordered before B. If A and B are both loads then their order need not be ordered.\n//   If B is a store then it cannot retire the store before A instruction completes. If A is a store and B is a load, then B must get its value forwarded from the store buffer or observe a later store\n//   from the cache. Thus Same Address LDST, STST, STLD cannot be reordered but Same Address LDLD can be reordered.\n//   Intel Itanium and SPARC RMO cpus allow and do Same Address LoadLoad Reordering.\n//   Let's look at an example.\n//\n//   ---------------------------\n//   Same Address LoadLoad\n//   ---------------------------\n//   Initial State:\n//   x = 0;\n//   ---------------------------\n//   Thread 0     |    Thread 1\n//   ---------------------------\n//   STORE(x, 1)  | r0 = LOAD(x)\n//                | r1 = LOAD(x)\n//   ---------------------------\n//   Observed: r0 = 1 && r0 = 0\n//   ---------------------------\n//\n//   Notice in the above example it has appeared as if the two loads from the same address have been reordered. If we first observed the new store of 1, then the next load should not observe a value in the past.\n//   Many programmers, expect same address sequential consistency, all accesses to a single address appear to execute in a sequential order.\n//   Notice this violates the Read-Read Coherence for all atomic objects defined by the std and thus provided by eastl::atomic<T>.\n//\n//   All operations on eastl::atomic<T> irrelevant of the memory ordering of the operation provides Same Address Sequential Consistency since it must abide by the coherence rules above.\n//\n//   ******** eastl::atomic_thread_fence ********\n//\n//   eastl::atomic_thread_fence(relaxed) : Provides no ordering guarantees\n//   eastl::atomic_thread_fence(acquire) : Prevents all prior loads from being reordered with all later loads and stores, LDLD && LDST memory barrier\n//   eastl::atomic_thread_fence(release) : Prevents all prior loads and stores from being reordered with all later stores, STST && LDST memory barrier\n//   eastl::atomic_thread_fence(acq_rel) : Union of acquire and release, LDLD && STST && LDST memory barrier\n//   eastl::atomic_thread_fence(seq_cst) : Full memory barrier that provides a single total order\n//\n//   See Reference [9] and Fence-Fence, Atomic-Fence, Fence-Atomic Synchronization, Atomics Order and Consistency in the C++ std.\n//\n//   ******** Atomic && Fence Synchronization ********\n//\n//   ---------------------------\n//   Fence-Fence Synchronization\n//   ---------------------------\n//   A release fence A synchronizes-with an acquire fence B if there exist operations X and Y on the same atomic object M, such that fence A is sequenced-before operation X and X modifies M,\n//   operation Y is sequenced-before B and Y reads the value written by X.\n//   In this case all non-atomic and relaxed atomic stores that are sequenced-before fence A will happen-before all non-atomic and relaxed atomic loads after fence B.\n//\n//   ----------------------------\n//   Atomic-Fence Synchronization\n//   ----------------------------\n//   An atomic release operation A on atomic object M synchronizes-with an acquire fence B if there exists some atomic operation X on atomic object M, such that X is sequenced-before B and reads\n//   the value written by A.\n//   In this case all non-atomic and relaxed atomic stores that are sequenced-before atomic release operation A will happen-before all non-atomic and relaxed atomic loads after fence B.\n//\n//   ----------------------------\n//   Fence-Atomic Synchronization\n//   ----------------------------\n//   A release fence A synchronizes-with an atomic acquire operation B on an atomic object M if there exists an atomic operation X such that A is sequenced-before X, X modifies M and B reads the\n//   value written by X.\n//   In this case all non-atomic and relaxed atomic stores that are sequenced-before fence A will happen-before all non-atomic and relaxed atomic loads after atomic acquire operation B.\n//\n//   This can be used to add synchronization to a series of several relaxed atomic operations, as in the following trivial example.\n//\n//   ----------------------------------------------------------------------------------------\n//   Initial State:\n//   x = 0;\n//   eastl::atomic<int> y = 0;\n//   z = 0;\n//   eastl::atomic<int> w = 0;\n//   ----------------------------------------------------------------------------------------\n//   Thread 0                                   | Thread 1\n//   ----------------------------------------------------------------------------------------\n//   x = 2                                      | r0 = y.load(memory_order_relaxed);\n//   z = 2                                      | r1 = w.load(memory_order_relaxed);\n//   atomic_thread_fence(memory_order_release); | atomic_thread_fence(memory_order_acquire);\n//   y.store(1, memory_order_relaxed);          | r2 = x\n//   w.store(1, memory_order_relaxed);          | r3 = z\n//   ----------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 1 && r2 = 0 && r3 = 0\n//   ----------------------------------------------------------------------------------------\n//\n//   ******** Atomic vs Standalone Fence ********\n//\n//   A sequentially consistent fence is stronger than a sequentially consistent operation because it is not tied to a specific atomic object.\n//   An atomic fence must provide synchronization with ANY atomic object whereas the ordering on the atomic object itself must only provide\n//   that ordering on that SAME atomic object. Thus this can provide cheaper guarantees on architectures with dependency tracking hardware.\n//   Let's look at a concrete example that will make this all clear.\n//\n//   ----------------------------------------------------------------------------------------\n//   Initial State:\n//   eastl::atomic<int> y = 0;\n//   eastl::atomic<int> z = 0;\n//   ----------------------------------------------------------------------------------------\n//   Thread 0                                   | Thread 1\n//   ----------------------------------------------------------------------------------------\n//   z.store(2, memory_order_relaxed);          | r0 = y.load(memory_order_relaxed);\n//   atomic_thread_fence(memory_order_seq_cst); | atomic_thread_fence(memory_order_seq_cst);\n//   y.store(1, memory_order_relaxed);          | r1 = z.load(memory_order_relaxed);\n//   ----------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 0\n//   ----------------------------------------------------------------------------------------\n//\n//   Here the two sequentially consistent fences synchronize-with each other thus ensuring that if we observe r0 = 1 then we also observe that r1 = 2.\n//   In the above example if we observe r0 = 1 it is impossible to observe r1 = 0.\n//\n//   ----------------------------------------------------------------------------------------\n//   Initial State:\n//   eastl::atomic<int> x = 0;\n//   eastl::atomic<int> y = 0;\n//   eastl::atomic<int> z = 0;\n//   ----------------------------------------------------------------------------------------\n//   Thread 0                                   | Thread 1\n//   ----------------------------------------------------------------------------------------\n//   z.store(2, memory_order_relaxed);          | r0 = y.load(memory_order_relaxed);\n//   x.fetch_add(1, memory_order_seq_cst);      | x.fetch_add(1, memory_order_seq_cst);\n//   y.store(1, memory_order_relaxed);          | r1 = z.load(memory_order_relaxed);\n//   ----------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 0\n//   ----------------------------------------------------------------------------------------\n//\n//   Here the two fetch_add sequentially consistent operations on x synchronize-with each other ensuring that if we observe r0 = 1 then we cannot observer r1 = 0;\n//   The thing to take note here is that we synchronized on the SAME atomic object, that being the atomic object x.\n//   Note that replacing the x.fetch_add() in Thread 1 with a sequentially consistent operation on another atomic object or a sequentially consistent fence can lead to\n//   observing r1 = 0 even if we observe r0 = 1. For example the following code may fail.\n//\n//   ----------------------------------------------------------------------------------------\n//   Initial State:\n//   eastl::atomic<int> x = 0;\n//   eastl::atomic<int> y = 0;\n//   eastl::atomic<int> z = 0;\n//   ----------------------------------------------------------------------------------------\n//   Thread 0                                   | Thread 1\n//   ----------------------------------------------------------------------------------------\n//   z.store(2, memory_order_relaxed);          | r0 = y.load(memory_order_relaxed);\n//                                              | x.fetch_add(1, memory_order_seq_cst);\n//   y.fetch_add(1, memory_order_seq_cst);      | r1 = z.load(memory_order_relaxed);\n//   ----------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 0\n//   ----------------------------------------------------------------------------------------\n//\n//   ----------------------------------------------------------------------------------------\n//   Initial State:\n//   eastl::atomic<int> x = 0;\n//   eastl::atomic<int> y = 0;\n//   eastl::atomic<int> z = 0;\n//   ----------------------------------------------------------------------------------------\n//   Thread 0                                   | Thread 1\n//   ----------------------------------------------------------------------------------------\n//   z.store(2, memory_order_relaxed);          | r0 = y.load(memory_order_relaxed);\n//   x.fetch_add(1, memory_order_seq_cst);      | atomic_thread_fence(memory_order_seq_cst);\n//   y.store(1, memory_order_relaxed);          | r1 = z.load(memory_order_relaxed);\n//   ----------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 0\n//   ----------------------------------------------------------------------------------------\n//\n//   In this example it is entirely possible that we observe r0 = 1 && r1 = 0 even though we have source code causality and sequentially consistent operations.\n//   Observability is tied to the atomic object on which the operation was performed and the thread fence doesn't synchronize-with the fetch_add because\n//   there is no load above the fence that reads the value from the fetch_add.\n//\n//   ******** Sequential Consistency Semantics ********\n//\n//   See section, Order and consistency, in the C++ std and Reference [9].\n//\n//   A load with memory_order_seq_cst performs an acquire operation\n//   A store with memory_order_seq_cst performs a release operation\n//   A RMW with memory_order_seq_cst performs both an acquire and a release operation\n//\n//   All memory_order_seq_cst operations exhibit the below single total order in which all threads observe all modifications in the same order\n//\n//   Paraphrasing, there is a single total order on all memory_order_seq_cst operations, S, such that each sequentially consistent operation B that loads a value from\n//   atomic object M observes either the result of the last sequentially consistent modification A on M, or some modification on M that isn't memory_order_seq_cst.\n//   For atomic modifications A and B on an atomic object M, B occurs after A in the total order of M if:\n//   there is a memory_order_seq_cst fence X whereby A is sequenced before X, and X precedes B,\n//   there is a memory_order_seq_cst fence Y whereby Y is sequenced before B, and A precedes Y,\n//   there are memory_order_seq_cst fences X and Y such that A is sequenced before X, Y is sequenced before B, and X precedes Y.\n//\n//   Let's look at some examples using memory_order_seq_cst.\n//\n//   ------------------------------------------------------------\n//   Store-Buffer\n//   ------------------------------------------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ------------------------------------------------------------\n//   Thread 0                     |    Thread 1\n//   ------------------------------------------------------------\n//   STORE_RELAXED(x, 1)          | STORE_RELAXED(y, 1)\n//   ATOMIC_THREAD_FENCE(SEQ_CST) | ATOMIC_THREAD_FENCE(SEQ_CST)\n//   r0 = LOAD_RELAXED(y)         | r1 = LOAD_RELAXED(x)\n//   ------------------------------------------------------------\n//   Observed: r0 = 0 && r1 = 0\n//   ------------------------------------------------------------\n//\n//   ------------------------------------------------------------\n//   Store-Buffer\n//   ------------------------------------------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ------------------------------------------------------------\n//   Thread 0                     |    Thread 1\n//   ------------------------------------------------------------\n//   STORE_SEQ_CST(x, 1)          | STORE_SEQ_CST(y, 1)\n//   r0 = LOAD_SEQ_CST(y)         | r1 = LOAD_SEQ_CST(x)\n//   ------------------------------------------------------------\n//   Observed: r0 = 0 && r1 = 0\n//   ------------------------------------------------------------\n//\n//   Both solutions above are correct to ensure that the end results cannot lead to both r0 and r1 returning 0. Notice that the second one requires memory_order_seq_cst on both\n//   operations to ensure they are in the total order, S, for all memory_order_seq_cst operations. The other example uses the stronger guarantee provided by a sequentially consistent fence.\n//\n//   ------------------------------------------------------------------------------------------------\n//   Read-To-Write Causality\n//   ------------------------------------------------------------------------------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ------------------------------------------------------------------------------------------------\n//   Thread 0                     |    Thread 1                  |   Thread 2\n//   ------------------------------------------------------------------------------------------------\n//   STORE_SEQ_CST(x, 1)          | r0 = LOAD_RELAXED(x)         | STORE_RELAXED(y, 1)\n//                                | ATOMIC_THREAD_FENCE(SEQ_CST) | ATOMIC_THREAD_FENCE(SEQ_CST)\n//                                | r1 = LOAD_RELAXED(y)         | r2 = LOAD_RELAXED(x)\n//   ------------------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 0 && r2 = 0\n//   ------------------------------------------------------------------------------------------------\n//\n//   You'll notice this example is an in between example of the Store-Buffer and IRIW examples we have seen earlier. The store in Thread 0 needs to be sequentially consistent so it synchronizes with the\n//   thread fence in Thread 1. C++20 due to Reference [9], increased the strength of sequentially consistent fences has been increased to allow for the following.\n//\n//   ------------------------------------------------------------------------------------------------\n//   Read-To-Write Causality - C++20\n//   ------------------------------------------------------------------------------------------------\n//   Initial State:\n//   x = 0; y = 0;\n//   ------------------------------------------------------------------------------------------------\n//   Thread 0                     |    Thread 1                  |   Thread 2\n//   ------------------------------------------------------------------------------------------------\n//   STORE_RELAXED(x, 1)          | r0 = LOAD_RELAXED(x)         | STORE_RELAXED(y, 1)\n//                                | ATOMIC_THREAD_FENCE(SEQ_CST) | ATOMIC_THREAD_FENCE(SEQ_CST)\n//                                | r1 = LOAD_RELAXED(y)         | r2 = LOAD_RELAXED(x)\n//   ------------------------------------------------------------------------------------------------\n//   Observed: r0 = 1 && r1 = 0 && r2 = 0\n//   ------------------------------------------------------------------------------------------------\n//\n//   Notice we were able to turn the store in Thread 0 into a relaxed store and still properly observe either r1 or r2 returning 1.\n//   Note that all implementations of the C++11 standard for every architecture even now allows the C++20 behaviour.\n//   The C++20 standard memory model was brought up to recognize that all current implementations are able to implement them stronger.\n//\n//   ******** False Sharing ********\n//\n//   As we know operations work on the granularity of a cacheline. A RMW operation obviously must have some help from the cache to ensure the entire operation\n//   is seen as one whole unit. Conceptually we can think of this as the cpu's cache taking a lock on the cacheline, the cpu doing the read-modify-write operation on the\n//   locked cacheline, and then releasing the lock on the cacheline. This means during that time any other cpu needing that cacheline must wait for the lock to be released.\n//\n//   If we have two atomic objects doing RMW operations and they are within the same cacheline, they are unintentionally contending and serializing with each other even\n//   though they are two completely separate objects. This gives us the common name to this phenomona called false sharing.\n//   You can cacheline align your structure or the eastl::atomic<T> object to prevent false sharing.\n//\n//   ******** union of eastl::atomic<T> ********\n//\n//   union { eastl::atomic<uint8_t> atomic8; eastl::atomic<uint32_t> atomic32; };\n//\n//   While we know that operations operate at the granularity of a processor's cacheline size and so we may expect that storing and loading\n//   from different width atomic variables at the same address to not cause weird observable behaviour but it may.\n//   Store Buffers allow smaller stores to replace parts of larger loads that are forwarded from a store buffer.\n//   This means if there is 2 bytes of modified data in the store buffer that overlaps with a 4 byte load, the 2 bytes will be forwarded\n//   from the store buffer. This is even documented behaviour of the x86 store buffer in the x86 architecture manual.\n//   This behaviour can cause processors to observe values that have never and will never be visible on the bus to other processors.\n//   The use of a union with eastl::atomic<T> is not wrong but your code must be able to withstand these effects.\n//\n//   Assume everything starts out initially as zero.\n//\n//   -------------------------------------------------------------------------------------------------------\n//   Thread 0                 | Thread 1                          | Thread 2\n//   --------------------------------------------------------------------------------------------------------\n//   cmpxchg 0 -> 0x11111111  | cmpxchg 0x11111111 -> 0x22222222  | mov byte 0x33; mov 4 bytes into register;\n//   ---------------------------------------------------------------------------------------------------------\n//\n//   After all operations complete, the value in memory at that location is, 0x22222233.\n//   It is possible that the 4 byte load in thread 2 actually returns 0x11111133.\n//   Now 0x11111133 is an observed value that no other cpu could observe because it was never globally visible on the data bus.\n//\n//   If the value in memory is 0x22222233 then the first cmpxchg succeeded, then the second cmpxchg succeeded and finally our\n//   byte to memory was stored, yet our load returned 0x11111133. This is because store buffer contents can be forwarded to overlapping loads.\n//   It is possible that the byte store got put in the store buffer. Our load happened after the first cmpxchg with the byte forwarded.\n//   This behaviour is fine as long as your algorithm is able to cope with this kind of store buffer forwarding effects.\n//\n//   Reference [13] is a great read on more about this topic of mixed-size concurrency.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/atomic/atomic.h>\n#include <EASTL/internal/atomic/atomic_standalone.h>\n#include <EASTL/internal/atomic/atomic_flag.h>\n#include <EASTL/internal/atomic/atomic_flag_standalone.h>\n\n\n#endif /* EASTL_ATOMIC_H */\n"
  },
  {
    "path": "include/EASTL/atomic_raw.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n\n#include <EASTL/atomic.h>\n\n// This header provides extension functions for atomically operating on non-atomic types with\n// specific memory order semantics. These functions should be used as a last resort when using\n// the standard atomic types is impossible (for example due to having to cross established API\n// boundaries which can't change).\n//\n// The reason the atomic<T> template should be preferred is that all operations on that type\n// are atomic by design, using the functions provided by this header and mixing atomic and\n// non-atomic accesses leads to potential data races unless done with extreme care. However, as\n// mentioned above sometimes there are circumstances where using atomic<T> is\n// unfeasible. Whenever this API is used, it is recommended to verify that your data access\n// assumptions are consistent and correct by using tools like TSAN (thread sanitizer).\n//\n// For every member function of the form atomic<T>::foo(...) where T is bool, an integral type,\n// or a pointer type, we provide an equivalent free function atomic_raw_foo(T* ptr, ...) which\n// operates on the T pointed to by ptr. Specifically:\n//\n// For bool we provide:\n//    - bool atomic_raw_load(bool*, mem_order)\n//    - void atomic_raw_store(bool*, bool, mem_order)\n//    - bool atomic_raw_exchange(bool*, bool, mem_order)\n//    - bool atomic_raw_compare_exchange_weak/strong(bool*, bool&, bool, mem_ord(, mem_ord))\n//\n// For integral T we provide:\n//    - T atomic_raw_load(T*, mem_order)\n//    - void atomic_raw_store(T*, T, mem_order)\n//    - T atomic_raw_exchange(T*, T, mem_order)\n//    - bool atomic_raw_compare_exchange_weak/strong(T*, T&, T, mem_ord(, mem_ord))\n//    - T atomic_raw_fetch_add/atomic_raw_add_fetch(T*, T, mem_ord)\n//    - T atomic_raw_fetch_sub/atomic_raw_sub_fetch(T*, T, mem_ord)\n//    - T atomic_raw_fetch_and/atomic_raw_and_fetch(T*, T, mem_ord)\n//    - T atomic_raw_fetch_or / atomic_raw_or_fetch(T*, T, mem_ord)\n//    - T atomic_raw_fetch_xor/atomic_raw_xor_fetch(T*, T, mem_ord)\n//\n// For any T we provide:\n//    - T* atomic_raw_load(T**, mem_order)\n//    - void atomic_raw_store(T**, T*, mem_order)\n//    - T* atomic_raw_exchange(T**, T*, mem_order)\n//    - bool atomic_raw_compare_exchange_weak/strong(T**, T*&, T*, mem_ord(, mem_ord))\n//    - T* atomic_raw_fetch_add/atomic_raw_add_fetch(T**, T*, mem_ord)\n//    - T* atomic_raw_fetch_sub/atomic_raw_sub_fetch(T**, T*, mem_ord)\n\n// For pointer types, the fetch operations which look like:\n// T* fetch_add(T** p, ptrdiff_t arg, memory_order)\n// T* add_fetch(T** p, ptrdiff_t arg, memory_order)\n// The supported operations for pointer types are: add, sub.\n\n#define EASTL_ATOMIC_RAW_OPERATION_IMPL(Operation, OpAlias, p, MemOrderMacro, BitCount)      \\\n\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_, Operation), FUNC_WITH_PTR_IMPL) \\\n\t(EASTL_ATOMIC_BASE_OP_JOIN(OpAlias, MemOrderMacro), BitCount, ptr);\n\n#define EASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_WITH_ALIAS_IMPL(Operation, OpAlias, MemOrderMacro) \\\n\tstatic_assert(sizeof(T) <= 8, \"Atomic functions only support up to 64bit types\");                \\\n\tstatic_assert(eastl::is_integral_v<T> || eastl::is_pointer_v<T>,                                 \\\n\t              \"We only support these for integral and pointer types\");                           \\\n\tif constexpr (sizeof(T) == 1)                                                                    \\\n\t{                                                                                                \\\n\t\tEASTL_ATOMIC_RAW_OPERATION_IMPL(Operation, OpAlias, ptr, MemOrderMacro, 8)                   \\\n\t}                                                                                                \\\n\telse if constexpr (sizeof(T) == 2)                                                               \\\n\t{                                                                                                \\\n\t\tEASTL_ATOMIC_RAW_OPERATION_IMPL(Operation, OpAlias, ptr, MemOrderMacro, 16)                  \\\n\t}                                                                                                \\\n\telse if constexpr (sizeof(T) == 4)                                                               \\\n\t{                                                                                                \\\n\t\tEASTL_ATOMIC_RAW_OPERATION_IMPL(Operation, OpAlias, ptr, MemOrderMacro, 32)                  \\\n\t}                                                                                                \\\n\telse if constexpr (sizeof(T) == 8)                                                               \\\n\t{                                                                                                \\\n\t\tEASTL_ATOMIC_RAW_OPERATION_IMPL(Operation, OpAlias, ptr, MemOrderMacro, 64)                  \\\n\t}\n\n#define EASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_IMPL(Operation, MemOrderMacro) \\\n\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_WITH_ALIAS_IMPL(Operation, Operation, MemOrderMacro)\n\n#define EASTL_ATOMIC_RAW_LOAD_TMPL(MemOrderType, MemOrderMacro)              \\\n\ttemplate <typename T>                                                    \\\n\tT atomic_raw_load(T* ptr, MemOrderType)                                  \\\n\t{                                                                        \\\n\t\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_IMPL(LOAD_, MemOrderMacro) \\\n\t}\n\n// Special memory order only provided for pointers\n#define EASTL_ATOMIC_RAW_POINTER_READ_DEPENDS_LOAD_TMPL()                          \\\n\ttemplate <typename T>                                                          \\\n\tT* atomic_raw_load(T** p, internal::memory_order_read_depends_s)               \\\n\t{                                                                              \\\n\t\tstatic_assert(sizeof(T*) == 8 || sizeof(T*) == 4, \"Invalid pointer size\"); \\\n\t\tif constexpr (sizeof(T*) == 4)                                             \\\n\t\t{                                                                          \\\n\t\t\tEASTL_ATOMIC_POINTER_READ_DEPENDS_LOAD_IMPL(32, p)                     \\\n\t\t}                                                                          \\\n\t\tif constexpr (sizeof(T*) == 8)                                             \\\n\t\t{                                                                          \\\n\t\t\tEASTL_ATOMIC_POINTER_READ_DEPENDS_LOAD_IMPL(64, p)                     \\\n\t\t}                                                                          \\\n\t}\n\n#define EASTL_ATOMIC_RAW_STORE_TMPL(MemOrderType, MemOrderMacro)              \\\n\ttemplate <typename T>                                                     \\\n\tvoid atomic_raw_store(T* ptr, T desired, MemOrderType)                    \\\n\t{                                                                         \\\n\t\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_IMPL(STORE_, MemOrderMacro) \\\n\t}\n\n#define EASTL_ATOMIC_RAW_EXCHANGE_TMPL(MemOrderType, MemOrderMacro)              \\\n\ttemplate <typename T>                                                        \\\n\tT atomic_raw_exchange(T* ptr, T desired, MemOrderType)                       \\\n\t{                                                                            \\\n\t\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_IMPL(EXCHANGE_, MemOrderMacro) \\\n\t}\n\n#define EASTL_ATOMIC_RAW_CMPXCHG1_TMPL(MemOrderType, MemOrderMacro)                                         \\\n\ttemplate <typename T>                                                                                   \\\n\tbool atomic_raw_compare_exchange_weak(T* ptr, T& expected, T desired, MemOrderType)                     \\\n\t{                                                                                                       \\\n\t\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_WITH_ALIAS_IMPL(CMPXCHG_, CMPXCHG_WEAK_, MemOrderMacro)   \\\n\t}                                                                                                       \\\n\ttemplate <typename T>                                                                                   \\\n\tbool atomic_raw_compare_exchange_strong(T* ptr, T& expected, T desired, MemOrderType)                   \\\n\t{                                                                                                       \\\n\t\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_WITH_ALIAS_IMPL(CMPXCHG_, CMPXCHG_STRONG_, MemOrderMacro) \\\n\t}\n\n#define EASTL_ATOMIC_RAW_CMPXCHG2_TMPL(MemOrderType1, MemOrderType2, MemOrderMacro)                         \\\n\ttemplate <typename T>                                                                                   \\\n\tbool atomic_raw_compare_exchange_weak(T* ptr, T& expected, T desired, MemOrderType1, MemOrderType2)     \\\n\t{                                                                                                       \\\n\t\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_WITH_ALIAS_IMPL(CMPXCHG_, CMPXCHG_WEAK_, MemOrderMacro)   \\\n\t}                                                                                                       \\\n\ttemplate <typename T>                                                                                   \\\n\tbool atomic_raw_compare_exchange_strong(T* ptr, T& expected, T desired, MemOrderType1, MemOrderType2)   \\\n\t{                                                                                                       \\\n\t\tEASTL_ATOMIC_RAW_SIZE_DEPENDANT_OPERATION_WITH_ALIAS_IMPL(CMPXCHG_, CMPXCHG_STRONG_, MemOrderMacro) \\\n\t}\n\n#define EASTL_ATOMIC_RAW_INTEGRAL_FETCH_ORDER_TMPL(FuncName, MacroFnName, MemOrderType, MemOrderMacro)                 \\\n\ttemplate <typename T>                                                                                              \\\n\tT EA_PREPROCESSOR_JOIN(atomic_raw_, FuncName)(T * p, T arg, MemOrderType)                                          \\\n\t{                                                                                                                  \\\n\t\tstatic_assert(eastl::is_integral_v<T> && !eastl::is_same_v<bool, T>,                                           \\\n\t\t              \"This API is only enabled for integral non boolean types.\");                                     \\\n\t\tif constexpr (sizeof(T) == 1)                                                                                  \\\n\t\t{                                                                                                              \\\n\t\t\tEASTL_ATOMIC_INTEGRAL_FUNC_IMPL(EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(MacroFnName, MemOrderMacro), 8, p, T); \\\n\t\t}                                                                                                              \\\n\t\telse if constexpr (sizeof(T) == 2)                                                                             \\\n\t\t{                                                                                                              \\\n\t\t\tEASTL_ATOMIC_INTEGRAL_FUNC_IMPL(EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(MacroFnName, MemOrderMacro), 16, p,    \\\n\t\t\t                                T);                                                                        \\\n\t\t}                                                                                                              \\\n\t\telse if constexpr (sizeof(T) == 4)                                                                             \\\n\t\t{                                                                                                              \\\n\t\t\tEASTL_ATOMIC_INTEGRAL_FUNC_IMPL(EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(MacroFnName, MemOrderMacro), 32, p,    \\\n\t\t\t                                T);                                                                        \\\n\t\t}                                                                                                              \\\n\t\telse if constexpr (sizeof(T) == 8)                                                                             \\\n\t\t{                                                                                                              \\\n\t\t\tEASTL_ATOMIC_INTEGRAL_FUNC_IMPL(EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(MacroFnName, MemOrderMacro), 64, p,    \\\n\t\t\t                                T);                                                                        \\\n\t\t}                                                                                                              \\\n\t}\n\n#define EASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(FuncName, MacroFnName)                                          \\\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_relaxed_s, RELAXED_) \\\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_acquire_s, ACQUIRE_) \\\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_release_s, RELEASE_) \\\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_acq_rel_s, ACQ_REL_) \\\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_seq_cst_s, SEQ_CST_)\n\n// Ptr version of the fetch functions.\n#define EASTL_ATOMIC_RAW_POINTER_FETCH_FUNC_IMPL(FetchOp, BitCount, ptr)                     \\\n\tusing ptr_integral_type = EA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(int, BitCount), _t); \\\n\tEASTL_ATOMIC_STATIC_ASSERT_TYPE_IS_OBJECT(T);                                            \\\n\tEASTL_ATOMIC_POINTER_FUNC_IMPL(FetchOp, BitCount, ptr);\n\n#define EASTL_ATOMIC_RAW_PTR_FETCH_ORDER_TMPL(FuncName, MacroFnName, MemOrderType, MemOrderMacro)                    \\\n\ttemplate <typename T>                                                                                            \\\n\tT* EA_PREPROCESSOR_JOIN(atomic_raw_, FuncName)(T * *p, ptrdiff_t arg, MemOrderType)                              \\\n\t{                                                                                                                \\\n\t\tif constexpr (sizeof(T*) == 4)                                                                               \\\n\t\t{                                                                                                            \\\n\t\t\tEASTL_ATOMIC_RAW_POINTER_FETCH_FUNC_IMPL(EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(MacroFnName, MemOrderMacro), \\\n\t\t\t                                         32, p)                                                          \\\n\t\t}                                                                                                            \\\n\t\telse if constexpr (sizeof(T*) == 8)                                                                          \\\n\t\t{                                                                                                            \\\n\t\t\tEASTL_ATOMIC_RAW_POINTER_FETCH_FUNC_IMPL(EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(MacroFnName, MemOrderMacro), \\\n\t\t\t                                         64, p)                                                          \\\n\t\t}                                                                                                            \\\n\t}\n\n#define EASTL_ATOMIC_RAW_PTR_FETCH_FUNC_TMPL(FuncName, MacroFnName)                                          \\\n\tEASTL_ATOMIC_RAW_PTR_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_relaxed_s, RELAXED_) \\\n\tEASTL_ATOMIC_RAW_PTR_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_acquire_s, ACQUIRE_) \\\n\tEASTL_ATOMIC_RAW_PTR_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_release_s, RELEASE_) \\\n\tEASTL_ATOMIC_RAW_PTR_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_acq_rel_s, ACQ_REL_) \\\n\tEASTL_ATOMIC_RAW_PTR_FETCH_ORDER_TMPL(FuncName, MacroFnName, internal::memory_order_seq_cst_s, SEQ_CST_)\n\nnamespace eastl\n{\n\tEASTL_ATOMIC_RAW_LOAD_TMPL(internal::memory_order_relaxed_s, RELAXED_)\n\tEASTL_ATOMIC_RAW_LOAD_TMPL(internal::memory_order_acquire_s, ACQUIRE_)\n\tEASTL_ATOMIC_RAW_LOAD_TMPL(internal::memory_order_seq_cst_s, SEQ_CST_)\n\n\t// Special memory order for pointers\n\tEASTL_ATOMIC_RAW_POINTER_READ_DEPENDS_LOAD_TMPL()\n\n\tEASTL_ATOMIC_RAW_STORE_TMPL(internal::memory_order_relaxed_s, RELAXED_)\n\tEASTL_ATOMIC_RAW_STORE_TMPL(internal::memory_order_release_s, RELEASE_)\n\tEASTL_ATOMIC_RAW_STORE_TMPL(internal::memory_order_seq_cst_s, SEQ_CST_)\n\n\tEASTL_ATOMIC_RAW_EXCHANGE_TMPL(internal::memory_order_relaxed_s, RELAXED_)\n\tEASTL_ATOMIC_RAW_EXCHANGE_TMPL(internal::memory_order_acquire_s, ACQUIRE_)\n\tEASTL_ATOMIC_RAW_EXCHANGE_TMPL(internal::memory_order_release_s, RELEASE_)\n\tEASTL_ATOMIC_RAW_EXCHANGE_TMPL(internal::memory_order_acq_rel_s, ACQ_REL_)\n\tEASTL_ATOMIC_RAW_EXCHANGE_TMPL(internal::memory_order_seq_cst_s, SEQ_CST_)\n\n\tEASTL_ATOMIC_RAW_CMPXCHG1_TMPL(internal::memory_order_relaxed_s, RELAXED_)\n\tEASTL_ATOMIC_RAW_CMPXCHG1_TMPL(internal::memory_order_acquire_s, ACQUIRE_)\n\tEASTL_ATOMIC_RAW_CMPXCHG1_TMPL(internal::memory_order_release_s, RELEASE_)\n\tEASTL_ATOMIC_RAW_CMPXCHG1_TMPL(internal::memory_order_acq_rel_s, ACQ_REL_)\n\tEASTL_ATOMIC_RAW_CMPXCHG1_TMPL(internal::memory_order_seq_cst_s, SEQ_CST_)\n\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_relaxed_s, internal::memory_order_relaxed_s, RELAXED_RELAXED_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_acquire_s, internal::memory_order_relaxed_s, ACQUIRE_RELAXED_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_acquire_s, internal::memory_order_acquire_s, ACQUIRE_ACQUIRE_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_release_s, internal::memory_order_relaxed_s, RELEASE_RELAXED_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_acq_rel_s, internal::memory_order_relaxed_s, ACQ_REL_RELAXED_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_acq_rel_s, internal::memory_order_acquire_s, ACQ_REL_ACQUIRE_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_seq_cst_s, internal::memory_order_relaxed_s, SEQ_CST_RELAXED_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_seq_cst_s, internal::memory_order_acquire_s, SEQ_CST_ACQUIRE_)\n\tEASTL_ATOMIC_RAW_CMPXCHG2_TMPL(internal::memory_order_seq_cst_s, internal::memory_order_seq_cst_s, SEQ_CST_SEQ_CST_)\n\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(fetch_add, FETCH_ADD_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(add_fetch, ADD_FETCH_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(fetch_sub, FETCH_SUB_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(sub_fetch, SUB_FETCH_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(fetch_and, FETCH_AND_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(and_fetch, AND_FETCH_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(fetch_or, FETCH_OR_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(or_fetch, OR_FETCH_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(fetch_xor, FETCH_XOR_)\n\tEASTL_ATOMIC_RAW_INTEGRAL_FETCH_FUNC_TMPL(xor_fetch, XOR_FETCH_)\n\n\tEASTL_ATOMIC_RAW_PTR_FETCH_FUNC_TMPL(fetch_add, FETCH_ADD_)\n\tEASTL_ATOMIC_RAW_PTR_FETCH_FUNC_TMPL(add_fetch, ADD_FETCH_)\n\tEASTL_ATOMIC_RAW_PTR_FETCH_FUNC_TMPL(fetch_sub, FETCH_SUB_)\n\tEASTL_ATOMIC_RAW_PTR_FETCH_FUNC_TMPL(sub_fetch, SUB_FETCH_)\n} // namespace eastl\n"
  },
  {
    "path": "include/EASTL/bit.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_BIT_H\n#define EASTL_BIT_H\n\n#include <EASTL/internal/config.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/memory_base.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/numeric_limits.h>\n#include <string.h> // memcpy\n\n#if defined(EA_COMPILER_MSVC) && !defined(__clang__)\n#include <intrin.h>\n#endif\n\nnamespace eastl\n{\n\t// eastl::bit_cast\n\t// Obtains a value of type To by reinterpreting the object representation of 'from'.\n\t// Every bit in the value representation of the returned To object is equal to the\n\t// corresponding bit in the object representation of 'from'.\n\t//\n\t// In order for bit_cast to be constexpr, the compiler needs to explicitly support\n\t// it by providing the __builtin_bit_cast builtin. If that builtin is not available,\n\t// then we memcpy into aligned storage at runtime and return that instead.\n\t//\n\t// Both types To and From must be equal in size, and must be trivially copyable.\n\n\t#if defined(EASTL_CONSTEXPR_BIT_CAST_SUPPORTED) && EASTL_CONSTEXPR_BIT_CAST_SUPPORTED\n\n\t\ttemplate<typename To, typename From,\n\t\t\ttypename = eastl::enable_if_t<\n\t\t\t\tsizeof(To) == sizeof(From)\n\t\t\t\t&& eastl::is_trivially_copyable<To>::value\n\t\t\t\t&& eastl::is_trivially_copyable<From>::value\n\t\t\t>\n\t\t>\n\t\tconstexpr To bit_cast(const From& from) noexcept\n\t\t{\n\t\t\treturn __builtin_bit_cast(To, from);\n\t\t}\n\n\t#else\n\n\t\ttemplate<typename To, typename From,\n\t\t\ttypename = eastl::enable_if_t<\n\t\t\t\tsizeof(To) == sizeof(From)\n\t\t\t\t&& eastl::is_trivially_copyable<To>::value\n\t\t\t\t&& eastl::is_trivially_copyable<From>::value\n\t\t\t>\n\t\t>\n\t\tinline To bit_cast(const From& from) noexcept\n\t\t{\n\t\t\ttypename eastl::aligned_storage<sizeof(To), alignof(To)>::type to;\n\t\t\t::memcpy(eastl::addressof(to), eastl::addressof(from), sizeof(To));\n\t\t\treturn reinterpret_cast<To&>(to);\n\t\t}\n\n\t#endif // EASTL_CONSTEXPR_BIT_CAST_SUPPORTED\n\nnamespace internal\n{\n\nconstexpr int countl_zero64(uint64_t x) noexcept\n{\n\tif (x)\n\t{\n\t\tint n = 0;\n\t\tif (x & UINT64_C(0xFFFFFFFF00000000))\n\t\t{\n\t\t\tn += 32;\n\t\t\tx >>= 32;\n\t\t}\n\t\tif (x & 0xFFFF0000)\n\t\t{\n\t\t\tn += 16;\n\t\t\tx >>= 16;\n\t\t}\n\t\tif (x & 0xFFFFFF00)\n\t\t{\n\t\t\tn += 8;\n\t\t\tx >>= 8;\n\t\t}\n\t\tif (x & 0xFFFFFFF0)\n\t\t{\n\t\t\tn += 4;\n\t\t\tx >>= 4;\n\t\t}\n\t\tif (x & 0xFFFFFFFC)\n\t\t{\n\t\t\tn += 2;\n\t\t\tx >>= 2;\n\t\t}\n\t\tif (x & 0xFFFFFFFE)\n\t\t{\n\t\t\tn += 1;\n\t\t}\n\t\treturn 63 - n;\n\t}\n\treturn 64;\n}\n\n// Count leading zeroes in an integer.\n//\n// todo: consolidate with EA::StdC::CountLeading0Bits() and bitset's GetLastBit() + 1.\n// this implementation has these improvements:\n//  - has overloads for all unsigned integral types. CountLeading0Bits() may not compile with ambiguous overloads because it doesn't match all unsigned integral types.\n//  - supports 128 bit types.\n//  - is noexcept.\n//  - is constexpr, if available.\n#if defined(EA_COMPILER_MSVC) && !defined(__clang__)\n\n// MSVC overloads are not constexpr because _BitScanReverse is not constexpr.\ninline int countl_zero(unsigned char x) noexcept\n{\n\tunsigned long index;\n\treturn _BitScanReverse(&index, static_cast<unsigned long>(x)) ? (sizeof(unsigned char) * CHAR_BIT - 1 - index) : (sizeof(unsigned char) * CHAR_BIT);\n}\n\ninline int countl_zero(unsigned short x) noexcept\n{\n\tunsigned long index;\n\treturn _BitScanReverse(&index, static_cast<unsigned long>(x)) ? (sizeof(unsigned short) * CHAR_BIT - 1 - index) : (sizeof(unsigned short) * CHAR_BIT);\n}\n\ninline int countl_zero(unsigned int x) noexcept\n{\n\tunsigned long index;\n\treturn _BitScanReverse(&index, static_cast<unsigned long>(x)) ? (sizeof(unsigned int) * CHAR_BIT - 1 - index) : (sizeof(unsigned int) * CHAR_BIT);\n}\n\ninline int countl_zero(unsigned long x) noexcept\n{\n\tunsigned long index;\n\treturn _BitScanReverse(&index, x) ? (sizeof(unsigned long) * CHAR_BIT - 1 - index) : (sizeof(unsigned long) * CHAR_BIT);\n}\n\n#if (EA_PLATFORM_PTR_SIZE == 8)\ninline int countl_zero(unsigned long long x) noexcept\n{\n\tunsigned long index;\n\treturn _BitScanReverse64(&index, x) ? (sizeof(unsigned long long) * CHAR_BIT - 1 - index) : (sizeof(unsigned long long) * CHAR_BIT);\n}\n#else\ninline int countl_zero(unsigned long long x) noexcept\n{\n\treturn countl_zero64(static_cast<uint64_t>(x));\n}\n#endif\n\n#elif defined(__GNUC__) || defined(__clang__)\n// __builtin_clz\nconstexpr inline int countl_zero(unsigned char x) noexcept\n{\n\tconstexpr auto diff = eastl::numeric_limits<unsigned int>::digits - eastl::numeric_limits<unsigned char>::digits;\n\treturn x ? (__builtin_clz(static_cast<unsigned int>(x)) - diff) : (sizeof(unsigned char) * CHAR_BIT);\n}\nconstexpr inline int countl_zero(unsigned short x) noexcept\n{\n\tconstexpr auto diff = eastl::numeric_limits<unsigned int>::digits - eastl::numeric_limits<unsigned short>::digits;\n\treturn x ? (__builtin_clz(static_cast<unsigned int>(x)) - diff) : (sizeof(unsigned short) * CHAR_BIT);\n}\nconstexpr inline int countl_zero(unsigned int x) noexcept\n{\n\treturn x ? __builtin_clz(x) : (sizeof(unsigned int) * CHAR_BIT);\n}\n\n// __builtin_clzl\nconstexpr inline int countl_zero(unsigned long x) noexcept\n{\n\treturn x ? __builtin_clzl(x) : (sizeof(unsigned long) * CHAR_BIT);\n}\n\n// __builtin_clzll\n#if (EA_PLATFORM_PTR_SIZE == 8)\nconstexpr inline int countl_zero(unsigned long long x) noexcept\n{\n\treturn x ? __builtin_clzll(x) : (sizeof(unsigned long long) * CHAR_BIT);\n}\n#else\nconstexpr inline int countl_zero(unsigned long long x) noexcept\n{\n\treturn countl_zero64(static_cast<uint64_t>(x));\n}\n#endif\n\n#if EASTL_INT128_SUPPORTED\n// todo: once we are using Clang 19.1.0 and GCC ??? use __builtin_clzg(x)\nconstexpr inline int countl_zero(eastl_uint128_t x) noexcept\n{\n\tconst int first64bits = countl_zero(static_cast<uint64_t>(x >> 64));\n\treturn first64bits == 64 ? (64 + countl_zero(static_cast<uint64_t>(x))) : first64bits;\n}\n#endif\n\n#else // not MSVC, clang or GCC\n\ntemplate <typename T, eastl::enable_if_t<eastl::is_unsigned_v<T> && sizeof(T) < 4, bool > = true>\nconstexpr int countl_zero(const T num) noexcept\n{\n\tconstexpr auto diff = 32 - eastl::numeric_limits<T>::digits;\n\treturn countl_zero(static_cast<uint32_t>(num)) - diff;\n}\n\ntemplate <typename T, eastl::enable_if_t<eastl::is_unsigned_v<T> && sizeof(T) == 4, bool> = true>\nconstexpr int countl_zero(T x) noexcept\n{\n\tif (x)\n\t{\n\t\tint n = 0;\n\t\tif (x <= 0x0000FFFF)\n\t\t{\n\t\t\tn += 16;\n\t\t\tx <<= 16;\n\t\t}\n\t\tif (x <= 0x00FFFFFF)\n\t\t{\n\t\t\tn += 8;\n\t\t\tx <<= 8;\n\t\t}\n\t\tif (x <= 0x0FFFFFFF)\n\t\t{\n\t\t\tn += 4;\n\t\t\tx <<= 4;\n\t\t}\n\t\tif (x <= 0x3FFFFFFF)\n\t\t{\n\t\t\tn += 2;\n\t\t\tx <<= 2;\n\t\t}\n\t\tif (x <= 0x7FFFFFFF)\n\t\t{\n\t\t\tn += 1;\n\t\t}\n\t\treturn n;\n\t}\n\treturn 32;\n}\n\ntemplate <typename T, eastl::enable_if_t<eastl::is_unsigned_v<T> && sizeof(T) == 8, bool> = true>\nconstexpr int countl_zero(T x) noexcept\n{\n\treturn countl_zero64(static_cast<uint64_t>(x));\n}\n\n#if EASTL_INT128_SUPPORTED\nconstexpr inline int countl_zero(eastl_uint128_t x) noexcept\n{\n\tif (x)\n\t{\n\t\tint n = 0;\n\t\tif (x & (~eastl_uint128_t(0) << 64))\n\t\t{\n\t\t\tn += 64;\n\t\t\tx >>= 64;\n\t\t}\n\t\tif (x & UINT64_C(0xFFFFFFFF00000000))\n\t\t{\n\t\t\tn += 32;\n\t\t\tx >>= 32;\n\t\t}\n\t\tif (x & 0xFFFF0000)\n\t\t{\n\t\t\tn += 16;\n\t\t\tx >>= 16;\n\t\t}\n\t\tif (x & 0xFFFFFF00)\n\t\t{\n\t\t\tn += 8;\n\t\t\tx >>= 8;\n\t\t}\n\t\tif (x & 0xFFFFFFF0)\n\t\t{\n\t\t\tn += 4;\n\t\t\tx >>= 4;\n\t\t}\n\t\tif (x & 0xFFFFFFFC)\n\t\t{\n\t\t\tn += 2;\n\t\t\tx >>= 2;\n\t\t}\n\t\tif (x & 0xFFFFFFFE)\n\t\t{\n\t\t\tn += 1;\n\t\t}\n\t\treturn 127 - n;\n\t}\n\treturn 128;\n}\n#endif\n\n#endif\n\n}  // namespace internal\n\n\ttemplate <typename T, typename = eastl::enable_if_t<eastl::is_unsigned_v<T>>>\n\tconstexpr int countl_zero(T x) noexcept { return internal::countl_zero(x); }\n\n\ttemplate <typename T, typename = eastl::enable_if_t<eastl::is_unsigned_v<T>>>\n\tconstexpr bool has_single_bit(const T num) noexcept\n\t{\n\t\treturn num != 0 && (num & (num - 1)) == 0;\n\t}\n\n\ttemplate <typename T, typename = eastl::enable_if_t<eastl::is_unsigned_v<T>>>\n\tconstexpr T bit_ceil(const T num) noexcept\n\t{\n\t\tif (num <= 1U)\n\t\t{\n\t\t\treturn T(1);\n\t\t}\n\n\t\tconst auto shift = eastl::numeric_limits<T>::digits - eastl::countl_zero(static_cast<T>(num - 1));\n\t\treturn static_cast<T>(T(1) << shift);\n\t}\n\n\ttemplate <typename T, typename = eastl::enable_if_t<eastl::is_unsigned_v<T>>>\n\tconstexpr T bit_floor(const T num) noexcept\n\t{\n\t\tif (num == 0)\n\t\t{\n\t\t\treturn T(0);\n\t\t}\n\n\t\tconst auto shift = eastl::numeric_limits<T>::digits - eastl::countl_zero(num) - 1;\n\t\treturn static_cast<T>(T(1) << shift);\n\t}\n\n\ttemplate <typename T, typename = eastl::enable_if_t<eastl::is_unsigned_v<T>>>\n\tconstexpr int bit_width(const T num) noexcept\n\t{\n\t\treturn eastl::numeric_limits<T>::digits - eastl::countl_zero(num);\n\t}\n\nnamespace internal\n{\n\nconst static char kBitsPerUint16[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };\n\ntemplate <typename T>\nconstexpr int popcount_non_intrinsic(T num) noexcept\n{\n\tint n = 0;\n\tfor (T w = num; w; w >>= 4)\n\t\tn += kBitsPerUint16[w & 0xF];\n\treturn n;\n}\n\n#if defined(EA_COMPILER_MSVC) && !defined(__clang__)\n\n// __popcnt is not constexpr\n\n// __popcnt16\ninline int popcount(unsigned char num) noexcept { return __popcnt16(static_cast<unsigned short>(num)); }\ninline int popcount(unsigned short num) noexcept { return __popcnt16(num); }\n\n// __popcnt\ninline int popcount(unsigned int num) noexcept { return __popcnt(num); }\n\n#if defined(EA_PROCESSOR_X86_64)\n// __popcnt64\ninline int popcount(unsigned long num) noexcept { return static_cast<int>(__popcnt64(num)); }\ninline int popcount(unsigned long long num) noexcept { return static_cast<int>(__popcnt64(num)); }\n#else\n// todo: is it better to use __popcnt() or the fallback implementation?\ninline int popcount(unsigned long num) noexcept { return popcount_non_intrinsic(num); }\ninline int popcount(unsigned long long num) noexcept { return popcount_non_intrinsic(num); }\n#endif\n#elif defined(__GNUC__) || defined(__clang__)\n// __builtin_popcount\nconstexpr inline int popcount(unsigned char num) noexcept { return __builtin_popcount(num); }\nconstexpr inline int popcount(unsigned short num) noexcept { return __builtin_popcount(num); }\nconstexpr inline int popcount(unsigned int num) noexcept { return __builtin_popcount(num); }\n\n// __builtin_popcountl\nconstexpr inline int popcount(unsigned long num) noexcept { return __builtin_popcountl(num); }\n\n// __builtin_popcountll\nconstexpr inline int popcount(unsigned long long num) noexcept { return __builtin_popcountll(num); }\n#endif\n\n#if EASTL_INT128_SUPPORTED\n// todo: once we are using Clang 19.1.0 and GCC ??? use __builtin_popcountg(num)\nconstexpr inline int popcount(eastl_uint128_t num) noexcept\n{\n\treturn popcount(static_cast<uint64_t>(num >> 64)) + popcount(static_cast<uint64_t>(num));\n}\n#endif\n\n} // namespace internal\n\n\ttemplate <typename T, typename = eastl::enable_if_t<eastl::is_unsigned_v<T>>>\n\tconstexpr int popcount(T x) noexcept { return internal::popcount(x); }\n\n} // namespace eastl\n\n#endif // EASTL_BIT_H\n"
  },
  {
    "path": "include/EASTL/bitset.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a bitset much like the C++ std::bitset class. \n// The primary distinctions between this bitset and std::bitset are:\n//    - bitset is more efficient than some other std::bitset implementations,\n//      notably the bitset that comes with Microsoft and other 1st party platforms.\n//    - bitset is savvy to an environment that doesn't have exception handling,\n//      as is sometimes the case with console or embedded environments.\n//    - bitset is savvy to environments in which 'unsigned long' is not the \n//      most efficient integral data type. std::bitset implementations use\n//      unsigned long, even if it is an inefficient integer type.\n//    - bitset removes as much function calls as practical, in order to allow\n//      debug builds to run closer in speed and code footprint to release builds.\n//    - bitset doesn't support string functionality. We can add this if \n//      it is deemed useful.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_BITSET_H\n#define EASTL_BITSET_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/bit.h>\n\nEA_DISABLE_ALL_VC_WARNINGS();\n\n#include <stddef.h>\n#include <string.h>\n\nEA_RESTORE_ALL_VC_WARNINGS();\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS();\n\n\t#include <stdexcept> // std::out_of_range, std::length_error.\n\n\tEA_RESTORE_ALL_VC_WARNINGS();\n#endif\n\nEA_DISABLE_VC_WARNING(4127); // Conditional expression is constant\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t// To consider: Enable this for backwards compatibility with any user code that might be using BitsetWordType:\n\t// #define BitsetWordType EASTL_BITSET_WORD_TYPE_DEFAULT\n\n\n\t/// BITSET_WORD_COUNT\n\t///\n\t/// Defines the number of words we use, based on the number of bits.\n\t/// nBitCount refers to the number of bits in a bitset.\n\t/// WordType refers to the type of integer word which stores bitet data. By default it is BitsetWordType.\n\t///\n\t/// Note: for nBitCount == 0, returns 1!\n\t#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x can't handle the simpler declaration below.\n\t\t#define BITSET_WORD_COUNT(nBitCount, WordType) (nBitCount == 0 ? 1 : ((nBitCount - 1) / (8 * sizeof(WordType)) + 1))\n\t#else\n\t\t#define BITSET_WORD_COUNT(nBitCount, WordType) ((nBitCount - 1) / (8 * sizeof(WordType)) + 1)\n\t#endif\n\n\n\t/// EASTL_DISABLE_BITSET_ARRAYBOUNDS_WARNING\n\t/// Before GCC 4.7 the '-Warray-bounds' buggy and was very likely to issue false positives for loops that are\n\t/// difficult to evaluate.\n\t/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45978\n\t///\n\t#if defined(__GNUC__) && (EA_COMPILER_VERSION > 4007) && defined(EA_PLATFORM_ANDROID) // Earlier than GCC 4.7 \n\t\t#define EASTL_DISABLE_BITSET_ARRAYBOUNDS_WARNING 1\n\t#else\n\t\t#define EASTL_DISABLE_BITSET_ARRAYBOUNDS_WARNING 0\n\t#endif\n\n\ttemplate <size_t N, typename WordType = EASTL_BITSET_WORD_TYPE_DEFAULT>\n\tclass bitset;\n\n\tnamespace detail\n\t{\n\t\ttemplate<typename T>\n\t\tstruct is_word_type : bool_constant<!is_const_v<T> && !is_volatile_v<T> && !is_same_v<T, bool> && is_integral_v<T> && is_unsigned_v<T>> {};\n\n\t\ttemplate<typename T>\n\t\tconstexpr bool is_word_type_v = is_word_type<T>::value;\n\n\t\t// slices the min(N, UInt) lowest significant bits from value.\n\t\ttemplate<size_t N, typename WordType, typename UInt>\n\t\teastl::enable_if_t<is_word_type_v<UInt>> from_unsigned_integral(bitset<N, WordType>& bs, UInt value)\n\t\t{\n\t\t\tconstexpr size_t numWords = (N > 0) ? ((N - 1) / (CHAR_BIT * sizeof(WordType)) + 1) : 0; // BITSET_WORD_COUNT(N, WordType) but 0 for N == 0\n\n\t\t\tWordType* data = bs.data();\n\n\t\t\tEA_CONSTEXPR_IF (numWords > 0)\n\t\t\t{\n\t\t\t\t// copy everything from value into our word array:\n\t\t\t\tconstexpr size_t bytes_to_copy = eastl::min_alt(numWords * sizeof(WordType), sizeof(UInt));\n\t\t\t\tmemcpy(data, &value, bytes_to_copy);\n\n\t\t\t\t// zero any remaining elements in our array:\n\t\t\t\tmemset(reinterpret_cast<unsigned char*>(data) + bytes_to_copy, 0, numWords * sizeof(WordType) - bytes_to_copy);\n\n\t\t\t\t// we may have copied bits into the final element that are unusable (ie. bit positions > N).\n\t\t\t\t// zero these bits out, as this is an invariant for our implementation.\n\t\t\t\tEA_CONSTEXPR_IF (N % (CHAR_BIT * sizeof(WordType)) != 0)\n\t\t\t\t{\n\t\t\t\t\tconstexpr WordType lastElemUsedBitsMask = (WordType(1) << (N % (CHAR_BIT * sizeof(WordType)))) - 1;\n\t\t\t\t\tdata[numWords - 1] &= lastElemUsedBitsMask;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdata[0] = 0; // our bitset implementation has a single element even when N == 0.\n\t\t\t}\n\t\t}\n\n\t\t// This is here to work around the lack of `if constexpr` in C++14, so that calling\n\t\t// (WordType(1) << (CHAR_BIT * sizeof(UInt))) doesn't trigger warnings/errors when\n\t\t// sizeof(UInt) >= sizeof(WordType)\n\t\ttemplate<typename UInt, typename WordType, size_t NumWords, bool bAssertOnOverflow, bool bDoPartialCopy = (sizeof(UInt) < sizeof(WordType))>\n\t\tstruct to_unsigned_integral_helper\n\t\t{};\n\n\t\ttemplate<typename UInt, typename WordType, size_t NumWords, bool bAssertOnOverflow>\n\t\tstruct to_unsigned_integral_helper<UInt, WordType, NumWords, bAssertOnOverflow, true>\n\t\t{\n\t\t\tstatic size_t copyWords(const WordType* data, UInt* result)\n\t\t\t{\n\t\t\t\tconstexpr size_t bytes_to_copy = sizeof(UInt);\n\t\t\t\tmemcpy(result, data, bytes_to_copy);\n\n\t\t\t\t// check remaining uncopied bits from the first word are zero:\n\t\t\t\tconstexpr WordType lastElemOverflowBitsMask = static_cast<WordType>(~((WordType(1) << (CHAR_BIT * sizeof(UInt))) - 1));\n\t\t\t\tif ((data[0] & lastElemOverflowBitsMask) != 0)\n\t\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tthrow std::overflow_error(\"target type cannot represent the full bitset.\");\n#elif EASTL_ASSERT_ENABLED\n\t\t\t\t\tEA_CONSTEXPR_IF(bAssertOnOverflow)\n\t\t\t\t\t\tEASTL_FAIL_MSG(\"overflow_error\");\n#endif\n\t\t\t\t}\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t};\n\n\t\ttemplate<typename UInt, typename WordType, size_t NumWords, bool bAssertOnOverflow>\n\t\tstruct to_unsigned_integral_helper<UInt, WordType, NumWords, bAssertOnOverflow, false>\n\t\t{\n\t\t\tstatic size_t copyWords(const WordType* data, UInt* result)\n\t\t\t{\n\t\t\t\tconstexpr size_t bytes_to_copy = eastl::min_alt(NumWords * sizeof(WordType), sizeof(UInt));\n\t\t\t\tmemcpy(result, data, bytes_to_copy);\n\n\t\t\t\treturn bytes_to_copy / sizeof(WordType);\n\t\t\t}\n\t\t};\n\n\n\n\t\ttemplate<typename UInt, bool bAssertOnOverflow, size_t N, typename WordType>\n\t\teastl::enable_if_t<is_word_type_v<UInt>, UInt> to_unsigned_integral(const bitset<N, WordType>& bs)\n\t\t{\n\t\t\tconstexpr size_t kNumWords = (N > 0) ? ((N - 1) / (CHAR_BIT * sizeof(WordType)) + 1) : 0; // BITSET_WORD_COUNT(N, WordType) but 0 for N == 0\n\n\t\t\tEA_CONSTEXPR_IF (kNumWords > 0)\n\t\t\t{\n\t\t\t\tconst WordType* data = bs.data();\n\n\t\t\t\tUInt result = 0;\n\n\t\t\t\tconst size_t numWordsCopied = to_unsigned_integral_helper<UInt, WordType, kNumWords, bAssertOnOverflow>::copyWords(data, &result);\n\n\t\t\t\t// check any remaining uncopied words are zero (don't contain any useful information).\n\t\t\t\tfor (size_t wordIndex = numWordsCopied; wordIndex < kNumWords; ++wordIndex)\n\t\t\t\t{\n\t\t\t\t\tif (data[wordIndex] != 0)\n\t\t\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t\tthrow std::overflow_error(\"target type cannot represent the full bitset.\");\n#elif EASTL_ASSERT_ENABLED\n\t\t\t\t\t\tEA_CONSTEXPR_IF (bAssertOnOverflow)\n\t\t\t\t\t\t\tEASTL_FAIL_MSG(\"overflow_error\");\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t} // namespace detail\n\n\t/// BitsetBase\n\t///\n\t/// This is a default implementation that works for any number of words.\n\t///\n\ttemplate <size_t NW, typename WordType> // Templated on the number of words used to hold the bitset and the word type.\n\tstruct BitsetBase\n\t{\n\t\ttypedef WordType                 word_type;\n\t\ttypedef BitsetBase<NW, WordType> this_type;\n\t  #if EASTL_BITSET_SIZE_T\n\t\ttypedef size_t                   size_type;\n\t  #else\n\t\ttypedef eastl_size_t             size_type;\n\t  #endif\n\n\t\tenum {\n\t\t\tkBitsPerWord      = (8 * sizeof(word_type)),\n\t\t\tkBitsPerWordMask  = (kBitsPerWord - 1),\n\t\t\tkBitsPerWordShift = ((kBitsPerWord == 8) ? 3 : ((kBitsPerWord == 16) ? 4 : ((kBitsPerWord == 32) ? 5 : (((kBitsPerWord == 64) ? 6 : 7)))))\n\t\t};\n\n\tpublic:\n\t\t// invariant: we keep any high bits in the last word that are unneeded set to 0\n\t\t// so that our to_ulong() conversion can simply copy the words into the target type.\n\t\tword_type mWord[NW];\n\n\tpublic:\n\t\tvoid operator&=(const this_type& x);\n\t\tvoid operator|=(const this_type& x);\n\t\tvoid operator^=(const this_type& x);\n\n\t\tvoid operator<<=(size_type n);\n\t\tvoid operator>>=(size_type n);\n\n\t\tvoid flip();\n\t\tvoid set();\n\t\tvoid set(size_type i, bool value);\n\t\tvoid reset();\n\n\t\tbool operator==(const this_type& x) const;\n\n\t\tbool      any() const;\n\t\tsize_type count() const;\n\n\t\tword_type& DoGetWord(size_type i);\n\t\tword_type  DoGetWord(size_type i) const;\n\n\t\tsize_type DoFindFirst() const;\n\t\tsize_type DoFindNext(size_type last_find) const;\n\n\t\tsize_type DoFindLast() const;                       // Returns NW * kBitsPerWord (the bit count) if no bits are set.\n\t\tsize_type DoFindPrev(size_type last_find) const;    // Returns NW * kBitsPerWord (the bit count) if no bits are set.\n\n\t}; // class BitsetBase\n\n\n\n\t/// BitsetBase<1, WordType>\n\t/// \n\t/// This is a specialization for a bitset that fits within one word.\n\t///\n\ttemplate <typename WordType>\n\tstruct BitsetBase<1, WordType>\n\t{\n\t\ttypedef WordType                word_type;\n\t\ttypedef BitsetBase<1, WordType> this_type;\n\t  #if EASTL_BITSET_SIZE_T\n\t\ttypedef size_t                  size_type;\n\t  #else\n\t\ttypedef eastl_size_t            size_type;\n\t  #endif\n\n\t\tenum {\n\t\t\tkBitsPerWord      = (8 * sizeof(word_type)),\n\t\t\tkBitsPerWordMask  = (kBitsPerWord - 1),\n\t\t\tkBitsPerWordShift = ((kBitsPerWord == 8) ? 3 : ((kBitsPerWord == 16) ? 4 : ((kBitsPerWord == 32) ? 5 : (((kBitsPerWord == 64) ? 6 : 7)))))\n\t\t};\n\n\tpublic:\n\t\tword_type mWord[1]; // Defined as an array of 1 so that bitset can treat this BitsetBase like others.\n\n\tpublic:\n\t\tvoid operator&=(const this_type& x);\n\t\tvoid operator|=(const this_type& x);\n\t\tvoid operator^=(const this_type& x);\n\n\t\tvoid operator<<=(size_type n);\n\t\tvoid operator>>=(size_type n);\n\n\t\tvoid flip();\n\t\tvoid set();\n\t\tvoid set(size_type i, bool value);\n\t\tvoid reset();\n\n\t\tbool operator==(const this_type& x) const;\n\n\t\tbool      any() const;\n\t\tsize_type count() const;\n\n\t\tword_type& DoGetWord(size_type);\n\t\tword_type  DoGetWord(size_type) const;\n\n\t\tsize_type DoFindFirst() const;\n\t\tsize_type DoFindNext(size_type last_find) const;\n\n\t\tsize_type DoFindLast() const;                       // Returns 1 * kBitsPerWord (the bit count) if no bits are set.\n\t\tsize_type DoFindPrev(size_type last_find) const;    // Returns 1 * kBitsPerWord (the bit count) if no bits are set.\n\n\t}; // BitsetBase<1, WordType>\n\n\n\n\t/// BitsetBase<2, WordType>\n\t/// \n\t/// This is a specialization for a bitset that fits within two words.\n\t/// The difference here is that we avoid branching (ifs and loops).\n\t///\n\ttemplate <typename WordType>\n\tstruct BitsetBase<2, WordType>\n\t{\n\t\ttypedef WordType                 word_type;\n\t\ttypedef BitsetBase<2, WordType>  this_type;\n\t  #if EASTL_BITSET_SIZE_T\n\t\ttypedef size_t                   size_type;\n\t  #else\n\t\ttypedef eastl_size_t             size_type;\n\t  #endif\n\n\t\tenum {\n\t\t\tkBitsPerWord      = (8 * sizeof(word_type)),\n\t\t\tkBitsPerWordMask  = (kBitsPerWord - 1),\n\t\t\tkBitsPerWordShift = ((kBitsPerWord == 8) ? 3 : ((kBitsPerWord == 16) ? 4 : ((kBitsPerWord == 32) ? 5 : (((kBitsPerWord == 64) ? 6 : 7)))))\n\t\t};\n\n\tpublic:\n\t\tword_type mWord[2];\n\n\tpublic:\n\t\tvoid operator&=(const this_type& x);\n\t\tvoid operator|=(const this_type& x);\n\t\tvoid operator^=(const this_type& x);\n\n\t\tvoid operator<<=(size_type n);\n\t\tvoid operator>>=(size_type n);\n\n\t\tvoid flip();\n\t\tvoid set();\n\t\tvoid set(size_type i, bool value);\n\t\tvoid reset();\n\n\t\tbool operator==(const this_type& x) const;\n\n\t\tbool      any() const;\n\t\tsize_type count() const;\n\n\t\tword_type& DoGetWord(size_type);\n\t\tword_type  DoGetWord(size_type) const;\n\n\t\tsize_type DoFindFirst() const;\n\t\tsize_type DoFindNext(size_type last_find) const;\n\n\t\tsize_type DoFindLast() const;                       // Returns 2 * kBitsPerWord (the bit count) if no bits are set.\n\t\tsize_type DoFindPrev(size_type last_find) const;    // Returns 2 * kBitsPerWord (the bit count) if no bits are set.\n\n\t}; // BitsetBase<2, WordType>\n\n\n\n\n\t/// bitset\n\t///\n\t/// Implements a bitset much like the C++ std::bitset.\n\t///\n\t/// As of this writing we don't implement a specialization of bitset<0>,\n\t/// as it is deemed an academic exercise that nobody would actually\n\t/// use and it would increase code space and provide little practical\n\t/// benefit. Note that this doesn't mean bitset<0> isn't supported; \n\t/// it means that our version of it isn't as efficient as it would be \n\t/// if a specialization was made for it.\n\t///\n\t/// - N can be any unsigned (non-zero) value, though memory usage is \n\t///   linear with respect to N, so large values of N use large amounts of memory.\n\t/// - WordType must be a non-cv qualified unsigned integral other than bool.\n\t///   By default the WordType is the largest native register type that the\n\t///   target platform supports.\n\t///\n\ttemplate <size_t N, typename WordType>\n\tclass bitset : private BitsetBase<BITSET_WORD_COUNT(N, WordType), WordType>\n\t{\n\tpublic:\n\t\tstatic_assert(detail::is_word_type_v<WordType>, \"Word type must be a non-cv qualified, unsigned integral other than bool.\");\n\n\t\ttypedef BitsetBase<BITSET_WORD_COUNT(N, WordType), WordType>  base_type;\n\t\ttypedef bitset<N, WordType>                                   this_type;\n\t\ttypedef WordType                                              word_type;\n\t\ttypedef typename base_type::size_type                         size_type;\n\n\t\tenum\n\t\t{\n\t\t\tkBitsPerWord      = (8 * sizeof(word_type)),\n\t\t\tkBitsPerWordMask  = (kBitsPerWord - 1),\n\t\t\tkBitsPerWordShift = ((kBitsPerWord == 8) ? 3 : ((kBitsPerWord == 16) ? 4 : ((kBitsPerWord == 32) ? 5 : (((kBitsPerWord == 64) ? 6 : 7))))),\n\t\t\tkSize             = N,                               // The number of bits the bitset holds\n\t\t\tkWordSize         = sizeof(word_type),               // The size of individual words the bitset uses to hold the bits.\n\t\t\tkWordCount        = BITSET_WORD_COUNT(N, WordType)   // The number of words the bitset uses to hold the bits. sizeof(bitset<N, WordType>) == kWordSize * kWordCount.\n\t\t};\n\n\t\t// internal implementation details. do not use.\n\t\tusing base_type::mWord;\n\t\tusing base_type::DoGetWord;\n\t\tusing base_type::DoFindFirst;\n\t\tusing base_type::DoFindNext;\n\t\tusing base_type::DoFindLast;\n\t\tusing base_type::DoFindPrev;\n\n\t\tusing base_type::count;\n\t\tusing base_type::any;\n\n\tpublic:\n\t\t/// reference\n\t\t///\n\t\t/// A reference is a reference to a specific bit in the bitset.\n\t\t/// The C++ standard specifies that this be a nested class, \n\t\t/// though it is not clear if a non-nested reference implementation\n\t\t/// would be non-conforming.\n\t\t///\n\t\tclass reference\n\t\t{\n\t\tprotected:\n\t\t\tfriend class bitset<N, WordType>;\n\n\t\t\tword_type* mpBitWord;\n\t\t\tsize_type  mnBitIndex;\n\t\t\n\t\t\treference(){} // The C++ standard specifies that this is private.\n\t\n\t\tpublic:\n\t\t\treference(const bitset& x, size_type i);\n\n\t\t\treference& operator=(bool value);\n\t\t\treference& operator=(const reference& x);\n\n\t\t\tbool operator~() const;\n\t\t\toperator bool() const // Defined inline because CodeWarrior fails to be able to compile it outside.\n\t\t\t   { return (*mpBitWord & (static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask))) != 0; }\n\n\t\t\treference& flip();\n\t\t};\n\n\tpublic:\n\t\tfriend class reference;\n\n\t\tbitset();\n\n#if EA_IS_ENABLED(EASTL_DEPRECATIONS_FOR_2024_SEPT)\n\t\t// note: this constructor will only copy the minimum of N or unsigned long long's size least significant bits.\n\t\tbitset(unsigned long long value);\n#else\n\t\tbitset(uint32_t value);\n#endif\n\n\t\t// We don't define copy constructor and operator= because \n\t\t// the compiler-generated versions will suffice.\n\n\t\tthis_type& operator&=(const this_type& x);\n\t\tthis_type& operator|=(const this_type& x);\n\t\tthis_type& operator^=(const this_type& x);\n\n\t\tthis_type& operator<<=(size_type n);\n\t\tthis_type& operator>>=(size_type n);\n\n\t\tthis_type& set();\n\t\tthis_type& set(size_type i, bool value = true);\n\n\t\tthis_type& reset();\n\t\tthis_type& reset(size_type i);\n\t\t\t\n\t\tthis_type& flip();\n\t\tthis_type& flip(size_type i);\n\t\tthis_type  operator~() const;\n\n\t\treference operator[](size_type i);\n\t\tbool      operator[](size_type i) const;\n\n\t\tconst word_type* data() const;\n\t\tword_type*       data();\n\n\t\t// Deprecated: use the bitset(unsigned long long) constructor instead.\n\t\t// this was a workaround for when our constructor was defined as bitset(uint32_t) and could cause a narrowing conversion.\n\t\tEASTL_REMOVE_AT_2024_SEPT void          from_uint32(uint32_t value);\n\t\tEASTL_REMOVE_AT_2024_SEPT void          from_uint64(uint64_t value);\n\n\t\t/// to_xxx()\n\t\t/// \n\t\t/// Not recommended: Use one of\n\t\t///   as_xxx() which is a compile time error if the target type cannot represent the entire bitset, or\n\t\t///   to_xxx_assert_convertible() which is the standard conformant version of this function, or\n\t\t///   to_xxx_no_assert_convertible() which has the same behaviour, explicit naming\n\t\t/// \n\t\t/// Different from the standard:\n\t\t/// Does *NOT* assert that the bitset can be represented as the target integer type (has bits set outside the target type).\n\t\t/// However, if exceptions are enabled, it does throw an exception if the bitset cannot be represented as the target integer type.\n\t\tunsigned long to_ulong()  const;\n\t\tuint32_t      to_uint32() const;\n\t\tuint64_t      to_uint64() const;\n\n\t\t/// to_xxx_assert_convertible()\n\t\t///\n\t\t/// Equivalent to the standard library's to_ulong() / to_ullong().\n\t\t/// Asserts / throws an exception if the bitset cannot be represented as the target integer type.\n\t\tuint32_t\t\t\tto_uint32_assert_convertible() const { return detail::to_unsigned_integral<uint32_t, true>(*this); }\n\t\tuint64_t\t\t\tto_uint64_assert_convertible() const { return detail::to_unsigned_integral<uint64_t, true>(*this); }\n\t\tunsigned long\t\tto_ulong_assert_convertible()  const { return detail::to_unsigned_integral<unsigned long, true>(*this); }\n\t\tunsigned long long\tto_ullong_assert_convertible() const { return detail::to_unsigned_integral<unsigned long long, true>(*this); }\n\n\t\t/// to_xxx_no_assert_convertible()\n\t\t///\n\t\t/// Prefer to_xxx_assert_convertible() instead of these functions.\n\t\t/// \n\t\t/// Different from the standard:\n\t\t/// Does *NOT* assert that the bitset can be represented as the target integer type (has bits set outside the target type).\n\t\t/// However, if exceptions are enabled, it does throw an exception if the bitset cannot be represented as the target integer type.\n\t\tuint32_t\t\t\tto_uint32_no_assert_convertible() const { return detail::to_unsigned_integral<uint32_t, false>(*this); }\n\t\tuint64_t\t\t\tto_uint64_no_assert_convertible() const { return detail::to_unsigned_integral<uint64_t, false>(*this); }\n\t\tunsigned long\t\tto_ulong_no_assert_convertible()  const { return detail::to_unsigned_integral<unsigned long, false>(*this); }\n\t\tunsigned long long\tto_ullong_no_assert_convertible() const { return detail::to_unsigned_integral<unsigned long long, false>(*this); }\n\n\t\t/// as_uint<UInt>() / as_xxx()\n\t\t/// \n\t\t/// Extension to the standard: Cast to a unsigned integral that can represent the entire bitset.\n\t\t/// If the target type cannot represent the entire bitset, then issue a compile error (overload does not exist).\n\t\t/// Never throws / asserts.\n\t\ttemplate<typename UInt>\n\t\teastl::enable_if_t<detail::is_word_type_v<UInt> && N <= (CHAR_BIT * sizeof(UInt)), UInt>\tas_uint() const noexcept { return detail::to_unsigned_integral<UInt, true>(*this); }\n\n\t\ttemplate<size_t NumBits = N>\n\t\teastl::enable_if_t<NumBits <= (CHAR_BIT * sizeof(uint32_t)), uint32_t>\t\t\t\t\t\tas_uint32() const noexcept { return to_uint32_assert_convertible(); }\n\t\ttemplate<size_t NumBits = N>\n\t\teastl::enable_if_t<NumBits <= (CHAR_BIT * sizeof(uint64_t)), uint64_t>\t\t\t\t\t\tas_uint64() const noexcept { return to_uint64_assert_convertible(); }\n\t\ttemplate<size_t NumBits = N>\n\t\teastl::enable_if_t<NumBits <= (CHAR_BIT * sizeof(unsigned long)), unsigned long>\t\t\tas_ulong() const noexcept { return to_ulong_assert_convertible(); }\n\t\ttemplate<size_t NumBits = N>\n\t\teastl::enable_if_t<NumBits <= (CHAR_BIT * sizeof(unsigned long long)), unsigned long long>\tas_ullong() const noexcept { return to_ullong_assert_convertible(); }\n\n\t  //size_type count() const;            // We inherit this from the base class.\n\t\tsize_type size() const;\n\n\t\tbool operator==(const this_type& x) const;\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\tbool operator!=(const this_type& x) const;\n#endif\n\n\t\tbool test(size_type i) const;\n\t  //bool any() const;                   // We inherit this from the base class.\n\t\tbool all() const;\n\t\tbool none() const;\n\n\t\tthis_type operator<<(size_type n) const;\n\t\tthis_type operator>>(size_type n) const;\n\n\t\t// Finds the index of the first \"on\" bit, returns kSize if none are set.\n\t\tsize_type find_first() const;\n\n\t\t// Finds the index of the next \"on\" bit after last_find, returns kSize if none are set.\n\t\tsize_type find_next(size_type last_find) const;\n\n\t\t// Finds the index of the last \"on\" bit, returns kSize if none are set.\n\t\tsize_type find_last() const;\n\n\t\t// Finds the index of the last \"on\" bit before last_find, returns kSize if none are set.\n\t\tsize_type find_prev(size_type last_find) const;\n\n\t}; // bitset\n\n\n\n\n\n\n\n\t/// BitsetCountBits\n\t///\n\t/// This is a fast trick way to count bits without branches nor memory accesses.\n\t///\n\t/// todo: Use bit.h's popcount instead?\n\ttemplate<typename UInt64>\n\teastl::enable_if_t<detail::is_word_type_v<UInt64> && sizeof(UInt64) == 8, uint32_t> BitsetCountBits(UInt64 x)\n\t{\n\t\t// GCC 3.x's implementation of UINT64_C is broken and fails to deal with \n\t\t// the code below correctly. So we make a workaround for it. Earlier and \n\t\t// later versions of GCC don't have this bug.\n\n\t\t#if defined(__GNUC__) && (__GNUC__ == 3)\n\t\t\tx = x - ((x >> 1) & 0x5555555555555555ULL);\n\t\t\tx = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);\n\t\t\tx = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0FULL;\n\t\t\treturn (uint32_t)((x * 0x0101010101010101ULL) >> 56);\n\t\t#else\n\t\t\tx = x - ((x >> 1) & UINT64_C(0x5555555555555555));\n\t\t\tx = (x & UINT64_C(0x3333333333333333)) + ((x >> 2) & UINT64_C(0x3333333333333333));\n\t\t\tx = (x + (x >> 4)) & UINT64_C(0x0F0F0F0F0F0F0F0F);\n\t\t\treturn (uint32_t)((x * UINT64_C(0x0101010101010101)) >> 56);\n\t\t#endif\n\t}\n\n\ttemplate<typename UInt32>\n\teastl::enable_if_t<detail::is_word_type_v<UInt32> && sizeof(UInt32) == 4, uint32_t> BitsetCountBits(UInt32 x)\n\t{\n\t\tx = x - ((x >> 1) & 0x55555555);\n\t\tx = (x & 0x33333333) + ((x >> 2) & 0x33333333);\n\t\tx = (x + (x >> 4)) & 0x0F0F0F0F;\n\t\treturn (uint32_t)((x * 0x01010101) >> 24);\n\t}\n\n\ttemplate<typename SmallUInt>\n\teastl::enable_if_t< detail::is_word_type_v<SmallUInt> && sizeof(SmallUInt) < 4, uint32_t> BitsetCountBits(SmallUInt x)\n\t{\n\t\treturn BitsetCountBits((uint32_t)x);\n\t}\n\n\n\t// const static char kBitsPerUint16[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };\n\t#define EASTL_BITSET_COUNT_STRING \"\\0\\1\\1\\2\\1\\2\\2\\3\\1\\2\\2\\3\\2\\3\\3\\4\"\n\n\n\ttemplate<typename UInt8>\n\teastl::enable_if_t<detail::is_word_type_v<UInt8> && sizeof(UInt8) == 1, uint32_t> GetFirstBit(UInt8 x)\n\t{\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 1;\n\n\t\t\tif((x & 0x0000000F) == 0) { n +=  4; x >>=  4; }\n\t\t\tif((x & 0x00000003) == 0) { n +=  2; x >>=  2; }\n\n\t\t\treturn (uint32_t)(n - (x & 1));\n\t\t}\n\n\t\treturn 8;\n\t}\n\n\t// To do: Update this to use VC++ _BitScanForward, _BitScanForward64;\n\t// GCC __builtin_ctz, __builtin_ctzl.\n\t// VC++ __lzcnt16, __lzcnt, __lzcnt64 requires recent CPUs (2013+) and probably can't be used.\n\t// http://en.wikipedia.org/wiki/Haswell_%28microarchitecture%29#New_features\n\ttemplate<typename UInt16>\n\teastl::enable_if_t<detail::is_word_type_v<UInt16> && sizeof(UInt16) == 2, uint32_t> GetFirstBit(UInt16 x)\n\t{\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 1;\n\n\t\t\tif((x & 0x000000FF) == 0) { n +=  8; x >>=  8; }\n\t\t\tif((x & 0x0000000F) == 0) { n +=  4; x >>=  4; }\n\t\t\tif((x & 0x00000003) == 0) { n +=  2; x >>=  2; }\n\n\t\t\treturn (uint32_t)(n - (x & 1));\n\t\t}\n\n\t\treturn 16;\n\t}\n\n\ttemplate<typename UInt32>\n\teastl::enable_if_t<detail::is_word_type_v<UInt32> && sizeof(UInt32) == 4, uint32_t> GetFirstBit(UInt32 x)\n\t{\n#if defined(EA_COMPILER_MSVC) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\t// This has been benchmarked as significantly faster than the generic code below.\n\t\tunsigned char isNonZero;\n\t\tunsigned long index;\n\t\tisNonZero = _BitScanForward(&index, x);\n\t\treturn isNonZero ? (int)index : 32;\n#elif (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) && !defined(EA_COMPILER_EDG)\n\t\tif (x)\n\t\t\treturn __builtin_ctz(x);\n\t\treturn 32;\n#else\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 1;\n\n\t\t\tif((x & 0x0000FFFF) == 0) { n += 16; x >>= 16; }\n\t\t\tif((x & 0x000000FF) == 0) { n +=  8; x >>=  8; }\n\t\t\tif((x & 0x0000000F) == 0) { n +=  4; x >>=  4; }\n\t\t\tif((x & 0x00000003) == 0) { n +=  2; x >>=  2; }\n\n\t\t\treturn (n - (x & 1));\n\t\t}\n\n\t\treturn 32;\n#endif\n\t}\n\n\ttemplate<typename UInt64>\n\teastl::enable_if_t<detail::is_word_type_v<UInt64> && sizeof(UInt64) == 8, uint32_t> GetFirstBit(UInt64 x)\n\t{\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86_64)\n\t\t// This has been benchmarked as significantly faster than the generic code below.\n\t\tunsigned char isNonZero;\n\t\tunsigned long index;\n\t\tisNonZero = _BitScanForward64(&index, x);\n\t\treturn isNonZero ? (int)index : 64;\n#elif (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) && !defined(EA_COMPILER_EDG)\n\t\tif (x)\n\t\t\treturn __builtin_ctzll(x);\n\t\treturn 64;\n#else\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 1;\n\n\t\t\tif((x & 0xFFFFFFFF) == 0) { n += 32; x >>= 32; }\n\t\t\tif((x & 0x0000FFFF) == 0) { n += 16; x >>= 16; }\n\t\t\tif((x & 0x000000FF) == 0) { n +=  8; x >>=  8; }\n\t\t\tif((x & 0x0000000F) == 0) { n +=  4; x >>=  4; }\n\t\t\tif((x & 0x00000003) == 0) { n +=  2; x >>=  2; }\n\n\t\t\treturn (n - ((uint32_t)x & 1));\n\t\t}\n\n\t\treturn 64;\n#endif\n\t}\n\n\n\t#if EASTL_INT128_SUPPORTED\n\t\tinline uint32_t GetFirstBit(eastl_uint128_t x)\n\t\t{\n\t\t\tif(x)\n\t\t\t{\n\t\t\t\tuint32_t n = 1;\n\n\t\t\t\tif((x & UINT64_C(0xFFFFFFFFFFFFFFFF)) == 0) { n += 64; x >>= 64; }\n\t\t\t\tif((x & 0xFFFFFFFF) == 0)                   { n += 32; x >>= 32; }\n\t\t\t\tif((x & 0x0000FFFF) == 0)                   { n += 16; x >>= 16; }\n\t\t\t\tif((x & 0x000000FF) == 0)                   { n +=  8; x >>=  8; }\n\t\t\t\tif((x & 0x0000000F) == 0)                   { n +=  4; x >>=  4; }\n\t\t\t\tif((x & 0x00000003) == 0)                   { n +=  2; x >>=  2; }\n\n\t\t\t\treturn (n - ((uint32_t)x & 1));\n\t\t\t}\n\n\t\t\treturn 128;\n\t\t}\n\t#endif\n\n\ttemplate<typename UInt8>\n\teastl::enable_if_t<detail::is_word_type_v<UInt8> && sizeof(UInt8) == 1, uint32_t> GetLastBit(UInt8 x)\n\t{\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 0;\n\n\t\t\tif(x & 0xFFF0) { n +=  4; x >>=  4; }\n\t\t\tif(x & 0xFFFC) { n +=  2; x >>=  2; }\n\t\t\tif(x & 0xFFFE) { n +=  1;           }\n\n\t\t\treturn n;\n\t\t}\n\n\t\treturn 8;\n\t}\n\n\ttemplate<typename UInt16>\n\teastl::enable_if_t<detail::is_word_type_v<UInt16> && sizeof(UInt16) == 2, uint32_t> GetLastBit(UInt16 x)\n\t{\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 0;\n\n\t\t\tif(x & 0xFF00) { n +=  8; x >>=  8; }\n\t\t\tif(x & 0xFFF0) { n +=  4; x >>=  4; }\n\t\t\tif(x & 0xFFFC) { n +=  2; x >>=  2; }\n\t\t\tif(x & 0xFFFE) { n +=  1;           }\n\n\t\t\treturn n;\n\t\t}\n\n\t\treturn 16;\n\t}\n\n\ttemplate<typename UInt32>\n\teastl::enable_if_t<detail::is_word_type_v<UInt32> && sizeof(UInt32) == 4, uint32_t> GetLastBit(UInt32 x)\n\t{\n#if defined(EA_COMPILER_MSVC) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\t// This has been benchmarked as significantly faster than the generic code below.\n\t\tunsigned char isNonZero;\n\t\tunsigned long index;\n\t\tisNonZero = _BitScanReverse(&index, x);\n\t\treturn isNonZero ? (int)index : 32;\n#elif (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) && !defined(EA_COMPILER_EDG)\n\t\tif (x)\n\t\t\treturn 31 - __builtin_clz(x);\n\t\treturn 32;\n#else\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 0;\n\n\t\t\tif(x & 0xFFFF0000) { n += 16; x >>= 16; }\n\t\t\tif(x & 0xFFFFFF00) { n +=  8; x >>=  8; }\n\t\t\tif(x & 0xFFFFFFF0) { n +=  4; x >>=  4; }\n\t\t\tif(x & 0xFFFFFFFC) { n +=  2; x >>=  2; }\n\t\t\tif(x & 0xFFFFFFFE) { n +=  1;           }\n\n\t\t\treturn n;\n\t\t}\n\n\t\treturn 32;\n#endif\n\t}\n\n\ttemplate<typename UInt64>\n\teastl::enable_if_t<detail::is_word_type_v<UInt64> && sizeof(UInt64) == 8, uint32_t> GetLastBit(UInt64 x)\n\t{\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86_64)\n\t\t// This has been benchmarked as significantly faster than the generic code below.\n\t\tunsigned char isNonZero;\n\t\tunsigned long index;\n\t\tisNonZero = _BitScanReverse64(&index, x);\n\t\treturn isNonZero ? (int)index : 64;\n#elif (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) && !defined(EA_COMPILER_EDG)\n\t\tif (x)\n\t\t\treturn 63 - __builtin_clzll(x);\n\t\treturn 64;\n#else\n\t\tif(x)\n\t\t{\n\t\t\tuint32_t n = 0;\n\n\t\t\tif(x & UINT64_C(0xFFFFFFFF00000000)) { n += 32; x >>= 32; }\n\t\t\tif(x & 0xFFFF0000)                   { n += 16; x >>= 16; }\n\t\t\tif(x & 0xFFFFFF00)                   { n +=  8; x >>=  8; }\n\t\t\tif(x & 0xFFFFFFF0)                   { n +=  4; x >>=  4; }\n\t\t\tif(x & 0xFFFFFFFC)                   { n +=  2; x >>=  2; }\n\t\t\tif(x & 0xFFFFFFFE)                   { n +=  1;           }\n\n\t\t\treturn n;\n\t\t}\n\n\t\treturn 64;\n#endif\n\t}\n\n\t#if EASTL_INT128_SUPPORTED\n\t\tinline uint32_t GetLastBit(eastl_uint128_t x)\n\t\t{\n\t\t\tif(x)\n\t\t\t{\n\t\t\t\tuint32_t n = 0;\n\t\t\t\t\n\t\t\t\teastl_uint128_t mask(UINT64_C(0xFFFFFFFFFFFFFFFF)); // There doesn't seem to exist compiler support for INT128_C() by any compiler. EAStdC's int128_t supports it though.\n\t\t\t\tmask <<= 64;\n\n\t\t\t\tif(x & mask)                         { n += 64; x >>= 64; }\n\t\t\t\tif(x & UINT64_C(0xFFFFFFFF00000000)) { n += 32; x >>= 32; }\n\t\t\t\tif(x & UINT64_C(0x00000000FFFF0000)) { n += 16; x >>= 16; }\n\t\t\t\tif(x & UINT64_C(0x00000000FFFFFF00)) { n +=  8; x >>=  8; }\n\t\t\t\tif(x & UINT64_C(0x00000000FFFFFFF0)) { n +=  4; x >>=  4; }\n\t\t\t\tif(x & UINT64_C(0x00000000FFFFFFFC)) { n +=  2; x >>=  2; }\n\t\t\t\tif(x & UINT64_C(0x00000000FFFFFFFE)) { n +=  1;           }\n\n\t\t\t\treturn n;\n\t\t\t}\n\n\t\t\treturn 128;\n\t\t}\n\t#endif\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// BitsetBase\n\t//\n\t// We tried two forms of array access here:\n\t//     for(word_type *pWord(mWord), *pWordEnd(mWord + NW); pWord < pWordEnd; ++pWord)\n\t//         *pWord = ...\n\t// and\n\t//     for(size_t i = 0; i < NW; i++)\n\t//         mWord[i] = ...\n\t//\n\t// For our tests (~NW < 16), the latter (using []) access resulted in faster code. \n\t///////////////////////////////////////////////////////////////////////////\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::operator&=(const this_type& x)\n\t{\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t\tmWord[i] &= x.mWord[i];\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::operator|=(const this_type& x)\n\t{\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t\tmWord[i] |= x.mWord[i];\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::operator^=(const this_type& x)\n\t{\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t\tmWord[i] ^= x.mWord[i];\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::operator<<=(size_type n)\n\t{\n\t\tconst size_type nWordShift = (size_type)(n >> kBitsPerWordShift);\n\n\t\tif(nWordShift)\n\t\t{\n\t\t\tfor(int i = (int)(NW - 1); i >= 0; --i)\n\t\t\t\tmWord[i] = (nWordShift <= (size_type)i) ? mWord[i - nWordShift] : (word_type)0;\n\t\t}\n\n\t\tif(n &= kBitsPerWordMask)\n\t\t{\n\t\t\tfor(size_t i = (NW - 1); i > 0; --i)\n\t\t\t\tmWord[i] = (word_type)((mWord[i] << n) | (mWord[i - 1] >> (kBitsPerWord - n)));\n\t\t\tmWord[0] <<= n;\n\t\t}\n\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::operator>>=(size_type n)\n\t{\n\t\tconst size_type nWordShift = (size_type)(n >> kBitsPerWordShift);\n\n\t\tif(nWordShift)\n\t\t{\n\t\t\tfor(size_t i = 0; i < NW; ++i)\n\t\t\t\tmWord[i] = ((nWordShift < (NW - i)) ? mWord[i + nWordShift] : (word_type)0);\n\t\t}\n\n\t\tif(n &= kBitsPerWordMask)\n\t\t{\n\t\t\tfor(size_t i = 0; i < (NW - 1); ++i)\n\t\t\t\tmWord[i] = (word_type)((mWord[i] >> n) | (mWord[i + 1] << (kBitsPerWord - n)));\n\t\t\tmWord[NW - 1] >>= n;\n\t\t}\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::flip()\n\t{\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t\tmWord[i] = ~mWord[i];\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::set()\n\t{\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t\tmWord[i] = static_cast<word_type>(~static_cast<word_type>(0));\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::set(size_type i, bool value)\n\t{\n\t\tif(value)\n\t\t\tmWord[i >> kBitsPerWordShift] |=  (static_cast<word_type>(1) << (i & kBitsPerWordMask));\n\t\telse\n\t\t\tmWord[i >> kBitsPerWordShift] &= ~(static_cast<word_type>(1) << (i & kBitsPerWordMask));\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline void BitsetBase<NW, WordType>::reset()\n\t{\n\t\tif(NW > 16) // This is a constant expression and should be optimized away.\n\t\t{\n\t\t\t// This will be fastest if compiler intrinsic function optimizations are enabled.\n\t\t\tmemset(mWord, 0, sizeof(mWord));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(size_t i = 0; i < NW; i++)\n\t\t\t\tmWord[i] = 0;\n\t\t}\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline bool BitsetBase<NW, WordType>::operator==(const this_type& x) const\n\t{\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t{\n\t\t\tif(mWord[i] != x.mWord[i])\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline bool BitsetBase<NW, WordType>::any() const\n\t{\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t{\n\t\t\tif(mWord[i])\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline typename BitsetBase<NW, WordType>::size_type\n\tBitsetBase<NW, WordType>::count() const\n\t{\n\t\tsize_type n = 0;\n\t\tfor(size_t i = 0; i < NW; i++)\n\t\t\tn += popcount(mWord[i]);\n\t\treturn n;\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline typename BitsetBase<NW, WordType>::word_type&\n\tBitsetBase<NW, WordType>::DoGetWord(size_type i)\n\t{\n\t\treturn mWord[i >> kBitsPerWordShift];\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline typename BitsetBase<NW, WordType>::word_type\n\tBitsetBase<NW, WordType>::DoGetWord(size_type i) const\n\t{\n\t\treturn mWord[i >> kBitsPerWordShift];\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline typename BitsetBase<NW, WordType>::size_type \n\tBitsetBase<NW, WordType>::DoFindFirst() const\n\t{\n\t\tfor(size_type word_index = 0; word_index < NW; ++word_index)\n\t\t{\n\t\t\tconst size_type fbiw = GetFirstBit(mWord[word_index]);\n\n\t\t\tif(fbiw != kBitsPerWord)\n\t\t\t\treturn (word_index * kBitsPerWord) + fbiw;\n\t\t}\n\n\t\treturn (size_type)NW * kBitsPerWord;\n\t}\n\n\n#if EASTL_DISABLE_BITSET_ARRAYBOUNDS_WARNING\nEA_DISABLE_GCC_WARNING(-Warray-bounds)\n#endif\n\n\ttemplate <size_t NW, typename WordType>\n\tinline typename BitsetBase<NW, WordType>::size_type \n\tBitsetBase<NW, WordType>::DoFindNext(size_type last_find) const\n\t{\n\t\t// Start looking from the next bit.\n\t\t++last_find;\n\n\t\t// Set initial state based on last find.\n\t\tsize_type word_index = static_cast<size_type>(last_find >> kBitsPerWordShift);\n\t\tsize_type bit_index  = static_cast<size_type>(last_find  & kBitsPerWordMask);\n\n\t\t// To do: There probably is a more elegant way to write looping below.\n\t\tif(word_index < NW)\n\t\t{\n\t\t\t// Mask off previous bits of the word so our search becomes a \"find first\".\n\t\t\tword_type this_word = mWord[word_index] & (static_cast<word_type>(~0) << bit_index);\n\n\t\t\tfor(;;)\n\t\t\t{\n\t\t\t\tconst size_type fbiw = GetFirstBit(this_word);\n\n\t\t\t\tif(fbiw != kBitsPerWord)\n\t\t\t\t\treturn (word_index * kBitsPerWord) + fbiw;\n\n\t\t\t\tif(++word_index < NW)\n\t\t\t\t\tthis_word = mWord[word_index];\n\t\t\t\telse\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn (size_type)NW * kBitsPerWord;\n\t}\n\n#if EASTL_DISABLE_BITSET_ARRAYBOUNDS_WARNING\nEA_RESTORE_GCC_WARNING()\n#endif\n\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline typename BitsetBase<NW, WordType>::size_type \n\tBitsetBase<NW, WordType>::DoFindLast() const\n\t{\n\t\tfor(size_type word_index = (size_type)NW; word_index > 0; --word_index)\n\t\t{\n\t\t\tconst size_type lbiw = GetLastBit(mWord[word_index - 1]);\n\n\t\t\tif(lbiw != kBitsPerWord)\n\t\t\t\treturn ((word_index - 1) * kBitsPerWord) + lbiw;\n\t\t}\n\n\t\treturn (size_type)NW * kBitsPerWord;\n\t}\n\n\n\ttemplate <size_t NW, typename WordType>\n\tinline typename BitsetBase<NW, WordType>::size_type \n\tBitsetBase<NW, WordType>::DoFindPrev(size_type last_find) const\n\t{\n\t\tif(last_find > 0)\n\t\t{\n\t\t\t// Set initial state based on last find.\n\t\t\tsize_type word_index = static_cast<size_type>(last_find >> kBitsPerWordShift);\n\t\t\tsize_type bit_index  = static_cast<size_type>(last_find  & kBitsPerWordMask);\n\n\t\t\t// Mask off subsequent bits of the word so our search becomes a \"find last\".\n\t\t\t// We do two shifts here because it's undefined behaviour to right shift greater than or equal to the number of bits in the integer.\n\t\t\t// \n\t\t\t// Note: operator~() is an arithmetic operator and performs integral promotions, ie. small integrals are promoted to an int.\n\t\t\t// Because the promotion is before applying operator~() we need to cast back to our word type otherwise we end up with extraneous set bits.\n\t\t\tword_type mask      = (static_cast<word_type>(~static_cast<word_type>(0)) >> (kBitsPerWord - 1 - bit_index)) >> 1;\n\t\t\tword_type this_word = mWord[word_index] & mask;\n\n\t\t\tfor(;;)\n\t\t\t{\n\t\t\t\tconst size_type lbiw = GetLastBit(this_word);\n\n\t\t\t\tif(lbiw != kBitsPerWord)\n\t\t\t\t\treturn (word_index * kBitsPerWord) + lbiw;\n\n\t\t\t\tif(word_index > 0)\n\t\t\t\t\tthis_word = mWord[--word_index];\n\t\t\t\telse\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn (size_type)NW * kBitsPerWord;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// BitsetBase<1, WordType>\n\t///////////////////////////////////////////////////////////////////////////\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::operator&=(const this_type& x)\n\t{\n\t\tmWord[0] &= x.mWord[0];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::operator|=(const this_type& x)\n\t{\n\t\tmWord[0] |= x.mWord[0];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::operator^=(const this_type& x)\n\t{\n\t\tmWord[0] ^= x.mWord[0];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::operator<<=(size_type n)\n\t{\n\t\tmWord[0] <<= n;\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::operator>>=(size_type n)\n\t{\n\t\tmWord[0] >>= n;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::flip()\n\t{\n\t\tmWord[0] = ~mWord[0];\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::set()\n\t{\n\t\tmWord[0] = static_cast<word_type>(~static_cast<word_type>(0));\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::set(size_type i, bool value)\n\t{\n\t\tif(value)\n\t\t\tmWord[0] |=  (static_cast<word_type>(1) << i);\n\t\telse\n\t\t\tmWord[0] &= ~(static_cast<word_type>(1) << i);\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<1, WordType>::reset()\n\t{\n\t\tmWord[0] = 0;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline bool BitsetBase<1, WordType>::operator==(const this_type& x) const\n\t{\n\t\treturn mWord[0] == x.mWord[0];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline bool BitsetBase<1, WordType>::any() const\n\t{\n\t\treturn mWord[0] != 0;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<1, WordType>::size_type\n\tBitsetBase<1, WordType>::count() const\n\t{\n\t\treturn popcount(mWord[0]);\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<1, WordType>::word_type&\n\tBitsetBase<1, WordType>::DoGetWord(size_type)\n\t{\n\t\treturn mWord[0];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<1, WordType>::word_type\n\tBitsetBase<1, WordType>::DoGetWord(size_type) const\n\t{\n\t\treturn mWord[0];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<1, WordType>::size_type\n\tBitsetBase<1, WordType>::DoFindFirst() const\n\t{\n\t\treturn GetFirstBit(mWord[0]);\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<1, WordType>::size_type \n\tBitsetBase<1, WordType>::DoFindNext(size_type last_find) const\n\t{\n\t\tif(++last_find < kBitsPerWord)\n\t\t{\n\t\t\t// Mask off previous bits of word so our search becomes a \"find first\".\n\t\t\tconst word_type this_word = mWord[0] & (static_cast<word_type>(~0) << last_find);\n\n\t\t\treturn GetFirstBit(this_word);\n\t\t}\n\n\t\treturn kBitsPerWord;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<1, WordType>::size_type \n\tBitsetBase<1, WordType>::DoFindLast() const\n\t{\n\t\treturn GetLastBit(mWord[0]);\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<1, WordType>::size_type \n\tBitsetBase<1, WordType>::DoFindPrev(size_type last_find) const\n\t{\n\t\tif(last_find > 0)\n\t\t{\n\t\t\t// Mask off previous bits of word so our search becomes a \"find first\".\n\t\t\tconst word_type this_word = mWord[0] & (static_cast<word_type>(~static_cast<word_type>(0)) >> (kBitsPerWord - last_find));\n\n\t\t\treturn GetLastBit(this_word);\n\t\t}\n\n\t\treturn kBitsPerWord;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// BitsetBase<2, WordType>\n\t///////////////////////////////////////////////////////////////////////////\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::operator&=(const this_type& x)\n\t{\n\t\tmWord[0] &= x.mWord[0];\n\t\tmWord[1] &= x.mWord[1];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::operator|=(const this_type& x)\n\t{\n\t\tmWord[0] |= x.mWord[0];\n\t\tmWord[1] |= x.mWord[1];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::operator^=(const this_type& x)\n\t{\n\t\tmWord[0] ^= x.mWord[0];\n\t\tmWord[1] ^= x.mWord[1];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::operator<<=(size_type n)\n\t{\n\t\tif(n) // to avoid a shift by kBitsPerWord, which is undefined\n\t\t{\n\t\t\tif(EASTL_UNLIKELY(n >= kBitsPerWord))   // parent expected to handle high bits and n >= 64\n\t\t\t{\n\t\t\t\tmWord[1] = mWord[0];\n\t\t\t\tmWord[0] = 0;\n\t\t\t\tn -= kBitsPerWord;\n\t\t\t}\n\n\t\t\tmWord[1] = (mWord[1] << n) | (mWord[0] >> (kBitsPerWord - n)); // Intentionally use | instead of +.\n\t\t\tmWord[0] <<= n;\n\t\t\t// We let the parent class turn off any upper bits.\n\t\t}\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::operator>>=(size_type n)\n\t{\n\t\tif(n) // to avoid a shift by kBitsPerWord, which is undefined\n\t\t{\n\t\t\tif(EASTL_UNLIKELY(n >= kBitsPerWord))   // parent expected to handle n >= 64\n\t\t\t{\n\t\t\t\tmWord[0] = mWord[1];\n\t\t\t\tmWord[1] = 0;\n\t\t\t\tn -= kBitsPerWord;\n\t\t\t}\n\t\t\t\n\t\t\tmWord[0] = (mWord[0] >> n) | (mWord[1] << (kBitsPerWord - n)); // Intentionally use | instead of +.\n\t\t\tmWord[1] >>= n;\n\t\t}\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::flip()\n\t{\n\t\tmWord[0] = ~mWord[0];\n\t\tmWord[1] = ~mWord[1];\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::set()\n\t{\n\t\tEA_DISABLE_VC_WARNING(4245); // '=': conversion from 'int' to 'unsigned short', signed/unsigned mismatch \n\t\t// https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-4-c4245?view=msvc-170\n\t\t// MSVC incorrectly believes 0 is a negative value.\n\t\tmWord[0] = ~static_cast<word_type>(0);\n\t\tmWord[1] = ~static_cast<word_type>(0);\n\t\tEA_RESTORE_VC_WARNING();\n\t\t// We let the parent class turn off any upper bits.\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::set(size_type i, bool value)\n\t{\n\t\tif(value)\n\t\t\tmWord[i >> kBitsPerWordShift] |=  (static_cast<word_type>(1) << (i & kBitsPerWordMask));\n\t\telse\n\t\t\tmWord[i >> kBitsPerWordShift] &= ~(static_cast<word_type>(1) << (i & kBitsPerWordMask));\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline void BitsetBase<2, WordType>::reset()\n\t{\n\t\tmWord[0] = 0;\n\t\tmWord[1] = 0;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline bool BitsetBase<2, WordType>::operator==(const this_type& x) const\n\t{\n\t\treturn (mWord[0] == x.mWord[0]) && (mWord[1] == x.mWord[1]);\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline bool BitsetBase<2, WordType>::any() const\n\t{\n\t\t// Or with two branches: { return (mWord[0] != 0) || (mWord[1] != 0); }\n\t\treturn (mWord[0] | mWord[1]) != 0; \n\t}\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<2, WordType>::size_type\n\tBitsetBase<2, WordType>::count() const\n\t{\n\t\treturn popcount(mWord[0]) + popcount(mWord[1]);\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<2, WordType>::word_type&\n\tBitsetBase<2, WordType>::DoGetWord(size_type i)\n\t{\n\t\treturn mWord[i >> kBitsPerWordShift];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<2, WordType>::word_type\n\tBitsetBase<2, WordType>::DoGetWord(size_type i) const\n\t{\n\t\treturn mWord[i >> kBitsPerWordShift];\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<2, WordType>::size_type \n\tBitsetBase<2, WordType>::DoFindFirst() const\n\t{\n\t\tsize_type fbiw = GetFirstBit(mWord[0]);\n\n\t\tif(fbiw != kBitsPerWord)\n\t\t\treturn fbiw;\n\n\t\tfbiw = GetFirstBit(mWord[1]);\n\n\t\tif(fbiw != kBitsPerWord)\n\t\t\treturn kBitsPerWord + fbiw;\n\n\t\treturn 2 * kBitsPerWord;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<2, WordType>::size_type \n\tBitsetBase<2, WordType>::DoFindNext(size_type last_find) const\n\t{\n\t\t// If the last find was in the first word, we must check it and then possibly the second.\n\t\tif(++last_find < (size_type)kBitsPerWord)\n\t\t{\n\t\t\t// Mask off previous bits of word so our search becomes a \"find first\".\n\t\t\tword_type this_word = mWord[0] & (static_cast<word_type>(~0) << last_find);\n\n\t\t\t// Step through words.\n\t\t\tsize_type fbiw = GetFirstBit(this_word);\n\n\t\t\tif(fbiw != kBitsPerWord)\n\t\t\t\treturn fbiw;\n\n\t\t\tfbiw = GetFirstBit(mWord[1]);\n\n\t\t\tif(fbiw != kBitsPerWord)\n\t\t\t\treturn kBitsPerWord + fbiw;\n\t\t}\n\t\telse if(last_find < (size_type)(2 * kBitsPerWord))\n\t\t{\n\t\t\t// The last find was in the second word, remove the bit count of the first word from the find.\n\t\t\tlast_find -= kBitsPerWord;\n\n\t\t\t// Mask off previous bits of word so our search becomes a \"find first\".\n\t\t\tword_type this_word = mWord[1] & (static_cast<word_type>(~0) << last_find);\n\n\t\t\tconst size_type fbiw = GetFirstBit(this_word);\n\n\t\t\tif(fbiw != kBitsPerWord)\n\t\t\t\treturn kBitsPerWord + fbiw;\n\t\t}\n\n\t\treturn 2 * kBitsPerWord;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<2, WordType>::size_type \n\tBitsetBase<2, WordType>::DoFindLast() const\n\t{\n\t\tsize_type lbiw = GetLastBit(mWord[1]);\n\n\t\tif(lbiw != kBitsPerWord)\n\t\t\treturn kBitsPerWord + lbiw;\n\n\t\tlbiw = GetLastBit(mWord[0]);\n\n\t\tif(lbiw != kBitsPerWord)\n\t\t\treturn lbiw;\n\n\t\treturn 2 * kBitsPerWord;\n\t}\n\n\n\ttemplate <typename WordType>\n\tinline typename BitsetBase<2, WordType>::size_type \n\tBitsetBase<2, WordType>::DoFindPrev(size_type last_find) const\n\t{\n\t\t// If the last find was in the second word, we must check it and then possibly the first.\n\t\tif(last_find > (size_type)kBitsPerWord)\n\t\t{\n\t\t\t// This has the same effect as last_find %= kBitsPerWord in our case.\n\t\t\tlast_find -= kBitsPerWord;\n\n\t\t\t// Mask off previous bits of word so our search becomes a \"find first\".\n\t\t\tword_type this_word = mWord[1] & (static_cast<word_type>(~static_cast<word_type>(0)) >> (kBitsPerWord - last_find));\n\n\t\t\t// Step through words.\n\t\t\tsize_type lbiw = GetLastBit(this_word);\n\n\t\t\tif(lbiw != kBitsPerWord)\n\t\t\t\treturn kBitsPerWord + lbiw;\n\n\t\t\tlbiw = GetLastBit(mWord[0]);\n\n\t\t\tif(lbiw != kBitsPerWord)\n\t\t\t\treturn lbiw;\n\t\t}\n\t\telse if(last_find != 0)\n\t\t{\n\t\t\t// Mask off previous bits of word so our search becomes a \"find first\".\n\t\t\tword_type this_word = mWord[0] & (static_cast<word_type>(~static_cast<word_type>(0)) >> (kBitsPerWord - last_find));\n\n\t\t\tconst size_type lbiw = GetLastBit(this_word);\n\n\t\t\tif(lbiw != kBitsPerWord)\n\t\t\t\treturn lbiw;\n\t\t}\n\n\t\treturn 2 * kBitsPerWord;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// bitset::reference\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <size_t N, typename WordType>\n\tinline bitset<N, WordType>::reference::reference(const bitset& x, size_type i)\n\t\t: mpBitWord(&const_cast<bitset&>(x).DoGetWord(i)),\n\t\t  mnBitIndex(i & kBitsPerWordMask)\n\t{   // We have an issue here because the above is casting away the const-ness of the source bitset.\n\t\t// Empty\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::reference&\n\tbitset<N, WordType>::reference::operator=(bool value)\n\t{\n\t\tif(value)\n\t\t\t*mpBitWord |=  (static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask));\n\t\telse\n\t\t\t*mpBitWord &= ~(static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask));\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::reference&\n\tbitset<N, WordType>::reference::operator=(const reference& x)\n\t{\n\t\tif(*x.mpBitWord & (static_cast<word_type>(1) << (x.mnBitIndex & kBitsPerWordMask)))\n\t\t\t*mpBitWord |=  (static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask));\n\t\telse\n\t\t\t*mpBitWord &= ~(static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask));\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline bool bitset<N, WordType>::reference::operator~() const\n\t{\n\t\treturn (*mpBitWord & (static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask))) == 0;\n\t}\n\n\n\t//Defined inline in the class because Metrowerks fails to be able to compile it here.\n\t//template <size_t N, typename WordType>\n\t//inline bitset<N, WordType>::reference::operator bool() const\n\t//{\n\t//    return (*mpBitWord & (static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask))) != 0;\n\t//}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::reference&\n\tbitset<N, WordType>::reference::flip()\n\t{\n\t\t*mpBitWord ^= static_cast<word_type>(1) << (mnBitIndex & kBitsPerWordMask);\n\t\treturn *this;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// bitset\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <size_t N, typename WordType>\n\tinline bitset<N, WordType>::bitset()\n\t{\n\t\treset();\n\t}\n\n\tEA_DISABLE_VC_WARNING(6313)\n#if EA_IS_ENABLED(EASTL_DEPRECATIONS_FOR_2024_SEPT)\n\ttemplate <size_t N, typename WordType>\n\tinline bitset<N, WordType>::bitset(unsigned long long value)\n\t{\n\t\tdetail::from_unsigned_integral(*this, value);\n\t}\n#else\n\ttemplate <size_t N, typename WordType>\n\tinline bitset<N, WordType>::bitset(uint32_t value)\n\t{\n\t\tdetail::from_unsigned_integral(*this, value);\n\t}\n#endif\n\tEA_RESTORE_VC_WARNING()\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::operator&=(const this_type& x)\n\t{\n\t\tbase_type::operator&=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::operator|=(const this_type& x)\n\t{\n\t\tbase_type::operator|=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::operator^=(const this_type& x)\n\t{\n\t\tbase_type::operator^=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::operator<<=(size_type n)\n\t{\n\t\tif(EASTL_LIKELY((intptr_t)n < (intptr_t)N))\n\t\t{\n\t\t\tEA_DISABLE_VC_WARNING(6313)\n\t\t\tbase_type::operator<<=(n);\n\t\t\tif((N & kBitsPerWordMask) || (N == 0)) // If there are any high bits to clear... (If we didn't have this check, then the code below would do the wrong thing when N == 32.\n\t\t\t\tmWord[kWordCount - 1] &= ~(static_cast<word_type>(~static_cast<word_type>(0)) << (N & kBitsPerWordMask)); // This clears any high unused bits. We need to do this so that shift operations proceed correctly.\n\t\t\tEA_RESTORE_VC_WARNING()\n\t\t}\n\t\telse\n\t\t\tbase_type::reset();\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::operator>>=(size_type n)\n\t{\n\t\tif(EASTL_LIKELY(n < N))\n\t\t\tbase_type::operator>>=(n);\n\t\telse\n\t\t\tbase_type::reset();\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::set()\n\t{\n\t\tbase_type::set(); // This sets all bits.\n\t\tif((N & kBitsPerWordMask) || (N == 0)) // If there are any high bits to clear... (If we didn't have this check, then the code below would do the wrong thing when N == 32.\n\t\t\tmWord[kWordCount - 1] &= ~(static_cast<word_type>(~static_cast<word_type>(0)) << (N & kBitsPerWordMask)); // This clears any high unused bits. We need to do this so that shift operations proceed correctly.\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::set(size_type i, bool value)\n\t{\n\t\tif(i < N)\n\t\t\tbase_type::set(i, value);\n\t\telse\n\t\t{\n\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(!(i < N)))\n\t\t\t\t\tEASTL_FAIL_MSG(\"bitset::set -- out of range\");\n\t\t\t#endif\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow std::out_of_range(\"bitset::set\");\n\t\t\t#endif\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::reset()\n\t{\n\t\tbase_type::reset();\n\t\treturn *this;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::reset(size_type i)\n\t{\n\t\tif(EASTL_LIKELY(i < N))\n\t\t\tDoGetWord(i) &= ~(static_cast<word_type>(1) << (i & kBitsPerWordMask));\n\t\telse\n\t\t{\n\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(!(i < N)))\n\t\t\t\t\tEASTL_FAIL_MSG(\"bitset::reset -- out of range\");\n\t\t\t#endif\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow std::out_of_range(\"bitset::reset\");\n\t\t\t#endif\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\t\t\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::flip()\n\t{\n\t\tEA_DISABLE_VC_WARNING(6313)\n\t\tbase_type::flip();\n\t\tif((N & kBitsPerWordMask) || (N == 0)) // If there are any high bits to clear... (If we didn't have this check, then the code below would do the wrong thing when N == 32.\n\t\t\tmWord[kWordCount - 1] &= ~(static_cast<word_type>(~static_cast<word_type>(0)) << (N & kBitsPerWordMask)); // This clears any high unused bits. We need to do this so that shift operations proceed correctly.\n\t\treturn *this;\n\t\tEA_RESTORE_VC_WARNING()\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type&\n\tbitset<N, WordType>::flip(size_type i)\n\t{\n\t\tif(EASTL_LIKELY(i < N))\n\t\t\tDoGetWord(i) ^= (static_cast<word_type>(1) << (i & kBitsPerWordMask));\n\t\telse\n\t\t{\n\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(!(i < N)))\n\t\t\t\t\tEASTL_FAIL_MSG(\"bitset::flip -- out of range\");\n\t\t\t#endif\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow std::out_of_range(\"bitset::flip\");\n\t\t\t#endif\n\t\t}\n\t\treturn *this;\n\t}\n\t\t\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type\n\tbitset<N, WordType>::operator~() const\n\t{\n\t\treturn this_type(*this).flip();\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::reference\n\tbitset<N, WordType>::operator[](size_type i)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(!(i < N)))\n\t\t\t\tEASTL_FAIL_MSG(\"bitset::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn reference(*this, i);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline bool bitset<N, WordType>::operator[](size_type i) const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(!(i < N)))\n\t\t\t\tEASTL_FAIL_MSG(\"bitset::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn (DoGetWord(i) & (static_cast<word_type>(1) << (i & kBitsPerWordMask))) != 0;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline const typename bitset<N, WordType>::word_type* bitset<N, WordType>::data() const\n\t{\n\t\treturn base_type::mWord;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::word_type* bitset<N, WordType>::data()\n\t{\n\t\treturn base_type::mWord;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline void bitset<N, WordType>::from_uint32(uint32_t value)\n\t{\n\t\tdetail::from_unsigned_integral(*this, value);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline void bitset<N, WordType>::from_uint64(uint64_t value)\n\t{\n\t\tdetail::from_unsigned_integral(*this, value);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline unsigned long bitset<N, WordType>::to_ulong() const\n\t{\n\t\treturn detail::to_unsigned_integral<unsigned long, false>(*this);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline uint32_t bitset<N, WordType>::to_uint32() const\n\t{\n\t\treturn detail::to_unsigned_integral<uint32_t, false>(*this);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline uint64_t bitset<N, WordType>::to_uint64() const\n\t{\n\t\treturn detail::to_unsigned_integral<uint64_t, false>(*this);\n\t}\n\n\n\t// template <size_t N, typename WordType>\n\t// inline typename bitset<N, WordType>::size_type\n\t// bitset<N, WordType>::count() const\n\t// {\n\t//     return base_type::count();\n\t// }\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::size_type\n\tbitset<N, WordType>::size() const\n\t{\n\t\treturn (size_type)N;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline bool bitset<N, WordType>::operator==(const this_type& x) const\n\t{\n\t\treturn base_type::operator==(x);\n\t}\n\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <size_t N, typename WordType>\n\tinline bool bitset<N, WordType>::operator!=(const this_type& x) const\n\t{\n\t\treturn !base_type::operator==(x);\n\t}\n#endif\n\n\ttemplate <size_t N, typename WordType>\n\tinline bool bitset<N, WordType>::test(size_type i) const\n\t{\n\t\tif(EASTL_UNLIKELY(i < N))\n\t\t\treturn (DoGetWord(i) & (static_cast<word_type>(1) << (i & kBitsPerWordMask))) != 0;\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tEASTL_FAIL_MSG(\"bitset::test -- out of range\");\n\t\t#endif\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tthrow std::out_of_range(\"bitset::test\");\n\t\t#else\n\t\t\treturn false;\n\t\t#endif\n\t}\n\n\n\t// template <size_t N, typename WordType>\n\t// inline bool bitset<N, WordType>::any() const\n\t// {\n\t//     return base_type::any();\n\t// }\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline bool bitset<N, WordType>::all() const\n\t{\n\t\treturn count() == size();\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline bool bitset<N, WordType>::none() const\n\t{\n\t\treturn !base_type::any();\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type\n\tbitset<N, WordType>::operator<<(size_type n) const\n\t{\n\t\treturn this_type(*this).operator<<=(n);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::this_type\n\tbitset<N, WordType>::operator>>(size_type n) const\n\t{\n\t\treturn this_type(*this).operator>>=(n);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::size_type\n\tbitset<N, WordType>::find_first() const\n\t{\n\t\tconst size_type i = base_type::DoFindFirst();\n\n\t\tif(i < kSize)\n\t\t\treturn i;\n\t\t// Else i could be the base type bit count, so we clamp it to our size.\n\n\t\treturn kSize;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::size_type\n\tbitset<N, WordType>::find_next(size_type last_find) const\n\t{\n\t\tconst size_type i = base_type::DoFindNext(last_find);\n\n\t\tif(i < kSize)\n\t\t\treturn i;\n\t\t// Else i could be the base type bit count, so we clamp it to our size.\n\n\t\treturn kSize;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::size_type\n\tbitset<N, WordType>::find_last() const\n\t{\n\t\tconst size_type i = base_type::DoFindLast();\n\n\t\tif(i < kSize)\n\t\t\treturn i;\n\t\t// Else i could be the base type bit count, so we clamp it to our size.\n\n\t\treturn kSize;\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline typename bitset<N, WordType>::size_type\n\tbitset<N, WordType>::find_prev(size_type last_find) const\n\t{\n\t\tconst size_type i = base_type::DoFindPrev(last_find);\n\n\t\tif(i < kSize)\n\t\t\treturn i;\n\t\t// Else i could be the base type bit count, so we clamp it to our size.\n\n\t\treturn kSize;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <size_t N, typename WordType>\n\tinline bitset<N, WordType> operator&(const bitset<N, WordType>& a, const bitset<N, WordType>& b)\n\t{\n\t\t// We get betting inlining when we don't declare temporary variables.\n\t\treturn bitset<N, WordType>(a).operator&=(b);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline bitset<N, WordType> operator|(const bitset<N, WordType>& a, const bitset<N, WordType>& b)\n\t{\n\t\treturn bitset<N, WordType>(a).operator|=(b);\n\t}\n\n\n\ttemplate <size_t N, typename WordType>\n\tinline bitset<N, WordType> operator^(const bitset<N, WordType>& a, const bitset<N, WordType>& b)\n\t{\n\t\treturn bitset<N, WordType>(a).operator^=(b);\n\t}\n\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/bitvector.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Implements a bit vector, which is essentially a vector of bool but which\n// uses bits instead of bytes. It is thus similar to the original std::vector<bool>.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Note: This code is not yet complete: it isn't tested and doesn't yet \n//       support containers other than vector.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_BITVECTOR_H\n#define EASTL_BITVECTOR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/vector.h>\n#include <EASTL/fixed_vector.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/bitset.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\nEA_DISABLE_VC_WARNING(4480); // nonstandard extension used: specifying underlying type for enum\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_BITVECTOR_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_BITVECTOR_DEFAULT_NAME\n\t\t#define EASTL_BITVECTOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" bitvector\" // Unless the user overrides something, this is \"EASTL bitvector\".\n\t#endif\n\n\t/// EASTL_BITVECTOR_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_BITVECTOR_DEFAULT_ALLOCATOR\n\t\t#define EASTL_BITVECTOR_DEFAULT_ALLOCATOR allocator_type(EASTL_BITVECTOR_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// BitvectorWordType\n\t/// Defines the integral data type used by bitvector.\n\ttypedef EASTL_BITSET_WORD_TYPE_DEFAULT BitvectorWordType;\n\n\n\ttemplate <typename Element>\n\tclass bitvector_const_iterator;\n\n\n\ttemplate <typename Element>\n\tclass bitvector_reference\n\t{\n\tpublic:\n\t\ttypedef eastl_size_t size_type;\n\t\tbitvector_reference(Element* ptr, eastl_size_t i);\n\t\tbitvector_reference(const bitvector_reference& other);\n\n\t\tbitvector_reference& operator=(bool value);\n\t\tbitvector_reference& operator=(const bitvector_reference& rhs);\n\n\t\toperator bool() const // Defined here because some compilers fail otherwise.\n\t\t\t{ return (*mpBitWord & (Element(1) << mnBitIndex)) != 0; }\n\n\tprotected:\n\t\tfriend class bitvector_const_iterator<Element>;\n\n\t\tElement*  mpBitWord;\n\t\tsize_type mnBitIndex;\n\n\t\tbitvector_reference() {}\n\t\tvoid CopyFrom(const bitvector_reference& rhs);\n\t};\n\n\n\n\ttemplate <typename Element>\n\tclass bitvector_const_iterator\n\t{\n\tpublic:\n\t\ttypedef eastl::random_access_iterator_tag iterator_category;\n\t\ttypedef bitvector_const_iterator<Element>        this_type;\n\t\ttypedef bool                                     value_type;\n\t\ttypedef bitvector_reference<Element>             reference_type;\n\t\ttypedef ptrdiff_t                                difference_type;\n\t\ttypedef Element                                  element_type;\n\t\ttypedef element_type*                            pointer;           // This is wrong. It needs to be someting that acts as a pointer to a bit.\n\t\ttypedef element_type&                            reference;         // This is not right. It needs to be someting that acts as a pointer to a bit.\n\t\ttypedef eastl_size_t                             size_type;\n\n\tprotected:\n\t\treference_type mReference;\n\n\t\tenum\n\t\t{\n\t\t\tkBitCount = (8 * sizeof(Element))\n\t\t};\n\n\tpublic:\n\t\tbool operator*() const;\n\t\tbool operator[](difference_type n) const;\n\n\t\tbitvector_const_iterator();\n\t\tbitvector_const_iterator(const element_type* p, eastl_size_t i);\n\t\tbitvector_const_iterator(const reference_type& referenceType);\n\t\tbitvector_const_iterator(const bitvector_const_iterator& other);\n\n\t\tbitvector_const_iterator& operator++();\n\t\tbitvector_const_iterator  operator++(int);\n\t\tbitvector_const_iterator& operator--();\n\t\tbitvector_const_iterator  operator--(int);\n\n\t\tbitvector_const_iterator& operator+=(difference_type dist);\n\t\tbitvector_const_iterator& operator-=(difference_type dist);\n\t\tbitvector_const_iterator  operator+ (difference_type dist) const;\n\t\tbitvector_const_iterator  operator- (difference_type dist) const;\n\n\t\tdifference_type operator-(const this_type& rhs) const;\n\n\t\tbitvector_const_iterator& operator= (const this_type& rhs);\n\n\t\tbool operator==(const this_type& rhs) const;\n\t\tbool operator!=(const this_type& rhs) const;\n\n\t\tbool operator< (const this_type& rhs) const;\n\t\tbool operator<=(const this_type& rhs) const;\n\t\tbool operator> (const this_type& rhs) const;\n\t\tbool operator>=(const this_type& rhs) const;\n\n\t\tint validate(const element_type* pStart, const element_type* pEnd, eastl_size_t nExtraBits) const;\n\n\tprotected:\n\t\ttemplate <typename, typename, typename>\n\t\tfriend class bitvector;\n\n\t\treference_type& get_reference_type() { return mReference; }\n\t};\n\n\n\n\ttemplate <typename Element>\n\tclass bitvector_iterator : public bitvector_const_iterator<Element>\n\t{\n\tpublic:\n\t\ttypedef eastl::random_access_iterator_tag iterator_category;\n\t\ttypedef bitvector_iterator                       this_type;\n\t\ttypedef bitvector_const_iterator<Element>        base_type;\n\t\ttypedef bool                                     value_type;\n\t\ttypedef bitvector_reference<Element>             reference_type;\n\t\ttypedef ptrdiff_t                                difference_type;\n\t\ttypedef Element                                  element_type;\n\t\ttypedef element_type*                            pointer;           // This is wrong. It needs to be someting that acts as a pointer to a bit.\n\t\ttypedef element_type&                            reference;         // This is not right. It needs to be someting that acts as a pointer to a bit.\n\n\tpublic:\n\t\treference_type operator*() const;\n\t\treference_type operator[](difference_type n) const;\n\n\t\tbitvector_iterator();\n\t\tbitvector_iterator(element_type* p, eastl_size_t i);\n\t\tbitvector_iterator(reference_type& referenceType);\n\n\t\tbitvector_iterator& operator++()    { base_type::operator++(); return *this; }\n\t\tbitvector_iterator& operator--()    { base_type::operator--(); return *this; }\n\t\tbitvector_iterator  operator++(int);\n\t\tbitvector_iterator  operator--(int);\n\n\t\tbitvector_iterator& operator+=(difference_type dist) { base_type::operator+=(dist); return *this; }\n\t\tbitvector_iterator& operator-=(difference_type dist) { base_type::operator-=(dist); return *this; }\n\t\tbitvector_iterator  operator+ (difference_type dist) const;\n\t\tbitvector_iterator  operator- (difference_type dist) const;\n\n\t\t// We need this here because we are overloading operator-, so for some reason the\n\t\t// other overload of the function can't be found unless it's explicitly specified.\n\t\tdifference_type operator-(const base_type& rhs) const { return base_type::operator-(rhs); }\n\t};\n\n\n\n\t/// bitvector\n\t///\n\t/// Implements an array of bits treated as boolean values.\n\t/// bitvector is similar to vector<bool> but uses bits instead of bytes and \n\t/// allows the user to use other containers such as deque instead of vector.\n\t/// bitvector is different from bitset in that bitset is less flexible but\n\t/// uses less memory and has higher performance.\n\t///\n\t/// To consider: Rename the Element template parameter to WordType, for \n\t/// consistency with bitset.\n\t///\n\ttemplate <typename Allocator = EASTLAllocatorType, \n\t\t\t  typename Element   = BitvectorWordType, \n\t\t\t  typename Container = eastl::vector<Element, Allocator> >\n\tclass bitvector\n\t{\n\tpublic:\n\t\ttypedef bitvector<Allocator, Element, Container>    this_type;\n\t\ttypedef bool                                        value_type;\n\t\ttypedef bitvector_reference<Element>                reference;\n\t\ttypedef bool                                        const_reference;\n\t\ttypedef bitvector_iterator<Element>                 iterator;\n\t\ttypedef bitvector_const_iterator<Element>           const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>           reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>     const_reverse_iterator;\n\t\ttypedef Allocator                                   allocator_type;\n\t\ttypedef Element                                     element_type;\n\t\ttypedef Container                                   container_type;\n\t\ttypedef eastl_size_t                                size_type;\n\t\ttypedef ptrdiff_t                                   difference_type;\n\n\t\t#if defined(_MSC_VER) && (_MSC_VER >= 1400) && (_MSC_VER <= 1600) && !EASTL_STD_CPP_ONLY  // _MSC_VER of 1400 means VS2005, 1600 means VS2010. VS2012 generates errors with usage of enum:size_type.\n\t\t\tenum : size_type {                      // Use Microsoft enum language extension, allowing for smaller debug symbols than using a static const. Users have been affected by this.\n\t\t\t\tnpos     = container_type::npos,\n\t\t\t\tkMaxSize = container_type::kMaxSize\n\t\t\t};\n\t\t#else\n\t\t\tstatic const size_type npos     = container_type::npos;      /// 'npos' means non-valid position or simply non-position.\n\t\t\tstatic const size_type kMaxSize = container_type::kMaxSize;  /// -1 is reserved for 'npos'. It also happens to be slightly beneficial that kMaxSize is a value less than -1, as it helps us deal with potential integer wraparound issues.\n\t\t#endif\n\n\t\tenum\n\t\t{\n\t\t\tkBitCount = 8 * sizeof(Element)\n\t\t};\n\n\tprotected:\n\t\tcontainer_type mContainer;\n\t\tsize_type      mFreeBitCount;      // Unused bits in the last word of mContainer.\n\n\tpublic:\n\t\tbitvector();\n\t\texplicit bitvector(const allocator_type& allocator);\n\t\texplicit bitvector(size_type n, const allocator_type& allocator = EASTL_BITVECTOR_DEFAULT_ALLOCATOR);\n\t\tbitvector(size_type n, value_type value, const allocator_type& allocator = EASTL_BITVECTOR_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tbitvector(InputIterator first, InputIterator last);\n\n\t\tvoid swap(this_type& x);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid assign(InputIterator first, InputIterator last);\n\n\t\titerator       begin() EA_NOEXCEPT;\n\t\tconst_iterator begin() const EA_NOEXCEPT;\n\t\tconst_iterator cbegin() const EA_NOEXCEPT;\n\n\t\titerator       end() EA_NOEXCEPT;\n\t\tconst_iterator end() const EA_NOEXCEPT;\n\t\tconst_iterator cend() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rbegin() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crbegin() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rend() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rend() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crend() const EA_NOEXCEPT;\n\n\t\tbool      empty() const EA_NOEXCEPT;\n\t\tsize_type size() const EA_NOEXCEPT;\n\t\tsize_type capacity() const EA_NOEXCEPT;\n\n\t\tvoid resize(size_type n, value_type value);\n\t\tvoid resize(size_type n);\n\t\tvoid reserve(size_type n);\n\t\tvoid set_capacity(size_type n = npos);                  // Revises the capacity to the user-specified value. Resizes the container to match the capacity if the requested capacity n is less than the current size. If n == npos then the capacity is reallocated (if necessary) such that capacity == size.\n\n\t\tvoid push_back();\n\t\tvoid push_back(value_type value);\n\t\tvoid pop_back();\n\n\t\treference       front();\n\t\tconst_reference front() const;\n\t\treference       back();\n\t\tconst_reference back() const;\n\n\t\tbool            test(size_type n, bool defaultValue) const; // Returns true if the bit index is < size() and set. Returns defaultValue if the bit is >= size().\n\t\tvoid            set(size_type n, bool value);               // Resizes the container to accomodate n if necessary. \n\n\t\treference       at(size_type n);                    // throws an out_of_range exception if n is invalid.\n\t\tconst_reference at(size_type n) const;\n\n\t\treference       operator[](size_type n);            // behavior is undefined if n is invalid.\n\t\tconst_reference operator[](size_type n) const;\n\n\t\t/*\n\t\tWork in progress:\n\t\ttemplate <bool value = true> iterator find_first();                                 // Finds the lowest \"on\" bit.\n\t\ttemplate <bool value = true> iterator find_next(const_iterator it);                 // Finds the next lowest \"on\" bit after it.\n\t\ttemplate <bool value = true> iterator find_last();                                  // Finds the index of the last \"on\" bit, returns size if none are set.\n\t\ttemplate <bool value = true> iterator find_prev(const_iterator it);                 // Finds the index of the last \"on\" bit before last_find, returns size if none are set.\n\n\t\ttemplate <bool value = true> const_iterator find_first() const;                     // Finds the lowest \"on\" bit.\n\t\ttemplate <bool value = true> const_iterator find_next(const_iterator it) const;     // Finds the next lowest \"on\" bit after it.\n\t\ttemplate <bool value = true> const_iterator find_last() const;                      // Finds the index of the last \"on\" bit, returns size if none are set.\n\t\ttemplate <bool value = true> const_iterator find_prev(const_iterator it) const;     // Finds the index of the last \"on\" bit before last_find, returns size if none are set.\n\t\t*/\n\n\t\telement_type*       data() EA_NOEXCEPT;\n\t\tconst element_type* data() const EA_NOEXCEPT;\n\t\t\n\t\titerator insert(const_iterator position, value_type value);\n\t\tvoid     insert(const_iterator position, size_type n, value_type value);\n\n\t\t// template <typename InputIterator> Not yet implemented. See below for disabled definition.\n\t\t// void insert(const_iterator position, InputIterator first, InputIterator last);\n\n\t\titerator erase(const_iterator position);\n\t\titerator erase(const_iterator first, const_iterator last);\n\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\tvoid clear();\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tcontainer_type&       get_container();\n\t\tconst container_type& get_container() const;\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\t\tbool any() const;\n\t\tbool all() const;\n\t};\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// bitvector_reference\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Element>\n\tbitvector_reference<Element>::bitvector_reference(Element* p, eastl_size_t i)\n\t  : mpBitWord(p), \n\t\tmnBitIndex(i)\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_reference<Element>::bitvector_reference(const bitvector_reference& other)\n\t  : mpBitWord(other.mpBitWord), \n\t\tmnBitIndex(other.mnBitIndex)\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_reference<Element>&\n\tbitvector_reference<Element>::operator=(bool value)\n\t{\n\t\tconst Element mask = (Element)(Element(1) << mnBitIndex);\n\n\t\tif(value)\n\t\t\t*mpBitWord |= mask;\n\t\telse\n\t\t\t*mpBitWord &= ~mask;\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_reference<Element>&\n\tbitvector_reference<Element>::operator=(const bitvector_reference& rhs)\n\t{\n\t\treturn (*this = (bool)rhs);\n\t}\n\n\n\ttemplate <typename Element>\n\tvoid bitvector_reference<Element>::CopyFrom(const bitvector_reference& rhs)\n\t{\n\t\tmpBitWord  = rhs.mpBitWord;\n\t\tmnBitIndex = rhs.mnBitIndex;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// bitvector_const_iterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>::bitvector_const_iterator()\n\t\t: mReference(0, 0)\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>::bitvector_const_iterator(const Element* p, eastl_size_t i)\n\t\t: mReference(const_cast<Element*>(p), i) // const_cast is safe here because we never let mReference leak and we don't modify it.\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>::bitvector_const_iterator(const reference_type& reference)\n\t\t: mReference(reference)\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>::bitvector_const_iterator(const bitvector_const_iterator& other)\n\t\t: mReference(other.mReference)\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>&\n\tbitvector_const_iterator<Element>::operator++()\n\t{\n\t\t++mReference.mnBitIndex;\n\n\t\tif(mReference.mnBitIndex == kBitCount)\n\t\t{\n\t\t\t++mReference.mpBitWord;\n\t\t\tmReference.mnBitIndex = 0;\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>&\n\tbitvector_const_iterator<Element>::operator--()\n\t{\n\t\tif(mReference.mnBitIndex == 0)\n\t\t{\n\t\t\t--mReference.mpBitWord;\n\t\t\tmReference.mnBitIndex = kBitCount;\n\t\t}\n\n\t\t--mReference.mnBitIndex;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>\n\tbitvector_const_iterator<Element>::operator++(int)\n\t{\n\t\tbitvector_const_iterator copy(*this);\n\t\t++*this;\n\t\treturn copy;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>\n\tbitvector_const_iterator<Element>::operator--(int)\n\t{\n\t\tbitvector_const_iterator copy(*this);\n\t\t--*this;\n\t\treturn copy;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>&\n\tbitvector_const_iterator<Element>::operator+=(difference_type n)\n\t{\n\t\tn += mReference.mnBitIndex;\n\n\t\tif(n >= difference_type(0))\n\t\t{\n\t\t\tmReference.mpBitWord  += n / kBitCount;\n\t\t\tmReference.mnBitIndex  = (size_type)(n % kBitCount);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// backwards is tricky\n\t\t\t// figure out how many full words backwards we need to move\n\t\t\t// n = [-1..-32] => 1\n\t\t\t// n = [-33..-64] => 2\n\t\t\tconst size_type backwards = (size_type)(-n + kBitCount - 1);\n\t\t\tmReference.mpBitWord -= backwards / kBitCount;\n\n\t\t\t// -1 => 31; backwards = 32; 31 - (backwards % 32) = 31\n\t\t\t// -2 => 30; backwards = 33; 31 - (backwards % 32) = 30\n\t\t\t// -3 => 29; backwards = 34\n\t\t\t// ..\n\t\t\t// -32 => 0; backwards = 63; 31 - (backwards % 32) = 0\n\t\t\t// -33 => 31; backwards = 64; 31 - (backwards % 32) = 31\n\t\t\tmReference.mnBitIndex = (kBitCount - 1) - (backwards % kBitCount);\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>&\n\tbitvector_const_iterator<Element>::operator-=(difference_type n)\n\t{\n\t\treturn (*this += -n);\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>\n\tbitvector_const_iterator<Element>::operator+(difference_type n) const\n\t{\n\t\tbitvector_const_iterator copy(*this);\n\t\tcopy += n;\n\t\treturn copy;\n\t}\n\n\t\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>\n\tbitvector_const_iterator<Element>::operator-(difference_type n) const\n\t{\n\t\tbitvector_const_iterator copy(*this);\n\t\tcopy -= n;\n\t\treturn copy;\n\t}\n\n\n\ttemplate <typename Element>\n\ttypename bitvector_const_iterator<Element>::difference_type\n\tbitvector_const_iterator<Element>::operator-(const this_type& rhs) const\n\t{\n\t\treturn ((mReference.mpBitWord - rhs.mReference.mpBitWord) * kBitCount) + mReference.mnBitIndex - rhs.mReference.mnBitIndex;\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator==(const this_type& rhs) const\n\t{\n\t\treturn (mReference.mpBitWord == rhs.mReference.mpBitWord) && (mReference.mnBitIndex == rhs.mReference.mnBitIndex);\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator!=(const this_type& rhs) const\n\t{\n\t\treturn !(*this == rhs);\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator<(const this_type& rhs) const\n\t{\n\t\treturn (mReference.mpBitWord < rhs.mReference.mpBitWord) || \n\t\t\t   ((mReference.mpBitWord == rhs.mReference.mpBitWord) && (mReference.mnBitIndex < rhs.mReference.mnBitIndex));\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator<=(const this_type& rhs) const\n\t{\n\t\treturn (mReference.mpBitWord < rhs.mReference.mpBitWord) || \n\t\t\t   ((mReference.mpBitWord == rhs.mReference.mpBitWord) && (mReference.mnBitIndex <= rhs.mReference.mnBitIndex));\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator>(const this_type& rhs) const\n\t{\n\t\treturn !(*this <= rhs);\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator>=(const this_type& rhs) const\n\t{\n\t\treturn !(*this < rhs);\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator*() const\n\t{\n\t\treturn mReference;\n\t}\n\n\n\ttemplate <typename Element>\n\tbool bitvector_const_iterator<Element>::operator[](difference_type n) const\n\t{\n\t\treturn *(*this + n);\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_const_iterator<Element>& bitvector_const_iterator<Element>::operator= (const this_type& rhs)\n\t{\n\t\tmReference.CopyFrom(rhs.mReference);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Element>\n\tint bitvector_const_iterator<Element>::validate(const Element* pStart, const Element* pEnd, eastl_size_t nExtraBits) const\n\t{\n\t\tconst Element* const pCurrent = mReference.mpBitWord;\n\n\t\tif(pCurrent >= pStart)\n\t\t{\n\t\t\tif(nExtraBits == 0)\n\t\t\t{\n\t\t\t\tif(pCurrent == pEnd && mReference)\n\t\t\t\t\treturn eastl::isf_valid | eastl::isf_current;\n\t\t\t\telse if(pCurrent < pEnd)\n\t\t\t\t\treturn eastl::isf_valid | eastl::isf_current | eastl::isf_can_dereference;\n\t\t\t}\n\t\t\telse if(pCurrent == (pEnd - 1))\n\t\t\t{\n\t\t\t\tconst size_type bit     = mReference.mnBitIndex;\n\t\t\t\tconst size_type lastbit = kBitCount - nExtraBits;\n\t\t\t\t\n\t\t\t\tif(bit == lastbit)\n\t\t\t\t\treturn eastl::isf_valid | eastl::isf_current;\n\t\t\t\telse if(bit < lastbit)\n\t\t\t\t\treturn eastl::isf_valid | eastl::isf_current | eastl::isf_can_dereference;\n\t\t\t}\n\t\t\telse if(pCurrent < pEnd)\n\t\t\t{\n\t\t\t\treturn eastl::isf_valid | eastl::isf_current | eastl::isf_can_dereference;\n\t\t\t}\n\t\t}\n\n\t\treturn eastl::isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// bitvector_iterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Element>\n\tbitvector_iterator<Element>::bitvector_iterator()\n\t\t: base_type()\n\t{\n\t}\n\n\ttemplate <typename Element>\n\tbitvector_iterator<Element>::bitvector_iterator(Element* p, eastl_size_t i)\n\t\t: base_type(p, i)\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_iterator<Element>::bitvector_iterator(reference_type& reference)\n\t\t: base_type(reference)\n\t{\n\t}\n\n\n\ttemplate <typename Element>\n\ttypename bitvector_iterator<Element>::reference_type\n\tbitvector_iterator<Element>::operator*() const\n\t{\n\t\treturn base_type::mReference;\n\t}\n\n\n\ttemplate <typename Element>\n\ttypename bitvector_iterator<Element>::reference_type\n\tbitvector_iterator<Element>::operator[](difference_type n) const\n\t{\n\t\treturn *(*this + n);\n\t}\n\n\n\ttemplate <typename Element>\n\tvoid MoveBits(bitvector_iterator<Element> start, \n\t\t\t\t  bitvector_iterator<Element> end, \n\t\t\t\t  bitvector_iterator<Element> dest)\n\t{\n\t\t// Slow implemenation; could optimize by moving a word at a time.\n\t\tif(dest <= start)\n\t\t{\n\t\t\twhile(start != end)\n\t\t\t{\n\t\t\t\t*dest = *start;\n\t\t\t\t++dest;\n\t\t\t\t++start;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Need to move backwards\n\t\t\tdest += (end - start);\n\n\t\t\twhile(start != end)\n\t\t\t{\n\t\t\t\t--dest;\n\t\t\t\t--end;\n\t\t\t\t*dest = *end;\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_iterator<Element>\n\tbitvector_iterator<Element>::operator++(int)\n\t{\n\t\tbitvector_iterator copy(*this);\n\t\t++*this;\n\t\treturn copy;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_iterator<Element>\n\tbitvector_iterator<Element>::operator--(int)\n\t{\n\t\tbitvector_iterator copy(*this);\n\t\t--*this;\n\t\treturn copy;\n\t}\n\n\n\ttemplate <typename Element>\n\tbitvector_iterator<Element>\n\tbitvector_iterator<Element>::operator+(difference_type n) const\n\t{\n\t\tbitvector_iterator copy(*this);\n\t\tcopy += n;\n\t\treturn copy;\n\t}\n\n\t\n\ttemplate <typename Element>\n\tbitvector_iterator<Element>\n\tbitvector_iterator<Element>::operator-(difference_type n) const\n\t{\n\t\tbitvector_iterator copy(*this);\n\t\tcopy -= n;\n\t\treturn copy;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// bitvector\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttemplate <typename InputIterator>\n\tvoid bitvector<Allocator, Element, Container>::assign(InputIterator first, InputIterator last)\n\t{\n\t\t// To consider: We can maybe specialize this on bitvector_iterator to do a fast bitwise copy.\n\t\t// We can also specialize for random access iterators to figure out the size & reserve first.\n\n\t\tclear();\n\n\t\twhile(first != last)\n\t\t{\n\t\t\tpush_back(*first);\n\t\t\t++first;\n\t\t}\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::iterator\n\tbitvector<Allocator, Element, Container>::begin() EA_NOEXCEPT\n\t{\n\t\treturn iterator(mContainer.begin(), 0);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_iterator\n\tbitvector<Allocator, Element, Container>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mContainer.begin(), 0);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_iterator\n\tbitvector<Allocator, Element, Container>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mContainer.begin(), 0);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::iterator\n\tbitvector<Allocator, Element, Container>::end() EA_NOEXCEPT\n\t{\n\t\treturn iterator(mContainer.end(), 0) - mFreeBitCount;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_iterator\n\tbitvector<Allocator, Element, Container>::end() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mContainer.end(), 0) - mFreeBitCount;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_iterator\n\tbitvector<Allocator, Element, Container>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mContainer.end(), 0) - mFreeBitCount;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbool bitvector<Allocator, Element, Container>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn mContainer.empty();\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::size_type\n\tbitvector<Allocator, Element, Container>::size() const EA_NOEXCEPT\n\t{\n\t\treturn (mContainer.size() * kBitCount) - mFreeBitCount;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::size_type\n\tbitvector<Allocator, Element, Container>::capacity() const EA_NOEXCEPT\n\t{\n\t\treturn mContainer.capacity() * kBitCount;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::set_capacity(size_type n)\n\t{\n\t\tif(n == npos)\n\t\t\tmContainer.set_capacity(npos);\n\t\telse\n\t\t\tmContainer.set_capacity((n + kBitCount - 1) / kBitCount);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reverse_iterator\n\tbitvector<Allocator, Element, Container>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(end());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reverse_iterator\n\tbitvector<Allocator, Element, Container>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(end());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reverse_iterator\n\tbitvector<Allocator, Element, Container>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(end());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reverse_iterator\n\tbitvector<Allocator, Element, Container>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(begin());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reverse_iterator\n\tbitvector<Allocator, Element, Container>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(begin());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reverse_iterator\n\tbitvector<Allocator, Element, Container>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(begin());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reference\n\tbitvector<Allocator, Element, Container>::front()\n\t{\n\t\tEASTL_ASSERT(!empty());\n\t\treturn reference(&mContainer[0], 0);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reference\n\tbitvector<Allocator, Element, Container>::front() const\n\t{\n\t\tEASTL_ASSERT(!empty());\n\n\t\t// To consider: make a better solution to this than const_cast.\n\t\treturn reference(const_cast<Element*>(&mContainer[0]), 0);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reference\n\tbitvector<Allocator, Element, Container>::back()\n\t{\n\t\tEASTL_ASSERT(!empty());\n\t\treturn *(--end());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reference\n\tbitvector<Allocator, Element, Container>::back() const\n\t{\n\t\tEASTL_ASSERT(!empty());\n\t\treturn *(--end());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::push_back()\n\t{\n\t\tif(!mFreeBitCount)\n\t\t{\n\t\t\tmContainer.push_back();\n\t\t\tmFreeBitCount = kBitCount;\n\t\t}\n\n\t\t--mFreeBitCount;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::push_back(value_type value)\n\t{\n\t\tpush_back();\n\t\t*--end() = value;\n\t}\n\t\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::pop_back()\n\t{\n\t\tEASTL_ASSERT(!empty());\n\n\t\tif(++mFreeBitCount == kBitCount)\n\t\t{\n\t\t\tmContainer.pop_back();\n\t\t\tmFreeBitCount = 0;\n\t\t}\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::reserve(size_type n)\n\t{\n\t\tconst size_type wordCount = (n + kBitCount - 1) / kBitCount;\n\t\tmContainer.reserve(wordCount);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::resize(size_type n)\n\t{\n\t\tconst size_type wordCount = (n + kBitCount - 1) / kBitCount;\n\t\tconst size_type extra     = (wordCount * kBitCount) - n;\n\n\t\tmContainer.resize(wordCount);\n\t\tmFreeBitCount = extra;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::resize(size_type n, value_type value)\n\t{\n\t\tconst size_type s = size();\n\t\tif(n < s)\n\t\t\tresize(n);\n\n\t\t// Fill up to the end of a word\n\t\tsize_type newbits = n - s;\n\n\t\twhile(mFreeBitCount && newbits)\n\t\t{\n\t\t\tpush_back(value);\n\t\t\t--newbits;\n\t\t}\n\n\t\t// Fill the rest a word at a time\n\t\tif(newbits)\n\t\t{\n\t\t\telement_type element(0);\n\t\t\tif(value)\n\t\t\t\telement = ~element;\n\n\t\t\tconst size_type words = (n + kBitCount - 1) / kBitCount;\n\t\t\tconst size_type extra = words * kBitCount - n;\n\t\t\tmContainer.resize(words, element);\n\t\t\tmFreeBitCount = extra;\n\t\t}\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbool bitvector<Allocator, Element, Container>::test(size_type n, bool defaultValue) const\n\t{\n\t\tif(n < size())\n\t\t\treturn *(begin() + (difference_type)n);\n\n\t\treturn defaultValue;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::set(size_type n, bool value)\n\t{\n\t\tif(EASTL_UNLIKELY(n >= size()))\n\t\t\tresize(n + 1);\n\n\t\t*(begin() + (difference_type)n) = value;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reference\n\tbitvector<Allocator, Element, Container>::at(size_type n)\n\t{\n\t\t// The difference between at and operator[] is that at signals \n\t\t// if the requested position is out of range by throwing an \n\t\t// out_of_range exception.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= size()))\n\t\t\t\tthrow std::out_of_range(\"bitvector::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= size()))\n\t\t\t\tEASTL_FAIL_MSG(\"bitvector::at -- out of range\");\n\t\t#endif\n\t\t\n\t\treturn *(begin() + (difference_type)n);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reference\n\tbitvector<Allocator, Element, Container>::at(size_type n) const\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= size()))\n\t\t\t\tthrow std::out_of_range(\"bitvector::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= size()))\n\t\t\t\tEASTL_FAIL_MSG(\"bitvector::at -- out of range\");\n\t\t#endif\n\t\t\n\t\treturn *(begin() + (difference_type)n);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reference\n\tbitvector<Allocator, Element, Container>::operator[](size_type n)\n\t{\n\t\treturn *(begin() + (difference_type)n);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::const_reference\n\tbitvector<Allocator, Element, Container>::operator[](size_type n) const\n\t{\n\t\treturn *(begin() + (difference_type)n);\n\t}\n\n\n/*\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttemplate <bool value>\n\ttypename bitvector<Allocator, Element, Container>::iterator \n\tbitvector<Allocator, Element, Container>::find_first()\n\t{\n\t\treturn begin();\n\t}\n\n\ttemplate <bool value> iterator find_next(const_iterator it);\n\ttemplate <bool value> iterator find_last();\n\ttemplate <bool value> iterator find_prev(const_iterator it);\n\t\t\t\t\t\t\n\ttemplate <bool value> const_iterator find_first() const;\n\ttemplate <bool value> const_iterator find_next(const_iterator it) const;\n\ttemplate <bool value> const_iterator find_last() const;\n\ttemplate <bool value> const_iterator find_prev(const_iterator it) const;\n*/\n\n\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline typename bitvector<Allocator, Element, Container>::container_type&\n\tbitvector<Allocator, Element, Container>::get_container()\n\t{\n\t\treturn mContainer;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline const typename bitvector<Allocator, Element, Container>::container_type&\n\tbitvector<Allocator, Element, Container>::get_container() const\n\t{\n\t\treturn mContainer;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbool bitvector<Allocator, Element, Container>::validate() const\n\t{\n\t\tif(!mContainer.validate())\n\t\t\treturn false;\n\n\t\tif((unsigned)mFreeBitCount >= kBitCount)\n\t\t\treturn false;\n\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tint bitvector<Allocator, Element, Container>::validate_iterator(const_iterator i) const\n\t{\n\t\treturn i.validate(mContainer.begin(), mContainer.end(), mFreeBitCount);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::element_type*\n\tbitvector<Allocator, Element, Container>::data() EA_NOEXCEPT\n\t{\n\t\treturn mContainer.data();\n\t}\n\t\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tconst typename bitvector<Allocator, Element, Container>::element_type*\n\tbitvector<Allocator, Element, Container>::data() const EA_NOEXCEPT\n\t{\n\t\treturn mContainer.data();\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::iterator\n\tbitvector<Allocator, Element, Container>::insert(const_iterator position, value_type value)\n\t{\n\t\titerator iPosition(position.get_reference_type()); // This is just a non-const version of position.\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(validate_iterator(iPosition) & eastl::isf_valid) == 0)\n\t\t\t\tEASTL_FAIL_MSG(\"bitvector::insert -- invalid iterator\");\n\t\t#endif\n\n\t\t// Save because we might reallocate\n\t\tconst typename iterator::difference_type n = iPosition - begin();\n\t\tpush_back();\n\t\tiPosition = begin() + n;\n\n\t\tMoveBits(iPosition, --end(), ++iterator(iPosition));\n\t\t*iPosition = value;\n\n\t\treturn iPosition;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::insert(const_iterator position, size_type n, value_type value)\n\t{\n\t\titerator iPosition(position.get_reference_type()); // This is just a non-const version of position.\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(validate_iterator(iPosition) & eastl::isf_valid) == 0)\n\t\t\t\tEASTL_FAIL_MSG(\"bitvector::insert -- invalid iterator\");\n\t\t#endif\n\n\t\t// Save because we might reallocate.\n\t\tconst typename iterator::difference_type p = iPosition - begin();\n\t\tresize(size() + n);\n\t\tiPosition = begin() + p;\n\n\t\titerator insert_end = iPosition + n;\n\t\tMoveBits(iPosition, end() - n, insert_end);\n\n\t\t// To do: Optimize this to word-at-a-time for large inserts\n\t\twhile(iPosition != insert_end)\n\t\t{\n\t\t\t*iPosition = value;\n\t\t\t++iPosition;\n\t\t}\n\t}\n\n\n\t/*\n\tThe following is a placeholder for a future implementation. It turns out that a correct implementation of \n\tinsert(pos, first, last) is a non-trivial exercise that would take a few hours to implement and test. \n\tThe reasons why involve primarily the problem of handling the case where insertion source comes from \n\twithin the container itself, and the case that first and last (note they are templated) might not refer \n\tto iterators might refer to a value/count pair. The C++ Standard requires you to handle this case and \n\tI (Paul Pedriana) believe that it applies even for a bitvector, given that bool is an integral type. \n\tSo you have to set up a compile-time type traits function chooser. See vector, for example.\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttemplate <typename InputIterator>\n\tvoid bitvector<Allocator, Element, Container>::insert(const_iterator position, InputIterator first, InputIterator last)\n\t{\n\t\titerator iPosition(position.get_reference_type()); // This is just a non-const version of position.\n\n\t\t// This implementation is probably broken due to not handling insertion into self.\n\t\t// To do: Make a more efficient version of this.\n\t\tdifference_type distance = (iPosition - begin());\n\n\t\twhile(first != last)\n\t\t{\n\t\t\tinsert(iPosition, *first);\n\t\t\tiPosition = begin() + ++distance;\n\t\t\t++first;\n\t\t}\n\t}\n\t*/\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::iterator\n\tbitvector<Allocator, Element, Container>::erase(const_iterator position)\n\t{\n\t\titerator iPosition(position.get_reference_type()); // This is just a non-const version of position.\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(validate_iterator(iPosition) & eastl::isf_can_dereference) == 0)\n\t\t\t\tEASTL_FAIL_MSG(\"bitvector::erase -- invalid iterator\");\n\t\t#endif\n\n\t\tMoveBits(++iterator(iPosition), end(), iPosition);\n\t\tresize(size() - 1);\n\n\t\t// Verify that no reallocation occurred.\n\t\tEASTL_ASSERT(validate_iterator(iPosition) & eastl::isf_valid);\n\t\treturn iPosition;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::iterator\n\tbitvector<Allocator, Element, Container>::erase(const_iterator first, const_iterator last)\n\t{\n\t\titerator iFirst(first.get_reference_type()); // This is just a non-const version of first.\n\t\titerator iLast(last.get_reference_type());   // This is just a non-const version of last.\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(validate_iterator(iLast) & eastl::isf_valid) == 0)\n\t\t\t\tEASTL_FAIL_MSG(\"bitvector::erase -- invalid iterator\");\n\t\t#endif\n\n\t\tif(!(iFirst == iLast))\n\t\t{\n\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(validate_iterator(iFirst) & eastl::isf_can_dereference) == 0)\n\t\t\t\t\tEASTL_FAIL_MSG(\"bitvector::erase -- invalid iterator\");\n\t\t\t#endif\n\n\t\t\tconst size_type eraseCount = (size_type)(iLast - iFirst);\n\t\t\tMoveBits(iLast, end(), iFirst);\n\t\t\tresize(size() - eraseCount);\n\n\t\t\t// Verify that no reallocation occurred.\n\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(validate_iterator(iFirst) & eastl::isf_valid) == 0)\n\t\t\t\t\tEASTL_FAIL_MSG(\"bitvector::erase -- invalid iterator\");\n\t\t\t#endif\n\t\t}\n\n\t\treturn iFirst;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reverse_iterator\n\tbitvector<Allocator, Element, Container>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttypename bitvector<Allocator, Element, Container>::reverse_iterator\n\tbitvector<Allocator, Element, Container>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase(last.base(), first.base()));\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::swap(this_type& rhs)\n\t{\n\t\tmContainer.swap(rhs.mContainer);\n\t\teastl::swap(mFreeBitCount, rhs.mFreeBitCount);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::reset_lose_memory()\n\t{\n\t\tmContainer.reset_lose_memory(); // intentional memory leak.\n\t\tmFreeBitCount = 0;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tvoid bitvector<Allocator, Element, Container>::clear()\n\t{\n\t\tmContainer.clear();\n\t\tmFreeBitCount = 0;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbitvector<Allocator, Element, Container>::bitvector()\n\t  : mContainer(), \n\t\tmFreeBitCount(0)\n\t{\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbitvector<Allocator, Element, Container>::bitvector(const allocator_type& allocator)\n\t  : mContainer(allocator), \n\t\tmFreeBitCount(0)\n\t{\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbitvector<Allocator, Element, Container>::bitvector(size_type n, const allocator_type& allocator)\n\t   : mContainer((n + kBitCount - 1) / kBitCount, allocator)\n\t{\n\t\tmFreeBitCount = kBitCount - (n % kBitCount);\n\n\t\tif(mFreeBitCount == kBitCount)\n\t\t\tmFreeBitCount = 0;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbitvector<Allocator, Element, Container>::bitvector(size_type n, value_type value, const allocator_type& allocator)\n\t  : mContainer((n + kBitCount - 1) / kBitCount, value ? ~element_type(0) : element_type(0), allocator)\n\t{\n\t\tmFreeBitCount = kBitCount - (n % kBitCount);\n\n\t\tif(mFreeBitCount == kBitCount)\n\t\t\tmFreeBitCount = 0;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\ttemplate <typename InputIterator>\n\tbitvector<Allocator, Element, Container>::bitvector(InputIterator first, InputIterator last)\n\t  : mContainer(), \n\t\tmFreeBitCount(0)\n\t{\n\t\tassign(first, last);\n\t}\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbool bitvector<Allocator, Element, Container>::any() const\n\t{\n\t\tif (mContainer.size() == 0) \n\t\t\treturn false;\n\n\t\tfor (eastl_size_t i = 0, count = mContainer.size() - 1; i < count; ++i)\n\t\t{\n\t\t\tif (mContainer[i] != 0)\n\t\t\t\treturn true;\n\t\t}\n\t\tElement mask = mFreeBitCount == 0 ? (Element)-1 : ((Element(1) << Element(kBitCount - mFreeBitCount)) - 1);\n\t\treturn (mContainer.back() & mask);\n\t}\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tbool bitvector<Allocator, Element, Container>::all() const\n\t{\n\t\tif (mContainer.size() == 0) \n\t\t\treturn true;\n\n\t\tfor (eastl_size_t i = 0, count = mContainer.size() - 1; i < count; ++i)\n\t\t{\n\t\t\tif (mContainer[i] != (~(Element)0))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tElement mask = mFreeBitCount == 0 ? (Element)-1 : ((Element(1) << Element(kBitCount - mFreeBitCount)) - 1);\n\t\treturn (mContainer.back() & mask) == mask;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline bool operator==(const bitvector<Allocator, Element, Container>& a, \n\t\t\t\t\t\t   const bitvector<Allocator, Element, Container>& b)\n\t{\n\t\t// To do: Replace this with a smart compare implementation. This is much slower than it needs to be.\n\t\treturn ((a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin()));\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline bool operator!=(const bitvector<Allocator, Element, Container>& a, \n\t\t\t\t\t\t   const bitvector<Allocator, Element, Container>& b)\n\t{\n\t\treturn !operator==(a, b);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline bool operator<(const bitvector<Allocator, Element, Container>& a, \n\t\t\t\t\t\t  const bitvector<Allocator, Element, Container>& b)\n\t{\n\t\t// To do: Replace this with a smart compare implementation. This is much slower than it needs to be.\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline bool operator>(const bitvector<Allocator, Element, Container>& a, \n\t\t\t\t\t\t  const bitvector<Allocator, Element, Container>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline bool operator<=(const bitvector<Allocator, Element, Container>& a, \n\t\t\t\t\t\t   const bitvector<Allocator, Element, Container>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline bool operator>=(const bitvector<Allocator, Element, Container>& a, \n\t\t\t\t\t\t   const bitvector<Allocator, Element, Container>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\ttemplate <typename Allocator, typename Element, typename Container>\n\tinline void swap(bitvector<Allocator, Element, Container>& a,\n\t\t\t\t\t bitvector<Allocator, Element, Container>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\ttemplate <size_t nodeCount,\n              typename Allocator = EASTLAllocatorType, \n              typename Element   = BitvectorWordType, \n              typename Container = eastl::fixed_vector<Element, ((nodeCount + (sizeof(Element) << 3ULL)  - 1ULL) / (sizeof(Element) << 3ULL)), true, Allocator>>\n\tusing fixed_bitvector = eastl::bitvector<Allocator, Element, Container>;\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/bonus/adaptors.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ADAPTORS_H\n#define EASTL_ADAPTORS_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\nEA_DISABLE_VC_WARNING(4512 4626)\n#if defined(_MSC_VER) && (_MSC_VER >= 1900) // VS2015+\n\tEA_DISABLE_VC_WARNING(5027) // move assignment operator was implicitly defined as deleted\n#endif\n\n\nnamespace eastl\n{\n\t/// reverse\n\t///\n\t/// This adaptor allows reverse iteration of a container in ranged base for-loops.\n\t///\n\t/// for (auto& i : reverse(c)) { ... }\n\t///\n\ttemplate <typename Container>\n\tstruct reverse_wrapper\n\t{\n\t\ttemplate <typename C>\n\t\treverse_wrapper(C&& c)\n\t\t\t: mContainer(eastl::forward<C>(c))\n\t\t{\n\t\t\t/**\n\t\t\t * NOTE:\n\t\t\t *\n\t\t\t * Due to reference collapsing rules of universal references Container type is either\n\t\t\t *\n\t\t\t * const C&  if the input is a const lvalue\n\t\t\t * C&        if the input is a non-const lvalue\n\t\t\t * C         if the input is an rvalue\n\t\t\t * const C   if the input is a const rvalue thus the object will have to be copied and the copy-ctor will be called\n\t\t\t *\n\t\t\t *\n\t\t\t * Thus we either move the whole container into this object or take a reference to the lvalue avoiding the copy.\n\t\t\t * The static_assert below ensures this.\n\t\t\t */\n\t\t\tstatic_assert(eastl::is_same_v<C, Container>, \"Reference collapsed deduced type must be the same as the deduced Container type!\");\n\t\t}\n\n\t\tContainer mContainer;\n\t};\n\n\ttemplate <typename Container>\n\tauto begin(const reverse_wrapper<Container>& w) -> decltype(eastl::rbegin(w.mContainer))\n\t{\n\t\treturn eastl::rbegin(w.mContainer);\n\t}\n\n\ttemplate <typename Container>\n\tauto end(const reverse_wrapper<Container>& w) -> decltype(eastl::rend(w.mContainer))\n\t{\n\t\treturn eastl::rend(w.mContainer);\n\t}\n\n\ttemplate <typename Container>\n\treverse_wrapper<Container> reverse(Container&& c)\n\t{\n\t\treturn reverse_wrapper<Container>(eastl::forward<Container>(c));\n\t}\n\n} // namespace eastl\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1900) // VS2015+\n\tEA_RESTORE_VC_WARNING()\n#endif\nEA_RESTORE_VC_WARNING()\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/bonus/call_traits.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// The design for call_traits here is very similar to that found in template\n// metaprogramming libraries such as Boost, GCC, and Metrowerks, given that  \n// these libraries have established this interface as a defacto standard for \n// solving this problem. Also, these are described in various books on the \n// topic of template metaprogramming, such as \"Modern C++ Design\".\n//\n// See http://www.boost.org/libs/utility/call_traits.htm or search for \n// call_traits in Google for a description of call_traits.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_CALL_TRAITS_H\n#define EASTL_CALL_TRAITS_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>     \n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\n\ttemplate <typename T, bool small_>\n\tstruct ct_imp2 { typedef const T& param_type; };\n\n\ttemplate <typename T>\n\tstruct ct_imp2<T, true> { typedef const T param_type; };\n\n\ttemplate <typename T, bool isp, bool b1>\n\tstruct ct_imp { typedef const T& param_type; };\n\n\ttemplate <typename T, bool isp>\n\tstruct ct_imp<T, isp, true> { typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type; };\n\n\ttemplate <typename T, bool b1>\n\tstruct ct_imp<T, true, b1> { typedef T const param_type; };\n\n\n\n\ttemplate <typename T>\n\tstruct call_traits\n\t{\n\tpublic:\n\t\ttypedef T        value_type;\n\t\ttypedef T&       reference;\n\t\ttypedef const T& const_reference;\n\t\ttypedef typename ct_imp<T, is_pointer<T>::value, is_arithmetic<T>::value>::param_type param_type;\n\t};\n\n\n\ttemplate <typename T>\n\tstruct call_traits<T&>\n\t{\n\t\ttypedef T&       value_type;\n\t\ttypedef T&       reference;\n\t\ttypedef const T& const_reference;\n\t\ttypedef T&       param_type;\n\t};\n\n\n\ttemplate <typename T, size_t N>\n\tstruct call_traits<T [N]>\n\t{\n\tprivate:\n\t\ttypedef T array_type[N];\n\n\tpublic:\n\t\ttypedef const T*          value_type;\n\t\ttypedef array_type&       reference;\n\t\ttypedef const array_type& const_reference;\n\t\ttypedef const T* const    param_type;\n\t};\n\n\n\ttemplate <typename T, size_t N>\n\tstruct call_traits<const T [N]>\n\t{\n\tprivate:\n\t\ttypedef const T array_type[N];\n\n\tpublic:\n\t\ttypedef const T*          value_type;\n\t\ttypedef array_type&       reference;\n\t\ttypedef const array_type& const_reference;\n\t\ttypedef const T* const    param_type;\n\t};\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/compressed_pair.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// The compressed pair class is very similar to std::pair, but if either of the \n// template arguments are empty classes, then the \"empty base-class optimization\" \n// is applied to compress the size of the pair.\n//\n// The design for compressed_pair here is very similar to that found in template\n// metaprogramming libraries such as Boost, GCC, and Metrowerks, given that  \n// these libraries have established this interface as a defacto standard for \n// solving this problem. Also, these are described in various books on the \n// topic of template metaprogramming, such as \"Modern C++ Design\".\n// \n// template <typename T1, typename T2>\n// class compressed_pair\n// {\n// public:\n//     typedef T1                                                 first_type;\n//     typedef T2                                                 second_type;\n//     typedef typename call_traits<first_type>::param_type       first_param_type;\n//     typedef typename call_traits<second_type>::param_type      second_param_type;\n//     typedef typename call_traits<first_type>::reference        first_reference;\n//     typedef typename call_traits<second_type>::reference       second_reference;\n//     typedef typename call_traits<first_type>::const_reference  first_const_reference;\n//     typedef typename call_traits<second_type>::const_reference second_const_reference;\n// \n//     compressed_pair() : base() {}\n//     compressed_pair(first_param_type x, second_param_type y);\n//     explicit compressed_pair(first_param_type x);\n//     explicit compressed_pair(second_param_type y);\n// \n//     compressed_pair& operator=(const compressed_pair&);\n// \n//     first_reference       first();\n//     first_const_reference first() const;\n// \n//     second_reference       second();\n//     second_const_reference second() const;\n// \n//     void swap(compressed_pair& y);\n// };\n// \n// The two members of the pair can be accessed using the member functions first() \n// and second(). Note that not all member functions can be instantiated for all \n// template parameter types. In particular compressed_pair can be instantiated for \n// reference and array types, however in these cases the range of constructors that \n// can be used are limited. If types T1 and T2 are the same type, then there is \n// only one version of the single-argument constructor, and this constructor \n// initialises both values in the pair to the passed value.\n// \n// Note that compressed_pair can not be instantiated if either of the template \n// arguments is a union type, unless there is compiler support for is_union, \n// or if is_union is specialised for the union type.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_COMPRESSED_PAIR_H\n#define EASTL_COMPRESSED_PAIR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>     \n#include <EASTL/bonus/call_traits.h>     \n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1900)  // VS2015 or later\n\tEA_DISABLE_VC_WARNING(4626 5027) // warning C4626: 'eastl::compressed_pair_imp<T1,T2,0>': assignment operator was implicitly defined as deleted because a base class assignment operator is inaccessible or deleted\n#endif\n\nnamespace eastl\n{\n\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair;\n\n\n\ttemplate <typename T1, typename T2, bool isSame, bool firstEmpty, bool secondEmpty>\n\tstruct compressed_pair_switch;\n\n\ttemplate <typename T1, typename T2>\n\tstruct compressed_pair_switch<T1, T2, false, false, false>{ static const int value = 0; };\n\n\ttemplate <typename T1, typename T2>\n\tstruct compressed_pair_switch<T1, T2, false, true, false> { static const int value = 1; };\n\n\ttemplate <typename T1, typename T2>\n\tstruct compressed_pair_switch<T1, T2, false, false, true> { static const int value = 2; };\n\n\ttemplate <typename T1, typename T2>\n\tstruct compressed_pair_switch<T1, T2, false, true, true>  { static const int value = 3; };\n\n\ttemplate <typename T1, typename T2>\n\tstruct compressed_pair_switch<T1, T2, true, true, true>   { static const int value = 4; };\n\n\ttemplate <typename T1, typename T2>\n\tstruct compressed_pair_switch<T1, T2, true, false, false> { static const int value = 5; };\n\n\ttemplate <typename T1, typename T2, int version>\n\tclass compressed_pair_imp;\n\n\n\n\ttemplate <typename T>\n\tinline void cp_swap(T& t1, T& t2)\n\t{\n\t\tT tTemp = t1;\n\t\tt1 = t2;\n\t\tt2 = tTemp;\n\t}\n\n\n\t// Derive from neither\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair_imp<T1, T2, 0>\n\t{\n\tpublic:\n\t\ttypedef T1                                                 first_type;\n\t\ttypedef T2                                                 second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair_imp() {} \n\n\t\tcompressed_pair_imp(first_param_type x, second_param_type y)\n\t\t\t: mFirst(x), mSecond(y) {}\n\n\t\tcompressed_pair_imp(first_param_type x)\n\t\t\t: mFirst(x) {}\n\n\t\tcompressed_pair_imp(second_param_type y)\n\t\t\t: mSecond(y) {}\n\n\t\tfirst_reference       first()       { return mFirst; }\n\t\tfirst_const_reference first() const { return mFirst; }\n\n\t\tsecond_reference       second()       { return mSecond; }\n\t\tsecond_const_reference second() const { return mSecond; }\n\n\t\tvoid swap(compressed_pair<T1, T2>& y)\n\t\t{\n\t\t\tcp_swap(mFirst, y.first());\n\t\t\tcp_swap(mSecond, y.second());\n\t\t}\n\n\tprivate:\n\t\tfirst_type  mFirst;\n\t\tsecond_type mSecond;\n\t};\n\n\n\t// Derive from T1\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair_imp<T1, T2, 1> : private T1\n\t{\n\tpublic:\n\t\ttypedef T1                                                 first_type;\n\t\ttypedef T2                                                 second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair_imp() {}\n\n\t\tcompressed_pair_imp(first_param_type x, second_param_type y)\n\t\t\t: first_type(x), mSecond(y) {}\n\n\t\tcompressed_pair_imp(first_param_type x)\n\t\t\t: first_type(x) {}\n\n\t\tcompressed_pair_imp(second_param_type y)\n\t\t\t: mSecond(y) {}\n\n\t\tfirst_reference       first()       { return *this; }\n\t\tfirst_const_reference first() const { return *this; }\n\n\t\tsecond_reference       second()       { return mSecond; }\n\t\tsecond_const_reference second() const { return mSecond; }\n\n\t\tvoid swap(compressed_pair<T1,T2>& y)\n\t\t{\n\t\t\t// No need to swap empty base class\n\t\t\tcp_swap(mSecond, y.second());\n\t\t}\n\n\tprivate:\n\t\tsecond_type mSecond;\n\t};\n\n\n\n\t// Derive from T2\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair_imp<T1, T2, 2> : private T2\n\t{\n\tpublic:\n\t\ttypedef T1                                                 first_type;\n\t\ttypedef T2                                                 second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair_imp() {}\n\n\t\tcompressed_pair_imp(first_param_type x, second_param_type y)\n\t\t\t: second_type(y), mFirst(x) {}\n\n\t\tcompressed_pair_imp(first_param_type x)\n\t\t\t: mFirst(x) {}\n\n\t\tcompressed_pair_imp(second_param_type y)\n\t\t\t: second_type(y) {}\n\n\t\tfirst_reference       first()       { return mFirst; }\n\t\tfirst_const_reference first() const { return mFirst; }\n\n\t\tsecond_reference       second()       { return *this; }\n\t\tsecond_const_reference second() const { return *this; }\n\n\t\tvoid swap(compressed_pair<T1,T2>& y)\n\t\t{\n\t\t\t// No need to swap empty base class\n\t\t\tcp_swap(mFirst, y.first());\n\t\t}\n\n\tprivate:\n\t\tfirst_type mFirst;\n\t};\n\n\n\n\t// Derive from T1 and T2\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair_imp<T1, T2, 3> : private T1, private T2\n\t{\n\tpublic:\n\t\ttypedef T1                                                 first_type;\n\t\ttypedef T2                                                 second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair_imp() {}\n\n\t\tcompressed_pair_imp(first_param_type x, second_param_type y)\n\t\t\t: first_type(x), second_type(y) {}\n\n\t\tcompressed_pair_imp(first_param_type x)\n\t\t\t: first_type(x) {}\n\n\t\tcompressed_pair_imp(second_param_type y)\n\t\t\t: second_type(y) {}\n\n\t\tfirst_reference       first()       { return *this; }\n\t\tfirst_const_reference first() const { return *this; }\n\n\t\tsecond_reference       second()       { return *this; }\n\t\tsecond_const_reference second() const { return *this; }\n\n\t\t// No need to swap empty bases\n\t\tvoid swap(compressed_pair<T1, T2>&) \n\t\t\t{ }\n\t};\n\n\n\t// T1 == T2, T1 and T2 are both empty\n\t// Note does not actually store an instance of T2 at all;\n\t// but reuses T1 base class for both first() and second().\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair_imp<T1, T2, 4> : private T1\n\t{\n\tpublic:\n\t\ttypedef T1                                                 first_type;\n\t\ttypedef T2                                                 second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair_imp() {}\n\n\t\tcompressed_pair_imp(first_param_type x, second_param_type)\n\t\t\t: first_type(x) {}\n\n\t\tcompressed_pair_imp(first_param_type x)\n\t\t\t: first_type(x) {}\n\n\t\tfirst_reference       first()       { return *this; }\n\t\tfirst_const_reference first() const { return *this; }\n\n\t\tsecond_reference       second()       { return *this; }\n\t\tsecond_const_reference second() const { return *this; }\n\n\t\tvoid swap(compressed_pair<T1, T2>&) { }\n\t};\n\n\n\t// T1 == T2 and are not empty\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair_imp<T1, T2, 5>\n\t{\n\tpublic:\n\t\ttypedef T1                                                 first_type;\n\t\ttypedef T2                                                 second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair_imp() {}\n\n\t\tcompressed_pair_imp(first_param_type x, second_param_type y)\n\t\t\t: mFirst(x), mSecond(y) {}\n\n\t\tcompressed_pair_imp(first_param_type x)\n\t\t\t: mFirst(x), mSecond(x) {}\n\n\t\tfirst_reference       first()       { return mFirst; }\n\t\tfirst_const_reference first() const { return mFirst; }\n\n\t\tsecond_reference       second()       { return mSecond; }\n\t\tsecond_const_reference second() const { return mSecond; }\n\n\t\tvoid swap(compressed_pair<T1, T2>& y)\n\t\t{\n\t\t\tcp_swap(mFirst, y.first());\n\t\t\tcp_swap(mSecond, y.second());\n\t\t}\n\n\tprivate:\n\t\tfirst_type  mFirst;\n\t\tsecond_type mSecond;\n\t};\n\n\n\n\ttemplate <typename T1, typename T2>\n\tclass compressed_pair\n\t\t: private compressed_pair_imp<T1, T2,\n\t\t\t\t\tcompressed_pair_switch<\n\t\t\t\t\t\t\tT1,\n\t\t\t\t\t\t\tT2,\n\t\t\t\t\t\t\tis_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,\n\t\t\t\t\t\t\tis_empty<T1>::value,\n\t\t\t\t\t\t\tis_empty<T2>::value>::value>\n\t{\n\tprivate:\n\t\ttypedef compressed_pair_imp<T1, T2,\n\t\t\t\tcompressed_pair_switch<\n\t\t\t\t\t\tT1,\n\t\t\t\t\t\tT2,\n\t\t\t\t\t\tis_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,\n\t\t\t\t\t\tis_empty<T1>::value,\n\t\t\t\t\t\tis_empty<T2>::value>::value> base;\n\tpublic:\n\t\ttypedef T1                                                 first_type;\n\t\ttypedef T2                                                 second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair() : base() {}\n\t\tcompressed_pair(first_param_type x, second_param_type y) : base(x, y) {}\n\t\texplicit compressed_pair(first_param_type x) : base(x) {}\n\t\texplicit compressed_pair(second_param_type y) : base(y) {}\n\n\t\tfirst_reference       first()       { return base::first(); }\n\t\tfirst_const_reference first() const { return base::first(); }\n\n\t\tsecond_reference       second()       { return base::second(); }\n\t\tsecond_const_reference second() const { return base::second(); }\n\n\t\tvoid swap(compressed_pair& y) { base::swap(y); }\n\t};\n\n\n\t// Partial specialisation for case where T1 == T2:\n\ttemplate <typename T>\n\tclass compressed_pair<T, T>\n\t\t: private compressed_pair_imp<T, T,\n\t\t\t\t\tcompressed_pair_switch<\n\t\t\t\t\t\t\tT,\n\t\t\t\t\t\t\tT,\n\t\t\t\t\t\t\tis_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,\n\t\t\t\t\t\t\tis_empty<T>::value,\n\t\t\t\t\t\t\tis_empty<T>::value>::value>\n\t{\n\tprivate:\n\t\ttypedef compressed_pair_imp<T, T,\n\t\t\t\tcompressed_pair_switch<\n\t\t\t\t\t\tT,\n\t\t\t\t\t\tT,\n\t\t\t\t\t\tis_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,\n\t\t\t\t\t\tis_empty<T>::value,\n\t\t\t\t\t\tis_empty<T>::value>::value> base;\n\tpublic:\n\t\ttypedef T                                                  first_type;\n\t\ttypedef T                                                  second_type;\n\t\ttypedef typename call_traits<first_type>::param_type       first_param_type;\n\t\ttypedef typename call_traits<second_type>::param_type      second_param_type;\n\t\ttypedef typename call_traits<first_type>::reference        first_reference;\n\t\ttypedef typename call_traits<second_type>::reference       second_reference;\n\t\ttypedef typename call_traits<first_type>::const_reference  first_const_reference;\n\t\ttypedef typename call_traits<second_type>::const_reference second_const_reference;\n\n\t\tcompressed_pair() : base() {}\n\t\tcompressed_pair(first_param_type x, second_param_type y) : base(x, y) {}\n\t\texplicit compressed_pair(first_param_type x) : base(x) {}\n\n\t\tfirst_reference       first()       { return base::first(); }\n\t\tfirst_const_reference first() const { return base::first(); }\n\n\t\tsecond_reference       second()       { return base::second(); }\n\t\tsecond_const_reference second() const { return base::second(); }\n\n\t\tvoid swap(compressed_pair<T, T>& y) { base::swap(y); }\n\t};\n\n\n\ttemplate <typename T1, typename T2>\n\tinline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)\n\t{\n\t\tx.swap(y);\n\t}\n\n\n} // namespace eastl\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1900)  // VS2015 or later\n\tEA_RESTORE_VC_WARNING()\n#endif\n\n#endif // Header include guard\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/fixed_ring_buffer.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FIXED_RING_BUFFER_H\n#define EASTL_FIXED_RING_BUFFER_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/fixed_vector.h>\n#include <EASTL/bonus/ring_buffer.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\nnamespace eastl\n{\n\n\t/// fixed_ring_buffer\n\t///\n\t/// This is a convenience template alias for creating a fixed-sized\n\t/// ring_buffer using eastl::fixed_vector as its storage container. This has\n\t/// been tricky for users to get correct due to the constructor requirements\n\t/// of eastl::ring_buffer leaking the implementation detail of the sentinel\n\t/// value being used internally.  In addition, it was not obvious what the\n\t/// correct allocator_type template parameter should be used for containers\n\t/// providing both a default allocator type and an overflow allocator type.\n\t///\n\t/// We are over-allocating the fixed_vector container to accommodate the\n\t/// ring_buffer sentinel to prevent that implementation detail leaking into\n\t/// user code.\n\t///\n\t/// Example usage:\n\t///\n\t/// \tfixed_ring_buffer<int, 8> rb = {0, 1, 2, 3, 4, 5, 6, 7};\n\t///  or\n\t/// \tfixed_ring_buffer<int, 8> rb(8); // capacity doesn't need to respect sentinel\n\t/// \trb.push_back(0);\n\t///\n\t///\n#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\ttemplate <typename T, size_t N>\n\tusing fixed_ring_buffer =\n\t    ring_buffer<T, fixed_vector<T, N + 1, false>, typename fixed_vector<T, N + 1, false>::overflow_allocator_type>;\n#endif\n\n} // namespace eastl\n\n#endif // Header include guard\n\n"
  },
  {
    "path": "include/EASTL/bonus/fixed_tuple_vector.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FIXEDTUPLEVECTOR_H\n#define EASTL_FIXEDTUPLEVECTOR_H\n\n#include <EASTL/bonus/tuple_vector.h>\n#include <EASTL/internal/fixed_pool.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\nnamespace eastl\n{\n\n\t/// EASTL_FIXED_TUPLE_VECTOR_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_TUPLE_VECTOR_DEFAULT_NAME\n\t\t#define EASTL_FIXED_TUPLE_VECTOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_tuple_vector\" // Unless the user overrides something, this is \"EASTL fixed_vector\".\n\t#endif\n\n\n\t/// EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_TUPLE_VECTOR_DEFAULT_NAME)\n\t#endif\n\n// External interface of fixed_tuple_vector\ntemplate <size_t nodeCount, bool bEnableOverflow, typename... Ts>\nclass fixed_tuple_vector : public TupleVecInternal::TupleVecImpl<fixed_vector_allocator<\n\tTupleVecInternal::TupleRecurser<Ts...>::GetTotalAllocationSize(nodeCount, 0), 1,\n\tTupleVecInternal::TupleRecurser<Ts...>::GetTotalAlignment(), 0,\n\tbEnableOverflow, EASTLAllocatorType>, make_index_sequence<sizeof...(Ts)>, Ts...>\n{\npublic:\n\ttypedef fixed_vector_allocator<\n\t\tTupleVecInternal::TupleRecurser<Ts...>::GetTotalAllocationSize(nodeCount, 0), 1,\n\t\tTupleVecInternal::TupleRecurser<Ts...>::GetTotalAlignment(), 0,\n\t\tbEnableOverflow, EASTLAllocatorType> fixed_allocator_type;\n\ttypedef aligned_buffer<fixed_allocator_type::kNodesSize, fixed_allocator_type::kNodeAlignment> aligned_buffer_type;\n\ttypedef fixed_tuple_vector<nodeCount, bEnableOverflow, Ts...> this_type;\n\ttypedef EASTLAllocatorType overflow_allocator_type;\n\n\ttypedef TupleVecInternal::TupleVecImpl<fixed_allocator_type, make_index_sequence<sizeof...(Ts)>, Ts...> base_type;\n\ttypedef typename base_type::size_type size_type;\n\nprivate:\n\taligned_buffer_type mBuffer;\n\npublic:\n\tfixed_tuple_vector()\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{ }\n\n\tfixed_tuple_vector(const overflow_allocator_type& allocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{ }\n\n\tfixed_tuple_vector(this_type&& x)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{ \n\t\tbase_type::get_allocator().copy_overflow_allocator(x.get_allocator());\n\t\tbase_type::DoInitFromIterator(eastl::make_move_iterator(x.begin()), eastl::make_move_iterator(x.end()));\n\t\tx.clear();\n\t}\n\n\tfixed_tuple_vector(this_type&& x, const overflow_allocator_type& allocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFromIterator(eastl::make_move_iterator(x.begin()), eastl::make_move_iterator(x.end()));\n\t\tx.clear();\n\t}\n\n\tfixed_tuple_vector(const this_type& x)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{ \n\t\tbase_type::get_allocator().copy_overflow_allocator(x.get_allocator());\n\t\tbase_type::DoInitFromIterator(x.begin(), x.end());\n\t}\n\n\tfixed_tuple_vector(const this_type& x, const overflow_allocator_type& allocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFromIterator(x.begin(), x.end());\n\t}\n\n\ttemplate <typename MoveIterBase>\n\tfixed_tuple_vector(move_iterator<MoveIterBase> begin, move_iterator<MoveIterBase> end, const overflow_allocator_type& allocator = EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFromIterator(begin, end);\n\t}\n\n\ttemplate <typename Iterator>\n\tfixed_tuple_vector(Iterator begin, Iterator end, const overflow_allocator_type& allocator = EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFromIterator(begin, end);\n\t}\n\n\tfixed_tuple_vector(size_type n, const overflow_allocator_type& allocator = EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitDefaultFill(n);\n\t}\n\n\tfixed_tuple_vector(size_type n, const Ts&... args)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFillArgs(n, args...);\n\t}\n\n\tfixed_tuple_vector(size_type n, const Ts&... args, const overflow_allocator_type& allocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFillArgs(n, args...);\n\t}\n\n\tfixed_tuple_vector(size_type n,\n\t\t\t\ttypename base_type::const_reference_tuple tup,\n\t\t\t\tconst overflow_allocator_type& allocator = EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFillTuple(n, tup);\n\t}\n\n\tfixed_tuple_vector(const typename base_type::value_tuple* first, const typename base_type::value_tuple* last,\n\t\tconst overflow_allocator_type& allocator = EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFromTupleArray(first, last);\n\t}\n\n\tfixed_tuple_vector(std::initializer_list<typename base_type::value_tuple> iList,\n\t\tconst overflow_allocator_type& allocator = EASTL_FIXED_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, allocator), mBuffer.buffer, nodeCount, fixed_allocator_type::kNodeSize)\n\t{\n\t\tbase_type::DoInitFromTupleArray(iList.begin(), iList.end());\n\t}\n\n\tthis_type& operator=(const this_type& other)\n\t{\n\t\tbase_type::operator=(other);\n\t\treturn *this;\n\t}\n\n\tthis_type& operator=(this_type&& other)\n\t{\n\t\tbase_type::clear();\n\t\t// OK to call DoInitFromIterator in a non-ctor scenario because clear() reset everything, more-or-less\n\t\tbase_type::DoInitFromIterator(eastl::make_move_iterator(other.begin()), eastl::make_move_iterator(other.end()));\n\t\tother.clear();\n\t\treturn *this;\n\t}\n\n\tthis_type& operator=(std::initializer_list<typename base_type::value_tuple> iList)\n\t{\n\t\tbase_type::operator=(iList);\n\t\treturn *this;\n\t}\n\n\tvoid swap(this_type& x)\n\t{\n\t\t// If both containers are using the heap instead of local memory \n\t\t// then we can do a fast pointer swap instead of content swap.\n\t\tif ((has_overflowed() && x.has_overflowed()) && (get_overflow_allocator() == x.get_overflow_allocator()))\n\t\t{\n\t\t\tbase_type::swap(x);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\t\teastl::fixed_swap(*this, x);\n\t\t}\n\t}\n\n\t// Returns the max fixed size, which is the user-supplied nodeCount parameter.\n\tsize_type max_size() const { return nodeCount; }\n\t// Returns true if the fixed space has been fully allocated. Note that if overflow is enabled,\n\t// the container size can be greater than nodeCount but full() could return true because the\n\t// fixed space may have a recently freed slot.\n\tbool full() const { return (base_type::mNumElements >= nodeCount) || ((void*)base_type::mpData != (void*)mBuffer.buffer);\t}\n\t// Returns true if the allocations spilled over into the overflow allocator. Meaningful\n\t// only if overflow is enabled.\n\tbool has_overflowed() const { return ((void*)base_type::mpData != (void*)mBuffer.buffer); }\n\t// Returns the value of the bEnableOverflow template parameter.\n\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\n\tconst overflow_allocator_type& get_overflow_allocator() const { return base_type::get_allocator().get_overflow_allocator(); }\n};\n\n\ntemplate <size_t nodeCount, bool bEnableOverflow, typename... Ts>\ninline void swap(fixed_tuple_vector<nodeCount, bEnableOverflow, Ts...>& a,\n\t\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, Ts...>& b)\n{\n\ta.swap(b);\n}\n\n\n}  // namespace eastl\n\n#endif  // EASTL_TUPLEVECTOR_H\n"
  },
  {
    "path": "include/EASTL/bonus/flags.h",
    "content": "// Copyright (c) Electronic Arts Inc. All rights reserved.\n\n#pragma once\n\n//\n// introduction\n// --------------\n// \n// hello there.\n// \n// Flags are usually defined on a per-bit basis, and stored in integrals. This file\n// defines a templated type that encapsulates that logic as a thin-wrapper around an\n// integral. The benefit here is that [i.e.] enums that are not already shifted can\n// be seamlessly used if the corresponding flags type knows they're pre-shifted.\n// \n// \n// context\n// ---------\n// Here's a really common example where everything is _easy_:\n// (operators & conversions left out for brevity)\n// \n//    enum class Dragons : uint32_t { Fire = 1, Ice = 2, Poison = 4, Golden = 8 };\n//    uint32_t flags = Dragons::Fire | Dragons::Poison;\n// \n// Here's a really common example where things are _harder_:\n// \n//    enum class Knights : uint16_t { Armoured, Cowardly, Shining, Ni };\n//    uint32_t flags = (1 << Knights::Armoured) | (1 << Knights::Shining);\n// \n// Fun fact: the shift operator's resultant type is the type of the LHS, and\n// bitwise or-operator will promote its arguments of uint16_t to int on 64-bit\n// systems, meaning there are _many more_ omitted casts then may first appear.\n// \n// In the above examples, we would call `Dragons` _post-shifted_, and `Knights`\n// _pre-shifted_. Example code perhaps trivialises the issue; in large codebases\n// keeping track of which flags are pre- or post-shifted can be annoying, and\n// there is genuine need for both mixed within the same code. Awful!\n// \n// \n// basic_flags (prefer using bitflags/maskflags)\n// -----------------------------------------------\n// This structure wraps an integral and provides all common bitwise operations for\n// that integral. It will automatically shift pre-shifted flags (kind of, you need\n// to tell it that a flag is pre-shifted (bitflags), or post-shifted (maskflags)).\n// \n// This example demonstrates pre-shifted flags being used without any shifting\n// required on the user's part. If the user had accidentally used eastl::maskflags<>\n// instead of bitflags<>, then no shifting would occur and there would be _bugs_:\n// \n//    enum class Knights : uint16_t { Armoured, Cowardly, Shining, Ni };\n//    using KnightFlags = eastl::bitflags<Knights>;\n// \n//    // default construct = all bits zero\n//    KnightFlags knight_useless;\n// \n//    // takes an initializer_list if so desired\n//    KnightFlags knight_in_shining_armour{Knights::Armoured, Knights::Shining};\n//    \n//    // supports all typical operators\n//    if (knight_in_shining_armour & Knights::Shining)\n//    {\n//       // ...\n//    }\n// \n//    // being brave is part of the job description\n//    knight_useless = Knights::Cowardly;\n// \n//    // integrals would support implicit conversion to bool, so we do too\n//    if (knight_useless)\n//    {\n//    }\n// \n// \n// \n//\n// macros for defining flags\n// ---------------------------\n// \n// The following macros are shorthands for defining a flag-type based off\n// an enum-type. This enum-type can either be known ahead of time, using\n// EASTL_DECLARE_BITFLAGS or EASTL_DECLARE_MASKFLAGS, or it can be defined\n// directly then and there, using the \"_ENUM_CLASS\" versions of the macros.\n// \n// These macros help by defining certain bitwise operators for enum-classes.\n// \n// \n// \n// \n// EASTL_DECLARE_BITFLAGS\n// EASTL_DECLARE_MASKFLAGS\n// -------------------------\n// These macros simply take an existing enum-type and define an alias for a\n// flags-type (bitflags or maskflags) of that enum-type:\n// \n//    enum class DragonType { Happy, Sad, Drunk };\n// \n//    EASTL_DECLARE_BITFLAGS(DragonFlags, DragonType);\n// \n//      ^ the above macro has expanded to something akin to:\n// \n//        using DragonFlags = ::eastl::bitflags<DragonType>;\n//        inline constexpr DragonFlags operator | (DragonType lhs, DragonType rhs) { /* snip */ }\n//\n// This example shows a post-shifted enum using MASKFLAGS. Note that pre-shifted\n// flags can be combined and thus more than the bitwise-or operator has been\n// provided (the bitwse and-operator and xor-operator and included free of charge):\n//\n//    enum class WizardType\n//    {\n//        Brilliant = 1, Imbecile = 2, Evil = 4, Forgetful = 8,\n//        MaybeHarmless = (Evil | Forgetful)\n//    };\n// \n//    EASTL_DECLARE_MASKFLAGS(WizardFlags, WizardType);\n// \n//      ^ macro expansion for the above macro looks like:\n// \n//        using WizardFlags = ::eastl::maskflags<WizardType>;\n//        inline constexpr WizardFlags operator | (WizardType lhs, WizardType rhs) { /* snip */ }\n//        inline constexpr WizardFlags operator & (WizardType lhs, WizardType rhs) { /* snip */ }\n//        inline constexpr WizardFlags operator ^ (WizardType lhs, WizardType rhs) { /* snip */ }\n// \n// \n// \n// \n// EASTL_DECLARE_BITFLAGS_ENUM_CLASS\n// EASTL_DECLARE_MASKFLAGS_ENUM_CLASS\n// -----------------------------------\n// These macros are convenience macros to both declare the flag-type, and\n// in-place define an enum-class (the second parameter). Operators for the\n// enum-type are automatically generated too:\n// \n// Note that this first example is again using BITFLAGS.\n// \n//    EASTL_DECLARE_BITFLAGS_ENUM_CLASS(DragonFlags, DragonType)\n//    {\n//        Jubilent,\n//        Depressed,\n//        Smashed\n//    };\n// \n// This generates code similar to the following:\n// \n//    enum class DragonType;\n//    using DragonFlags = ::eastl::bitflags<DragonType>;\n//    inline constexpr DragonFlags operator | (DragonType lhs, DragonType rhs) { /* snip */ }\n//    enum class DragonType\n//    {\n//        Jubilent,\n//        Depressed,\n//        Smashed\n//    };\n// \n// \n// Note: You will still need to pre-shift your enum values yourself when using\n// the MASKFLAGS version of these macros, just as if you were writing the enum\n// without the macro:\n// \n//    EASTL_DECLARE_MASKFLAGS_ENUM_CLASS(SquireFlags, Squires)\n//    {\n//        Absent = 0,\n//        Inexperienced = (1<<0),\n//        Keen =          (1<<1),\n//        Jaded =         (1<<2),\n//        Competant =     (1<<3),\n// \n//        FreshOutOfUni = Inexperienced | Keen\n//    };\n// \n// Macro expansion:\n// \n//    enum class Squires;\n//    using SquireFlags = ::eastl::bitflags<Squires>;\n//    inline constexpr SquireFlags operator | (Squires lhs, Squires rhs) { /* snip */ }\n//    inline constexpr SquireFlags operator & (Squires lhs, Squires rhs) { /* snip */ }\n//    inline constexpr SquireFlags operator ^ (Squires lhs, Squires rhs) { /* snip */ }\n//    enum class Squires\n//    {\n//        Absent = 0,\n//        Inexperienced = (1<<0),\n//        Keen =          (1<<1),\n//        Jaded =         (1<<2),\n//        Competant =     (1<<3),\n// \n//        FreshOutOfUni = Inexperienced | Keen\n//    };\n// \n// Usage:\n// \n//    SquireFlags flags{Squires::FreshOutOfUni};\n//    if (flags & Squires::Keen) { /* snip */ }\n//    if (flags != Squires::Absent) { /* snip */ }\n//\n\n\n#include <EASTL/type_traits.h>\n#include <initializer_list>\n\n\n\n// forward-declares\nnamespace eastl\n{\n\ttemplate <typename Flag, typename Marshaller>\n\tstruct basic_flags;\n\n\ttemplate <typename TagType, typename FlagType>\n\tstruct flag_marshaller;\n\n\t// tags to determine between flag-types\n\tstruct bitflag_tag {};\n\tstruct maskflag_tag {};\n\n\t// aliases\n\ttemplate <typename Flag>\n\tusing bitflags = basic_flags<Flag, flag_marshaller<bitflag_tag, Flag>>;\n\n\ttemplate <typename Flag>\n\tusing maskflags = basic_flags<Flag, flag_marshaller<maskflag_tag, Flag>>;\n}\n\n\n// the mask-type for an enum of a given size\nnamespace eastl::detail\n{\n\ttemplate <size_t N>\n\tstruct flags_mask_type;\n\n\ttemplate <> struct flags_mask_type<1> { using type = uint8_t; };\n\ttemplate <> struct flags_mask_type<2> { using type = uint16_t; };\n\ttemplate <> struct flags_mask_type<4> { using type = uint32_t; };\n\ttemplate <> struct flags_mask_type<8> { using type = uint64_t; };\n\n\ttemplate <typename T>\n\tusing flags_mask_type_t = typename flags_mask_type<sizeof(T)>::type;\n}\n\n\nnamespace eastl\n{\n\ttemplate <typename Flag, typename Marshaller>\n\tstruct basic_flags\n\t{\n\t\tusing flag_type = Flag;\n\t\tusing marshaller_type = Marshaller;\n\t\tusing mask_type = detail::flags_mask_type_t<Flag>;\n\n\t\tstatic_assert(is_integral_v<mask_type>, \"mask_type must be integral\");\n\t\tstatic_assert(is_unsigned_v<mask_type>, \"mask_type must be unsigned\");\n\n\t\t// constructors\n\t\tstatic constexpr basic_flags from_mask(mask_type) noexcept;\n\n\t\tconstexpr basic_flags() noexcept = default;\n\t\tconstexpr basic_flags(flag_type) noexcept;\n\t\tconstexpr basic_flags(const basic_flags&) = default;\n\t\tconstexpr basic_flags(std::initializer_list<flag_type>) noexcept;\n\n\t\t// explicit conversions\n\t\tconstexpr operator bool() const noexcept;\n\t\tconstexpr explicit operator mask_type() const noexcept;\n\n\t\t// standard flags operators\n\t\tconstexpr basic_flags& operator = (flag_type) noexcept;\n\t\tconstexpr basic_flags& operator = (const basic_flags&) noexcept = default;\n\n\t\tconstexpr basic_flags& operator |= (basic_flags) noexcept;\n\t\tconstexpr basic_flags& operator &= (basic_flags) noexcept;\n\t\tconstexpr basic_flags& operator ^= (basic_flags) noexcept;\n\t\t\n\t\tconstexpr basic_flags& operator |= (flag_type) noexcept;\n\t\tconstexpr basic_flags& operator &= (flag_type) noexcept;\n\t\tconstexpr basic_flags& operator ^= (flag_type) noexcept;\n\n\t\tconstexpr basic_flags operator ~ () const noexcept;\n\n\t\t// named versions of common operations\n\t\tconstexpr basic_flags& set(flag_type, bool enabled) noexcept;\n\t\tconstexpr basic_flags& set(flag_type) noexcept;\n\t\tconstexpr basic_flags& unset(flag_type) noexcept;\n\t\tconstexpr basic_flags& toggle(flag_type) noexcept;\n\t\tconstexpr void clear() noexcept;\n\t\tconstexpr void reset(mask_type = 0u) noexcept;\n\n\tprivate:\n\t\tconstexpr basic_flags(mask_type mask) noexcept\n\t\t\t: m_mask{mask}\n\t\t{}\n\n\tprivate:\n\t\tmask_type m_mask{};\n\n\tprivate:\n\t\t// friend non-member bitwise operations\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator & (basic_flags<Y, U>, basic_flags<Y, U>) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator | (basic_flags<Y, U>, basic_flags<Y, U>) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator ^ (basic_flags<Y, U>, basic_flags<Y, U>) noexcept;\n\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator & (basic_flags<Y, U>, typename basic_flags<Y, U>::flag_type) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator | (basic_flags<Y, U>, typename basic_flags<Y, U>::flag_type) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator ^ (basic_flags<Y, U>, typename basic_flags<Y, U>::flag_type) noexcept;\n\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator & (typename basic_flags<Y, U>::flag_type, basic_flags<Y, U>) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator | (typename basic_flags<Y, U>::flag_type, basic_flags<Y, U>) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr basic_flags<Y, U> operator ^ (typename basic_flags<Y, U>::flag_type, basic_flags<Y, U>) noexcept;\n\n\t\t// friend comparison operators\n\t\ttemplate <typename Y, typename U> friend constexpr bool operator == (basic_flags<Y, U>, basic_flags<Y, U>) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr bool operator == (basic_flags<Y, U>, typename basic_flags<Y, U>::flag_type) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr bool operator == (typename basic_flags<Y, U>::flag_type, basic_flags<Y, U>) noexcept;\n\n\t\ttemplate <typename Y, typename U> friend constexpr bool operator != (basic_flags<Y, U>, basic_flags<Y, U>) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr bool operator != (basic_flags<Y, U>, typename basic_flags<Y, U>::flag_type) noexcept;\n\t\ttemplate <typename Y, typename U> friend constexpr bool operator != (typename basic_flags<Y, U>::flag_type, basic_flags<Y, U>) noexcept;\n\t};\n}\n\n\n\n\n\n\n\n//\n// flag_marshaller\n// -----------------\n// marshalls the flag-type into a mask-type we can perform bitwise operations\n// on with our mask member\n// \n// 'bitflags' expects the flags to be sequentially numbered, where the\n// value of each flag signifies the bit-position within the mask-type that\n// will be affected\n// \n//      // the bottom four bits (position 0, 1, 2, 3) will be affected\n//      enum class MaidenType { Distressed, Defiant, Conniving, Charasmatic };\n// \n//      // bits at positions 3, 4, and 8\n//      enum class KnightType { Armoured = 3, Lazy = 4, Jousting = 8 };\n// \n// \n// 'maskflags' on the other hand, expects the values of the flags to be\n// _already_ shifted to the correct position. taking the above examples\n// and rewriting them as bitmasks:\n// \n//      // the bottom four bits (position 0, 1, 2, 3) will be affected\n//      enum class MaidenType { Distressed = 1, Defiant = 2, Conniving = 4, Charasmatic = 8 };\n// \n//      // bits at positions 3, 4, and 8 (note that \"Absent\" contributes nothing)\n//      enum class KnightType { Absent = 0, Armoured = (1<<3), Lazy = (1<<4), Jousting = (1<<8) };\n//\n//\nnamespace eastl\n{\n\ttemplate <typename TagType, typename FlagType>\n\tstruct flag_marshaller\n\t{\n\t\tstatic_assert(!std::is_integral_v<FlagType>);\n\n\t\tusing tag_type = TagType;\n\t\tusing flag_type = FlagType;\n\t\tusing mask_type = detail::flags_mask_type_t<FlagType>;\n\n\t\t// we really want C++ constexpr-if\n\t\ttemplate <size_t AdditionalOffset = 0>\n\t\tstatic constexpr mask_type to_mask(flag_type f)\n\t\t{\n\t\t\treturn to_mask_impl<AdditionalOffset>(tag_type{}, f);\n\t\t}\n\n\tprivate:\n\t\ttemplate <size_t AdditionalOffset>\n\t\tstatic constexpr mask_type to_mask_impl(bitflag_tag, flag_type f)\n\t\t{\n\t\t\treturn mask_type{1} << static_cast<mask_type>(f) << AdditionalOffset;\n\t\t}\n\n\t\ttemplate <size_t AdditionalOffset>\n\t\tstatic constexpr mask_type to_mask_impl(maskflag_tag, flag_type f)\n\t\t{\n\t\t\treturn static_cast<mask_type>(f) << AdditionalOffset;\n\t\t}\n\t};\n}\n\n\n\n\n//\n// basic_flags implementation\n//\nnamespace eastl\n{\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T> basic_flags<F, T>::from_mask(mask_type mask) noexcept\n\t{\n\t\treturn basic_flags<F, T>{mask};\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>::basic_flags(flag_type flag) noexcept\n\t\t: m_mask{marshaller_type::to_mask(flag)}\n\t{}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>::basic_flags(std::initializer_list<flag_type> flags) noexcept\n\t{\n\t\tfor (auto f : flags)\n\t\t\tset(f);\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>::operator bool() const noexcept\n\t{\n\t\treturn static_cast<bool>(m_mask);\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>::operator mask_type() const noexcept\n\t{\n\t\treturn m_mask;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::operator = (flag_type flag) noexcept\n\t{\n\t\tm_mask = marshaller_type::to_mask(flag);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::operator |= (basic_flags<F, T> flag) noexcept\n\t{\n\t\tm_mask |= flag.m_mask;\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::operator &= (basic_flags<F, T> flag) noexcept\n\t{\n\t\tm_mask &= flag.m_mask;\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::operator ^= (basic_flags<F, T> flag) noexcept\n\t{\n\t\tm_mask ^= flag.m_mask;\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::operator |= (flag_type flag) noexcept\n\t{\n\t\tm_mask |= marshaller_type::to_mask(flag);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::operator &= (flag_type flag) noexcept\n\t{\n\t\tm_mask &= marshaller_type::to_mask(flag);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::operator ^= (flag_type flag) noexcept\n\t{\n\t\tm_mask ^= marshaller_type::to_mask(flag);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T> basic_flags<F, T>::operator ~ () const noexcept\n\t{\n\t\treturn basic_flags<F, T>{~m_mask};\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::set(flag_type flag, bool enabled) noexcept\n\t{\n\t\tmask_type const rhs = marshaller_type::to_mask(flag);\n\t\tm_mask = (m_mask & ~rhs) ^ (rhs * static_cast<mask_type>(enabled));\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::set(flag_type flag) noexcept\n\t{\n\t\tm_mask |= marshaller_type::to_mask(flag);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::unset(flag_type flag) noexcept\n\t{\n\t\tm_mask &= ~marshaller_type::to_mask(flag);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr basic_flags<F, T>& basic_flags<F, T>::toggle(flag_type flag) noexcept\n\t{\n\t\tm_mask ^= marshaller_type::to_mask(flag);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr void basic_flags<F, T>::clear() noexcept\n\t{\n\t\tm_mask = 0u;\n\t}\n\n\ttemplate <typename F, typename T>\n\tinline constexpr void basic_flags<F, T>::reset(mask_type mask) noexcept\n\t{\n\t\tm_mask = mask;\n\t}\n}\n\n\n//\n// BF_MASK_CAST_\n// ---------------\n//\n// bitwise operations will promote to int when available.\n//\n// that is undesireable, as we will then encounter narrowing conversion warnings\n// when assigning to our m_mask of those narrower types. so static-cast.\n//\n#define BF_MASK_CAST_(expr) static_cast<typename basic_flags<F, M>::mask_type>(expr)\n\n\n// non-member operators\nnamespace eastl\n{\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator & (basic_flags<F, M> lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(lhs.m_mask & rhs.m_mask)};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator | (basic_flags<F, M> lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(lhs.m_mask | rhs.m_mask)};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator ^ (basic_flags<F, M> lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(lhs.m_mask ^ rhs.m_mask)};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator & (basic_flags<F, M> lhs, typename basic_flags<F, M>::flag_type rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(lhs.m_mask & M::to_mask(rhs))};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator | (basic_flags<F, M> lhs, typename basic_flags<F, M>::flag_type rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(lhs.m_mask | M::to_mask(rhs))};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator ^ (basic_flags<F, M> lhs, typename basic_flags<F, M>::flag_type rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(lhs.m_mask ^ M::to_mask(rhs))};\n\t}\n\t\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator & (typename basic_flags<F, M>::flag_type lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(M::to_mask(lhs) & rhs.m_mask)};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator | (typename basic_flags<F, M>::flag_type lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(M::to_mask(lhs) | rhs.m_mask)};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr basic_flags<F, M> operator ^ (typename basic_flags<F, M>::flag_type lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn basic_flags<F, M>{BF_MASK_CAST_(M::to_mask(lhs) ^ rhs.m_mask)};\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr bool operator == (basic_flags<F, M> lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn lhs.m_mask == rhs.m_mask;\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr bool operator == (basic_flags<F, M> lhs, typename basic_flags<F, M>::flag_type rhs) noexcept\n\t{\n\t\treturn lhs.m_mask == M::to_mask(rhs);\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr bool operator == (typename basic_flags<F, M>::flag_type lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn M::to_mask(lhs) == rhs.m_mask;\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr bool operator != (basic_flags<F, M> lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn lhs.m_mask != rhs.m_mask;\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr bool operator != (basic_flags<F, M> lhs, typename basic_flags<F, M>::flag_type rhs) noexcept\n\t{\n\t\treturn lhs.m_mask != M::to_mask(rhs);\n\t}\n\n\ttemplate <typename F, typename M>\n\tinline constexpr bool operator != (typename basic_flags<F, M>::flag_type lhs, basic_flags<F, M> rhs) noexcept\n\t{\n\t\treturn M::to_mask(lhs) != rhs.m_mask;\n\t}\n}\n\n#undef BF_MASK_CAST_\n\n\n//\n// mask_of\n// ---------\n// returns the mask of a basic_flags. we have made the conversion operator\n// explicit, so users would have to first know (or get, as the case may be)\n// the mask_type, and perform an explicit cast.\n// \n// this is good because it makes people aware of when their flags are being\n// interpreted as an integral, but it is kind of wordy. so 'mask_of' has\n// been introduced to shorten this.\n// \n// 'mask' was not chosen due to the high potential for name clashes.\n//\nnamespace eastl\n{\n\ttemplate <typename F, typename T>\n\tinline constexpr typename basic_flags<F, T>::mask_type mask_of(basic_flags<F, T> flags)\n\t{\n\t\treturn static_cast<typename basic_flags<F, T>::mask_type>(flags);\n\t}\n}\n\n\n//\n// macros\n// --------\n// \n// see top-of-file for explanation\n//\n#define EASTL_DECLARE_BITFLAGS(flagstype, enumtype) \\\n\tusing flagstype = ::eastl::bitflags<enumtype>; \\\n\tinline constexpr flagstype operator | (enumtype lhs, enumtype rhs) \\\n\t{ \\\n\t\tusing msh = typename flagstype::marshaller_type; \\\n\t\treturn flagstype::from_mask(static_cast<msh::mask_type>(msh::to_mask(lhs) | msh::to_mask(rhs))); \\\n\t}\n\n#define EASTL_DECLARE_BITFLAGS_ENUM_CLASS(flagstype, enumtype) \\\n\tenum class enumtype; \\\n\tEASTL_DECLARE_BITFLAGS(flagstype, enumtype) \\\n\tenum class enumtype\n\n#define EASTL_DECLARE_BITFLAGS_ENUM_CLASS_SIZED(sizetype, flagstype, enumtype) \\\n\tenum class enumtype : sizetype; \\\n\tEASTL_DECLARE_BITFLAGS(flagstype, enumtype) \\\n\tenum class enumtype : sizetype\n\n\n\n\n#define EASTL_DECLARE_MASKFLAGS(flagstype, enumtype) \\\n\tusing flagstype = ::eastl::maskflags<enumtype>; \\\n\tinline constexpr flagstype operator | (enumtype lhs, enumtype rhs) \\\n\t{ \\\n\t\tusing msh = typename flagstype::marshaller_type; \\\n\t\treturn flagstype::from_mask(static_cast<msh::mask_type>(msh::to_mask(lhs) | msh::to_mask(rhs))); \\\n\t} \\\n\tinline constexpr flagstype operator & (enumtype lhs, enumtype rhs) \\\n\t{ \\\n\t\tusing msh = typename flagstype::marshaller_type; \\\n\t\treturn flagstype::from_mask(static_cast<msh::mask_type>(msh::to_mask(lhs) & msh::to_mask(rhs))); \\\n\t} \\\n\tinline constexpr flagstype operator ^ (enumtype lhs, enumtype rhs) \\\n\t{ \\\n\t\tusing msh = typename flagstype::marshaller_type; \\\n\t\treturn flagstype::from_mask(static_cast<msh::mask_type>(msh::to_mask(lhs) ^ msh::to_mask(rhs))); \\\n\t}\n\n#define EASTL_DECLARE_MASKFLAGS_ENUM_CLASS(flagstype, enumtype) \\\n\tenum class enumtype; \\\n\tEASTL_DECLARE_MASKFLAGS(flagstype, enumtype) \\\n\tenum class enumtype\n\n#define EASTL_DECLARE_MASKFLAGS_ENUM_CLASS_SIZED(sizetype, flagstype, enumtype) \\\n\tenum class enumtype : sizetype; \\\n\tEASTL_DECLARE_MASKFLAGS(flagstype, enumtype) \\\n\tenum class enumtype : sizetype\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/intrusive_sdlist.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// intrusive_sdlist is a special kind of intrusive list which we say is \n// \"singly-doubly\" linked. Instead of having a typical intrusive list node\n// which looks like this:\n//\n//     struct intrusive_sdlist_node {\n//         intrusive_sdlist_node *mpNext;\n//         intrusive_sdlist_node *mpPrev;\n//     };\n//\n// We instead have one that looks like this:\n//\n//     struct intrusive_sdlist_node {\n//         intrusive_sdlist_node*  mpNext;\n//         intrusive_sdlist_node** mppPrevNext;\n//     };\n// \n// This may seem to be suboptimal, but it has one specific advantage: it allows\n// the intrusive_sdlist class to be the size of only one pointer instead of two.\n// This may seem like a minor optimization, but some users have wanted to create\n// thousands of empty instances of these.\n// This is because while an intrusive_list class looks like this:\n//\n//     class intrusive_list {\n//         intrusive_list_node mBaseNode;\n//     };\n//     \n// an intrusive_sdlist class looks like this:\n//\n//     class intrusive_sdlist {\n//         intrusive_sdlist_node* mpNext;\n//     };\n//  \n// So here we make a list of plusses and minuses of intrusive sdlists\n// compared to intrusive_lists and intrusive_slists:\n//\n//                          |   list   |   slist   |   sdlist\n//      ---------------------------------------------------------\n//      min size            |    8     |     4     |     4\n//      node size           |    8     |     4     |     8\n//      anonymous erase     |   yes    |     no    |     yes\n//      reverse iteration   |   yes    |     no    |     no\n//    \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTRUSIVE_SDLIST_H\n#define EASTL_INTRUSIVE_SDLIST_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\n\t/// intrusive_sdlist_node\n\t///\n\tstruct intrusive_sdlist_node\n\t{\n\t\tintrusive_sdlist_node*  mpNext;\n\t\tintrusive_sdlist_node** mppPrevNext;\n\t};\n\n\n\t/// IntrusiveSDListIterator\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tstruct IntrusiveSDListIterator\n\t{\n\t\ttypedef IntrusiveSDListIterator<T, Pointer, Reference>   this_type;\n\t\ttypedef IntrusiveSDListIterator<T, T*, T&>               iterator;\n\t\ttypedef IntrusiveSDListIterator<T, const T*, const T&>   const_iterator;\n\t\ttypedef eastl_size_t                                     size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                        difference_type;\n\t\ttypedef T                                                value_type;\n\t\ttypedef T                                                node_type;\n\t\ttypedef Pointer                                          pointer;\n\t\ttypedef Reference                                        reference;\n\t\ttypedef eastl::forward_iterator_tag               iterator_category;\n\n\tpublic:\n\t\tpointer mpNode;\n\n\tpublic:\n\t\tIntrusiveSDListIterator();\n\t\texplicit IntrusiveSDListIterator(pointer pNode); // Note that you can also construct an iterator from T via this, since value_type == node_type.\n\t\tIntrusiveSDListIterator(const iterator& x);\n\n\t\treference operator*() const;\n\t\tpointer   operator->() const;\n\n\t\tthis_type& operator++();\n\t\tthis_type  operator++(int);\n\n\t}; // struct IntrusiveSDListIterator\n\n\n\n\n\t/// intrusive_sdlist_base\n\t///\n\t/// Provides a template-less base class for intrusive_sdlist.\n\t///\n\tclass intrusive_sdlist_base\n\t{\n\tpublic:\n\t\ttypedef eastl_size_t size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t    difference_type;\n\n\tprotected:\n\t\tintrusive_sdlist_node* mpNext;\n\n\tpublic:\n\t\tintrusive_sdlist_base();\n\n\t\tbool      empty() const;            ///< Returns true if the container is empty.\n\t\tsize_type size() const;             ///< Returns the number of elements in the list; O(n).\n\n\t\tvoid      clear();                  ///< Clears the list; O(1). No deallocation occurs.\n\t\tvoid      pop_front();              ///< Removes an element from the front of the list; O(1). The element must be present, but is not deallocated.\n\t\tvoid      reverse();                ///< Reverses a list so that front and back are swapped; O(n).\n\n\t\t//bool    validate() const;         ///< Scans a list for linkage inconsistencies; O(n) time, O(1) space. Returns false if errors are detected, such as loops or branching.\n\n\t}; // class intrusive_sdlist_base\n\n\n\n\t/// intrusive_sdlist\n\t///\n\ttemplate <typename T = intrusive_sdlist_node>\n\tclass intrusive_sdlist : public intrusive_sdlist_base\n\t{\n\tpublic:\n\t\ttypedef intrusive_sdlist<T>                             this_type;\n\t\ttypedef intrusive_sdlist_base                           base_type;\n\t\ttypedef T                                               node_type;\n\t\ttypedef T                                               value_type;\n\t\ttypedef typename base_type::size_type                   size_type;\n\t\ttypedef typename base_type::difference_type             difference_type;\n\t\ttypedef T&                                              reference;\n\t\ttypedef const T&                                        const_reference;\n\t\ttypedef T*                                              pointer;\n\t\ttypedef const T*                                        const_pointer;\n\t\ttypedef IntrusiveSDListIterator<T, T*, T&>              iterator;\n\t\ttypedef IntrusiveSDListIterator<T, const T*, const T&>  const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>               reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>         const_reverse_iterator;\n\n\tpublic:\n\t\tintrusive_sdlist();                       ///< Creates an empty list.\n\t\tintrusive_sdlist(const this_type& x);     ///< Creates an empty list; ignores the argument.\n\t\tthis_type& operator=(const this_type& x); ///< Clears the list; ignores the argument.\n\n\t\titerator         begin();                 ///< Returns an iterator pointing to the first element in the list.\n\t\tconst_iterator   begin() const;           ///< Returns a const_iterator pointing to the first element in the list.\n\t\tconst_iterator   cbegin() const;          ///< Returns a const_iterator pointing to the first element in the list.\n\n\t\titerator         end();                   ///< Returns an iterator pointing one-after the last element in the list.\n\t\tconst_iterator   end() const;             ///< Returns a const_iterator pointing one-after the last element in the list.\n\t\tconst_iterator   cend() const;            ///< Returns a const_iterator pointing one-after the last element in the list.\n\n\t\treference        front();                 ///< Returns a reference to the first element. The list must not be empty.\n\t\tconst_reference  front() const;           ///< Returns a const reference to the first element. The list must not be empty.\n\n\t\tvoid             push_front(value_type& value);                  ///< Adds an element to the front of the list; O(1). The element is not copied. The element must not be in any other list.\n\t\tvoid             push_back(value_type& value);                   ///< Adds an element to the back of the list; O(N). The element is not copied. The element must not be in any other list.\n\t\tvoid             pop_back();                                     ///< Removes an element from the back of the list; O(N). The element must be present, but is not deallocated.\n\n\t\tbool             contains(const value_type& value) const;        ///< Returns true if the given element is in the list; O(n). Equivalent to (locate(x) != end()).\n\n\t\titerator         locate(value_type& value);                      ///< Converts a reference to an object in the list back to an iterator, or returns end() if it is not part of the list. O(n)\n\t\tconst_iterator   locate(const value_type& value) const;          ///< Converts a const reference to an object in the list back to a const iterator, or returns end() if it is not part of the list. O(n)\n\n\t\titerator         insert(iterator position, value_type& value);   ///< Inserts an element before the element pointed to by the iterator. O(1)\n\t\titerator         erase(iterator position);                       ///< Erases the element pointed to by the iterator. O(1)\n\t\titerator         erase(iterator first, iterator last);           ///< Erases elements within the iterator range [first, last). O(1).\n\t\tvoid             swap(intrusive_sdlist& x);                      ///< Swaps the contents of two intrusive lists; O(1).\n\n\t\tstatic void      remove(value_type& value);                      ///< Erases an element from a list; O(1). Note that this is static so you don't need to know which list the element, although it must be in some list.\n\n\t\tvoid  splice(iterator position, value_type& value);              ///< Moves the given element into this list before the element pointed to by position; O(1).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ///< Required: x must be in some list or have first/next pointers that point it itself.\n\n\t\tvoid  splice(iterator position, this_type& x);                   ///< Moves the contents of a list into this list before the element pointed to by position; O(1).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ///< Required: &x != this (same as std::list).\n\n\t\tvoid  splice(iterator position, this_type& x, iterator xPosition);      ///< Moves the given element pointed to i within the list x into the current list before\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< the element pointed to by position; O(1).\n\n\t\tvoid  splice(iterator position, this_type& x, iterator first, iterator last);   ///< Moves the range of elements [first, last) from list x into the current list before\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< the element pointed to by position; O(1).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< Required: position must not be in [first, last). (same as std::list).\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\t}; // intrusive_sdlist\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// IntrusiveSDListIterator functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline IntrusiveSDListIterator<T, Pointer, Reference>::IntrusiveSDListIterator()\n\t{\n\t\t#if EASTL_DEBUG\n\t\t\tmpNode = NULL;\n\t\t#endif\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline IntrusiveSDListIterator<T, Pointer, Reference>::IntrusiveSDListIterator(pointer pNode)\n\t\t: mpNode(pNode)\n\t{\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline IntrusiveSDListIterator<T, Pointer, Reference>::IntrusiveSDListIterator(const iterator& x)\n\t\t: mpNode(x.mpNode)\n\t{\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename IntrusiveSDListIterator<T, Pointer, Reference>::reference\n\tIntrusiveSDListIterator<T, Pointer, Reference>::operator*() const\n\t{\n\t\treturn *mpNode;\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename IntrusiveSDListIterator<T, Pointer, Reference>::pointer\n\tIntrusiveSDListIterator<T, Pointer, Reference>::operator->() const\n\t{\n\t\treturn mpNode;\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename IntrusiveSDListIterator<T, Pointer, Reference>::this_type&\n\tIntrusiveSDListIterator<T, Pointer, Reference>::operator++()\n\t{\n\t\tmpNode = static_cast<node_type*>(mpNode->mpNext);\n\t\treturn *this;\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename IntrusiveSDListIterator<T, Pointer, Reference>::this_type\n\tIntrusiveSDListIterator<T, Pointer, Reference>::operator++(int)\n\t{\n\t\tthis_type temp = *this;\n\t\tmpNode = static_cast<node_type*>(mpNode->mpNext);\n\t\treturn temp;\n\t}\n\n\t// The C++ defect report #179 requires that we support comparisons between const and non-const iterators.\n\t// Thus we provide additional template paremeters here to support this. The defect report does not\n\t// require us to support comparisons between reverse_iterators and const_reverse_iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator==(const IntrusiveSDListIterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const IntrusiveSDListIterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode == b.mpNode;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator!=(const IntrusiveSDListIterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const IntrusiveSDListIterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\t// We provide a version of operator!= for the case where the iterators are of the \n\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline bool operator!=(const IntrusiveSDListIterator<T, Pointer, Reference>& a, \n\t\t\t\t\t\t   const IntrusiveSDListIterator<T, Pointer, Reference>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_sdlist_base\n\t///////////////////////////////////////////////////////////////////////\n\n\tinline intrusive_sdlist_base::intrusive_sdlist_base() \n\t\t{ mpNext = NULL; }\n\n\n\tinline bool intrusive_sdlist_base::empty() const\n\t\t{ return mpNext == NULL; }\n\n\n\tinline intrusive_sdlist_base::size_type intrusive_sdlist_base::size() const\n\t{\n\t\tsize_type n = 0;\n\t\tfor(const intrusive_sdlist_node* pCurrent = mpNext; pCurrent; pCurrent = pCurrent->mpNext)\n\t\t\tn++;\n\t\treturn n;\n\t}\n\n\n\tinline void intrusive_sdlist_base::clear()\n\t\t{ mpNext = NULL; } // Note that we don't do anything with the list nodes.\n\n\n\tinline void intrusive_sdlist_base::pop_front()\n\t{\n\t\t// To consider: Set mpNext's pointers to NULL in debug builds.\n\t\tmpNext = mpNext->mpNext;\n\t\tmpNext->mppPrevNext = &mpNext;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_sdlist\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T>\n\tinline intrusive_sdlist<T>::intrusive_sdlist()\n\t{\n\t}\n\n\n\ttemplate <typename T>\n\tinline intrusive_sdlist<T>::intrusive_sdlist(const this_type& /*x*/)\n\t  : intrusive_sdlist_base()\n\t{\n\t\t// We intentionally ignore argument x.\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::this_type& intrusive_sdlist<T>::operator=(const this_type& /*x*/)\n\t{ \n\t\treturn *this; // We intentionally ignore argument x.\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::iterator intrusive_sdlist<T>::begin()\n\t\t{ return iterator(static_cast<T*>(mpNext)); }\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::const_iterator intrusive_sdlist<T>::begin() const\n\t\t{ return const_iterator(static_cast<T*>(const_cast<intrusive_sdlist_node*>(mpNext))); }\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::const_iterator intrusive_sdlist<T>::cbegin() const\n\t\t{ return const_iterator(static_cast<T*>(const_cast<intrusive_sdlist_node*>(mpNext))); }\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::iterator intrusive_sdlist<T>::end()\n\t\t{ return iterator(static_cast<T*>(NULL)); }\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::const_iterator intrusive_sdlist<T>::end() const\n\t\t{ return const_iterator(static_cast<const T*>(NULL)); }\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::const_iterator intrusive_sdlist<T>::cend() const\n\t\t{ return const_iterator(static_cast<const T*>(NULL)); }\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::reference intrusive_sdlist<T>::front()\n\t\t{ return *static_cast<T*>(mpNext); }\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::const_reference intrusive_sdlist<T>::front() const\n\t\t{ return *static_cast<const T*>(mpNext); }\n\n\n\ttemplate <typename T>\n\tinline void intrusive_sdlist<T>::push_front(value_type& value)\n\t{\n\t\tvalue.mpNext = mpNext;\n\t\tvalue.mppPrevNext = &mpNext;\n\t\tif(mpNext)\n\t\t\tmpNext->mppPrevNext = &value.mpNext;\n\t\tmpNext = &value;\n\t}\n\n\n\ttemplate <typename T>\n\tinline void intrusive_sdlist<T>::push_back(value_type& value)\n\t{\n\t\tintrusive_sdlist_node*  pNext      =  mpNext;\n\t\tintrusive_sdlist_node** ppPrevNext = &mpNext;\n\n\t\twhile(pNext)\n\t\t{\n\t\t\tppPrevNext = &pNext->mpNext;\n\t\t\tpNext      =  pNext->mpNext;\n\t\t}\n\n\t\t*ppPrevNext       = &value;\n\t\tvalue.mppPrevNext = ppPrevNext;\n\t\tvalue.mpNext      = NULL;\n\t}\n\n\n\ttemplate <typename T>\n\tinline void intrusive_sdlist<T>::pop_back()\n\t{\n\t\tnode_type* pCurrent = static_cast<node_type*>(mpNext);\n\n\t\twhile(pCurrent->mpNext)\n\t\t\tpCurrent = static_cast<node_type*>(pCurrent->mpNext);\n\n\t\t*pCurrent->mppPrevNext = NULL;\n\t}\n\n\ttemplate <typename T>\n\tinline bool intrusive_sdlist<T>::contains(const value_type& value) const\n\t{\n\t\tconst intrusive_sdlist_node* pCurrent;\n\n\t\tfor(pCurrent = mpNext; pCurrent; pCurrent = pCurrent->mpNext)\n\t\t{\n\t\t\tif(pCurrent == &value)\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn (pCurrent != NULL);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::iterator intrusive_sdlist<T>::locate(value_type& value)\n\t{\n\t\tintrusive_sdlist_node* pCurrent;\n\n\t\tfor(pCurrent = static_cast<value_type*>(mpNext); pCurrent; pCurrent = pCurrent->mpNext)\n\t\t{\n\t\t\tif(pCurrent == &value)\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn iterator(static_cast<value_type*>(pCurrent));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::const_iterator intrusive_sdlist<T>::locate(const T& value) const\n\t{\n\t\tconst intrusive_sdlist_node* pCurrent;\n\n\t\tfor(pCurrent = static_cast<value_type*>(mpNext); pCurrent; pCurrent = pCurrent->mpNext)\n\t\t{\n\t\t\tif(pCurrent == &value)\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn const_iterator(static_cast<value_type*>(const_cast<intrusive_sdlist_node*>(pCurrent)));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::iterator\n\tintrusive_sdlist<T>::insert(iterator position, value_type& value)\n\t{\n\t\tvalue.mppPrevNext            = position.mpNode->mppPrevNext;\n\t\tvalue.mpNext                 = position.mpNode;\n\t   *value.mppPrevNext            = &value;\n\t\tposition.mpNode->mppPrevNext = &value.mpNext;\n\n\t\treturn iterator(&value);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::iterator\n\tintrusive_sdlist<T>::erase(iterator position)\n\t{\n\t   *position.mpNode->mppPrevNext         = position.mpNode->mpNext;\n\t\tposition.mpNode->mpNext->mppPrevNext = position.mpNode->mppPrevNext;\n\n\t\treturn iterator(position.mpNode);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_sdlist<T>::iterator\n\tintrusive_sdlist<T>::erase(iterator first, iterator last)\n\t{\n\t\tif(first.mpNode) // If not erasing the end...\n\t\t{\n\t\t\t*first.mpNode->mppPrevNext = last.mpNode;\n\n\t\t\tif(last.mpNode) // If not erasing to the end...\n\t\t\t\tlast.mpNode->mppPrevNext = first.mpNode->mppPrevNext;\n\t\t}\n\n\t\treturn last;\n\t}\n\n\n\ttemplate <typename T>\n\tinline void intrusive_sdlist<T>::remove(value_type& value)\n\t{\n\t\t*value.mppPrevNext = value.mpNext;\n\t\tif(value.mpNext)\n\t\t\tvalue.mpNext->mppPrevNext = value.mppPrevNext;\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_sdlist<T>::swap(intrusive_sdlist& x)\n\t{\n\t\t// swap anchors\n\t\tintrusive_sdlist_node* const temp(mpNext);\n\t\tmpNext   = x.mpNext;\n\t\tx.mpNext = temp;\n\n\t\tif(x.mpNext)\n\t\t\tx.mpNext->mppPrevNext = &mpNext;\n\n\t\tif(mpNext)\n\t\t\tmpNext->mppPrevNext = &x.mpNext;\n\t}\n\n\n\n\n\n\t// To do: Complete these splice functions. Might want to look at intrusive_sdlist for help.\n\n\ttemplate <typename T>\n\tvoid intrusive_sdlist<T>::splice(iterator /*position*/, value_type& /*value*/)\n\t{\n\t\tEASTL_ASSERT(false); // If you need this working, ask Paul Pedriana or submit a working version for inclusion.\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_sdlist<T>::splice(iterator /*position*/, intrusive_sdlist& /*x*/)\n\t{\n\t\tEASTL_ASSERT(false); // If you need this working, ask Paul Pedriana or submit a working version for inclusion.\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_sdlist<T>::splice(iterator /*position*/, intrusive_sdlist& /*x*/, iterator /*xPosition*/)\n\t{\n\t\tEASTL_ASSERT(false); // If you need this working, ask Paul Pedriana or submit a working version for inclusion.\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_sdlist<T>::splice(iterator /*position*/, intrusive_sdlist& /*x*/, iterator /*first*/, iterator /*last*/)\n\t{\n\t\tEASTL_ASSERT(false); // If you need this working, ask Paul Pedriana or submit a working version for inclusion.\n\t}\n\n\n\ttemplate <typename T>\n\tinline bool intrusive_sdlist<T>::validate() const\n\t{\n\t\treturn true; // To do.\n\t}\n\n\n\ttemplate <typename T>\n\tinline int intrusive_sdlist<T>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Come up with a more efficient mechanism of doing this.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T>\n\tbool operator==(const intrusive_sdlist<T>& a, const intrusive_sdlist<T>& b)\n\t{\n\t\t// If we store an mSize member for intrusive_sdlist, we want to take advantage of it here.\n\t\ttypename intrusive_sdlist<T>::const_iterator ia   = a.begin();\n\t\ttypename intrusive_sdlist<T>::const_iterator ib   = b.begin();\n\t\ttypename intrusive_sdlist<T>::const_iterator enda = a.end();\n\t\ttypename intrusive_sdlist<T>::const_iterator endb = b.end();\n\n\t\twhile((ia != enda) && (ib != endb) && (*ia == *ib))\n\t\t{\n\t\t\t++ia;\n\t\t\t++ib;\n\t\t}\n\t\treturn (ia == enda) && (ib == endb);\n\t}\n\n\ttemplate <typename T>\n\tbool operator<(const intrusive_sdlist<T>& a, const intrusive_sdlist<T>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\ttemplate <typename T>\n\tbool operator!=(const intrusive_sdlist<T>& a, const intrusive_sdlist<T>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\ttemplate <typename T>\n\tbool operator>(const intrusive_sdlist<T>& a, const intrusive_sdlist<T>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\ttemplate <typename T>\n\tbool operator<=(const intrusive_sdlist<T>& a, const intrusive_sdlist<T>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate <typename T>\n\tbool operator>=(const intrusive_sdlist<T>& a, const intrusive_sdlist<T>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\ttemplate <typename T>\n\tvoid swap(intrusive_sdlist<T>& a, intrusive_sdlist<T>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/intrusive_slist.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// *** Note ***\n// This implementation is incomplete.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTRUSIVE_SLIST_H\n#define EASTL_INTRUSIVE_SLIST_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// intrusive_slist_node\n\t///\n\tstruct intrusive_slist_node\n\t{\n\t\tintrusive_slist_node* mpNext;\n\t};\n\n\n\t/// IntrusiveSListIterator\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tstruct IntrusiveSListIterator\n\t{\n\t\ttypedef IntrusiveSListIterator<T, Pointer, Reference>   this_type;\n\t\ttypedef IntrusiveSListIterator<T, T*, T&>               iterator;\n\t\ttypedef IntrusiveSListIterator<T, const T*, const T&>   const_iterator;\n\t\ttypedef eastl_size_t                                    size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                       difference_type;\n\t\ttypedef T                                               value_type;\n\t\ttypedef T                                               node_type;\n\t\ttypedef Pointer                                         pointer;\n\t\ttypedef Reference                                       reference;\n\t\ttypedef eastl::forward_iterator_tag              iterator_category;\n\n\tpublic:\n\t\tnode_type* mpNode;\n\n\tpublic:\n\t\tIntrusiveSListIterator();\n\t\texplicit IntrusiveSListIterator(pointer pNode); // Note that you can also construct an iterator from T via this, since value_type == node_type.\n\t\tIntrusiveSListIterator(const iterator& x);\n\n\t\treference operator*() const;\n\t\tpointer   operator->() const;\n\n\t\tthis_type& operator++();\n\t\tthis_type  operator++(int);\n\n\t}; // struct IntrusiveSListIterator\n\n\n\n\t/// intrusive_slist_base\n\t///\n\t/// Provides a template-less base class for intrusive_slist.\n\t///\n\tclass intrusive_slist_base\n\t{\n\tpublic:\n\t\ttypedef eastl_size_t size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t    difference_type;\n\n\tprotected:\n\t\tintrusive_slist_node* mpNext;\n\n\tpublic:\n\t\tintrusive_slist_base();\n\n\t\tbool      empty() const;            ///< Returns true if the container is empty.\n\t\tsize_type size() const;             ///< Returns the number of elements in the list; O(n).\n\n\t\tvoid      clear();                  ///< Clears the list; O(1). No deallocation occurs.\n\t\tvoid      pop_front();              ///< Removes an element from the front of the list; O(1). The element must be present, but is not deallocated.\n\t\tvoid      reverse();                ///< Reverses a list so that front and back are swapped; O(n).\n\n\t\t//bool    validate() const;         ///< Scans a list for linkage inconsistencies; O(n) time, O(1) space. Returns false if errors are detected, such as loops or branching.\n\n\t}; // class intrusive_slist_base\n\n\n\n\t/// intrusive_slist\n\t///\n\ttemplate <typename T = intrusive_slist_node>\n\tclass intrusive_slist : public intrusive_slist_base\n\t{\n\tpublic:\n\t\ttypedef intrusive_slist<T>                              this_type;\n\t\ttypedef intrusive_slist_base                            base_type;\n\t\ttypedef T                                               node_type;\n\t\ttypedef T                                               value_type;\n\t\ttypedef typename base_type::size_type                   size_type;\n\t\ttypedef typename base_type::difference_type             difference_type;\n\t\ttypedef T&                                              reference;\n\t\ttypedef const T&                                        const_reference;\n\t\ttypedef T*                                              pointer;\n\t\ttypedef const T*                                        const_pointer;\n\t\ttypedef IntrusiveSListIterator<T, T*, T&>               iterator;\n\t\ttypedef IntrusiveSListIterator<T, const T*, const T&>   const_iterator;\n\n\tpublic:\n\t\tintrusive_slist();                        ///< Creates an empty list.\n\t  //intrusive_slist(const this_type& x);      ///< Creates an empty list; ignores the argument. To consider: Is this a useful function?\n\t  //this_type& operator=(const this_type& x); ///< Clears the list; ignores the argument.       To consider: Is this a useful function?\n\n\t\titerator         begin();                 ///< Returns an iterator pointing to the first element in the list. O(1).\n\t\tconst_iterator   begin() const;           ///< Returns a const_iterator pointing to the first element in the list. O(1).\n\t\tconst_iterator   cbegin() const;          ///< Returns a const_iterator pointing to the first element in the list. O(1).\n\t\titerator         end();                   ///< Returns an iterator pointing one-after the last element in the list. O(1).\n\t\tconst_iterator   end() const;             ///< Returns a const_iterator pointing one-after the last element in the list. O(1).\n\t\tconst_iterator   cend() const;            ///< Returns a const_iterator pointing one-after the last element in the list. O(1).\n\t\titerator         before_begin();          ///< Returns iterator to position before begin. O(1).\n\t\tconst_iterator   before_begin() const;    ///< Returns iterator to previous position. O(1).\n\t\tconst_iterator   cbefore_begin() const;   ///< Returns iterator to previous position. O(1).\n\n\t\titerator         previous(const_iterator position);         ///< Returns iterator to previous position. O(n).\n\t\tconst_iterator   previous(const_iterator position) const;   ///< Returns iterator to previous position. O(n).\n\n\t\treference        front();                 ///< Returns a reference to the first element. The list must be empty.\n\t\tconst_reference  front() const;           ///< Returns a const reference to the first element. The list must be empty.\n\n\t\tvoid             push_front(value_type& value);                 ///< Adds an element to the front of the list; O(1). The element is not copied. The element must not be in any other list.\n\t\tvoid             pop_front();                                   ///< Removes an element from the back of the list; O(n). The element must be present, but is not deallocated.\n\n\t\tbool             contains(const value_type& value) const;       ///< Returns true if the given element is in the list; O(n). Equivalent to (locate(x) != end()).\n\n\t\titerator         locate(value_type& value);                     ///< Converts a reference to an object in the list back to an iterator, or returns end() if it is not part of the list. O(n)\n\t\tconst_iterator   locate(const value_type& value) const;         ///< Converts a const reference to an object in the list back to a const iterator, or returns end() if it is not part of the list. O(n)\n\n\t\titerator insert(iterator position, value_type& value);          ///< Inserts an element before the element pointed to by the iterator. O(n)\n\t\titerator insert_after(iterator position, value_type& value);    ///< Inserts an element after the element pointed to by the iterator. O(1)\n\n\t\titerator erase(iterator position);                              ///< Erases the element pointed to by the iterator. O(n)\n\t\titerator erase_after(iterator position);                        ///< Erases the element after the element pointed to by the iterator. O(1)\n\n\t\titerator erase(iterator first, iterator last);                  ///< Erases elements within the iterator range [first, last). O(n).\n\t\titerator erase_after(iterator before_first, iterator last);     ///< Erases elements within the iterator range [before_first, last). O(1).\n\n\t\tvoid swap(this_type& x);                                        ///< Swaps the contents of two intrusive lists; O(1).\n\n\n\t\tvoid splice(iterator position, value_type& value);              ///< Moves the given element into this list before the element pointed to by position; O(n).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< Required: x must be in some list or have first/next pointers that point it itself.\n\n\t\tvoid splice(iterator position, this_type& x);                   ///< Moves the contents of a list into this list before the element pointed to by position; O(n).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< Required: &x != this (same as std::list).\n\n\t\tvoid splice(iterator position, this_type& x, iterator xPosition);      ///< Moves the given element pointed to i within the list x into the current list before\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ///< the element pointed to by position; O(n).\n\n\t\tvoid splice(iterator position, this_type& x, iterator first, iterator last);   ///< Moves the range of elements [first, last) from list x into the current list before\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ///< the element pointed to by position; O(n).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ///< Required: position must not be in [first, last). (same as std::list).\n\n\t\tvoid splice_after(iterator position, value_type& value);            ///< Moves the given element into this list after the element pointed to by position; O(1).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< Required: x must be in some list or have first/next pointers that point it itself.\n\n\t\tvoid splice_after(iterator position, this_type& x);                 ///< Moves the contents of a list into this list after the element pointed to by position; O(n).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< Required: &x != this (same as std::list).\n\n\t\tvoid splice_after(iterator position, this_type& x, iterator xPrevious); ///< Moves the element after xPrevious to be after position. O(1).\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t///< Required: &x != this (same as std::list).\n\n\t\tvoid splice_after(iterator position, this_type& x, iterator before_first, iterator before_last);  ///< Moves the elements in the range of [before_first+1, before_last+1) to be after position. O(1).\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\t}; // intrusive_slist\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// IntrusiveSListIterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline IntrusiveSListIterator<T, Pointer, Reference>::IntrusiveSListIterator()\n\t{\n\t\t#if EASTL_DEBUG\n\t\t\tmpNode = NULL;\n\t\t#endif\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline IntrusiveSListIterator<T, Pointer, Reference>::IntrusiveSListIterator(pointer pNode)\n\t\t: mpNode(pNode)\n\t{\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline IntrusiveSListIterator<T, Pointer, Reference>::IntrusiveSListIterator(const iterator& x)\n\t\t: mpNode(x.mpNode)\n\t{\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_slist_base\n\t///////////////////////////////////////////////////////////////////////\n\n\t// To do.\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_slist\n\t///////////////////////////////////////////////////////////////////////\n\n\t// To do.\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T>\n\tbool operator==(const intrusive_slist<T>& a, const intrusive_slist<T>& b)\n\t{\n\t\t// If we store an mSize member for intrusive_slist, we want to take advantage of it here.\n\t\ttypename intrusive_slist<T>::const_iterator ia   = a.begin();\n\t\ttypename intrusive_slist<T>::const_iterator ib   = b.begin();\n\t\ttypename intrusive_slist<T>::const_iterator enda = a.end();\n\t\ttypename intrusive_slist<T>::const_iterator endb = b.end();\n\n\t\twhile((ia != enda) && (ib != endb) && (*ia == *ib))\n\t\t{\n\t\t\t++ia;\n\t\t\t++ib;\n\t\t}\n\t\treturn (ia == enda) && (ib == endb);\n\t}\n\n\ttemplate <typename T>\n\tbool operator<(const intrusive_slist<T>& a, const intrusive_slist<T>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\ttemplate <typename T>\n\tbool operator!=(const intrusive_slist<T>& a, const intrusive_slist<T>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\ttemplate <typename T>\n\tbool operator>(const intrusive_slist<T>& a, const intrusive_slist<T>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\ttemplate <typename T>\n\tbool operator<=(const intrusive_slist<T>& a, const intrusive_slist<T>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate <typename T>\n\tbool operator>=(const intrusive_slist<T>& a, const intrusive_slist<T>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\ttemplate <typename T>\n\tvoid swap(intrusive_slist<T>& a, intrusive_slist<T>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/list_map.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_LIST_MAP_H\n#define EASTL_LIST_MAP_H\n\n\n#include <EASTL/map.h>\n\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4512 4626);\n\nnamespace eastl\n{\n\n\t/// EASTL_MAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_LIST_MAP_DEFAULT_NAME\n\t\t#define EASTL_LIST_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" list_map\" // Unless the user overrides something, this is \"EASTL list_map\".\n\t#endif\n\n\t/// EASTL_MAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_LIST_MAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_LIST_MAP_DEFAULT_ALLOCATOR allocator_type(EASTL_LIST_MAP_DEFAULT_NAME)\n\t#endif\n\n\n\t/// list_map_data_base\n\t///\n\t/// We define a list_map_data_base separately from list_map_data (below), because it \n\t/// allows us to have non-templated operations, and it makes it so that the \n\t/// list_map anchor node doesn't carry a T with it, which would waste space and \n\t/// possibly lead to surprising the user due to extra Ts existing that the user \n\t/// didn't explicitly create. The downside to all of this is that it makes debug \n\t/// viewing of an list_map harder, given that the node pointers are of type \n\t/// list_map_data_base and not list_map_data.\n\t///\n\tstruct list_map_data_base\n\t{\n\t\tlist_map_data_base* mpNext;\n\t\tlist_map_data_base* mpPrev;\n\t};\n\n\n\t/// list_map_data\n\t///\n\ttemplate <typename Value>\n\tstruct list_map_data : public list_map_data_base\n\t{\n\t\ttypedef Value       value_type;\n\n\t\tlist_map_data(const value_type& value);\n\n\t\tvalue_type mValue; // This is a pair of key/value.\n\t};\n\n\n\t/// list_map_iterator\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tstruct list_map_iterator\n\t{\n\t\ttypedef list_map_iterator<T, Pointer, Reference>    this_type;\n\t\ttypedef list_map_iterator<T, T*, T&>                iterator;\n\t\ttypedef list_map_iterator<T, const T*, const T&>    const_iterator;\n\t\ttypedef eastl_size_t                                size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                   difference_type;\n\t\ttypedef T                                           value_type;\n\t\ttypedef list_map_data_base                          base_node_type;\n\t\ttypedef list_map_data<T>                            node_type;\n\t\ttypedef Pointer                                     pointer;\n\t\ttypedef Reference                                   reference;\n\t\ttypedef eastl::bidirectional_iterator_tag    iterator_category;\n\n\tprivate:\n\t\tbase_node_type* mpNode;\n\n\tpublic:\n\t\tlist_map_iterator();\n\t\tlist_map_iterator(const base_node_type* pNode);\n\n\t\t// This is the converting constructor of a non-const iterator to a const iterator\n\t\t// This is never a copy constructor (due to enable_if)\n\t\ttemplate <typename This = this_type, enable_if_t<!is_same_v<This, iterator>, bool> = true>\n\t\tinline list_map_iterator(const iterator& x)\n\t\t\t: mpNode(x.mpNode)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\treference operator*() const;\n\t\tpointer   operator->() const;\n\n\t\tthis_type& operator++();\n\t\tthis_type  operator++(int);\n\n\t\tthis_type& operator--();\n\t\tthis_type  operator--(int);\n\n\tprivate:\n\t\ttemplate<class U, class PtrA, class RefA, class PtrB, class RefB>\n\t\tfriend bool operator==(const list_map_iterator<U, PtrA, RefA>&, const list_map_iterator<U, PtrB, RefB>&);\n\n\t\ttemplate<class U, class PtrA, class RefA, class PtrB, class RefB>\n\t\tfriend bool operator!=(const list_map_iterator<U, PtrA, RefA>&, const list_map_iterator<U, PtrB, RefB>&);\n\n\t\ttemplate<class U, class PtrA, class RefA>\n\t\tfriend bool operator!=(const list_map_iterator<U, PtrA, RefA>&, const list_map_iterator<U, PtrA, RefA>&);\n\n\t\t// list_map uses mpNode\n\t\ttemplate <typename Key, typename U, typename Compare, typename Allocator>\n\t\tfriend class list_map;\n\n\t\t// for the \"copy\" constructor, which uses non-const iterator even in the\n\t\t// const_iterator case.\n\t\tfriend iterator;\n\t\tfriend const_iterator;\n\t}; // list_map_iterator\n\n\n\t/// use_value_first\n\t///\n\t/// operator()(x) simply returns x.mValue.first. Used in list_map.\n\t/// This is similar to eastl::use_first, however it assumes that the input type is an object\n\t/// whose mValue is an eastl::pair, and the first value in the pair is the desired return.\n\t///\n\ttemplate <typename Object>\n\tstruct use_value_first\n\t{\n\t\ttypedef Object argument_type;\n\t\ttypedef typename Object::value_type::first_type result_type;\n\n\t\tconst result_type& operator()(const Object& x) const\n\t\t\t{ return x.mValue.first; }\n\t};\n\n\n\t/// list_map\n\t///\n\t/// Implements a map like container, which also provides functionality similar to a list.\n\t/// \n\t/// Note: Like a map, keys must still be unique.  As such, push_back() and push_front() operations\n\t///       return a bool indicating success, or failure if the entry's key is already in use.\n\t///\n\t/// list_map is designed to improve performance for situations commonly implemented as:\n\t///     A map, which must be iterated over to find the oldest entry, or purge expired entries.\n\t///     A list, which must be iterated over to remove a player's record when they sign off.\n\t/// \n\t/// list_map requires a little more memory per node than either a list or map alone,\n\t/// and many of list_map's functions have a higher operational cost (CPU time) than their\n\t/// counterparts in list and map.  However, as the node count increases, list_map quickly outperforms\n\t/// either a list or a map when find [by-index] and front/back type operations are required.\n\t/// \n\t/// In essence, list_map avoids O(n) iterations at the expense of additional costs to quick (O(1) and O(log n) operations:\n\t///     push_front(), push_back(), pop_front() and pop_back() have O(log n) operation time, similar to map::insert(), rather than O(1) time like a list,\n\t///     however, front() and back() maintain O(1) operation time.\n\t/// \n\t/// As a canonical example, consider a large backlog of player group invites, which are removed when either:\n\t///     The invitation times out - in main loop:  while( !listMap.empty() && listMap.front().IsExpired() ) { listMap.pop_front(); }\n\t///     The player rejects the outstanding invitation - on rejection:  iter = listMap.find(playerId);  if (iter != listMap.end()) { listMap.erase(iter); }\n\t/// \n\t/// For a similar example, consider a high volume pending request container which must:\n\t///     Time out old requests (similar to invites timing out above)\n\t///     Remove requests once they've been handled (similar to rejecting invites above)\n\t/// \n\t/// For such usage patterns, the performance benefits of list_map become dramatic with\n\t/// common O(n) operations once the node count rises to hundreds or more.\n\t/// \n\t/// When high performance is a priority, Containers with thousands of nodes or more\n\t/// can quickly result in unacceptable performance when executing even infrequenty O(n) operations.\n\t/// \n\t/// In order to maintain strong performance, avoid iterating over list_map whenever possible.\n\t/// \n\t///////////////////////////////////////////////////////////////////////\n\t/// find_as\n\t/// In order to support the ability to have a tree of strings but\n\t/// be able to do efficiently lookups via char pointers (i.e. so they\n\t/// aren't converted to string objects), we provide the find_as\n\t/// function. This function allows you to do a find with a key of a\n\t/// type other than the tree's key type. See the find_as function\n\t/// for more documentation on this.\n\t///\n\t///////////////////////////////////////////////////////////////////////\n\t/// Pool allocation\n\t/// If you want to make a custom memory pool for a list_map container, your pool \n\t/// needs to contain items of type list_map::node_type. So if you have a memory\n\t/// pool that has a constructor that takes the size of pool items and the\n\t/// count of pool items, you would do this (assuming that MemoryPool implements\n\t/// the Allocator interface):\n\t///     typedef list_map<Widget, int, less<Widget>, MemoryPool> WidgetMap;  // Delare your WidgetMap type.\n\t///     MemoryPool myPool(sizeof(WidgetMap::node_type), 100);               // Make a pool of 100 Widget nodes.\n\t///     WidgetMap myMap(&myPool);                                           // Create a map that uses the pool.\n\t///\n\ttemplate <typename Key, typename T, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>\n\tclass list_map\n\t\t: protected rbtree<Key, eastl::list_map_data<eastl::pair<const Key, T> >, Compare, Allocator, eastl::use_value_first<eastl::list_map_data<eastl::pair<const Key, T> > >, true, true>\n\t{\n\tpublic:\n\t\ttypedef rbtree<Key, eastl::list_map_data<eastl::pair<const Key, T> >, Compare, Allocator,\n\t\t\t\t\t   eastl::use_value_first<eastl::list_map_data<eastl::pair<const Key, T> > >, true, true>   base_type;\n\t\ttypedef list_map<Key, T, Compare, Allocator>                                                            this_type;\n\t\ttypedef typename base_type::size_type                                                                   size_type;\n\t\ttypedef typename base_type::key_type                                                                    key_type;\n\t\ttypedef T                                                                                               mapped_type;\n\t\ttypedef typename eastl::pair<const Key, T>                                                              value_type;          // This is intentionally different from base_type::value_type\n\t\ttypedef value_type&                                                                                     reference;\n\t\ttypedef const value_type&                                                                               const_reference;\n\t\ttypedef typename base_type::node_type                                                                   node_type;           // Despite the internal and external values being different, we're keeping the node type the same as the base\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t // in order to allow for pool allocation.  See EASTL/map.h for more information.\n\t\ttypedef typename eastl::list_map_iterator<value_type, value_type*, value_type&>                         iterator;            // This is intentionally different from base_type::iterator\n\t\ttypedef typename eastl::list_map_iterator<value_type, const value_type*, const value_type&>             const_iterator;      // This is intentionally different from base_type::const_iterator\n\t\ttypedef eastl::reverse_iterator<iterator>                                                               reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>                                                         const_reverse_iterator;\n\t\ttypedef typename base_type::allocator_type                                                              allocator_type;\n\t\ttypedef typename eastl::pair<iterator, bool>                                                            insert_return_type;  // This is intentionally removed, as list_map doesn't support insert() functions, in favor of list like push_back and push_front\n\t\ttypedef typename eastl::use_first<value_type>                                                           extract_key;         // This is intentionally different from base_type::extract_key\n\n\t\tusing base_type::get_allocator;\n\t\tusing base_type::set_allocator;\n\t\tusing base_type::key_comp;\n\t\tusing base_type::empty;\n\t\tusing base_type::size;\n\n\tprotected:\n\t\ttypedef typename eastl::list_map_data<eastl::pair<const Key, T> >                                       internal_value_type;\n\n\tprotected:\n\t\t// internal base node, acting as the sentinel for list like behaviors\n\t\tlist_map_data_base mNode;\n\n\tpublic:\n\t\tlist_map(const allocator_type& allocator = EASTL_LIST_MAP_DEFAULT_ALLOCATOR);\n\t\tlist_map(const Compare& compare, const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);\n\n\t\t// To do: Implement the following:\n\n\t\t//list_map(const this_type& x);\n\t\t//list_map(this_type&& x);\n\t\t//list_map(this_type&& x, const allocator_type& allocator);\n\t\t//list_map(std::initializer_list<mapped_type> ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_LIST_MAP_DEFAULT_ALLOCATOR);\n\n\t\t//template <typename Iterator>\n\t\t//list_map(Iterator itBegin, Iterator itEnd);\n\n\t\t//this_type& operator=(const this_type& x);\n\t\t//this_type& operator=(std::initializer_list<mapped_type> ilist);\n\t\t//this_type& operator=(this_type&& x);\n\n\t\t//void swap(this_type& x);\n\n\tpublic:\n\t\t// iterators\n\t\titerator       begin() EA_NOEXCEPT;\n\t\tconst_iterator begin() const EA_NOEXCEPT;\n\t\tconst_iterator cbegin() const EA_NOEXCEPT;\n\n\t\titerator       end() EA_NOEXCEPT;\n\t\tconst_iterator end() const EA_NOEXCEPT;\n\t\tconst_iterator cend() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rbegin() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crbegin() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rend() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rend() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crend() const EA_NOEXCEPT;\n\n\tpublic:\n\t\t// List like methods\n\t\treference       front();\n\t\tconst_reference front() const;\n\n\t\treference       back();\n\t\tconst_reference back() const;\n\n\t\t// push_front and push_back which takes in a key/value pair\n\t\tbool            push_front(const value_type& value);\n\t\tbool            push_back(const value_type& value);\n\n\t\t// push_front and push_back which take key and value separately, for convenience\n\t\tbool            push_front(const key_type& key, const mapped_type& value);\n\t\tbool            push_back(const key_type& key, const mapped_type& value);\n\n\t\tvoid            pop_front();\n\t\tvoid            pop_back();\n\n\tpublic:\n\t\t// Map like methods\n\t\titerator        find(const key_type& key);\n\t\tconst_iterator  find(const key_type& key) const;\n\n\t\ttemplate <typename U, typename Compare2>\n\t\titerator       find_as(const U& u, Compare2 compare2);\n\t\ttemplate <typename U, typename Compare2>\n\t\tconst_iterator find_as(const U& u, Compare2 compare2) const;\n\n\t\tsize_type count(const key_type& key) const;\n\t\tsize_type erase(const key_type& key);\n\n\t\t// todo: add heterogenous lookup support (using a heterogeneous comparator - a type 'Comp' where 'Comp::is_transparent' is valid and denotes a type):\n\t\t// template<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\t// iterator        find(const KX& key);\n\t\t//\n\t\t// ... also for count() ...\n\t\t// ... also for erase() ...\n\n\tpublic:\n\t\t// Shared methods which are common to list and map\n\t\titerator erase(const_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator position);\n\n\t\tvoid clear();\n\t\tvoid reset_lose_memory();\n\n\t\tbool validate() const;\n\t\tint validate_iterator(const_iterator i) const;\n\n\tpublic:\n\t\t// list like functionality which is in consideration for implementation:\n\t\t// iterator insert(const_iterator position, const value_type& value);\n\t\t// void remove(const mapped_type& x); \n\t\t \n\tpublic:\n\t\t// list like functionality which may be implemented, but is discouraged from implementation:\n\t\t// due to the liklihood that they would require O(n) time to execute.\n\t\t// template <typename Predicate>\n\t\t// void remove_if(Predicate);\n\t\t// void reverse();\n\t\t// void sort();\n\t\t// template<typename Compare>\n\t\t// void sort(Compare compare);          \n\n\tpublic:\n\t\t// map like functionality which list_map does not support, due to abmiguity with list like functionality:\n\t\t#if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\t\ttemplate <typename InputIterator>\n\t\t\tlist_map(InputIterator first, InputIterator last, const Compare& compare, const allocator_type& allocator = EASTL_RBTREE_DEFAULT_ALLOCATOR) = delete;\n\t\t \n\t\t\tinsert_return_type insert(const value_type& value) = delete;\n\t\t\titerator insert(const_iterator position, const value_type& value) = delete;\n\n\t\t\ttemplate <typename InputIterator>\n\t\t\tvoid insert(InputIterator first, InputIterator last) = delete;\n\t\t\t\t  \n\t\t\tinsert_return_type insert(const key_type& key) = delete;\n\t\t \n\t\t\titerator erase(const_iterator first, const_iterator last) = delete;\n\t\t\treverse_iterator erase(reverse_iterator first, reverse_iterator last) = delete;\n\t\t \n\t\t\tvoid erase(const key_type* first, const key_type* last) = delete;\n\t\t \n\t\t\titerator       lower_bound(const key_type& key) = delete;\n\t\t\tconst_iterator lower_bound(const key_type& key) const = delete;\n\n\t\t\titerator       upper_bound(const key_type& key) = delete;\n\t\t\tconst_iterator upper_bound(const key_type& key) const = delete;\n\t\t \n\t\t\teastl::pair<iterator, iterator>             equal_range(const key_type& key) = delete;\n\t\t\teastl::pair<const_iterator, const_iterator> equal_range(const key_type& key) const = delete;\n\n\t\t\tmapped_type& operator[](const key_type& key) = delete; // Of map, multimap, set, and multimap, only map has operator[].\n\t\t#endif\n\n\tpublic:\n\t\t// list like functionality which list_map does not support, due to ambiguity with map like functionality:\n\t\t#if 0\n\t\t\treference push_front() = delete;\n\t\t\tvoid*     push_front_uninitialized() = delete;\n\n\t\t\treference push_back() = delete;\n\t\t\tvoid*     push_back_uninitialized() = delete;\n\n\t\t\titerator insert(const_iterator position) = delete;\n\t\t \n\t\t\tvoid insert(const_iterator position, size_type n, const value_type& value) = delete;\n\n\t\ttemplate <typename InputIterator>\n\t\t\tvoid insert(const_iterator position, InputIterator first, InputIterator last) = delete;\n\t\t \n\t\t\titerator erase(const_iterator first, const_iterator last) = delete;\n\t\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last) = delete;\n\t\t \n\t\t\tvoid splice(const_iterator position, this_type& x) = delete\n\t\t\tvoid splice(const_iterator position, this_type& x, const_iterator i) = delete;\n\t\t\tvoid splice(const_iterator position, this_type& x, const_iterator first, const_iterator last) = delete;\n\n\t\t\tvoid merge(this_type& x) = delete;\n\n\t\ttemplate <typename Compare>\n\t\t\tvoid merge(this_type& x, Compare compare) = delete;\n\t\t \n\t\t\tvoid unique() = delete;  // Uniqueness is enforced by map functionality\n\n\t\ttemplate <typename BinaryPredicate>\n\t\t\tvoid unique(BinaryPredicate) = delete;  // Uniqueness is enforced by map functionality\n\t\t#endif\n\n\t}; // list_map\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// list_map_data\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value>\n\tinline list_map_data<Value>::list_map_data(const Value& value)\n\t  : mValue(value)\n\t{\n\t\tmpNext = NULL; // GCC 4.8 is generating warnings about referencing these values in list_map::push_front unless we \n\t\tmpPrev = NULL; // initialize them here. The compiler seems to be mistaken, as our code isn't actually using them unintialized.\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// list_map_iterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline list_map_iterator<T, Pointer, Reference>::list_map_iterator()\n\t\t: mpNode(NULL)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline list_map_iterator<T, Pointer, Reference>::list_map_iterator(const base_node_type* pNode)\n\t\t: mpNode(const_cast<base_node_type*>(pNode))\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename list_map_iterator<T, Pointer, Reference>::reference\n\tlist_map_iterator<T, Pointer, Reference>::operator*() const\n\t{\n\t\treturn static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename list_map_iterator<T, Pointer, Reference>::pointer\n\tlist_map_iterator<T, Pointer, Reference>::operator->() const\n\t{\n\t\treturn &static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename list_map_iterator<T, Pointer, Reference>::this_type&\n\tlist_map_iterator<T, Pointer, Reference>::operator++()\n\t{\n\t\tmpNode = mpNode->mpNext;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename list_map_iterator<T, Pointer, Reference>::this_type\n\tlist_map_iterator<T, Pointer, Reference>::operator++(int)\n\t{\n\t\tthis_type temp(*this);\n\t\tmpNode = mpNode->mpNext;\n\t\treturn temp;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename list_map_iterator<T, Pointer, Reference>::this_type&\n\tlist_map_iterator<T, Pointer, Reference>::operator--()\n\t{\n\t\tmpNode = mpNode->mpPrev;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename list_map_iterator<T, Pointer, Reference>::this_type \n\tlist_map_iterator<T, Pointer, Reference>::operator--(int)\n\t{\n\t\tthis_type temp(*this);\n\t\tmpNode = mpNode->mpPrev;\n\t\treturn temp;\n\t}\n\n\n\t// We provide additional template paremeters here to support comparisons between const and non-const iterators.\n\t// See C++ defect report #179, or EASTL/list.h for more information.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator==(const list_map_iterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const list_map_iterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode == b.mpNode;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator!=(const list_map_iterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const list_map_iterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\t// We provide a version of operator!= for the case where the iterators are of the \n\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline bool operator!=(const list_map_iterator<T, Pointer, Reference>& a, \n\t\t\t\t\t\t   const list_map_iterator<T, Pointer, Reference>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// list_map\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline list_map<Key, T, Compare, Allocator>::list_map(const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tmNode.mpNext = &mNode;\n\t\tmNode.mpPrev = &mNode;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline list_map<Key, T, Compare, Allocator>::list_map(const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(compare, allocator)\n\t{\n\t\tmNode.mpNext = &mNode;\n\t\tmNode.mpPrev = &mNode;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::iterator \n\tlist_map<Key, T, Compare, Allocator>::begin() EA_NOEXCEPT\n\t{\n\t\treturn iterator(mNode.mpNext);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_iterator \n\tlist_map<Key, T, Compare, Allocator>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mNode.mpNext);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_iterator \n\tlist_map<Key, T, Compare, Allocator>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mNode.mpNext);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::iterator \n\tlist_map<Key, T, Compare, Allocator>::end() EA_NOEXCEPT\n\t{\n\t\treturn iterator(&mNode);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_iterator \n\tlist_map<Key, T, Compare, Allocator>::end() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&mNode);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_iterator \n\tlist_map<Key, T, Compare, Allocator>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&mNode);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::reverse_iterator \n\tlist_map<Key, T, Compare, Allocator>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(&mNode);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_reverse_iterator \n\tlist_map<Key, T, Compare, Allocator>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(&mNode);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_reverse_iterator \n\tlist_map<Key, T, Compare, Allocator>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(&mNode);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::reverse_iterator \n\tlist_map<Key, T, Compare, Allocator>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(mNode.mpNext);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_reverse_iterator \n\tlist_map<Key, T, Compare, Allocator>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mNode.mpNext);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_reverse_iterator \n\tlist_map<Key, T, Compare, Allocator>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mNode.mpNext);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::reference\n\tlist_map<Key, T, Compare, Allocator>::front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<internal_value_type*>(mNode.mpNext) == &mNode))\n\t\t\t\tEASTL_FAIL_MSG(\"list_map::front -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<internal_value_type*>(mNode.mpNext)->mValue;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_reference\n\tlist_map<Key, T, Compare, Allocator>::front() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<internal_value_type*>(mNode.mpNext) == &mNode))\n\t\t\t\tEASTL_FAIL_MSG(\"list_map::front -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<internal_value_type*>(mNode.mpNext)->mValue;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::reference\n\tlist_map<Key, T, Compare, Allocator>::back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<internal_value_type*>(mNode.mpNext) == &mNode))\n\t\t\t\tEASTL_FAIL_MSG(\"list_map::back -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<internal_value_type*>(mNode.mpPrev)->mValue;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_reference\n\tlist_map<Key, T, Compare, Allocator>::back() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<internal_value_type*>(mNode.mpNext) == &mNode))\n\t\t\t\tEASTL_FAIL_MSG(\"list_map::back -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<internal_value_type*>(mNode.mpPrev)->mValue;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tbool list_map<Key, T, Compare, Allocator>::push_front(const value_type& value)\n\t{\n\t\tinternal_value_type tempValue(value);\n\t\ttypename base_type::insert_return_type baseReturn = base_type::insert(tempValue);\n\n\t\t// Did the insert succeed?\n\t\tif (baseReturn.second)\n\t\t{\n\t\t\tinternal_value_type* pNode = &(*baseReturn.first);\n\n\t\t\tpNode->mpNext = mNode.mpNext;\n\t\t\tpNode->mpPrev = &mNode;\n\n\t\t\tmNode.mpNext->mpPrev = pNode;\n\t\t\tmNode.mpNext = pNode;\n\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tbool list_map<Key, T, Compare, Allocator>::push_back(const value_type& value)\n\t{\n\t\tinternal_value_type tempValue(value);\n\t\ttypename base_type::insert_return_type baseReturn = base_type::insert(tempValue);\n\n\t\t// Did the insert succeed?\n\t\tif (baseReturn.second)\n\t\t{\n\t\t\tinternal_value_type* pNode = &(*baseReturn.first);\n\n\t\t\tpNode->mpPrev = mNode.mpPrev;\n\t\t\tpNode->mpNext = &mNode;\n\n\t\t\tmNode.mpPrev->mpNext = pNode;\n\t\t\tmNode.mpPrev = pNode;\n\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tbool list_map<Key, T, Compare, Allocator>::push_front(const key_type& key, const mapped_type& value)\n\t{\n\t\treturn push_front(eastl::make_pair(key, value));\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tbool list_map<Key, T, Compare, Allocator>::push_back(const key_type& key, const mapped_type& value)\n\t{\n\t\treturn push_back(eastl::make_pair(key, value));\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tvoid list_map<Key, T, Compare, Allocator>::pop_front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(empty()))\n\t\t\t\tEASTL_FAIL_MSG(\"list_map::pop_front -- empty container\");\n\t\t#endif\n\n\t\terase(static_cast<internal_value_type*>(mNode.mpNext)->mValue.first);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tvoid list_map<Key, T, Compare, Allocator>::pop_back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(empty()))\n\t\t\t\tEASTL_FAIL_MSG(\"list_map::pop_back -- empty container\");\n\t\t#endif\n\n\t\terase(static_cast<internal_value_type*>(mNode.mpPrev)->mValue.first);\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::iterator \n\tlist_map<Key, T, Compare, Allocator>::find(const key_type& key)\n\t{\n\t\ttypename base_type::iterator baseIter = base_type::find(key);\n\t\tif (baseIter != base_type::end())\n\t\t{\n\t\t\treturn iterator(&(*baseIter));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn end();\n\t\t}\n\t}\n\t\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_iterator\n\tlist_map<Key, T, Compare, Allocator>::find(const key_type& key) const\n\t{\n\t\ttypename base_type::const_iterator baseIter = base_type::find(key);\n\t\tif (baseIter != base_type::end())\n\t\t{\n\t\t\treturn const_iterator(&(*baseIter));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn end();\n\t\t}\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename U, typename Compare2>\n\tinline typename list_map<Key, T, Compare, Allocator>::iterator\n\tlist_map<Key, T, Compare, Allocator>::find_as(const U& u, Compare2 compare2)\n\t{\n\t\ttypename base_type::iterator baseIter = base_type::find_as(u, compare2);\n\t\tif (baseIter != base_type::end())\n\t\t{\n\t\t\treturn iterator(&(*baseIter));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn end();\n\t\t}\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename U, typename Compare2>\n\tinline typename list_map<Key, T, Compare, Allocator>::const_iterator\n\tlist_map<Key, T, Compare, Allocator>::find_as(const U& u, Compare2 compare2) const\n\t{\n\t\ttypename base_type::const_iterator baseIter = base_type::find_as(u, compare2);\n\t\tif (baseIter != base_type::end())\n\t\t{\n\t\t\treturn const_iterator(&(*baseIter));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn end();\n\t\t}\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::size_type\n\tlist_map<Key, T, Compare, Allocator>::count(const key_type& key) const\n\t{\n\t\tconst typename base_type::const_iterator it = base_type::find(key);\n\t\treturn (it != base_type::end()) ? 1 : 0;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::size_type\n\tlist_map<Key, T, Compare, Allocator>::erase(const key_type& key)\n\t{\n\t\ttypename base_type::iterator baseIter = base_type::find(key);\n\t\tif (baseIter != base_type::end())\n\t\t{\n\t\t\tinternal_value_type* node = &(*baseIter);\n\n\t\t\tnode->mpNext->mpPrev = node->mpPrev;\n\t\t\tnode->mpPrev->mpNext = node->mpNext;\n\n\t\t\tbase_type::erase(baseIter);\n\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::iterator\n\tlist_map<Key, T, Compare, Allocator>::erase(const_iterator position)\n\t{\n\t\titerator posIter(position.mpNode); // Convert from const.\n\t\titerator eraseIter(posIter++);\n\t\terase(eraseIter->first);\n\t\treturn posIter;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename list_map<Key, T, Compare, Allocator>::reverse_iterator\n\tlist_map<Key, T, Compare, Allocator>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tvoid list_map<Key, T, Compare, Allocator>::clear()\n\t{\n\t\tbase_type::clear();\n\n\t\tmNode.mpNext = &mNode;\n\t\tmNode.mpPrev = &mNode;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tvoid list_map<Key, T, Compare, Allocator>::reset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\n\t\tmNode.mpNext = &mNode;\n\t\tmNode.mpPrev = &mNode;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tbool list_map<Key, T, Compare, Allocator>::validate() const\n\t{\n\t\tif (!base_type::validate())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\tsize_type nodeCount(0);\n\t\tlist_map_data_base* node = mNode.mpNext;\n\t\twhile (node != &mNode)\n\t\t{\n\t\t\tinternal_value_type* data = static_cast<internal_value_type*>(node);\n\t\t\tif (base_type::find(data->mValue.first) == base_type::end())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tnode = node->mpNext;\n\t\t\t++nodeCount;\n\t\t}\n\t\tif (nodeCount != size())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tnodeCount = 0;\n\t\tnode = mNode.mpPrev;\n\t\twhile (node != &mNode)\n\t\t{\n\t\t\tinternal_value_type* data = static_cast<internal_value_type*>(node);\n\t\t\tif (base_type::find(data->mValue.first) == base_type::end())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tnode = node->mpPrev;\n\t\t\t++nodeCount;\n\t\t}\n\t\tif (nodeCount != size())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tint list_map<Key, T, Compare, Allocator>::validate_iterator(const_iterator iter) const\n\t{\n\t\tfor (const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif (temp == iter)\n\t\t\t{\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t\t}\n\t\t}\n\n\t\tif (iter == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING();\n\n#endif // Header include guard\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/lru_cache.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// lru_cache is a container that simplifies caching of objects in a map.\n// Basically, you give the container a key, like a string, and the data you want.\n// The container provides callback mechanisms to generate data if it's missing\n// as well as delete data when it's purged from the cache.  This container\n// uses a least recently used method: whatever the oldest item is will be \n// replaced with a new entry.\n//\n// Algorithmically, the container is a combination of a map and a list.\n// The list stores the age of the entries by moving the entry to the head\n// of the list on each access, either by a call to get() or to touch().\n// The map is just the map as one would expect.\n//\n// This is useful for caching off data that is expensive to generate, \n// for example text to speech wave files that are dynamically generated,\n// but that will need to be reused, as is the case in narration of menu\n// entries as a user scrolls through the entries.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_LRUCACHE_H\n#define EASTL_LRUCACHE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n#pragma once\n#endif\n\n#include <EASTL/list.h>\n#include <EASTL/unordered_map.h>\n#include <EASTL/optional.h>\n#include <EASTL/utility.h> // for pair\n#include <EASTL/functional.h> // for function, hash, equal_to\n\nnamespace eastl\n{\n\t/// EASTL_LRUCACHE_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_LRUCACHE_DEFAULT_NAME\n\t#define EASTL_LRUCACHE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" lru_cache\" // Unless the user overrides something, this is \"EASTL lru_cache\".\n\t#endif\n\n\n\t/// EASTL_LRUCACHE_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_LRUCACHE_DEFAULT_ALLOCATOR\n\t#define EASTL_LRUCACHE_DEFAULT_ALLOCATOR allocator_type(EASTL_LRUCACHE_DEFAULT_NAME)\n\t#endif\n\n\t/// lru_cache\n\t///\n\t/// Implements a caching map based off of a key and data.\n\t/// LRUList parameter is any container that guarantees the validity of its iterator even after a modification (e.g. list)\n\t/// LRUMap is any associative container that can map a key to some data.  By default, we use unordered_map, but it might be better\n\t/// to use hash_map or some other structure depending on your key/data combination.  For example, you may want to swap the \n\t/// map backing if using strings as keys or if the data objects are small.  In any case, unordered_map is a good default and should\n\t/// work well enough since the purpose of this class is to cache results of expensive, order of milliseconds, operations\n\t///\n\t/// Algorithmic Performance (default data structures):\n\t///\t\ttouch() -> O(1)\n\t///\t\tinsert() / update(), get() / operator[] -> equivalent to unordered_map (O(1) on average, O(n) worst)\n\t///\t\tsize() -> O(1)\n\t///\n\t/// All accesses to a given key (insert, update, get) will push that key to most recently used.\n\t/// If the data objects are shared between threads, it would be best to use a smartptr to manage the lifetime of the data.\n\t/// as it could be removed from the cache while in use by another thread.\n\ttemplate <typename Key,\n\t          typename Value,\n\t          typename Allocator = EASTLAllocatorType,\n\t          typename list_type = eastl::list<Key, Allocator>,\n\t          typename map_type = eastl::unordered_map<Key,\n\t                                                   eastl::pair<Value, typename list_type::iterator>,\n\t                                                   eastl::hash<Key>,\n\t                                                   eastl::equal_to<Key>,\n\t                                                   Allocator>>\n\tclass lru_cache\n\t{\n\tpublic:\n\t\tusing key_type = Key;\n\t\tusing value_type = Value;\n\t\tusing allocator_type = Allocator;\n\t\tusing size_type = eastl_size_t;\n\t\tusing list_iterator = typename list_type::iterator;\n\t\tusing map_iterator = typename map_type::iterator;\n\t\tusing data_container_type = eastl::pair<value_type, list_iterator>;\n\t\tusing iterator = typename map_type::iterator;\n\t\tusing const_iterator = typename map_type::const_iterator;\n\t\tusing this_type = lru_cache<key_type, value_type, Allocator, list_type, map_type>;\n\t\tusing create_callback_type = eastl::function<value_type(key_type)>;\n\t\tusing delete_callback_type = eastl::function<void(const value_type &)>;\n\n\t\t/// lru_cache constructor\n\t\t///\n\t\t/// Creates a Key / Value map that only stores size Value objects until it deletes them.\n\t\t/// For complex objects or operations, the creator and deletor callbacks can be used.\n\t\t/// This works just like a regular map object: on access, the Value will be created if it doesn't exist, returned otherwise.\n\t\texplicit lru_cache(size_type size,\n\t\t                   const allocator_type& allocator = EASTL_LRUCACHE_DEFAULT_ALLOCATOR,\n\t\t                   create_callback_type creator = nullptr,\n\t\t                   delete_callback_type deletor = nullptr)\n\t\t    : m_list(allocator)\n\t\t    , m_map(allocator)\n\t\t    , m_capacity(size)\n\t\t    , m_create_callback(creator)\n\t\t    , m_delete_callback(deletor)\n\t\t{\n\t\t}\n\n\t\t/// lru_cache destructor\n\t\t///\n\t\t/// Iterates across every entry in the map and calls the deletor before calling the standard destructors\n\t\t~lru_cache()\n\t\t{\n\t\t\t// Destruct everything we have cached\n\t\t\tfor (auto& iter : m_map)\n\t\t\t{\n\t\t\t\tif (m_delete_callback)\n\t\t\t\t\tm_delete_callback(iter.second.first);\n\t\t\t}\n\t\t}\n\n\t\tlru_cache(std::initializer_list<eastl::pair<Key, Value>> il)\n\t\t\t: lru_cache(static_cast<size_type>(il.size()))\n\t\t{\n\t\t\tfor(auto& p : il)\n\t\t\t\tinsert_or_assign(p.first, p.second);\n\t\t}\n\n\t\t// TODO(rparolin):  Why do we prevent copies? And what about moves?\n\t\tlru_cache(const this_type&) = delete;\n\t\tthis_type &operator=(const this_type&) = delete;\n\n\t\t/// insert\n\t\t/// \n\t\t/// insert key k with value v.\n\t\t/// If key already exists, no change is made and the return value is false.\n\t\t/// If the key doesn't exist, the data is added to the map and the return value is true.\n\t\tbool insert(const key_type& k, const value_type& v)\n\t\t{\n\t\t\tif (m_map.find(k) == m_map.end())\n\t\t\t{\n\t\t\t\tmake_space();\n\n\t\t\t\tm_list.push_front(k);\n\t\t\t\tm_map[k] = data_container_type(v, m_list.begin());\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t/// emplace\n\t\t/// \n\t\t/// Places a new object in place k created with args\n\t\t/// If the key already exists, no change is made.\n\t\t/// return value is a pair of the iterator to the emplaced or already-existing element and a bool denoting whether insertion took place.\n\t\ttemplate <typename... Args>\n\t\teastl::pair<iterator, bool> emplace(const key_type& k, Args&&... args)\n\t\t{\n\t\t\tauto it = m_map.find(k);\n\t\t\tif (it == m_map.end())\n\t\t\t{\n\t\t\t\tmake_space();\n\n\t\t\t\tm_list.push_front(k);\n\t\t\t\treturn m_map.emplace(k, data_container_type(piecewise_construct, eastl::forward_as_tuple(eastl::forward<Args>(args)...), make_tuple(m_list.begin())));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn make_pair(it, false);\n\t\t\t}\n\t\t}\n\n\t\t/// insert_or_assign\n\t\t///\n\t\t/// Same as add, but replaces the data at key k, if it exists, with the new entry v\n\t\t/// Note that the deletor for the old v will be called before it's replaced with the new value of v\n\t\tvoid insert_or_assign(const key_type& k, const value_type& v)\n\t\t{\n\t\t\tauto iter = m_map.find(k);\n\n\t\t\tif (m_map.find(k) != m_map.end())\n\t\t\t{\n\t\t\t\tassign(iter, v);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinsert(k, v);\n\t\t\t}\n\t\t}\n\n\t\t/// contains\n\t\t/// \n\t\t/// Returns true if key k exists in the cache\n\t\tbool contains(const key_type& k) const\n\t\t{\n\t\t\treturn m_map.find(k) != m_map.end();\n\t\t}\n\n\t\t/// at\n\t\t///\n\t\t/// Retrives the data for key k, not valid if k does not exist\n\t\teastl::optional<value_type> at(const key_type& k)\n\t\t{\n\t\t\tauto iter = m_map.find(k);\n\n\t\t\tif (iter != m_map.end())\n\t\t\t{\n\t\t\t\treturn iter->second.first;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn eastl::nullopt;\n\t\t\t}\n\t\t}\n\n\t\t/// get\n\t\t///\n\t\t/// Retrives the data for key k.  If no data exists, it will be created by calling the\n\t\t/// creator.\n\t\tvalue_type& get(const key_type& k)\n\t\t{\n\t\t\tauto iter = m_map.find(k);\n\n\t\t\t// The entry exists in the cache\n\t\t\tif (iter != m_map.end())\n\t\t\t{\n\t\t\t\ttouch(k);\n\t\t\t\treturn iter->second.first;\n\t\t\t}\n\t\t\telse // The entry doesn't exist in the cache, so create one\n\t\t\t{\n\t\t\t\t// Add the entry to the map\n\t\t\t\tinsert(k, m_create_callback ? m_create_callback(k) : value_type());\n\n\t\t\t\t// return the new data\n\t\t\t\treturn m_map[k].first;\n\t\t\t}\n\t\t}\n\n\t\t/// Equivalent to get(k)\n\t\tvalue_type& operator[](const key_type& k) { return get(k); }\n\n\t\t/// erase\n\t\t///\n\t\t/// erases key k from the cache.\n\t\t/// If k does not exist, returns false.  If k exists, returns true.\n\t\tbool erase(const key_type& k)\n\t\t{\n\t\t\tauto iter = m_map.find(k);\n\n\t\t\tif (iter != m_map.end())\n\t\t\t{\n\t\t\t\tm_list.erase(iter->second.second);\n\n\t\t\t\t// Delete the actual entry\n\t\t\t\tmap_erase(iter);\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\t/// erase_oldest\n\t\t///\n\t\t/// Removes the oldest entry from the cache.\n\t\tvoid erase_oldest()\n\t\t{\n\t\t\tauto key = m_list.back();\n\t\t\tm_list.pop_back();\n\n\t\t\t// Delete the actual entry\n\t\t\tauto iter = m_map.find(key);\n\t\t\tmap_erase(iter);\n\t\t}\n\n\t\t/// touch\n\t\t///\n\t\t/// Touches key k, marking it as most recently used.\n\t\t/// If k does not exist, returns false.  If the touch was successful, returns true.\n\t\tbool touch(const key_type& k)\n\t\t{\n\t\t\tauto iter = m_map.find(k);\n\n\t\t\tif (iter != m_map.end())\n\t\t\t{\n\t\t\t\ttouch(iter);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\t/// touch\n\t\t///\n\t\t/// Touches key at iterator iter, moving it to most recently used position\n\t\tvoid touch(iterator& iter)\n\t\t{\n\t\t\tauto listRef = iter->second.second;\n\n\t\t\tm_list.erase(listRef);\n\t\t\tm_list.push_front(iter->first);\n\t\t\titer->second.second = m_list.begin();\n\t\t}\n\n\t\t/// assign\n\t\t///\n\t\t/// Updates key k with data v.\n\t\t/// If key k does not exist, returns false and no changes are made.\n\t\t/// If key k exists, existing data has its deletor called and key k's data is replaced with new v data\n\t\tbool assign(const key_type& k, const value_type& v)\n\t\t{\n\t\t\tauto iter = m_map.find(k);\n\n\t\t\tif (iter != m_map.end())\n\t\t\t{\n\t\t\t\tassign(iter, v);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\t/// assign\n\t\t///\n\t\t/// Updates data at spot iter with data v.\n\t\tvoid assign(iterator& iter, const value_type& v)\n\t\t{\n\t\t\tif (m_delete_callback)\n\t\t\t\tm_delete_callback(iter->second.first);\n\t\t\ttouch(iter);\n\t\t\titer->second.first = v;\n\t\t}\n\n\t\t// standard container functions\n\t\titerator begin()               EA_NOEXCEPT { return m_map.begin(); }\n\t\titerator end()                 EA_NOEXCEPT { return m_map.end(); }\n\t\titerator rbegin()              EA_NOEXCEPT { return m_map.rbegin(); }\n\t\titerator rend()                EA_NOEXCEPT { return m_map.rend(); }\n\t\tconst_iterator begin() const   EA_NOEXCEPT { return m_map.begin(); }\n\t\tconst_iterator cbegin() const  EA_NOEXCEPT { return m_map.cbegin(); }\n\t\tconst_iterator crbegin() const EA_NOEXCEPT { return m_map.crbegin(); }\n\t\tconst_iterator end() const     EA_NOEXCEPT { return m_map.end(); }\n\t\tconst_iterator cend() const    EA_NOEXCEPT { return m_map.cend(); }\n\t\tconst_iterator crend() const   EA_NOEXCEPT { return m_map.crend(); }\n\n\t\tbool empty() const             EA_NOEXCEPT { return m_map.empty(); }\n\t\tsize_type size() const         EA_NOEXCEPT { return m_map.size(); }\n\t\tsize_type capacity() const     EA_NOEXCEPT { return m_capacity; }\n\n\t\tvoid clear() EA_NOEXCEPT\n\t\t{\n\t\t\t// Since we have a delete callback, we want to reuse the trim function by cheating the max\n\t\t\t// size to clear all the entries to avoid duplicating code.\n\t\t\tauto old_max = m_capacity;\n\n\t\t\tm_capacity = 0;\n\t\t\ttrim();\n\t\t\tm_capacity = old_max;\n\t\t}\n\n\t\t/// resize\n\t\t///\n\t\t/// Resizes the cache.  Can be used to either expand or contract the cache.\n\t\t/// In the case of a contraction, the oldest entries will be evicted with their respective\n\t\t/// deletors called before completing.\n\t\tvoid resize(size_type newSize)\t\n\t\t{\n\t\t\tm_capacity = newSize;\n\t\t\ttrim();\n\t\t}\n\t\t\n\t\tvoid setCreateCallback(create_callback_type callback) { m_create_callback = callback; }\n\t\tvoid setDeleteCallback(delete_callback_type callback) { m_delete_callback = callback; }\n\n\t\t// EASTL extensions\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT\t\t\t\t\t{ return m_map.get_allocator(); }\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT\t\t\t\t\t\t{ return m_map.get_allocator(); }\n\t\tvoid                  set_allocator(const allocator_type& allocator)\t{ m_map.set_allocator(allocator); m_list.set_allocator(allocator); }\n\n\t\t/// Does not reset the callbacks\n\t\tvoid reset_lose_memory() EA_NOEXCEPT\t\t\t\t\t\t\t\t\t{ m_map.reset_lose_memory(); m_list.reset_lose_memory(); }\n\n\tprivate:\n\t\tinline void map_erase(map_iterator pos)\n\t\t{\n\t\t\tif (m_delete_callback)\n\t\t\t\tm_delete_callback(pos->second.first);\n\t\t\tm_map.erase(pos);\n\t\t}\n\t\t\n\t\tbool trim()\n\t\t{\n\t\t\tif (size() <= m_capacity)\n\t\t\t{\n\t\t\t\treturn false; // No trim necessary\n\t\t\t}\n\n\t\t\t// We need to trim\n\t\t\tdo\n\t\t\t{\n\t\t\t\terase_oldest();\n\t\t\t} while (m_list.size() > m_capacity);\n\n\t\t\treturn true;\n\t\t}\n\n\t\tvoid make_space()\n\t\t{\n\t\t\tif (size() == m_capacity)\n\t\t\t{\n\t\t\t\terase_oldest();\n\t\t\t}\n\t\t}\n\n\tprivate:\n\t\tlist_type\t\t\t\tm_list;\n\t\tmap_type\t\t\t\tm_map;\n\t\tsize_type\t\t\t\tm_capacity;\n\t\tcreate_callback_type\tm_create_callback;\n\t\tdelete_callback_type\tm_delete_callback;\n\t};\n}\n\n\n\n#endif\n"
  },
  {
    "path": "include/EASTL/bonus/overloaded.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_OVERLOADED_H\n#define EASTL_OVERLOADED_H\n\n#include <EASTL/internal/move_help.h>\n#include <EASTL/type_traits.h>\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed\n\t\t\t // improvements in apps as a result.\n#endif\n\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4512 4626);\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////\n\t/// overloaded\n\t/// \n\t/// A helper class that permits you to combine multiple function objects into one.\n\t/// Typically, this helper is really handy when visiting an eastl::variant with multiple lambdas.\n\t/// Example:\n\t///\n\t/// eastl::variant<int, string> v{42};\n\t/// \n\t/// eastl::visit(\n\t///\t eastl::overloaded{\n\t///\t\t  [](const int& x) { std::cout << \"Visited an integer: \" << x  << \"\\n\"; }, // Will reach that lambda with x == 42.\n\t///\t\t  [](const string& s) { std::cout << \"Visited an string: \" << s  << \"\\n\"; }\n\t///\t },\n\t///\t v\n\t/// );\n\t///////////////////////////////////////////////////////////////////////////\n\ttemplate <class... T>\n\tstruct overloaded;\n\n\ttemplate <class T>\n\tstruct overloaded<T> : T\n\t{\n\t\ttemplate <class U>\n\t\tEA_CPP14_CONSTEXPR overloaded(U&& u) : T(eastl::forward<U>(u))\n\t\t{\n\t\t}\n\n\t\tusing T::operator();\n\t};\n\n\ttemplate <class T, class... R>\n\tstruct overloaded<T, R...> : T, overloaded<R...>\n\t{\n\t\ttemplate <class U, class... V>\n\t\tEA_CPP14_CONSTEXPR overloaded(U&& u, V&&... v) : T(eastl::forward<U>(u)), overloaded<R...>(eastl::forward<V>(v)...)\n\t\t{\n\t\t}\n\n\t\tusing T::operator();\n\t\tusing overloaded<R...>::operator();\n\t};\n\n\t#ifdef __cpp_deduction_guides\n\ttemplate <class... T>\n\toverloaded(T...) -> overloaded<T...>;\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////////\n\t/// make_overloaded\n\t///\n\t/// Helper function to create an overloaded instance when lacking deduction guides.\n\t/// make_overloaded(f1, f2, f3) == overloaded{f1, f2, f3}\n\t///////////////////////////////////////////////////////////////////////////\n\ttemplate <class... T>\n\tEA_CPP14_CONSTEXPR overloaded<typename eastl::remove_cvref<T>::type...> make_overloaded(T&&... t)\n\t{\n\t\treturn overloaded<typename eastl::remove_cvref<T>::type...>{eastl::forward<T>(t)...};\n\t}\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING();\n\n#endif // EASTL_OVERLOADED_H\n"
  },
  {
    "path": "include/EASTL/bonus/ring_buffer.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// A ring buffer is a FIFO (first-in, first-out) container which acts\n// much like a queue. The difference is that a ring buffer is implemented\n// via chasing pointers around a given container instead of like queue\n// adds to the writes to the end of the container are reads from the begin.\n// The benefit of a ring buffer is that memory allocations don't occur\n// and new elements are neither added nor removed from the container.\n// Elements in the container are simply assigned values in circles around\n// the container.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_RING_BUFFER_H\n#define EASTL_RING_BUFFER_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <EASTL/vector.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// EASTL_RING_BUFFER_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_RING_BUFFER_DEFAULT_NAME\n\t\t#define EASTL_RING_BUFFER_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" ring_buffer\" // Unless the user overrides something, this is \"EASTL ring_buffer\".\n\t#endif\n\n\t/// EASTL_RING_BUFFER_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_RING_BUFFER_DEFAULT_ALLOCATOR\n\t\t#define EASTL_RING_BUFFER_DEFAULT_ALLOCATOR allocator_type(EASTL_RING_BUFFER_DEFAULT_NAME)\n\t#endif\n\n\n\t/// ring_buffer_iterator\n\t///\n\t/// We force this iterator to act like a random access iterator even if \n\t/// the underlying container doesn't support random access iteration.\n\t/// Any BidirectionalIterator can be a RandomAccessIterator; it just\n\t/// might be inefficient in some cases.\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tstruct ring_buffer_iterator\n\t{\n\tpublic:\n\t\ttypedef ring_buffer_iterator<T, Pointer, Reference, Container>   this_type;\n\t\ttypedef T                                                        value_type;\n\t\ttypedef Pointer                                                  pointer;\n\t\ttypedef Reference                                                reference;\n\t\ttypedef typename Container::size_type                            size_type;\n\t\ttypedef typename Container::difference_type                      difference_type;\n\t\ttypedef typename Container::iterator                             container_iterator;\n\t\ttypedef typename Container::const_iterator                       container_const_iterator;\n\t\ttypedef ring_buffer_iterator<T, T*, T&, Container>               iterator;\n\t\ttypedef ring_buffer_iterator<T, const T*, const T&, Container>   const_iterator;\n\t\ttypedef eastl::random_access_iterator_tag                 iterator_category;\n\n\tpublic:\n\t\tContainer*         mpContainer;\n\t\tcontainer_iterator mContainerIterator;\n\n\tpublic:\n\t\tring_buffer_iterator();\n\t\tring_buffer_iterator(Container* pContainer, const container_iterator& containerIterator);\n\t\tring_buffer_iterator(const iterator& x);\n\n\t\tring_buffer_iterator& operator=(const iterator& x);\n\n\t\treference operator*() const;\n\t\tpointer   operator->() const;\n\n\t\tthis_type& operator++();\n\t\tthis_type  operator++(int);\n\n\t\tthis_type& operator--();\n\t\tthis_type  operator--(int);\n\n\t\tthis_type& operator+=(difference_type n);\n\t\tthis_type& operator-=(difference_type n);\n\n\t\tthis_type operator+(difference_type n) const;\n\t\tthis_type operator-(difference_type n) const;\n\n\tprotected:\n\t\tvoid increment(difference_type n, eastl::input_iterator_tag);\n\t\tvoid increment(difference_type n, eastl::random_access_iterator_tag);\n\n\t}; // struct ring_buffer_iterator\n\n\n\n\t/// ring_buffer\n\t///\n\t/// Implements a ring buffer via a given container type, which would \n\t/// typically be a vector or array, though any container which supports \n\t/// bidirectional iteration would work.\n\t///\n\t/// A ring buffer is a FIFO (first-in, first-out) container which acts\n\t/// much like a queue. The difference is that a ring buffer is implemented\n\t/// via chasing pointers around a container and moving the read and write\n\t/// positions forward (and possibly wrapping around) as the container is \n\t/// read and written via pop_front and push_back.\n\t///\n\t/// The benefit of a ring buffer is that memory allocations don't occur\n\t/// and new elements are neither added nor removed from the container.\n\t/// Elements in the container are simply assigned values in circles around\n\t/// the container.\n\t/// \n\t/// ring_buffer is different from other containers -- including adapter\n\t/// containers -- in how iteration is done. Iteration of a ring buffer\n\t/// starts at the current begin position, proceeds to the end of the underlying\n\t/// container, and continues at the begin of the underlying container until\n\t/// the ring buffer's current end position. Thus a ring_buffer does \n\t/// indeed have a begin and an end, though the values of begin and end \n\t/// chase each other around the container. An empty ring_buffer is one \n\t/// in which end == begin, and a full ring_buffer is one in which \n\t/// end + 1 == begin. \n\t///\n\t/// Example of a ring buffer layout, where + indicates queued items:\n\t///    ++++++++++--------------------------------+++++++++\n\t///              ^                               ^\n\t///              end                             begin\n\t///\n\t/// Empty ring buffer:\n\t///    ---------------------------------------------------\n\t///                              ^\n\t///                          begin / end\n\t///\n\t/// Full ring buffer. Note that one item is necessarily unused; it is \n\t/// analagous to a '\\0' at the end of a C string:\n\t///    +++++++++++++++++++++++++++++++++++++++++-+++++++++\n\t///                                             ^^\n\t///                                           end begin\n\t///\n\t/// A push_back operation on a ring buffer assigns the new value to end.  \n\t/// If there is no more space in the buffer, this will result in begin\n\t/// being overwritten and the begin position being moved foward one position.\n\t/// The user can use the full() function to detect this condition.\n\t/// Note that elements in a ring buffer are not created or destroyed as \n\t/// their are added and removed; they are merely assigned. Only on \n\t/// container construction and destruction are any elements created and \n\t/// destroyed.\n\t///\n\t/// The ring buffer can be used in either direction. By this we mean that \n\t/// you can use push_back to add items and pop_front to remove them; or you can\n\t/// use push_front to add items and pop_back to remove them. You aren't \n\t/// limited to these operations; you can push or pop from either side\n\t/// arbitrarily and you can insert or erase anywhere in the container.\n\t///\n\t/// The ring buffer requires the user to specify a Container type, which \n\t/// by default is vector. However, any container with bidirectional iterators\n\t/// will work, such as list, deque, string or any of the fixed_* versions\n\t/// of these containers, such as fixed_string. Since ring buffer works via copying\n\t/// elements instead of allocating and freeing nodes, inserting in the middle\n\t/// of a ring buffer based on list (instead of vector) is no more efficient.\n\t///\n\t/// To use the ring buffer, its container must be resized to the desired\n\t/// ring buffer size. Changing the size of a ring buffer may cause ring\n\t/// buffer iterators to invalidate.\n\t///\n\t/// An alternative to using a ring buffer is to use a list with a user-created \n\t/// node pool and custom allocator. There are various tradeoffs that result from this.\n\t///\n\t/// Example usage:\n\t///     ring_buffer< int, list<int> > rb(100);\n\t///     rb.push_back(1);\n\t/// \n\t/// Example usage:\n\t///     // Example of creating an on-screen debug log that shows 16 \n\t///     // strings at a time and scrolls older strings away.\n\t///\n\t///     // Create ring buffer of 16 strings.\n\t///     ring_buffer< string, vector<string> > debugLogText(16);\n\t///     \n\t///     // Reserve 128 chars for each line. This can make it so that no \n\t///     // runtime memory allocations occur.\n\t///     for(vector<string>::iterator it = debugLogText.get_container().begin(),\n\t///         itEnd = debugLogText.get_container().end(); it != itEnd; ++it)\n\t///     {\n\t///         (*it).reserve(128);\n\t///     }\n\t///     \n\t///     // Add a new string, using push_front() and front() instead of \n\t///     // push_front(str) in order to avoid creating a temporary str.\n\t///     debugLogText.push_front();\n\t///     debugLogText.front() = \"Player fired weapon\";\n\t///\n\ttemplate <typename T, typename Container = eastl::vector<T>, typename Allocator = typename Container::allocator_type>\n\tclass ring_buffer\n\t{\n\tpublic:\n\t\ttypedef ring_buffer<T, Container, Allocator>                   this_type;\n\t\ttypedef Container                                              container_type;\n\t\ttypedef Allocator                                              allocator_type;\n\n\t\ttypedef typename Container::value_type                         value_type;\n\t\ttypedef typename Container::reference                          reference;\n\t\ttypedef typename Container::const_reference                    const_reference;\n\t\ttypedef typename Container::size_type                          size_type;\n\t\ttypedef typename Container::difference_type                    difference_type;\n\t\ttypedef typename Container::iterator                           container_iterator;\n\t\ttypedef typename Container::const_iterator                     container_const_iterator;\n\t\ttypedef ring_buffer_iterator<T, T*, T&, Container>             iterator;\n\t\ttypedef ring_buffer_iterator<T, const T*, const T&, Container> const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>                      reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>                const_reverse_iterator;    \n\n\tpublic:                             // We declare public so that global comparison operators can be implemented without adding an inline level and without tripping up GCC 2.x friend declaration failures. GCC (through at least v4.0) is poor at inlining and performance wins over correctness.\n\t\tContainer          c;           // We follow the naming convention established for stack, queue, priority_queue and name this 'c'. This variable must always have a size of at least 1, as even an empty ring_buffer has an unused terminating element.\n\n\tprotected:\n\t\tcontainer_iterator mBegin;      // We keep track of where our begin and end are by using Container iterators. \n\t\tcontainer_iterator mEnd;\n\t\tsize_type          mSize;\n\n\tpublic:\n\t\t// There currently isn't a ring_buffer constructor that specifies an initial size, unlike other containers.\n\t\texplicit ring_buffer(size_type cap = 0);                                // Construct with an initial capacity (but size of 0).\n\t\texplicit ring_buffer(size_type cap, const allocator_type& allocator); \n\t\texplicit ring_buffer(const Container& x);\n\t\texplicit ring_buffer(const allocator_type& allocator);\n\t\tring_buffer(const this_type& x);\n\t\tring_buffer(this_type&& x);\n\t\tring_buffer(this_type&& x, const allocator_type& allocator);\n\t\tring_buffer(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_RING_BUFFER_DEFAULT_ALLOCATOR); // This function sets the capacity to be equal to the size of the initializer list.\n\n\t\t// No destructor necessary. Default will do.\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid assign(InputIterator first, InputIterator last);\n\n\t\tvoid swap(this_type& x);\n\n\t\titerator               begin()          EA_NOEXCEPT;\n\t\tconst_iterator         begin()    const EA_NOEXCEPT;\n\t\tconst_iterator         cbegin()   const EA_NOEXCEPT;\n\n\t\titerator               end()            EA_NOEXCEPT;\n\t\tconst_iterator         end()      const EA_NOEXCEPT;\n\t\tconst_iterator         cend()     const EA_NOEXCEPT;\n\n\t\treverse_iterator       rbegin()         EA_NOEXCEPT;\n\t\tconst_reverse_iterator rbegin()   const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crbegin()  const EA_NOEXCEPT;\n\n\t\treverse_iterator       rend()           EA_NOEXCEPT;\n\t\tconst_reverse_iterator rend()     const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crend()    const EA_NOEXCEPT;\n\n\t\tbool                   empty()    const EA_NOEXCEPT;\n\t\tbool                   full()     const EA_NOEXCEPT;\n\t\tsize_type              size()     const EA_NOEXCEPT;\n\t\tsize_type              capacity() const EA_NOEXCEPT;\n\n\t\tvoid                   resize(size_type n);\n\t\tvoid                   set_capacity(size_type n); // Sets the capacity to the given value, including values less than the current capacity. Adjusts the size downward if n < size, by throwing out the oldest elements in the buffer.\n\t\tvoid                   reserve(size_type n);      // Reserve a given capacity. Doesn't decrease the capacity; it only increases it (for compatibility with other containers' behavior).\n\n\t\treference       front();\n\t\tconst_reference front() const;\n\n\t\treference       back();              \n\t\tconst_reference back() const;\n\n\t\tvoid            push_back(const value_type& value);\n\t\treference       push_back();\n\n\t\tvoid            push_front(const value_type& value);\n\t\treference       push_front();\n\n\t\tvoid            pop_back();\n\t\tvoid            pop_front();\n\n\t\treference       operator[](size_type n);\n\t\tconst_reference operator[](size_type n) const;\n\n\t\t// To consider:\n\t\t// size_type read(value_type* pDestination, size_type nCount);\n\t\t// size_type read(iterator** pPosition1, iterator** pPosition2, size_type& nCount1, size_type& nCount2);\n\n\t\t/* To do:\n\t\t\ttemplate <class... Args>\n\t\t\treference emplace_front(Args&&... args);\n\n\t\t\ttemplate <class... Args>\n\t\t\treference emplace_back(Args&&... args);\n\n\t\t\ttemplate <class... Args>\n\t\t\titerator emplace(const_iterator position, Args&&... args);\n\t\t*/\n\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\tvoid     insert(const_iterator position, size_type n, const value_type& value);\n\t\tvoid     insert(const_iterator position, std::initializer_list<value_type> ilist);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(const_iterator position, InputIterator first, InputIterator last);\n\n\t\titerator         erase(const_iterator position);\n\t\titerator         erase(const_iterator first, const_iterator last);\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\tvoid clear();\n\n\t\tcontainer_type&       get_container();\n\t\tconst container_type& get_container() const;\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\tprotected:\n\t\t//size_type DoGetSize(eastl::input_iterator_tag) const;\n\t\t//size_type DoGetSize(eastl::random_access_iterator_tag) const;\n\n\t}; // class ring_buffer\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// ring_buffer_iterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tring_buffer_iterator<T, Pointer, Reference, Container>::ring_buffer_iterator()\n\t\t: mpContainer(NULL), mContainerIterator()\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tring_buffer_iterator<T, Pointer, Reference, Container>::ring_buffer_iterator(Container* pContainer, const container_iterator& containerIterator)\n\t\t: mpContainer(pContainer), mContainerIterator(containerIterator)\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tring_buffer_iterator<T, Pointer, Reference, Container>::ring_buffer_iterator(const iterator& x)\n\t\t: mpContainer(x.mpContainer), mContainerIterator(x.mContainerIterator)\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tring_buffer_iterator<T, Pointer, Reference, Container>& \n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator=(const iterator& x)\n\t{\n\t\tmpContainer        = x.mpContainer;\n\t\tmContainerIterator = x.mContainerIterator;\n\t\treturn *this;\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::reference\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator*() const\n\t{\n\t\treturn *mContainerIterator;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::pointer\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator->() const\n\t{\n\t\treturn &*mContainerIterator;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type&\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator++()\n\t{\n\t\tif(EASTL_UNLIKELY(++mContainerIterator == mpContainer->end()))\n\t\t\tmContainerIterator = mpContainer->begin();\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator++(int)\n\t{\n\t\tconst this_type temp(*this);\n\t\tif(EASTL_UNLIKELY(++mContainerIterator == mpContainer->end()))\n\t\t\tmContainerIterator = mpContainer->begin();\n\t\treturn temp;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type&\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator--()\n\t{\n\t\tif(EASTL_UNLIKELY(mContainerIterator == mpContainer->begin()))\n\t\t\tmContainerIterator = mpContainer->end();\n\t\t--mContainerIterator;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator--(int)\n\t{\n\t\tconst this_type temp(*this);\n\t\tif(EASTL_UNLIKELY(mContainerIterator == mpContainer->begin()))\n\t\t\tmContainerIterator = mpContainer->end();\n\t\t--mContainerIterator;\n\t\treturn temp;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type&\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator+=(difference_type n)\n\t{\n\t\ttypedef typename eastl::iterator_traits<container_iterator>::iterator_category IC;\n\t\tincrement(n, IC());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type&\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator-=(difference_type n)\n\t{\n\t\ttypedef typename eastl::iterator_traits<container_iterator>::iterator_category IC;\n\t\tincrement(-n, IC());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator+(difference_type n) const\n\t{\n\t\treturn this_type(*this).operator+=(n);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\ttypename ring_buffer_iterator<T, Pointer, Reference, Container>::this_type\n\tring_buffer_iterator<T, Pointer, Reference, Container>::operator-(difference_type n) const\n\t{\n\t\treturn this_type(*this).operator+=(-n);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tvoid ring_buffer_iterator<T, Pointer, Reference, Container>::increment(difference_type n, eastl::input_iterator_tag)\n\t{\n\t\t// n cannot be negative, as input iterators don't support reverse iteration.\n\t\twhile(n-- > 0)\n\t\t\toperator++();\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tvoid ring_buffer_iterator<T, Pointer, Reference, Container>::increment(difference_type n, eastl::random_access_iterator_tag)\n\t{\n\t\t// We make the assumption here that the user is incrementing from a valid\n\t\t// starting position to a valid ending position. Thus *this + n yields a \n\t\t// valid iterator, including if n happens to be a negative value.\n\n\t\tif(n >= 0)\n\t\t{\n\t\t\tconst difference_type d = mpContainer->end() - mContainerIterator;\n\n\t\t\tif(n < d)\n\t\t\t\tmContainerIterator += n;\n\t\t\telse\n\t\t\t\tmContainerIterator = mpContainer->begin() + (n - d);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Recall that n and d here will be negative and so the logic here works as intended.\n\t\t\tconst difference_type d = mpContainer->begin() - mContainerIterator;\n\n\t\t\tif(n >= d)\n\t\t\t\tmContainerIterator += n;\n\t\t\telse\n\t\t\t\tmContainerIterator = mpContainer->end() + (n - d);\n\t\t}\n\t}\n\n\n\t// Random access iterators must support operator + and operator -.\n\t// You can only add an integer to an iterator, and you cannot add two iterators.\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tinline ring_buffer_iterator<T, Pointer, Reference, Container>\n\toperator+(ptrdiff_t n, const ring_buffer_iterator<T, Pointer, Reference, Container>& x)\n\t{\n\t\treturn x + n; // Implement (n + x) in terms of (x + n).\n\t}\n\n\n\t// You can only add an integer to an iterator, but you can subtract two iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, typename Container>\n\tinline typename ring_buffer_iterator<T, PointerA, ReferenceA, Container>::difference_type\n\toperator-(const ring_buffer_iterator<T, PointerA, ReferenceA, Container>& a,\n\t\t\t  const ring_buffer_iterator<T, PointerB, ReferenceB, Container>& b)\n\t{\n\t\ttypedef typename ring_buffer_iterator<T, PointerA, ReferenceA, Container>::difference_type difference_type;\n\n\t\t// To do: If container_iterator is a random access iterator, then do a simple calculation.\n\t\t// Otherwise, we have little choice but to iterate from a to b and count as we go.\n\t\t// See the ring_buffer::size function for an implementation of this.\n\n\t\t// Iteration implementation:\n\t\tdifference_type d = 0;\n\n\t\tfor(ring_buffer_iterator<T, PointerA, ReferenceA, Container> temp(b); temp != a; ++temp)\n\t\t\t++d;\n\n\t\treturn d;\n\t}\n\n\n\t// The C++ defect report #179 requires that we support comparisons between const and non-const iterators.\n\t// Thus we provide additional template paremeters here to support this. The defect report does not\n\t// require us to support comparisons between reverse_iterators and const_reverse_iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename ContainerA,\n\t\t\t\t\t\t  typename PointerB, typename ReferenceB, typename ContainerB>\n\tinline bool operator==(const ring_buffer_iterator<T, PointerA, ReferenceA, ContainerA>& a, \n\t\t\t\t\t\t   const ring_buffer_iterator<T, PointerB, ReferenceB, ContainerB>& b)\n\t{\n\t\t// Perhaps we should compare the container pointer as well.\n\t\t// However, for valid iterators this shouldn't be necessary.\n\t\treturn a.mContainerIterator == b.mContainerIterator;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename ContainerA,\n\t\t\t\t\t\t  typename PointerB, typename ReferenceB, typename ContainerB>\n\tinline bool operator!=(const ring_buffer_iterator<T, PointerA, ReferenceA, ContainerA>& a, \n\t\t\t\t\t\t   const ring_buffer_iterator<T, PointerB, ReferenceB, ContainerB>& b)\n\t{\n\t\t// Perhaps we should compare the container pointer as well.\n\t\t// However, for valid iterators this shouldn't be necessary.\n\t\treturn !(a.mContainerIterator == b.mContainerIterator);\n\t}\n\n\n\t// We provide a version of operator!= for the case where the iterators are of the \n\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\ttemplate <typename T, typename Pointer, typename Reference, typename Container>\n\tinline bool operator!=(const ring_buffer_iterator<T, Pointer, Reference, Container>& a, \n\t\t\t\t\t\t   const ring_buffer_iterator<T, Pointer, Reference, Container>& b)\n\t{\n\t\treturn !(a.mContainerIterator == b.mContainerIterator);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// ring_buffer\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(size_type cap)\n\t\t: c() // Default construction with default allocator for the container.\n\t{\n\t\t// To do: This code needs to be amended to deal with possible exceptions \n\t\t// that could occur during the resize call below.\n\n\t\t// We add one because the element at mEnd is necessarily unused.\n\t\tc.resize(cap + 1); // Possibly we could construct 'c' with size, but c may not have such a ctor, though we rely on it having a resize function. \n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = 0;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(size_type cap, const allocator_type& allocator)\n\t\t: c(allocator)\n\t{\n\t\t// To do: This code needs to be amended to deal with possible exceptions \n\t\t// that could occur during the resize call below.\n\n\t\t// We add one because the element at mEnd is necessarily unused.\n\t\tc.resize(cap + 1); // Possibly we could construct 'c' with size, but c may not have such a ctor, though we rely on it having a resize function. \n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = 0;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(const Container& x)\n\t\t: c(x) // This copies elements from x, but unless the user is doing some tricks, the only thing that matters is that c.size() == x.size().\n\t{\n\t\t// To do: This code needs to be amended to deal with possible exceptions \n\t\t// that could occur during the resize call below.\n\t\tif(c.empty())\n\t\t\tc.resize(1);\n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = 0;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(const allocator_type& allocator)\n\t\t: c(allocator)\n\t{\n\t\t// To do: This code needs to be amended to deal with possible exceptions \n\t\t// that could occur during the resize call below.\n\n\t\t// We add one because the element at mEnd is necessarily unused.\n\t\tc.resize(1); // Possibly we could construct 'c' with size, but c may not have such a ctor, though we rely on it having a resize function.\n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = 0;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(const this_type& x)\n\t\t: c(x.c)\n\t{\n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = x.mSize;\n\n\t\teastl::advance(mBegin, eastl::distance(const_cast<this_type&>(x).c.begin(), x.mBegin)); // We can do a simple distance algorithm here, as there will be no wraparound.\n\t\teastl::advance(mEnd,   eastl::distance(const_cast<this_type&>(x).c.begin(), x.mEnd));\n\t}\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(this_type&& x)\n\t: c() // Default construction with default allocator for the container.\n\t{\n\t\tc.resize(1); // Possibly we could construct 'c' with size, but c may not have such a ctor, though we rely on it having a resize function.\n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = 0;\n\n\t\tswap(x); // We are leaving x in an unusual state by swapping default-initialized members with it, as it won't be usable and can be only destructible.\n\t}\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(this_type&& x, const allocator_type& allocator)\n\t\t: c(allocator)\n\t{\n\t\tc.resize(1); // Possibly we could construct 'c' with size, but c may not have such a ctor, though we rely on it having a resize function.\n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = 0;\n\n\t\tif(c.get_allocator() == x.c.get_allocator())\n\t\t\tswap(x); // We are leaving x in an unusual state by swapping default-initialized members with it, as it won't be usable and can be only destructible.\n\t\telse\n\t\t\toperator=(x);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tring_buffer<T, Container, Allocator>::ring_buffer(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: c(allocator)\n\t{\n\t\tc.resize((eastl_size_t)ilist.size() + 1);\n\t\tmBegin = c.begin();\n\t\tmEnd   = mBegin;\n\t\tmSize  = 0;\n\n\t\tassign(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::this_type&\n\tring_buffer<T, Container, Allocator>::operator=(const this_type& x)\n\t{\n\t\tif(&x != this)\n\t\t{\n\t\t\tc = x.c;\n\n\t\t\tmBegin = c.begin();\n\t\t\tmEnd   = mBegin;\n\t\t\tmSize  = x.mSize;\n\n\t\t\teastl::advance(mBegin, eastl::distance(const_cast<this_type&>(x).c.begin(), x.mBegin)); // We can do a simple distance algorithm here, as there will be no wraparound.\n\t\t\teastl::advance(mEnd,   eastl::distance(const_cast<this_type&>(x).c.begin(), x.mEnd));\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::this_type&\n\tring_buffer<T, Container, Allocator>::operator=(this_type&& x)\n\t{\n\t\tswap(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::this_type&\n\tring_buffer<T, Container, Allocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tassign(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttemplate <typename InputIterator>\n\tvoid ring_buffer<T, Container, Allocator>::assign(InputIterator first, InputIterator last)\n\t{\n\t\t// To consider: We can make specializations of this for pointer-based \n\t\t// iterators to PODs and turn the action into a memcpy.\n\t\tclear();\n\n\t\tfor(; first != last; ++first)\n\t\t\tpush_back(*first);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::swap(this_type& x)\n\t{\n\t\tif(&x != this)\n\t\t{\n\t\t\tconst difference_type dBegin  = eastl::distance(c.begin(), mBegin); // We can do a simple distance algorithm here, as there will be no wraparound.\n\t\t\tconst difference_type dEnd    = eastl::distance(c.begin(), mEnd);\n\n\t\t\tconst difference_type dxBegin = eastl::distance(x.c.begin(), x.mBegin);\n\t\t\tconst difference_type dxEnd   = eastl::distance(x.c.begin(), x.mEnd);\n\n\t\t\teastl::swap(c, x.c);\n\t\t\teastl::swap(mSize, x.mSize);\n\n\t\t\tmBegin = c.begin();\n\t\t\teastl::advance(mBegin, dxBegin); // We can do a simple advance algorithm here, as there will be no wraparound.\n\n\t\t\tmEnd = c.begin();\n\t\t\teastl::advance(mEnd, dxEnd);\n\n\t\t\tx.mBegin = x.c.begin();\n\t\t\teastl::advance(x.mBegin, dBegin);\n\n\t\t\tx.mEnd = x.c.begin();\n\t\t\teastl::advance(x.mEnd, dEnd);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::iterator\n\tring_buffer<T, Container, Allocator>::begin() EA_NOEXCEPT\n\t{\n\t\treturn iterator(&c, mBegin);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_iterator\n\tring_buffer<T, Container, Allocator>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(const_cast<Container*>(&c), mBegin); // We trust that the const_iterator will respect const-ness.\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_iterator\n\tring_buffer<T, Container, Allocator>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(const_cast<Container*>(&c), mBegin); // We trust that the const_iterator will respect const-ness.\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::iterator\n\tring_buffer<T, Container, Allocator>::end() EA_NOEXCEPT\n\t{\n\t\treturn iterator(&c, mEnd);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_iterator\n\tring_buffer<T, Container, Allocator>::end() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(const_cast<Container*>(&c), mEnd); // We trust that the const_iterator will respect const-ness.\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_iterator\n\tring_buffer<T, Container, Allocator>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(const_cast<Container*>(&c), mEnd); // We trust that the const_iterator will respect const-ness.\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reverse_iterator \n\tring_buffer<T, Container, Allocator>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(iterator(&c, mEnd));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_reverse_iterator\n\tring_buffer<T, Container, Allocator>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(const_cast<Container*>(&c), mEnd));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_reverse_iterator\n\tring_buffer<T, Container, Allocator>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(const_cast<Container*>(&c), mEnd));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reverse_iterator\n\tring_buffer<T, Container, Allocator>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(iterator(&c, mBegin));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_reverse_iterator\n\tring_buffer<T, Container, Allocator>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(const_cast<Container*>(&c), mBegin));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_reverse_iterator\n\tring_buffer<T, Container, Allocator>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(const_cast<Container*>(&c), mBegin));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tbool ring_buffer<T, Container, Allocator>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn mBegin == mEnd;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tbool ring_buffer<T, Container, Allocator>::full() const EA_NOEXCEPT\n\t{\n\t\t// Implementation that relies on c.size() being a fast operation:\n\t\t// return mSize == (c.size() - 1); // (c.size() - 1) == capacity(); we are attempting to reduce function calls.\n\n\t\t// Version that has constant speed guarantees, but is still pretty fast.\n\t\tconst_iterator afterEnd(end());\n\t\t++afterEnd;\n\t\treturn afterEnd.mContainerIterator == mBegin;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::size_type\n\tring_buffer<T, Container, Allocator>::size() const EA_NOEXCEPT\n\t{\n\t\treturn mSize;\n\n\t\t// Alternatives:\n\t\t// return eastl::distance(begin(), end());\n\t\t// return end() - begin(); // This is more direct than using distance().\n\t\t//typedef typename eastl::iterator_traits<container_iterator>::iterator_category IC;\n\t\t//return DoGetSize(IC()); // This is more direct than using iterator math.\n\t}\n\n\n\t/*\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::size_type\n\tring_buffer<T, Container, Allocator>::DoGetSize(eastl::input_iterator_tag) const\n\t{\n\t\t// We could alternatively just use eastl::distance() here, but we happen to\n\t\t// know that such code would boil down to what we have here, and we might\n\t\t// as well remove function calls where possible. \n\t\tdifference_type d = 0;\n\n\t\tfor(const_iterator temp(begin()), tempEnd(end()); temp != tempEnd; ++temp)\n\t\t\t++d;\n\n\t\treturn (size_type)d;\n\t}\n\t*/\n\n\t/*\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::size_type\n\tring_buffer<T, Container, Allocator>::DoGetSize(eastl::random_access_iterator_tag) const\n\t{\n\t\t// A simpler but less efficient implementation fo this function would be:\n\t\t//     return eastl::distance(mBegin, mEnd);\n\t\t//\n\t\t// The calculation of distance here takes advantage of the fact that random\n\t\t// access iterators' distances can be calculated by simple pointer calculation.\n\t\t// Thus the code below boils down to a few subtractions when using a vector,\n\t\t// string, or array as the Container type. \n\t\t//\n\t\tconst difference_type dBegin = eastl::distance(const_cast<Container&>(c).begin(), mBegin); // const_cast here solves a little compiler \n\t\tconst difference_type dEnd   = eastl::distance(const_cast<Container&>(c).begin(), mEnd);   // argument matching problem.\n\n\t\tif(dEnd >= dBegin)\n\t\t\treturn dEnd - dBegin;\n\n\t\treturn c.size() - (dBegin - dEnd);\n\t}\n\t*/\n\n\n\tnamespace Internal \n\t{\n\t\t///////////////////////////////////////////////////////////////\n\t\t// has_overflow_allocator\n\t\t//\n\t\t// returns true_type when the specified container type is an \n\t\t// eastl::fixed_*  container and therefore has an overflow \n\t\t// allocator type.\n\t\t//\n\t\ttemplate <typename T, typename = void>\n\t\tstruct has_overflow_allocator : false_type {};\n\n\t\ttemplate <typename T>\n\t\tstruct has_overflow_allocator<T, void_t<decltype(declval<T>().get_overflow_allocator())>> : true_type {};\n\n\n\t\t///////////////////////////////////////////////////////////////\n\t\t// GetFixedContainerCtorAllocator\n\t\t//\n\t\t// eastl::fixed_* containers are only constructible via their \n\t\t// overflow allocator type. This helper select the appropriate \n\t\t// allocator from the specified container.\n\t\t//\n\t\ttemplate <typename Container, bool UseOverflowAllocator = has_overflow_allocator<Container>()()>\n\t\tstruct GetFixedContainerCtorAllocator\n\t\t{\n\t\t\tauto& operator()(Container& c) { return c.get_overflow_allocator(); }\n\t\t};\n\n\t\ttemplate <typename Container>\n\t\tstruct GetFixedContainerCtorAllocator<Container, false>\n\t\t{\n\t\t\tauto& operator()(Container& c) { return c.get_allocator(); }\n\t\t};\n\t} // namespace Internal\n\n\n\t///////////////////////////////////////////////////////////////\n\t// ContainerTemporary\n\t// \n\t// Helper type which prevents utilizing excessive stack space \n\t// when creating temporaries when swapping/copying the underlying \n\t// ring_buffer container type. \n\t//\n\ttemplate <typename Container, bool UseHeapTemporary = (sizeof(Container) >= EASTL_MAX_STACK_USAGE)>\n\tstruct ContainerTemporary\n\t{\n\t\tContainer mContainer;\n\n\t\tContainerTemporary(Container& parentContainer)\n\t\t    : mContainer(Internal::GetFixedContainerCtorAllocator<Container>{}(parentContainer))\n\t\t{\n\t\t}\n\n\t\tContainer& get() { return mContainer; }\n\t};\n\n\ttemplate <typename Container>\n\tstruct ContainerTemporary<Container, true>\n\t{\n\t\ttypename Container::allocator_type* mAllocator;\n\t\tContainer* mContainer;\n\n\t\tContainerTemporary(Container& parentContainer)\n\t\t    : mAllocator(&parentContainer.get_allocator())\n\t\t    , mContainer(new (mAllocator->allocate(sizeof(Container))) Container)\n\t\t{\n\t\t}\n\n\t\t~ContainerTemporary()\n\t\t{\n\t\t\tmContainer->~Container();\n\t\t\tmAllocator->deallocate(mContainer, sizeof(Container));\n\t\t}\n\n\t\tContainer& get() { return *mContainer; }\n\t};\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::resize(size_type n)\n\t{\n\t\t// Note that if n > size(), we just move the end position out to\n\t\t// the begin + n, with the data being the old end and the new end\n\t\t// being stale values from the past. This is by design, as the concept\n\t\t// of arbitrarily resizing a ring buffer like this is currently deemed\n\t\t// to be vague in what it intends to do. We can only assume that the\n\t\t// user knows what he is doing and will deal with the stale values.\n\t\tEASTL_ASSERT(c.size() >= 1);\n\t\tconst size_type cap = (c.size() - 1);\n\n\t\tmSize = n;\n\n\t\tif(n > cap) // If we need to grow in capacity...\n\t\t{\n\t\t\t// Given that a growing operation will always result in memory allocation, \n\t\t\t// we currently implement this function via the usage of a temp container.\n\t\t\t// This makes for a simple implementation, but in some cases it is less\n\t\t\t// efficient. In particular, if the container is a node-based container like\n\t\t\t// a (linked) list, this function would be faster if we simply added nodes\n\t\t\t// to ourself. We would do this by inserting the nodes to be after end()\n\t\t\t// and adjusting the begin() position if it was after end().\n\n\t\t\t// To do: This code needs to be amended to deal with possible exceptions \n\t\t\t// that could occur during the resize call below.\n\n\t\t\tContainerTemporary<Container> cTemp(c);\n\t\t\tcTemp.get().resize(n + 1);\n\t\t\teastl::copy(begin(), end(), cTemp.get().begin());\n\t\t\teastl::swap(c, cTemp.get());\n\n\t\t\tmBegin = c.begin();\n\t\t\tmEnd   = mBegin;\n\t\t\teastl::advance(mEnd, n); // We can do a simple advance algorithm on this because we know that mEnd will not wrap around.\n\t\t}\n\t\telse // We could do a check here for n != size(), but that would be costly and people don't usually resize things to their same size.\n\t\t{\n\t\t\tmEnd = mBegin;\n\n\t\t\t// eastl::advance(mEnd, n); // We *cannot* use this because there may be wraparound involved.\n\n\t\t\t// To consider: Possibly we should implement some more detailed logic to optimize the code here.\n\t\t\t// We'd need to do different behaviour dending on whether the container iterator type is a \n\t\t\t// random access iterator or otherwise.\n\n\t\t\twhile(n--)\n\t\t\t{\n\t\t\t\tif(EASTL_UNLIKELY(++mEnd == c.end()))\n\t\t\t\t\tmEnd = c.begin();\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::size_type\n\tring_buffer<T, Container, Allocator>::capacity() const EA_NOEXCEPT\n\t{\n\t\tEASTL_ASSERT(c.size() >= 1); // This is required because even an empty ring_buffer has one unused termination element, somewhat like a \\0 at the end of a C string.\n\n\t\treturn (c.size() - 1); // Need to subtract one because the position at mEnd is unused.\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::set_capacity(size_type n)\n\t{\n\t\tconst size_type capacity = (c.size() - 1);\n\n\t\tif(n != capacity)    // If we need to change capacity...\n\t\t{\n\t\t\tContainerTemporary<Container> cTemp(c);\n\t\t\tcTemp.get().resize(n + 1);\n\n\t\t\titerator itCopyBegin = begin();\n\n\t\t\tif(n < mSize) // If we are shrinking the capacity, to less than our size...\n\t\t\t{\n\t\t\t\teastl::advance(itCopyBegin, mSize - n);\n\t\t\t\tmSize = n;\n\t\t\t}\n\n\t\t\teastl::copy(itCopyBegin, end(), cTemp.get().begin());  // The begin-end range may in fact be larger than n, in which case values will be overwritten.\n\t\t\teastl::swap(c, cTemp.get());\n\n\t\t\tmBegin = c.begin();\n\t\t\tmEnd   = mBegin;\n\t\t\teastl::advance(mEnd, mSize); // We can do a simple advance algorithm on this because we know that mEnd will not wrap around.\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::reserve(size_type n)\n\t{\n\t\t// We follow the pattern of vector and only do something if n > capacity.\n\t\tEASTL_ASSERT(c.size() >= 1);\n\n\t\tif(n > (c.size() - 1))    // If we need to grow in capacity... // (c.size() - 1) == capacity(); we are attempting to reduce function calls.\n\t\t{\n\t\t\tContainerTemporary<Container> cTemp(c);\n\t\t\tcTemp.get().resize(n + 1);\n\t\t\teastl::copy(begin(), end(), cTemp.get().begin());\n\t\t\teastl::swap(c, cTemp.get());\n\n\t\t\tmBegin = c.begin();\n\t\t\tmEnd   = mBegin;\n\t\t\teastl::advance(mEnd, mSize); // We can do a simple advance algorithm on this because we know that mEnd will not wrap around.\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reference\n\tring_buffer<T, Container, Allocator>::front()\n\t{\n\t\treturn *mBegin;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_reference\n\tring_buffer<T, Container, Allocator>::front() const\n\t{\n\t\treturn *mBegin;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reference\n\tring_buffer<T, Container, Allocator>::back()\n\t{\n\t\t// return *(end() - 1); // Can't use this because not all iterators support operator-.\n\n\t\titerator temp(end());   // To do: Find a way to construct this temporary in the return statement.\n\t\treturn *(--temp);       // We can do it by making all our containers' iterators support operator-.\n\t}\n\n\t\t\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_reference\n\tring_buffer<T, Container, Allocator>::back() const\n\t{\n\t\t// return *(end() - 1); // Can't use this because not all iterators support operator-.\n\n\t\tconst_iterator temp(end()); // To do: Find a way to construct this temporary in the return statement.\n\t\treturn *(--temp);           // We can do it by making all our containers' iterators support operator-.\n\t}\n\n\n\t/// A push_back operation on a ring buffer assigns the new value to end.  \n\t/// If there is no more space in the buffer, this will result in begin\n\t/// being overwritten and the begin position being moved foward one position.\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::push_back(const value_type& value)\n\t{\n\t\t*mEnd = value;\n\n\t\tif(++mEnd == c.end())\n\t\t\tmEnd = c.begin();\n\n\t\tif(mEnd == mBegin)\n\t\t{\n\t\t\tif(++mBegin == c.end())\n\t\t\t\tmBegin = c.begin();\n\t\t}\n\t\telse\n\t\t\t++mSize;\n\t}\n\n\n\t/// A push_back operation on a ring buffer assigns the new value to end.  \n\t/// If there is no more space in the buffer, this will result in begin\n\t/// being overwritten and the begin position being moved foward one position.\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reference\n\tring_buffer<T, Container, Allocator>::push_back()\n\t{\n\t\t// We don't do the following assignment, as the value at mEnd is already constructed;\n\t\t// it is merely possibly not default-constructed. However, the spirit of push_back\n\t\t// is that the user intends to do an assignment or data modification after the \n\t\t// push_back call. The user can always execute *back() = value_type() if he wants.\n\t\t//*mEnd = value_type();\n\n\t\tif(++mEnd == c.end())\n\t\t\tmEnd = c.begin();\n\n\t\tif(mEnd == mBegin)\n\t\t{\n\t\t\tif(++mBegin == c.end())\n\t\t\t\tmBegin = c.begin();\n\t\t}\n\t\telse\n\t\t\t++mSize;\n\n\t\treturn back();\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::pop_back()\n\t{\n\t\tEASTL_ASSERT(mEnd != mBegin); // We assume that size() > 0 and thus that there is something to pop.\n\n\t\tif(EASTL_UNLIKELY(mEnd == c.begin()))\n\t\t\tmEnd = c.end();\n\t\t--mEnd;\n\t\t--mSize;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::push_front(const value_type& value)\n\t{\n\t\tif(EASTL_UNLIKELY(mBegin == c.begin()))\n\t\t\tmBegin = c.end();\n\n\t\tif(--mBegin == mEnd)\n\t\t{\n\t\t\tif(EASTL_UNLIKELY(mEnd == c.begin()))\n\t\t\t\tmEnd = c.end();\n\t\t\t--mEnd;\n\t\t}\n\t\telse\n\t\t\t++mSize;\n\n\t\t*mBegin = value;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reference\n\tring_buffer<T, Container, Allocator>::push_front()\n\t{\n\t\tif(EASTL_UNLIKELY(mBegin == c.begin()))\n\t\t\tmBegin = c.end();\n\n\t\tif(--mBegin == mEnd)\n\t\t{\n\t\t\tif(EASTL_UNLIKELY(mEnd == c.begin()))\n\t\t\t\tmEnd = c.end();\n\t\t\t--mEnd;\n\t\t}\n\t\telse\n\t\t\t++mSize;\n\n\t\t// See comments above in push_back for why we don't execute this:\n\t\t// *mBegin = value_type();\n\n\t\treturn *mBegin; // Same as return front();\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::pop_front()\n\t{\n\t\tEASTL_ASSERT(mBegin != mEnd); // We assume that mEnd > mBegin and thus that there is something to pop.\n\n\t\tif(++mBegin == c.end())\n\t\t\tmBegin = c.begin();\n\t\t--mSize;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reference\n\tring_buffer<T, Container, Allocator>::operator[](size_type n)\n\t{\n\t\t// return *(begin() + n); // Can't use this because not all iterators support operator+.\n\n\t\t// This should compile to code that is nearly as efficient as that above.\n\t\t// The primary difference is the possible generation of a temporary in this case.\n\t\titerator temp(begin());\n\t\teastl::advance(temp, n);\n\t\treturn *(temp.mContainerIterator);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::const_reference\n\tring_buffer<T, Container, Allocator>::operator[](size_type n) const\n\t{\n\t\t// return *(begin() + n); // Can't use this because not all iterators support operator+.\n\n\t\t// This should compile to code that is nearly as efficient as that above.\n\t\t// The primary difference is the possible generation of a temporary in this case.\n\t\tconst_iterator temp(begin());\n\t\teastl::advance(temp, n);\n\t\treturn *(temp.mContainerIterator);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::iterator\n\tring_buffer<T, Container, Allocator>::insert(const_iterator position, const value_type& value)\n\t{\n\t\t// To consider: It would be faster if we could tell that position was in the first\n\t\t// half of the container and instead of moving things after the position back, \n\t\t// we could move things before the position forward. \n\n\t\titerator afterEnd(end());\n\t\titerator beforeEnd(afterEnd);\n\n\t\t++afterEnd;\n\n\t\tif(afterEnd.mContainerIterator == mBegin) // If we are at full capacity...\n\t\t\t--beforeEnd;\n\t\telse\n\t\t\tpush_back();\n\n\t\titerator itPosition(position.mpContainer, position.mContainerIterator); // We merely copy from const_iterator to iterator.\n\t\teastl::copy_backward(itPosition, beforeEnd, end());\n\t\t*itPosition = value;\n\n\t\treturn itPosition;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::insert(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\t// To do: This can be improved with a smarter version. However, \n\t\t// this is a little tricky because we need to deal with the case \n\t\t// whereby n is greater than the size of the container itself. \n\t\twhile(n--)\n\t\t\tinsert(position, value);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::insert(const_iterator position, std::initializer_list<value_type> ilist)\n\t{\n\t\tinsert(position, ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttemplate <typename InputIterator>\n\tvoid ring_buffer<T, Container, Allocator>::insert(const_iterator position, InputIterator first, InputIterator last)\n\t{\n\t\t// To do: This can possibly be improved with a smarter version.\n\t\t// However, this can be tricky if distance(first, last) is greater\n\t\t// than the size of the container itself.\n\t\tfor(; first != last; ++first, ++position)\n\t\t\tinsert(position, *first);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::iterator\n\tring_buffer<T, Container, Allocator>::erase(const_iterator position)\n\t{\n\t\titerator itPosition(position.mpContainer, position.mContainerIterator); // We merely copy from const_iterator to iterator.\n\t\titerator iNext(itPosition);\n\n\t\teastl::copy(++iNext, end(), itPosition);\n\t\tpop_back();\n\n\t\treturn itPosition;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::iterator\n\tring_buffer<T, Container, Allocator>::erase(const_iterator first, const_iterator last)\n\t{\n\t\titerator itFirst(first.mpContainer, first.mContainerIterator); // We merely copy from const_iterator to iterator.\n\t\titerator itLast(last.mpContainer, last.mContainerIterator);\n\n\t\ttypename iterator::difference_type d = eastl::distance(itFirst, itLast);\n\n\t\teastl::copy(itLast, end(), itFirst);\n\n\t\twhile(d--)      // To do: improve this implementation.\n\t\t\tpop_back();\n\n\t\treturn itFirst;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reverse_iterator\n\tring_buffer<T, Container, Allocator>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::reverse_iterator\n\tring_buffer<T, Container, Allocator>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tvoid ring_buffer<T, Container, Allocator>::clear()\n\t{\n\t\t// Don't clear the container; we use its valid data for our elements.\n\t\tmBegin = c.begin();\n\t\tmEnd   = c.begin();\n\t\tmSize  = 0;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\ttypename ring_buffer<T, Container, Allocator>::container_type&\n\tring_buffer<T, Container, Allocator>::get_container()\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tconst typename ring_buffer<T, Container, Allocator>::container_type&\n\tring_buffer<T, Container, Allocator>::get_container() const\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline bool ring_buffer<T, Container, Allocator>::validate() const\n\t{\n\t\tif(!c.validate())  // This requires that the container implement the validate function. That pretty much \n\t\t\treturn false;  // means that the container is an EASTL container and not a std STL container. \n\n\t\tif(c.empty())      // c must always have a size of at least 1, as even an empty ring_buffer has an unused terminating element.\n\t\t\treturn false;\n\n\t\tif(size() > capacity())\n\t\t\treturn false;\n\n\t\tif((validate_iterator(begin()) & (isf_valid | isf_current)) != (isf_valid | isf_current))\n\t\t\treturn false;\n\n\t\tif((validate_iterator(end()) & (isf_valid | isf_current)) != (isf_valid | isf_current))\n\t\t\treturn false;\n\n\t\t// Verify that the size calculation is consistent.\n\t\tsize_type n = 0;\n\t\tfor(const_iterator i(begin()), iEnd(end()); i != iEnd; ++i)\n\t\t\t++n;\n\t\tif(n != mSize)\n\t\t\treturn false;\n\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline int ring_buffer<T, Container, Allocator>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Replace this with a more efficient implementation if possible.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline bool operator==(const ring_buffer<T, Container, Allocator>& a, const ring_buffer<T, Container, Allocator>& b)\n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin());\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline bool operator<(const ring_buffer<T, Container, Allocator>& a, const ring_buffer<T, Container, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline bool operator!=(const ring_buffer<T, Container, Allocator>& a, const ring_buffer<T, Container, Allocator>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline bool operator>(const ring_buffer<T, Container, Allocator>& a, const ring_buffer<T, Container, Allocator>& b)\n\t{\n\t\treturn (b < a);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline bool operator<=(const ring_buffer<T, Container, Allocator>& a, const ring_buffer<T, Container, Allocator>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline bool operator>=(const ring_buffer<T, Container, Allocator>& a, const ring_buffer<T, Container, Allocator>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Allocator>\n\tinline void swap(ring_buffer<T, Container, Allocator>& a, ring_buffer<T, Container, Allocator>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/sort_extra.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////////\n// This file implements additional sort algorithms beyond the basic set.\n// Included here are:\n//    selection_sort        -- Unstable.\n//    shaker_sort           -- Stable.\n//    bucket_sort           -- Stable. \n//\n//////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SORT_EXTRA_H\n#define EASTL_SORT_EXTRA_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/functional.h>\n#include <EASTL/heap.h>\n#include <EASTL/sort.h>             // For backwards compatibility due to sorts moved from here to sort.h.\n#include <EASTL/allocator.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// selection_sort\n\t///\n\t/// Implements the SelectionSort algorithm.\n\t///\n\ttemplate <typename ForwardIterator, typename StrictWeakOrdering>\n\tvoid selection_sort(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)\n\t{\n\t\tForwardIterator iCurrent, iMin;\n\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tiCurrent = first;\n\t\t\tiMin     = iCurrent;\n\n\t\t\tfor(++iCurrent; iCurrent != last; ++iCurrent)\n\t\t\t{\n\t\t\t\tif(compare(*iCurrent, *iMin))\n\t\t\t\t{\n\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iMin, *iCurrent)); // Validate that the compare function is sane.\n\t\t\t\t\tiMin = iCurrent;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(first != iMin)\n\t\t\t\teastl::iter_swap(first, iMin);\n\t\t}\n\t} // selection_sort\n\n\ttemplate <typename ForwardIterator>\n\tinline void selection_sort(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;\n\n\t\teastl::selection_sort<ForwardIterator, Less>(first, last, Less());\n\t}\n\n\n\n\t/// shaker_sort\n\t///\n\t/// Implements the ShakerSort algorithm, which is a sorting algorithm which \n\t/// improves on bubble_sort by sweeping both from left to right and right \n\t/// to left, resulting in less iteration.\n\t///\n\ttemplate <typename BidirectionalIterator, typename StrictWeakOrdering>\n\tvoid shaker_sort(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering compare)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tBidirectionalIterator iCurrent, iNext, iLastModified;\n\n\t\t\t--last;\n\n\t\t\twhile(first != last)\n\t\t\t{\n\t\t\t\tiLastModified = first;\n\n\t\t\t\tfor(iCurrent = first; iCurrent != last; iCurrent = iNext)\n\t\t\t\t{\n\t\t\t\t\tiNext = iCurrent;\n\t\t\t\t\t++iNext;\n\n\t\t\t\t\tif(compare(*iNext, *iCurrent))\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.\n\t\t\t\t\t\tiLastModified = iCurrent;\n\t\t\t\t\t\teastl::iter_swap(iCurrent, iNext);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlast = iLastModified;\n\n\t\t\t\tif(first != last)\n\t\t\t\t{\n\t\t\t\t\tfor(iCurrent = last; iCurrent != first; iCurrent = iNext)\n\t\t\t\t\t{\n\t\t\t\t\t\tiNext = iCurrent;\n\t\t\t\t\t\t--iNext;\n\n\t\t\t\t\t\tif(compare(*iCurrent, *iNext))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iNext, *iCurrent)); // Validate that the compare function is sane.\n\t\t\t\t\t\t\tiLastModified = iCurrent;\n\t\t\t\t\t\t\teastl::iter_swap(iNext, iCurrent);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfirst = iLastModified;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} // shaker_sort\n\n\ttemplate <typename BidirectionalIterator>\n\tinline void shaker_sort(BidirectionalIterator first, BidirectionalIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<BidirectionalIterator>::value_type> Less;\n\n\t\teastl::shaker_sort<BidirectionalIterator, Less>(first, last, Less());\n\t}\n\n\n\n\t/// bucket_sort\n\t///\n\t/// Implements the BucketSort algorithm. \n\t///\n\t/// Example usage:\n\t///  const size_t kElementRange = 32;\n\t///  vector<int>  intArray(1000);\n\t///  \n\t///  for(int i = 0; i < 1000; i++)\n\t///     intArray[i] = rand() % kElementRange;\n\t///  \n\t///  vector< vector<int> > bucketArray(kElementRange);\n\t///  bucket_sort(intArray.begin(), intArray.end(), bucketArray, eastl::hash_use_self<int>());\n\t///\n\ttemplate <typename T>\n\tstruct hash_use_self\n\t{\n\t\tT operator()(const T& x) const\n\t\t\t{ return x; }\n\t};\n\n\t// Requires buckeyArray to be an array of arrays with a size equal to the range of values\n\t// returned by the hash function. The hash function is required to return a unique value\n\t// for each uniquely sorted element. Usually the way this is done is the elements are \n\t// integers of a limited range (e.g. 0-64) and the hash function returns the element value\n\t// itself. If you had a case where all elements were always even numbers (e.g. 0-128), \n\t// you could use a custom hash function that returns (element value / 2).\n\t//\n\t// The user is required to provide an empty bucketArray to this function. This function returns\n\t// with the bucketArray non-empty. This function doesn't clear the bucketArray because that takes\n\t// time and the user might not need it to be cleared, at least at that time.\n\t// \n\ttemplate <typename ForwardIterator, typename ContainerArray, typename HashFunction>\n\tvoid bucket_sort(ForwardIterator first, ForwardIterator last, ContainerArray& bucketArray, HashFunction hash /*= hash_use_self*/)\n\t{\n\t\tfor(ForwardIterator iInput = first; iInput != last; ++iInput)\n\t\t\tbucketArray[hash(*iInput)].push_back(*iInput);\n\n\t\tfor(typename ContainerArray::const_iterator iBucket = bucketArray.begin(); iBucket != bucketArray.end(); ++iBucket)\n\t\t\tfirst = eastl::copy((*iBucket).begin(), (*iBucket).end(), first);\n\t}\n\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/bonus/tuple_vector.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// tuple_vector is a data container that is designed to abstract and simplify\n// the handling of a \"structure of arrays\" layout of data in memory. In\n// particular, it mimics the interface of vector, including functionality to do\n// inserts, erases, push_backs, and random-access. It also provides a\n// RandomAccessIterator and corresponding functionality, making it compatible\n// with most STL (and STL-esque) algorithms such as ranged-for loops, find_if,\n// remove_if, or sort.\n\n// When used or applied properly, this container can improve performance of\n// some algorithms through cache-coherent data accesses or allowing for\n// sensible SIMD programming, while keeping the structure of a single\n// container, to permit a developer to continue to use existing algorithms in\n// STL and the like.\n//\n// Consult doc/Bonus/tuple_vector_readme.md for more information.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_TUPLEVECTOR_H\n#define EASTL_TUPLEVECTOR_H\n\n#include <EASTL/bonus/compressed_pair.h>\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <EASTL/memory.h>\n#include <EASTL/tuple.h>\n#include <EASTL/utility.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\nEA_DISABLE_VC_WARNING(4244) // warning C4244: 'conversion from '___' to '___', possible loss of data\nEA_DISABLE_VC_WARNING(4623) // warning C4623: default constructor was implicitly defined as deleted\nEA_DISABLE_VC_WARNING(4625) // warning C4625: copy constructor was implicitly defined as deleted\nEA_DISABLE_VC_WARNING(4510) // warning C4510: default constructor could not be generated\n\nnamespace eastl\n{\n\t/// EASTL_TUPLE_VECTOR_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_TUPLE_VECTOR_DEFAULT_NAME\n\t#define EASTL_TUPLE_VECTOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" tuple-vector\" // Unless the user overrides something, this is \"EASTL tuple-vector\".\n\t#endif\n\n\n\t/// EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR\n\t#define EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR allocator_type(EASTL_TUPLE_VECTOR_DEFAULT_NAME)\n\t#endif\n\nnamespace TupleVecInternal\n{\n\n// forward declarations\ntemplate <eastl_size_t I, typename... Ts>\nstruct tuplevec_element;\n\ntemplate <eastl_size_t I, typename... Ts>\nusing tuplevec_element_t = typename tuplevec_element<I, Ts...>::type;\n\ntemplate <typename... Ts>\nstruct TupleTypes {};\n\ntemplate <typename Allocator, typename Indices, typename... Ts>\nclass TupleVecImpl;\n\ntemplate <typename... Ts>\nstruct TupleRecurser;\n\ntemplate <eastl_size_t I, typename... Ts>\nstruct TupleIndexRecurser;\n\ntemplate <eastl_size_t I, typename T>\nstruct TupleVecLeaf;\n\ntemplate <typename Indices, typename... Ts>\nstruct TupleVecIter;\n\n// tuplevec_element helper to be able to isolate a type given an index\ntemplate <eastl_size_t I>\nstruct tuplevec_element<I>\n{\n\tstatic_assert(I != I, \"tuplevec_element index out of range\");\n};\n\ntemplate <typename T, typename... Ts>\nstruct tuplevec_element<0, T, Ts...>\n{\n\ttuplevec_element() = delete; // tuplevec_element should only be used for compile-time assistance, and never be instantiated\n\ttypedef T type;\n};\n\ntemplate <eastl_size_t I, typename T, typename... Ts>\nstruct tuplevec_element<I, T, Ts...>\n{\n\ttypedef tuplevec_element_t<I - 1, Ts...> type;\n};\n\n// attempt to isolate index given a type\ntemplate <typename T, typename TupleVector>\nstruct tuplevec_index\n{\n};\n\ntemplate <typename T>\nstruct tuplevec_index<T, TupleTypes<>>\n{\n\ttypedef void DuplicateTypeCheck;\n\ttuplevec_index() = delete; // tuplevec_index should only be used for compile-time assistance, and never be instantiated\n\tstatic const eastl_size_t index = 0;\n};\n\ntemplate <typename T, typename... TsRest>\nstruct tuplevec_index<T, TupleTypes<T, TsRest...>>\n{\n\ttypedef int DuplicateTypeCheck;\n\tstatic_assert(is_void<typename tuplevec_index<T, TupleTypes<TsRest...>>::DuplicateTypeCheck>::value, \"duplicate type T in tuple_vector::get<T>(); unique types must be provided in declaration, or only use get<eastl_size_t>()\");\n\n\tstatic const eastl_size_t index = 0;\n};\n\ntemplate <typename T, typename Ts, typename... TsRest>\nstruct tuplevec_index<T, TupleTypes<Ts, TsRest...>>\n{\n\ttypedef typename tuplevec_index<T, TupleTypes<TsRest...>>::DuplicateTypeCheck DuplicateTypeCheck;\n\tstatic const eastl_size_t index = tuplevec_index<T, TupleTypes<TsRest...>>::index + 1;\n};\n\ntemplate <typename Allocator, typename T, typename Indices, typename... Ts>\nstruct tuplevec_index<T, TupleVecImpl<Allocator, Indices, Ts...>> : public tuplevec_index<T, TupleTypes<Ts...>>\n{\n};\n\n\n// helper to calculate the layout of the allocations for the tuple of types (esp. to take alignment into account)\ntemplate <>\nstruct TupleRecurser<>\n{\n\ttypedef eastl_size_t size_type;\n\n\t// This class should never be instantiated. This is just a helper for working with static functions when anonymous functions don't work\n\t// and provide some other utilities\n\tTupleRecurser() = delete;\n\t\t\n\tstatic EA_CONSTEXPR size_type GetTotalAlignment()\n\t{\n\t\treturn 0;\n\t}\n\n\tstatic EA_CONSTEXPR size_type GetTotalAllocationSize(size_type capacity, size_type offset)\n\t{\n\t\tEA_UNUSED(capacity);\n\t\treturn offset;\n\t}\n\n\ttemplate<typename Allocator, size_type I, typename Indices, typename... VecTypes>\n\tstatic pair<void*, size_type> DoAllocate(TupleVecImpl<Allocator, Indices, VecTypes...> &vec, void** ppNewLeaf, size_type capacity, size_type offset)\n\t{\n\t\tEA_UNUSED(ppNewLeaf);\n\n\t\t// If n is zero, then we allocate no memory and just return NULL. \n\t\t// This is fine, as our default ctor initializes with NULL pointers. \n\t\tsize_type alignment = TupleRecurser<VecTypes...>::GetTotalAlignment();\n\t\tvoid* ptr = capacity ? allocate_memory(vec.get_allocator(), offset, alignment, 0) : nullptr;\n\n\t#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY((size_t)ptr & (alignment - 1)) != 0)\n\t\t{\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::DoAllocate -- memory not alignment at requested alignment\");\n\t\t}\n\t#endif\n\n\t\treturn make_pair(ptr, offset);\n\t}\n\n\ttemplate<typename TupleVecImplType, size_type I>\n\tstatic void SetNewData(TupleVecImplType &vec, void* pData, size_type capacity, size_type offset) \n\t{ \n\t\tEA_UNUSED(vec);\n\t\tEA_UNUSED(pData);\n\t\tEA_UNUSED(capacity);\n\t\tEA_UNUSED(offset);\n\t}\n};\n\ntemplate <typename T, typename... Ts>\nstruct TupleRecurser<T, Ts...> : TupleRecurser<Ts...>\n{\n\ttypedef eastl_size_t size_type;\n\t\n\tstatic EA_CONSTEXPR size_type GetTotalAlignment()\n\t{\n\t\treturn max(static_cast<size_type>(alignof(T)), TupleRecurser<Ts...>::GetTotalAlignment());\n\t}\n\n\tstatic EA_CONSTEXPR size_type GetTotalAllocationSize(size_type capacity, size_type offset)\n\t{\n\t\treturn TupleRecurser<Ts...>::GetTotalAllocationSize(capacity, CalculateAllocationSize(offset, capacity));\n\t}\n\n\ttemplate<typename Allocator, size_type I, typename Indices, typename... VecTypes>\n\tstatic pair<void*, size_type> DoAllocate(TupleVecImpl<Allocator, Indices, VecTypes...> &vec, void** ppNewLeaf, size_type capacity, size_type offset)\n\t{\n\t\tsize_type allocationOffset = CalculatAllocationOffset(offset);\n\t\tsize_type allocationSize = CalculateAllocationSize(offset, capacity);\n\t\tpair<void*, size_type> allocation = TupleRecurser<Ts...>::template DoAllocate<Allocator, I + 1, Indices, VecTypes...>(\n\t\t\tvec, ppNewLeaf, capacity, allocationSize);\n\t\tppNewLeaf[I] = (void*)((uintptr_t)(allocation.first) + allocationOffset);\n\t\treturn allocation;\n\t}\n\n\ttemplate<typename TupleVecImplType, size_type I>\n\tstatic void SetNewData(TupleVecImplType &vec, void* pData, size_type capacity, size_type offset)\n\t{\n\t\tsize_type allocationOffset = CalculatAllocationOffset(offset);\n\t\tsize_type allocationSize = CalculateAllocationSize(offset, capacity);\n\t\tvec.TupleVecLeaf<I, T>::mpData = (T*)((uintptr_t)pData + allocationOffset);\n\t\tTupleRecurser<Ts...>::template SetNewData<TupleVecImplType, I + 1>(vec, pData, capacity, allocationSize);\n\t}\n\nprivate:\n\tstatic EA_CONSTEXPR size_type CalculateAllocationSize(size_type offset, size_type capacity)\n\t{\n\t\treturn CalculatAllocationOffset(offset) + sizeof(T) * capacity;\n\t}\n\n\tstatic EA_CONSTEXPR size_type CalculatAllocationOffset(size_type offset) { return (offset + alignof(T) - 1) & (~alignof(T) + 1); }\n};\n\ntemplate <eastl_size_t I, typename T>\nstruct TupleVecLeaf\n{\n\ttypedef eastl_size_t size_type;\n\n\tvoid DoUninitializedMoveAndDestruct(const size_type begin, const size_type end, T* pDest)\n\t{\n\t\tT* pBegin = mpData + begin;\n\t\tT* pEnd = mpData + end;\n\t\teastl::uninitialized_move_if_noexcept(pBegin, pEnd, pDest);\n\t\teastl::destruct(pBegin, pEnd);\n\t}\n\n\tvoid DoInsertAndFill(size_type pos, size_type n, size_type numElements, const T& arg)\n\t{\n\t\tT* pDest = mpData + pos;\n\t\tT* pDataEnd = mpData + numElements;\n\t\tconst T temp = arg;\n\t\tconst size_type nExtra = (numElements - pos);\n\t\tif (n < nExtra) // If the inserted values are entirely within initialized memory (i.e. are before mpEnd)...\n\t\t{\n\t\t\teastl::uninitialized_move(pDataEnd - n, pDataEnd, pDataEnd);\n\t\t\teastl::move_backward(pDest, pDataEnd - n, pDataEnd); // We need move_backward because of potential overlap issues.\n\t\t\teastl::fill(pDest, pDest + n, temp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\teastl::uninitialized_fill_n(pDataEnd, n - nExtra, temp);\n\t\t\teastl::uninitialized_move(pDest, pDataEnd, pDataEnd + n - nExtra);\n\t\t\teastl::fill(pDest, pDataEnd, temp);\n\t\t}\n\t}\n\n\tvoid DoInsertRange(T* pSrcBegin, T* pSrcEnd, T* pDestBegin, size_type numDataElements)\n\t{\n\t\tsize_type pos = static_cast<size_type>(pDestBegin - mpData);\n\t\tsize_type n = static_cast<size_type>(pSrcEnd - pSrcBegin);\n\t\tT* pDataEnd = mpData + numDataElements;\n\t\tconst size_type nExtra = numDataElements - pos;\n\t\tif (n < nExtra) // If the inserted values are entirely within initialized memory (i.e. are before mpEnd)...\n\t\t{\n\t\t\teastl::uninitialized_move(pDataEnd - n, pDataEnd, pDataEnd);\n\t\t\teastl::move_backward(pDestBegin, pDataEnd - n, pDataEnd); // We need move_backward because of potential overlap issues.\n\t\t\teastl::copy(pSrcBegin, pSrcEnd, pDestBegin);\n\t\t}\n\t\telse\n\t\t{\n\t\t\teastl::uninitialized_copy(pSrcEnd - (n - nExtra), pSrcEnd, pDataEnd);\n\t\t\teastl::uninitialized_move(pDestBegin, pDataEnd, pDataEnd + n - nExtra);\n\t\t\teastl::copy(pSrcBegin, pSrcEnd - (n - nExtra), pDestBegin);\n\t\t}\n\t}\n\n\tvoid DoInsertValue(size_type pos, size_type numElements, T&& arg)\n\t{\n\t\tT* pDest = mpData + pos;\n\t\tT* pDataEnd = mpData + numElements;\n\n\t\teastl::uninitialized_move(pDataEnd - 1, pDataEnd, pDataEnd);\n\t\teastl::move_backward(pDest, pDataEnd - 1, pDataEnd); // We need move_backward because of potential overlap issues.\n\t\teastl::destruct(pDest);\n\t\t::new (pDest) T(eastl::forward<T>(arg));\n\t}\n\n\tT* mpData = nullptr;\n};\n\n// swallow allows for parameter pack expansion of arguments as means of expanding operations performed\n// if a void function is used for operation expansion, it should be wrapped in (..., 0) so that the compiler\n// thinks it has a parameter to pass into the function\ntemplate <typename... Ts>\nvoid swallow(Ts&&...) { }\n\ninline bool variadicAnd(bool cond) { return cond; }\n\ninline bool variadicAnd(bool cond, bool conds...) { return cond && variadicAnd(conds); }\n\n// Helper struct to check for strict compatibility between two iterators, whilst still allowing for\n// conversion between TupleVecImpl<Ts...>::iterator and TupleVecImpl<Ts...>::const_iterator. \ntemplate <bool IsSameSize, typename From, typename To>\nstruct TupleVecIterCompatibleImpl : public false_type { };\n\t\ntemplate<>\nstruct TupleVecIterCompatibleImpl<true, TupleTypes<>, TupleTypes<>> : public true_type { };\n\ntemplate <typename From, typename... FromRest, typename To, typename... ToRest>\nstruct TupleVecIterCompatibleImpl<true, TupleTypes<From, FromRest...>, TupleTypes<To, ToRest...>> : public integral_constant<bool,\n\t\tTupleVecIterCompatibleImpl<true, TupleTypes<FromRest...>, TupleTypes<ToRest...>>::value &&\n\t\tis_same<typename remove_const<From>::type, typename remove_const<To>::type>::value >\n{ };\n\ntemplate <typename From, typename To>\nstruct TupleVecIterCompatible;\n\ntemplate<typename... Us, typename... Ts>\nstruct TupleVecIterCompatible<TupleTypes<Us...>, TupleTypes<Ts...>> :\n\tpublic TupleVecIterCompatibleImpl<sizeof...(Us) == sizeof...(Ts), TupleTypes<Us...>, TupleTypes<Ts...>>\n{ };\n\n// The Iterator operates by storing a persistent index internally,\n// and resolving the tuple of pointers to the various parts of the original tupleVec when dereferenced.\n// While resolving the tuple is a non-zero operation, it consistently generated better code than the alternative of\n// storing - and harmoniously updating on each modification - a full tuple of pointers to the tupleVec's data\ntemplate <eastl_size_t... Indices, typename... Ts>\nstruct TupleVecIter<index_sequence<Indices...>, Ts...>\n{\nprivate:\n\ttypedef TupleVecIter<index_sequence<Indices...>, Ts...> this_type;\n\ttypedef eastl_size_t size_type;\n\n\ttemplate<typename U, typename... Us> \n\tfriend struct TupleVecIter;\n\n\ttemplate<typename U, typename V, typename... Us>\n\tfriend class TupleVecImpl;\n\n\ttemplate<typename U>\n\tfriend class move_iterator;\npublic:\n\ttypedef eastl::random_access_iterator_tag iterator_category;\n\ttypedef tuple<Ts...> value_type;\n\ttypedef eastl_size_t difference_type;\n\ttypedef tuple<Ts*...> pointer;\n\ttypedef tuple<Ts&... > reference;\n\n\tTupleVecIter() = default;\n\n\ttemplate<typename VecImplType>\n\tTupleVecIter(VecImplType* tupleVec, size_type index)\n\t\t: mIndex(index)\n\t\t, mpData{(void*)tupleVec->TupleVecLeaf<Indices, Ts>::mpData...}\n\t{ }\n\n\ttemplate <typename OtherIndicesType, typename... Us,\n\t\t\t  typename = typename enable_if<TupleVecIterCompatible<TupleTypes<Us...>, TupleTypes<Ts...>>::value, bool>::type>\n\tTupleVecIter(const TupleVecIter<OtherIndicesType, Us...>& other)\n\t\t: mIndex(other.mIndex)\n\t\t, mpData{other.mpData[Indices]...}\n\t{\n\t}\n\n\tbool operator==(const TupleVecIter& other) const { return mIndex == other.mIndex && mpData[0] == other.mpData[0]; }\n\tbool operator!=(const TupleVecIter& other) const { return mIndex != other.mIndex || mpData[0] != other.mpData[0]; }\n\treference operator*() const { return MakeReference(); }\n\n\tthis_type& operator++() { ++mIndex; return *this; }\n\tthis_type operator++(int)\n\t{\n\t\tthis_type temp = *this;\n\t\t++mIndex;\n\t\treturn temp;\n\t}\n\n\tthis_type& operator--() { --mIndex; return *this; }\n\tthis_type operator--(int)\n\t{\n\t\tthis_type temp = *this;\n\t\t--mIndex;\n\t\treturn temp;\n\t}\n\n\tthis_type& operator+=(difference_type n) { mIndex += n; return *this; }\n\tthis_type operator+(difference_type n) const\n\t{\n\t\tthis_type temp = *this;\n\t\treturn temp += n;\n\t}\n\tfriend this_type operator+(difference_type n, const this_type& rhs)\n\t{\n\t\tthis_type temp = rhs;\n\t\treturn temp += n;\n\t}\n\n\tthis_type& operator-=(difference_type n) { mIndex -= n; return *this; }\n\tthis_type operator-(difference_type n) const\n\t{\n\t\tthis_type temp = *this;\n\t\treturn temp -= n;\n\t}\n\tfriend this_type operator-(difference_type n, const this_type& rhs)\n\t{\n\t\tthis_type temp = rhs;\n\t\treturn temp -= n;\n\t}\n\n\tdifference_type operator-(const this_type& rhs) const { return mIndex - rhs.mIndex; }\n\tbool operator<(const this_type& rhs) const { return mIndex < rhs.mIndex; }\n\tbool operator>(const this_type& rhs) const { return mIndex > rhs.mIndex; }\n\tbool operator>=(const this_type& rhs) const { return mIndex >= rhs.mIndex; }\n\tbool operator<=(const this_type& rhs) const { return mIndex <= rhs.mIndex; }\n\n\treference operator[](const size_type n) const\n\t{\n\t\treturn *(*this + n);\n\t}\n\nprivate:\n\n\tvalue_type MakeValue() const\n\t{\n\t\treturn value_type(((Ts*)mpData[Indices])[mIndex]...);\n\t}\n\n\treference MakeReference() const\n\t{\n\t\treturn reference(((Ts*)mpData[Indices])[mIndex]...);\n\t}\n\n\tpointer MakePointer() const\n\t{\n\t\treturn pointer(&((Ts*)mpData[Indices])[mIndex]...);\n\t}\n\n\tsize_type mIndex = 0;\n\tconst void* mpData[sizeof...(Ts)];\n};\n\n// TupleVecImpl\ntemplate <typename Allocator, eastl_size_t... Indices, typename... Ts>\nclass TupleVecImpl<Allocator, index_sequence<Indices...>, Ts...> : public TupleVecLeaf<Indices, Ts>...\n{\n\ttypedef Allocator\tallocator_type;\n\ttypedef index_sequence<Indices...> index_sequence_type;\n\ttypedef TupleVecImpl<Allocator, index_sequence_type, Ts...> this_type;\n\ttypedef TupleVecImpl<Allocator, index_sequence_type, const Ts...> const_this_type;\n\npublic:\n\ttypedef TupleVecInternal::TupleVecIter<index_sequence_type, Ts...> iterator;\n\ttypedef TupleVecInternal::TupleVecIter<index_sequence_type, const Ts...> const_iterator;\n\ttypedef eastl::reverse_iterator<iterator> reverse_iterator;\n\ttypedef eastl::reverse_iterator<const_iterator> const_reverse_iterator;\n\ttypedef eastl_size_t size_type;\n\ttypedef eastl::tuple<Ts...> value_tuple;\n\ttypedef eastl::tuple<Ts&...> reference_tuple;\n\ttypedef eastl::tuple<const Ts&...> const_reference_tuple;\n\ttypedef eastl::tuple<Ts*...> ptr_tuple;\n\ttypedef eastl::tuple<const Ts*...> const_ptr_tuple;\n\ttypedef eastl::tuple<Ts&&...> rvalue_tuple;\n\n\tTupleVecImpl()\n\t\t: mDataSizeAndAllocator(0, EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t{}\n\n\tTupleVecImpl(const allocator_type& allocator)\n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{}\n\n\tTupleVecImpl(this_type&& x)\n\t\t: mDataSizeAndAllocator(0, eastl::move(x.get_allocator()))\n\t{\n\t\tswap(x);\n\t}\n\n\tTupleVecImpl(this_type&& x, const Allocator& allocator) \n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tif (get_allocator() == x.get_allocator()) // If allocators are equivalent, then we can safely swap member-by-member\n\t\t{\n\t\t\tswap(x);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis_type temp(eastl::move(*this));\n\t\t\ttemp.swap(x);\n\t\t}\n\t}\n\n\tTupleVecImpl(const this_type& x) \n\t\t: mDataSizeAndAllocator(0, x.get_allocator())\n\t{\n\t\tDoInitFromIterator(x.begin(), x.end());\n\t}\n\n\ttemplate<typename OtherAllocator>\n\tTupleVecImpl(const TupleVecImpl<OtherAllocator, index_sequence_type, Ts...>& x, const Allocator& allocator)  \n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tDoInitFromIterator(x.begin(), x.end());\n\t}\n\n\ttemplate<typename MoveIterBase>\n\tTupleVecImpl(move_iterator<MoveIterBase> begin, move_iterator<MoveIterBase> end, const allocator_type& allocator = EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tDoInitFromIterator(begin, end);\n\t}\n\n\tTupleVecImpl(const_iterator begin, const_iterator end, const allocator_type& allocator = EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: mDataSizeAndAllocator(0, allocator )\n\t{\n\t\tDoInitFromIterator(begin, end);\n\t}\n\n\tTupleVecImpl(size_type n, const allocator_type& allocator = EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tDoInitDefaultFill(n);\n\t}\n\n\tTupleVecImpl(size_type n, const Ts&... args) \n\t\t: mDataSizeAndAllocator(0, EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t{\n\t\tDoInitFillArgs(n, args...);\n\t}\n\n\tTupleVecImpl(size_type n, const Ts&... args, const allocator_type& allocator) \n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tDoInitFillArgs(n, args...);\n\t}\n\n\tTupleVecImpl(size_type n, const_reference_tuple tup, const allocator_type& allocator = EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tDoInitFillTuple(n, tup);\n\t}\n\n\tTupleVecImpl(const value_tuple* first, const value_tuple* last, const allocator_type& allocator = EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tDoInitFromTupleArray(first, last);\n\t}\n\n\tTupleVecImpl(std::initializer_list<value_tuple> iList, const allocator_type& allocator = EASTL_TUPLE_VECTOR_DEFAULT_ALLOCATOR)\n\t\t: mDataSizeAndAllocator(0, allocator)\n\t{\n\t\tDoInitFromTupleArray(iList.begin(), iList.end());\n\t}\n\nprotected:\n\t// ctor to provide a pre-allocated field of data that the container will own, specifically for fixed_tuple_vector\n\tTupleVecImpl(const allocator_type& allocator, void* pData, size_type capacity, size_type dataSize)\n\t\t: mpData(pData), mNumCapacity(capacity), mDataSizeAndAllocator(dataSize, allocator)\n\t{\n\t\tTupleRecurser<Ts...>::template SetNewData<this_type, 0>(*this, mpData, mNumCapacity, 0);\n\t}\n\npublic:\n\t~TupleVecImpl()\n\t{ \n\t\tswallow((eastl::destruct(TupleVecLeaf<Indices, Ts>::mpData, TupleVecLeaf<Indices, Ts>::mpData + mNumElements), 0)...);\n\t\tif (mpData)\n\t\t\tEASTLFree(get_allocator(), mpData, internalDataSize()); \n\t}\n\n\tvoid assign(size_type n, const Ts&... args)\n\t{\n\t\tif (n > mNumCapacity)\n\t\t{\n\t\t\tthis_type temp(n, args..., get_allocator()); // We have little choice but to reallocate with new memory.\n\t\t\tswap(temp);\n\t\t}\n\t\telse if (n > mNumElements) // If n > mNumElements ...\n\t\t{\n\t\t\tsize_type oldNumElements = mNumElements;\n\t\t\tswallow((eastl::fill(TupleVecLeaf<Indices, Ts>::mpData, TupleVecLeaf<Indices, Ts>::mpData + oldNumElements, args), 0)...);\n\t\t\tswallow((eastl::uninitialized_fill(TupleVecLeaf<Indices, Ts>::mpData + oldNumElements,\n\t\t\t\t\t                       TupleVecLeaf<Indices, Ts>::mpData + n, args), 0)...);\n\t\t\tmNumElements = n;\n\t\t}\n\t\telse // else 0 <= n <= mNumElements\n\t\t{\n\t\t\tswallow((eastl::fill(TupleVecLeaf<Indices, Ts>::mpData, TupleVecLeaf<Indices, Ts>::mpData + n, args), 0)...);\n\t\t\terase(begin() + n, end());\n\t\t}\n\t}\n\n\tvoid assign(const_iterator first, const_iterator last)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(!validate_iterator_pair(first, last)))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::assign -- invalid iterator pair\");\n#endif\n\t\tsize_type newNumElements = last - first;\n\t\tif (newNumElements > mNumCapacity)\n\t\t{\n\t\t\tthis_type temp(first, last, get_allocator());\n\t\t\tswap(temp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst void* ppOtherData[sizeof...(Ts)] = {first.mpData[Indices]...};\n\t\t\tsize_type firstIdx = first.mIndex;\n\t\t\tsize_type lastIdx = last.mIndex;\n\t\t\tif (newNumElements > mNumElements) // If n > mNumElements ...\n\t\t\t{\n\t\t\t\tsize_type oldNumElements = mNumElements;\n\t\t\t\tswallow((eastl::copy((Ts*)(ppOtherData[Indices]) + firstIdx,\n\t\t\t\t\t\t       (Ts*)(ppOtherData[Indices]) + firstIdx + oldNumElements,\n\t\t\t\t\t\t       TupleVecLeaf<Indices, Ts>::mpData), 0)...);\n\t\t\t\tswallow((eastl::uninitialized_copy((Ts*)(ppOtherData[Indices]) + firstIdx + oldNumElements,\n\t\t\t\t\t\t                       (Ts*)(ppOtherData[Indices]) + lastIdx,\n\t\t\t\t\t\t                       TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t\t\t\tmNumElements = newNumElements;\n\t\t\t}\n\t\t\telse // else 0 <= n <= mNumElements\n\t\t\t{\n\t\t\t\tswallow((eastl::copy((Ts*)(ppOtherData[Indices]) + firstIdx, (Ts*)(ppOtherData[Indices]) + lastIdx,\n\t\t\t\t\t\t       TupleVecLeaf<Indices, Ts>::mpData), 0)...);\n\t\t\t\terase(begin() + newNumElements, end());\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid assign(const value_tuple* first, const value_tuple* last)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(first > last || first == nullptr || last == nullptr))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::assign from tuple array -- invalid ptrs\");\n#endif\n        size_type newNumElements = static_cast<size_type>(last - first);\n\t\tif (newNumElements > mNumCapacity)\n\t\t{\n\t\t\tthis_type temp(first, last, get_allocator());\n\t\t\tswap(temp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (newNumElements > mNumElements) // If n > mNumElements ...\n\t\t\t{\n\t\t\t\tsize_type oldNumElements = mNumElements;\n\t\t\t\t\n\t\t\t\tDoCopyFromTupleArray(begin(), begin() + oldNumElements, first);\n\t\t\t\tDoUninitializedCopyFromTupleArray(begin() + oldNumElements, begin() + newNumElements, first + oldNumElements);\n\t\t\t\tmNumElements = newNumElements;\n\t\t\t}\n\t\t\telse // else 0 <= n <= mNumElements\n\t\t\t{\n\t\t\t\tDoCopyFromTupleArray(begin(), begin() + newNumElements, first);\n\t\t\t\terase(begin() + newNumElements, end());\n\t\t\t}\n\t\t}\n\t}\n\n\treference_tuple push_back()\n\t{\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = oldNumElements + 1;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tDoGrow(oldNumElements, oldNumCapacity, newNumElements);\n\t\tswallow((detail::allocator_construct(get_allocator(), TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t\treturn back();\n\t}\n\n\tvoid push_back(const Ts&... args)\n\t{\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = oldNumElements + 1;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tDoGrow(oldNumElements, oldNumCapacity, newNumElements);\n\t\tswallow((detail::allocator_construct(get_allocator(), TupleVecLeaf<Indices, Ts>::mpData + oldNumElements, args), 0)...);\n\t}\n\n\tvoid push_back_uninitialized()\n\t{\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = oldNumElements + 1;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tDoGrow(oldNumElements, oldNumCapacity, newNumElements);\n\t}\n\t\n\treference_tuple emplace_back(Ts&&... args)\n\t{\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = oldNumElements + 1;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tDoGrow(oldNumElements, oldNumCapacity, newNumElements);\n\t\tswallow((detail::allocator_construct(get_allocator(), TupleVecLeaf<Indices, Ts>::mpData + oldNumElements, eastl::forward<Ts>(args)), 0)...);\n\t\treturn back();\n\t}\n\n\titerator emplace(const_iterator pos, Ts&&... args)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(validate_iterator(pos) == isf_none))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::emplace -- invalid iterator\");\n#endif\n\t\tsize_type firstIdx = pos - cbegin();\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = mNumElements + 1;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tif (newNumElements > oldNumCapacity || firstIdx != oldNumElements)\n\t\t{\n\t\t\tif (newNumElements > oldNumCapacity)\n\t\t\t{\n\t\t\t\tconst size_type newCapacity = eastl::max(GetNewCapacity(oldNumCapacity), newNumElements);\n\n\t\t\t\tvoid* ppNewLeaf[sizeof...(Ts)];\n\t\t\t\tpair<void*, size_type> allocation =\tTupleRecurser<Ts...>::template DoAllocate<allocator_type, 0, index_sequence_type, Ts...>(\n\t\t\t\t\t*this, ppNewLeaf, newCapacity, 0);\n\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\t0, firstIdx, (Ts*)ppNewLeaf[Indices]), 0)...);\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\tfirstIdx, oldNumElements, (Ts*)ppNewLeaf[Indices] + firstIdx + 1), 0)...);\n\t\t\t\tswallow(::new ((Ts*)ppNewLeaf[Indices] + firstIdx) Ts(eastl::forward<Ts>(args))...);\n\t\t\t\tswallow(TupleVecLeaf<Indices, Ts>::mpData = (Ts*)ppNewLeaf[Indices]...);\n\n\t\t\t\tEASTLFree(get_allocator(), mpData, internalDataSize());\n\t\t\t\tmpData = allocation.first;\n\t\t\t\tmNumCapacity = newCapacity;\n\t\t\t\tinternalDataSize() = allocation.second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoInsertValue(firstIdx, oldNumElements, eastl::forward<Ts>(args)), 0)...);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswallow(::new (TupleVecLeaf<Indices, Ts>::mpData + oldNumElements) Ts(eastl::forward<Ts>(args))...);\n\t\t}\n\t\treturn begin() + firstIdx;\n\t}\n\n\titerator insert(const_iterator pos, size_type n, const Ts&... args)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(validate_iterator(pos) == isf_none))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::insert -- invalid iterator\");\n#endif\n\t\tsize_type firstIdx = pos - cbegin();\n\t\tsize_type lastIdx = firstIdx + n;\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = mNumElements + n;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tif (newNumElements > oldNumCapacity || firstIdx != oldNumElements)\n\t\t{\n\t\t\tif (newNumElements > oldNumCapacity)\n\t\t\t{\n\t\t\t\tconst size_type newCapacity = eastl::max(GetNewCapacity(oldNumCapacity), newNumElements);\n\n\t\t\t\tvoid* ppNewLeaf[sizeof...(Ts)];\n\t\t\t\tpair<void*, size_type> allocation = TupleRecurser<Ts...>::template DoAllocate<allocator_type, 0, index_sequence_type, Ts...>(\n\t\t\t\t\t\t*this, ppNewLeaf, newCapacity, 0);\n\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\t0, firstIdx, (Ts*)ppNewLeaf[Indices]), 0)...);\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\tfirstIdx, oldNumElements, (Ts*)ppNewLeaf[Indices] + lastIdx), 0)...);\n\t\t\t\tswallow((eastl::uninitialized_fill((Ts*)ppNewLeaf[Indices] + firstIdx, (Ts*)ppNewLeaf[Indices] + lastIdx, args), 0)...);\n\t\t\t\tswallow(TupleVecLeaf<Indices, Ts>::mpData = (Ts*)ppNewLeaf[Indices]...);\n\t\t\n\t\t\t\tEASTLFree(get_allocator(), mpData, internalDataSize());\n\t\t\t\tmpData = allocation.first;\n\t\t\t\tmNumCapacity = newCapacity;\n\t\t\t\tinternalDataSize() = allocation.second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoInsertAndFill(firstIdx, n, oldNumElements, args), 0)...);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswallow((eastl::uninitialized_fill(TupleVecLeaf<Indices, Ts>::mpData + oldNumElements,\n\t\t\t\t\t                       TupleVecLeaf<Indices, Ts>::mpData + newNumElements, args), 0)...);\n\t\t}\n\t\treturn begin() + firstIdx;\n\t}\n\n\titerator insert(const_iterator pos, const_iterator first, const_iterator last)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(validate_iterator(pos) == isf_none))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::insert -- invalid iterator\");\n\t\tif (EASTL_UNLIKELY(!validate_iterator_pair(first, last)))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::insert -- invalid iterator pair\");\n#endif\n\t\tsize_type posIdx = pos - cbegin();\n\t\tsize_type firstIdx = first.mIndex;\n\t\tsize_type lastIdx = last.mIndex;\n\t\tsize_type numToInsert = last - first;\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = oldNumElements + numToInsert;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tconst void* ppOtherData[sizeof...(Ts)] = {first.mpData[Indices]...};\n\t\tif (newNumElements > oldNumCapacity || posIdx != oldNumElements)\n\t\t{\n\t\t\tif (newNumElements > oldNumCapacity)\n\t\t\t{\n\t\t\t\tconst size_type newCapacity = eastl::max(GetNewCapacity(oldNumCapacity), newNumElements);\n\n\t\t\t\tvoid* ppNewLeaf[sizeof...(Ts)];\n\t\t\t\tpair<void*, size_type> allocation = TupleRecurser<Ts...>::template DoAllocate<allocator_type, 0, index_sequence_type, Ts...>(\n\t\t\t\t\t\t*this, ppNewLeaf, newCapacity, 0);\n\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\t0, posIdx, (Ts*)ppNewLeaf[Indices]), 0)...);\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\tposIdx, oldNumElements, (Ts*)ppNewLeaf[Indices] + posIdx + numToInsert), 0)...);\n\t\t\t\tswallow((eastl::uninitialized_copy((Ts*)(ppOtherData[Indices]) + firstIdx,\n\t\t\t\t\t\t                       (Ts*)(ppOtherData[Indices]) + lastIdx,\n\t\t\t\t\t\t                       (Ts*)ppNewLeaf[Indices] + posIdx), 0)...);\n\t\t\t\tswallow(TupleVecLeaf<Indices, Ts>::mpData = (Ts*)ppNewLeaf[Indices]...);\n\t\t\t\t\n\t\t\t\tEASTLFree(get_allocator(), mpData, internalDataSize());\n\t\t\t\tmpData = allocation.first;\n\t\t\t\tmNumCapacity = newCapacity;\n\t\t\t\tinternalDataSize() = allocation.second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoInsertRange(\n\t\t\t\t\t(Ts*)(ppOtherData[Indices]) + firstIdx, (Ts*)(ppOtherData[Indices]) + lastIdx,\n\t\t\t\t\tTupleVecLeaf<Indices, Ts>::mpData + posIdx, oldNumElements), 0)...);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswallow((eastl::uninitialized_copy((Ts*)(ppOtherData[Indices]) + firstIdx,\n\t\t\t\t\t                       (Ts*)(ppOtherData[Indices]) + lastIdx,\n\t\t\t\t\t                       TupleVecLeaf<Indices, Ts>::mpData + posIdx), 0)...);\n\t\t}\n\t\treturn begin() + posIdx;\n\t}\n\n\titerator insert(const_iterator pos, const value_tuple* first, const value_tuple* last)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(validate_iterator(pos) == isf_none))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::insert -- invalid iterator\");\n\t\tif (EASTL_UNLIKELY(first > last || first == nullptr || last == nullptr))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::insert -- invalid source pointers\");\n#endif\n\t\tsize_type posIdx = pos - cbegin();\n\t\tsize_type numToInsert = static_cast<size_type>(last - first);\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = oldNumElements + numToInsert;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = newNumElements;\n\t\tif (newNumElements > oldNumCapacity || posIdx != oldNumElements)\n\t\t{\n\t\t\tif (newNumElements > oldNumCapacity)\n\t\t\t{\n\t\t\t\tconst size_type newCapacity = eastl::max(GetNewCapacity(oldNumCapacity), newNumElements);\n\n\t\t\t\tvoid* ppNewLeaf[sizeof...(Ts)];\n\t\t\t\tpair<void*, size_type> allocation = TupleRecurser<Ts...>::template DoAllocate<allocator_type, 0, index_sequence_type, Ts...>(\n\t\t\t\t\t*this, ppNewLeaf, newCapacity, 0);\n\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\t0, posIdx, (Ts*)ppNewLeaf[Indices]), 0)...);\n\t\t\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(\n\t\t\t\t\tposIdx, oldNumElements, (Ts*)ppNewLeaf[Indices] + posIdx + numToInsert), 0)...);\n\t\t\t\t\n\t\t\t\tswallow(TupleVecLeaf<Indices, Ts>::mpData = (Ts*)ppNewLeaf[Indices]...);\n\n\t\t\t\t// Do this after mpData is updated so that we can use new iterators\n\t\t\t\tDoUninitializedCopyFromTupleArray(begin() + posIdx, begin() + posIdx + numToInsert, first);\n\n\t\t\t\tEASTLFree(get_allocator(), mpData, internalDataSize());\n\t\t\t\tmpData = allocation.first;\n\t\t\t\tmNumCapacity = newCapacity;\n\t\t\t\tinternalDataSize() = allocation.second;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconst size_type nExtra = oldNumElements - posIdx;\n\t\t\t\tvoid* ppDataEnd[sizeof...(Ts)] = { (void*)(TupleVecLeaf<Indices, Ts>::mpData + oldNumElements)... };\n\t\t\t\tvoid* ppDataBegin[sizeof...(Ts)] = { (void*)(TupleVecLeaf<Indices, Ts>::mpData + posIdx)... };\n\t\t\t\tif (numToInsert < nExtra) // If the inserted values are entirely within initialized memory (i.e. are before mpEnd)...\n\t\t\t\t{\n\t\t\t\t\tswallow((eastl::uninitialized_move((Ts*)ppDataEnd[Indices] - numToInsert,\n\t\t\t\t\t\t(Ts*)ppDataEnd[Indices], (Ts*)ppDataEnd[Indices]), 0)...);\n\t\t\t\t\t// We need move_backward because of potential overlap issues.\n\t\t\t\t\tswallow((eastl::move_backward((Ts*)ppDataBegin[Indices],\n\t\t\t\t\t\t(Ts*)ppDataEnd[Indices] - numToInsert, (Ts*)ppDataEnd[Indices]), 0)...); \n\t\t\t\t\t\n\t\t\t\t\tDoCopyFromTupleArray(pos, pos + numToInsert, first);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsize_type numToInitialize = numToInsert - nExtra;\n\t\t\t\t\tswallow((eastl::uninitialized_move((Ts*)ppDataBegin[Indices],\n\t\t\t\t\t\t(Ts*)ppDataEnd[Indices], (Ts*)ppDataEnd[Indices] + numToInitialize), 0)...);\n\t\t\t\t\t\n\t\t\t\t\tDoCopyFromTupleArray(pos, begin() + oldNumElements, first);\n\t\t\t\t\tDoUninitializedCopyFromTupleArray(begin() + oldNumElements, pos + numToInsert, first + nExtra);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDoUninitializedCopyFromTupleArray(pos, pos + numToInsert, first);\n\t\t}\n\t\treturn begin() + posIdx;\n\t}\n\n\titerator erase(const_iterator first, const_iterator last)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(validate_iterator(first) == isf_none || validate_iterator(last) == isf_none))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::erase -- invalid iterator\");\n\t\tif (EASTL_UNLIKELY(!validate_iterator_pair(first, last)))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::erase -- invalid iterator pair\");\n#endif\n\t\tif (first != last)\n\t\t{\n\t\t\tsize_type firstIdx = first - cbegin();\n\t\t\tsize_type lastIdx = last - cbegin();\n\t\t\tsize_type oldNumElements = mNumElements;\n\t\t\tsize_type newNumElements = oldNumElements - (lastIdx - firstIdx);\n\t\t\tmNumElements = newNumElements;\n\t\t\tswallow((eastl::move(TupleVecLeaf<Indices, Ts>::mpData + lastIdx,\n\t\t\t\t\t       TupleVecLeaf<Indices, Ts>::mpData + oldNumElements,\n\t\t\t\t\t       TupleVecLeaf<Indices, Ts>::mpData + firstIdx), 0)...);\n\t\t\tswallow((eastl::destruct(TupleVecLeaf<Indices, Ts>::mpData + newNumElements,\n\t\t\t\t\t           TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t\t}\n\t\treturn begin() + first.mIndex;\n\t}\n\t\n\titerator erase_unsorted(const_iterator pos)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(validate_iterator(pos) == isf_none))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::erase_unsorted -- invalid iterator\");\n#endif\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type newNumElements = oldNumElements - 1;\n\t\tmNumElements = newNumElements;\n\t\tswallow((eastl::move(TupleVecLeaf<Indices, Ts>::mpData + newNumElements,\n\t\t\t\t       TupleVecLeaf<Indices, Ts>::mpData + oldNumElements,\n\t\t\t\t       TupleVecLeaf<Indices, Ts>::mpData + (pos - begin())), 0)...);\n\t\tswallow((eastl::destruct(TupleVecLeaf<Indices, Ts>::mpData + newNumElements,\n\t\t\t\t           TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t\treturn begin() + pos.mIndex;\n\t}\n\n\tvoid resize(size_type n)\n\t{\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = n;\n\t\tif (n > oldNumElements)\n\t\t{\n\t\t\tif (n > oldNumCapacity)\n\t\t\t{\n\t\t\t\tDoReallocate(oldNumElements, eastl::max<size_type>(GetNewCapacity(oldNumCapacity), n));\n\t\t\t}\n\t\t\tswallow((eastl::uninitialized_value_construct_n(TupleVecLeaf<Indices, Ts>::mpData + oldNumElements, n - oldNumElements), 0)...);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswallow((eastl::destruct(TupleVecLeaf<Indices, Ts>::mpData + n,\n\t\t\t\t\t           TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t\t}\n\t}\n\n\tvoid resize(size_type n, const Ts&... args)\n\t{\n\t\tsize_type oldNumElements = mNumElements;\n\t\tsize_type oldNumCapacity = mNumCapacity;\n\t\tmNumElements = n;\n\t\tif (n > oldNumElements)\n\t\t{\n\t\t\tif (n > oldNumCapacity)\n\t\t\t{\n\t\t\t\tDoReallocate(oldNumElements, eastl::max<size_type>(GetNewCapacity(oldNumCapacity), n));\n\t\t\t} \n\t\t\tswallow((eastl::uninitialized_fill(TupleVecLeaf<Indices, Ts>::mpData + oldNumElements,\n\t\t\t\t\t                       TupleVecLeaf<Indices, Ts>::mpData + n, args), 0)...);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswallow((eastl::destruct(TupleVecLeaf<Indices, Ts>::mpData + n,\n\t\t\t\t\t           TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t\t}\n\t}\n\n\tvoid reserve(size_type n)\n\t{\n\t\tDoConditionalReallocate(mNumElements, mNumCapacity, n);\n\t}\n\n\tvoid shrink_to_fit()\n\t{\n\t\tthis_type temp(move_iterator<iterator>(begin()), move_iterator<iterator>(end()), get_allocator());\n\t\tswap(temp);\n\t}\n\n\tvoid clear() EA_NOEXCEPT\n\t{\n\t\tsize_type oldNumElements = mNumElements;\n\t\tmNumElements = 0;\n\t\tswallow((eastl::destruct(TupleVecLeaf<Indices, Ts>::mpData, TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t}\n\n\tvoid pop_back()\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(mNumElements <= 0))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::pop_back -- container is empty\");\n#endif\n\t\tsize_type oldNumElements = mNumElements--;\n\t\tswallow((eastl::destruct(TupleVecLeaf<Indices, Ts>::mpData + oldNumElements - 1,\n\t\t\t\t           TupleVecLeaf<Indices, Ts>::mpData + oldNumElements), 0)...);\n\t}\n\n\tvoid swap(this_type& x)\n\t{\n\t\tswallow((eastl::swap(TupleVecLeaf<Indices, Ts>::mpData, x.TupleVecLeaf<Indices, Ts>::mpData), 0)...);\n\t\teastl::swap(mpData, x.mpData);\n\t\teastl::swap(mNumElements, x.mNumElements);\n\t\teastl::swap(mNumCapacity, x.mNumCapacity);\n\t\teastl::swap(get_allocator(), x.get_allocator());\n\t\teastl::swap(internalDataSize(), x.internalDataSize());\n\t}\n\n\tvoid assign(size_type n, const_reference_tuple tup) { assign(n, eastl::get<Indices>(tup)...); }\n\tvoid assign(std::initializer_list<value_tuple> iList) { assign(iList.begin(), iList.end()); }\n\n\tvoid push_back(Ts&&... args) { emplace_back(eastl::forward<Ts>(args)...); }\n\tvoid push_back(const_reference_tuple tup) { push_back(eastl::get<Indices>(tup)...); }\n\tvoid push_back(rvalue_tuple tup) { emplace_back(eastl::forward<Ts>(eastl::get<Indices>(tup))...); }\n\n\tvoid emplace_back(rvalue_tuple tup) { emplace_back(eastl::forward<Ts>(eastl::get<Indices>(tup))...); }\n\tvoid emplace(const_iterator pos, rvalue_tuple tup) { emplace(pos, eastl::forward<Ts>(eastl::get<Indices>(tup))...); }\n\n\titerator insert(const_iterator pos, const Ts&... args) { return insert(pos, 1, args...); }\n\titerator insert(const_iterator pos, Ts&&... args) { return emplace(pos, eastl::forward<Ts>(args)...); }\n\titerator insert(const_iterator pos, rvalue_tuple tup) { return emplace(pos, eastl::forward<Ts>(eastl::get<Indices>(tup))...); }\n\titerator insert(const_iterator pos, const_reference_tuple tup) { return insert(pos, eastl::get<Indices>(tup)...); }\n\titerator insert(const_iterator pos, size_type n, const_reference_tuple tup) { return insert(pos, n, eastl::get<Indices>(tup)...); }\n\titerator insert(const_iterator pos, std::initializer_list<value_tuple> iList) { return insert(pos, iList.begin(), iList.end()); }\n\n\titerator erase(const_iterator pos) { return erase(pos, pos + 1); }\n\treverse_iterator erase(const_reverse_iterator pos) { return reverse_iterator(erase((pos + 1).base(), (pos).base())); }\n\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last) { return reverse_iterator(erase((last).base(), (first).base())); }\n\treverse_iterator erase_unsorted(const_reverse_iterator pos) { return reverse_iterator(erase_unsorted((pos + 1).base())); }\n\n\tvoid resize(size_type n, const_reference_tuple tup) { resize(n, eastl::get<Indices>(tup)...); }\n\n\tbool empty() const EA_NOEXCEPT { return mNumElements == 0; }\n\tsize_type size() const EA_NOEXCEPT { return mNumElements; }\n\tsize_type capacity() const EA_NOEXCEPT { return mNumCapacity; }\n\n\titerator begin() EA_NOEXCEPT { return iterator(this, 0); }\n\tconst_iterator begin() const EA_NOEXCEPT { return const_iterator((const_this_type*)(this), 0); }\n\tconst_iterator cbegin() const EA_NOEXCEPT { return const_iterator((const_this_type*)(this), 0); }\n\n\titerator end() EA_NOEXCEPT { return iterator(this, size()); }\n\tconst_iterator end() const EA_NOEXCEPT { return const_iterator((const_this_type*)(this), size()); }\n\tconst_iterator cend() const EA_NOEXCEPT { return const_iterator((const_this_type*)(this), size()); }\n\n\treverse_iterator rbegin() EA_NOEXCEPT { return reverse_iterator(end()); }\n\tconst_reverse_iterator rbegin() const  EA_NOEXCEPT { return const_reverse_iterator(end()); }\n\tconst_reverse_iterator crbegin() const EA_NOEXCEPT { return const_reverse_iterator(end()); }\n\t\n\treverse_iterator rend() EA_NOEXCEPT { return reverse_iterator(begin()); }\n\tconst_reverse_iterator rend() const EA_NOEXCEPT { return const_reverse_iterator(begin()); }\n\tconst_reverse_iterator crend() const EA_NOEXCEPT { return const_reverse_iterator(begin()); }\n\n\tptr_tuple data() EA_NOEXCEPT { return ptr_tuple(TupleVecLeaf<Indices, Ts>::mpData...); }\n\tconst_ptr_tuple data() const EA_NOEXCEPT { return const_ptr_tuple(TupleVecLeaf<Indices, Ts>::mpData...); }\n\n\treference_tuple at(size_type n) \n\t{ \n#if EASTL_EXCEPTIONS_ENABLED\n\t\tif (EASTL_UNLIKELY(n >= mNumElements))\n\t\t\tthrow std::out_of_range(\"tuple_vector::at -- out of range\");\n#elif EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(n >= mNumElements))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::at -- out of range\");\n#endif\n\t\treturn reference_tuple(*(TupleVecLeaf<Indices, Ts>::mpData + n)...); \n\t}\n\n\tconst_reference_tuple at(size_type n) const\n\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\tif (EASTL_UNLIKELY(n >= mNumElements))\n\t\t\tthrow std::out_of_range(\"tuple_vector::at -- out of range\");\n#elif EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(n >= mNumElements))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::at -- out of range\");\n#endif\n\t\treturn const_reference_tuple(*(TupleVecLeaf<Indices, Ts>::mpData + n)...); \n\t}\n\t\n\treference_tuple operator[](size_type n) { return at(n); }\n\tconst_reference_tuple operator[](size_type n) const { return at(n); }\n\t\n\treference_tuple front() \n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container.\n\t\t\t\tEASTL_FAIL_MSG(\"tuple_vector::front -- empty vector\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn at(0); \n\t}\n\n\tconst_reference_tuple front() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container.\n\t\t\t\tEASTL_FAIL_MSG(\"tuple_vector::front -- empty vector\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn at(0); \n\t}\n\t\n\treference_tuple back() \n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container.\n\t\t\t\tEASTL_FAIL_MSG(\"tuple_vector::back -- empty vector\");\n\t\t#endif\n\n\t\treturn at(size() - 1); \n\t}\n\n\tconst_reference_tuple back() const \n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container.\n\t\t\t\tEASTL_FAIL_MSG(\"tuple_vector::back -- empty vector\");\n\t\t#endif\n\n\t\treturn at(size() - 1); \n\t}\n\n\ttemplate <size_type I>\n\ttuplevec_element_t<I, Ts...>* get() \n\t{\n\t\ttypedef tuplevec_element_t<I, Ts...> Element;\n\t\treturn TupleVecLeaf<I, Element>::mpData;\n\t}\n\ttemplate <size_type I>\n\tconst tuplevec_element_t<I, Ts...>* get() const\n\t{\n\t\ttypedef tuplevec_element_t<I, Ts...> Element;\n\t\treturn TupleVecLeaf<I, Element>::mpData;\n\t}\n\n\ttemplate <typename T>\n\tT* get() \n\t{ \n\t\ttypedef tuplevec_index<T, TupleTypes<Ts...>> Index;\n\t\treturn TupleVecLeaf<Index::index, T>::mpData;\n\t}\n\ttemplate <typename T>\n\tconst T* get() const\n\t{\n\t\ttypedef tuplevec_index<T, TupleTypes<Ts...>> Index;\n\t\treturn TupleVecLeaf<Index::index, T>::mpData;\n\t}\n\n\tthis_type& operator=(const this_type& other)\n\t{\n\t\tif (this != &other)\n\t\t{\n\t\t\tclear();\n\t\t\tassign(other.begin(), other.end());\n\t\t}\n\t\treturn *this;\n\t}\n\n\tthis_type& operator=(this_type&& other)\n\t{\n\t\tif (this != &other)\n\t\t{\n\t\t\tswap(other);\n\t\t}\n\t\treturn *this;\n\t}\n\n\tthis_type& operator=(std::initializer_list<value_tuple> iList) \n\t{\n\t\tassign(iList.begin(), iList.end());\n\t\treturn *this; \n\t}\n\n\tbool validate() const EA_NOEXCEPT\n\t{\n\t\tif (mNumElements > mNumCapacity)\n\t\t\treturn false;\n\t\tif (!(variadicAnd(mpData <= TupleVecLeaf<Indices, Ts>::mpData...)))\n\t\t\treturn false;\n\t\tvoid* pDataEnd = (void*)((uintptr_t)mpData + internalDataSize());\n\t\tif (!(variadicAnd(pDataEnd >= TupleVecLeaf<Indices, Ts>::mpData...)))\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tint validate_iterator(const_iterator iter) const EA_NOEXCEPT\n\t{\n\t\tif (!(variadicAnd(iter.mpData[Indices] == TupleVecLeaf<Indices, Ts>::mpData...)))\n\t\t\treturn isf_none;\n\t\tif (iter.mIndex < mNumElements)\n\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\tif (iter.mIndex <= mNumElements)\n\t\t\treturn (isf_valid | isf_current);\n\t\treturn isf_none;\n\t}\n\n\tstatic bool validate_iterator_pair(const_iterator first, const_iterator last) EA_NOEXCEPT\n\t{\n\t\treturn (first.mIndex <= last.mIndex) && variadicAnd(first.mpData[Indices] == last.mpData[Indices]...);\n\t}\n\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // 'unwrap_iterator': was declared deprecated\n\t\n\ttemplate <typename Iterator, typename = typename enable_if<is_iterator_wrapper<Iterator>::value, bool>::type>\n\tEASTL_REMOVE_AT_2024_SEPT int validate_iterator(Iterator iter) const EA_NOEXCEPT { return validate_iterator(unwrap_iterator(iter)); }\n\n\ttemplate <typename Iterator, typename = typename enable_if<is_iterator_wrapper<Iterator>::value, bool>::type>\n\tEASTL_REMOVE_AT_2024_SEPT static bool validate_iterator_pair(Iterator first, Iterator last) EA_NOEXCEPT { return validate_iterator_pair(unwrap_iterator(first), unwrap_iterator(last)); }\n\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\tallocator_type& get_allocator() EA_NOEXCEPT { return mDataSizeAndAllocator.second(); }\n\tconst allocator_type& get_allocator() const EA_NOEXCEPT { return mDataSizeAndAllocator.second(); }\n\n\tvoid set_allocator(const allocator_type& alloc)\n\t{\n\t\tif(mNumCapacity > 0 && mDataSizeAndAllocator.second() != alloc)\n\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"tuple_vector::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\tmDataSizeAndAllocator.second() = alloc;\n\t}\n\nprotected:\n\n\tvoid* mpData = nullptr;\n\tsize_type mNumElements = 0;\n\tsize_type mNumCapacity = 0;\n\n\tcompressed_pair<size_type, allocator_type> mDataSizeAndAllocator;\n\n\tsize_type& internalDataSize() EA_NOEXCEPT { return mDataSizeAndAllocator.first(); }\n\tsize_type const& internalDataSize() const EA_NOEXCEPT { return mDataSizeAndAllocator.first(); }\n\n\tfriend struct TupleRecurser<>;\n\ttemplate<typename... Us>\n\tfriend struct TupleRecurser;\n\n\ttemplate <typename MoveIterBase>\n\tvoid DoInitFromIterator(move_iterator<MoveIterBase> begin, move_iterator<MoveIterBase> end)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(!validate_iterator_pair(begin.base(), end.base())))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::erase -- invalid iterator pair\");\n#endif\n\t\tsize_type newNumElements = (size_type)(end - begin);\n\t\tconst void* ppOtherData[sizeof...(Ts)] = { begin.base().mpData[Indices]... };\n\t\tsize_type beginIdx = begin.base().mIndex;\n\t\tsize_type endIdx = end.base().mIndex;\n\t\tDoConditionalReallocate(0, mNumCapacity, newNumElements);\n\t\tmNumElements = newNumElements;\n\t\tswallow((eastl::uninitialized_move(eastl::move_iterator<Ts*>((Ts*)(ppOtherData[Indices]) + beginIdx),\n\t\t\t\t                       eastl::move_iterator<Ts*>((Ts*)(ppOtherData[Indices]) + endIdx),\n\t\t\t\t                       TupleVecLeaf<Indices, Ts>::mpData), 0)...);\n\t}\n\n\tvoid DoInitFromIterator(const_iterator begin, const_iterator end)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(!validate_iterator_pair(begin, end)))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::erase -- invalid iterator pair\");\n#endif\n\t\tsize_type newNumElements = (size_type)(end - begin);\n\t\tconst void* ppOtherData[sizeof...(Ts)] = { begin.mpData[Indices]... };\n\t\tsize_type beginIdx = begin.mIndex;\n\t\tsize_type endIdx = end.mIndex;\n\t\tDoConditionalReallocate(0, mNumCapacity, newNumElements);\n\t\tmNumElements = newNumElements;\n\t\tswallow((eastl::uninitialized_copy((Ts*)(ppOtherData[Indices]) + beginIdx,\n\t\t\t\t                       (Ts*)(ppOtherData[Indices]) + endIdx,\n\t\t\t\t                       TupleVecLeaf<Indices, Ts>::mpData), 0)...);\n\t}\n\n\tvoid DoInitFillTuple(size_type n, const_reference_tuple tup) { DoInitFillArgs(n, eastl::get<Indices>(tup)...); }\n\n\tvoid DoInitFillArgs(size_type n, const Ts&... args)\n\t{\n\t\tDoConditionalReallocate(0, mNumCapacity, n);\n\t\tmNumElements = n;\n\t\tswallow((eastl::uninitialized_fill(TupleVecLeaf<Indices, Ts>::mpData, TupleVecLeaf<Indices, Ts>::mpData + n, args), 0)...);\n\t}\n\n\tvoid DoInitDefaultFill(size_type n)\n\t{\n\t\tDoConditionalReallocate(0, mNumCapacity, n);\n\t\tmNumElements = n;\n\t\tswallow((eastl::uninitialized_value_construct_n(TupleVecLeaf<Indices, Ts>::mpData, n), 0)...);\n\t}\n\n\tvoid DoInitFromTupleArray(const value_tuple* first, const value_tuple* last)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(first > last || first == nullptr || last == nullptr))\n\t\t\tEASTL_FAIL_MSG(\"tuple_vector::ctor from tuple array -- invalid ptrs\");\n#endif\n\t\tsize_type newNumElements = static_cast<size_type>(last - first);\n\t\tDoConditionalReallocate(0, mNumCapacity, newNumElements);\n\t\tmNumElements = newNumElements;\n\t\tDoUninitializedCopyFromTupleArray(begin(), end(), first);\n\t}\n\n\tvoid DoCopyFromTupleArray(iterator destPos, iterator destEnd, const value_tuple* srcTuple)\n\t{\n\t\t// assign to constructed region\n\t\twhile (destPos < destEnd)\n\t\t{\n\t\t\t*destPos = *srcTuple;\n\t\t\t++destPos;\n\t\t\t++srcTuple;\n\t\t}\n\t}\n\n\tvoid DoUninitializedCopyFromTupleArray(iterator destPos, iterator destEnd, const value_tuple* srcTuple)\n\t{\n\t\t// placement-new/copy-ctor to unconstructed regions\n\t\twhile (destPos < destEnd)\n\t\t{\n\t\t\tswallow((detail::allocator_construct(get_allocator(), eastl::get<Indices>(destPos.MakePointer()), eastl::get<Indices>(*srcTuple)), 0)...);\n\t\t\t++destPos;\n\t\t\t++srcTuple;\n\t\t}\n\t}\n\n\t// Try to grow the size of the container \"naturally\" given the number of elements being used\n\tvoid DoGrow(size_type oldNumElements, size_type oldNumCapacity, size_type requiredCapacity)\n\t{\n\t\tif (requiredCapacity > oldNumCapacity)\n\t\t\tDoReallocate(oldNumElements, GetNewCapacity(requiredCapacity));\n\t}\n\n\t// Reallocate to the newCapacity (IFF it's actually larger, though)\n\tvoid DoConditionalReallocate(size_type oldNumElements, size_type oldNumCapacity, size_type requiredCapacity)\n\t{\n\t\tif (requiredCapacity > oldNumCapacity)\n\t\t\tDoReallocate(oldNumElements, requiredCapacity);\n\t}\n\n\tvoid DoReallocate(size_type oldNumElements, size_type requiredCapacity)\n\t{\n\t\tvoid* ppNewLeaf[sizeof...(Ts)];\n\t\tpair<void*, size_type> allocation = TupleRecurser<Ts...>::template DoAllocate<allocator_type, 0, index_sequence_type, Ts...>(\n\t\t\t*this, ppNewLeaf, requiredCapacity, 0);\n\t\tswallow((TupleVecLeaf<Indices, Ts>::DoUninitializedMoveAndDestruct(0, oldNumElements, (Ts*)ppNewLeaf[Indices]), 0)...);\n\t\tswallow(TupleVecLeaf<Indices, Ts>::mpData = (Ts*)ppNewLeaf[Indices]...);\n\n\t\tEASTLFree(get_allocator(), mpData, internalDataSize());\n\t\tmpData = allocation.first;\n\t\tmNumCapacity = requiredCapacity;\n\t\tinternalDataSize() = allocation.second;\n\t}\n\n\tsize_type GetNewCapacity(size_type oldNumCapacity)\n\t{\n\t\treturn (oldNumCapacity > 0) ? (2 * oldNumCapacity) : 1;\n\t}\n};\n\n}  // namespace TupleVecInternal\n\n// Move_iterator specialization for TupleVecIter.\n// An rvalue reference of a move_iterator would normaly be \"tuple<Ts...> &&\" whereas\n// what we actually want is \"tuple<Ts&&...>\". This specialization gives us that.\ntemplate <eastl_size_t... Indices, typename... Ts>\nclass move_iterator<TupleVecInternal::TupleVecIter<index_sequence<Indices...>, Ts...>>\n{\npublic:\n\ttypedef TupleVecInternal::TupleVecIter<index_sequence<Indices...>, Ts...> iterator_type;\n\ttypedef iterator_traits<iterator_type> traits_type;\n\ttypedef typename traits_type::iterator_category iterator_category;\n\ttypedef typename traits_type::value_type value_type;\n\ttypedef typename traits_type::difference_type difference_type;\n\ttypedef typename traits_type::pointer pointer;\n\ttypedef tuple<Ts&&...> reference;\n\ttypedef move_iterator<iterator_type> this_type;\n\nprotected:\n\titerator_type mIterator;\n\npublic:\n\tmove_iterator() : mIterator() {}\n\texplicit move_iterator(iterator_type mi) : mIterator(mi) {}\n\n\ttemplate <typename U>\n\tmove_iterator(const move_iterator<U>& mi) : mIterator(mi.base()) {}\n\n\titerator_type base() const { return mIterator; }\n\treference operator*() const { return eastl::move(MakeReference()); }\n\tpointer operator->() const { return mIterator; }\n\n\tthis_type& operator++() { ++mIterator; return *this; }\n\tthis_type operator++(int) {\n\t\tthis_type tempMoveIterator = *this;\n\t\t++mIterator;\n\t\treturn tempMoveIterator;\n\t}\n\n\tthis_type& operator--() { --mIterator; return *this; }\n\tthis_type operator--(int)\n\t{\n\t\tthis_type tempMoveIterator = *this;\n\t\t--mIterator;\n\t\treturn tempMoveIterator;\n\t}\n\n\tthis_type operator+(difference_type n) const { return move_iterator(mIterator + n); }\n\tthis_type& operator+=(difference_type n)\n\t{\n\t\tmIterator += n;\n\t\treturn *this;\n\t}\n\n\tthis_type operator-(difference_type n) const { return move_iterator(mIterator - n); }\n\tthis_type& operator-=(difference_type n)\n\t{\n\t\tmIterator -= n;\n\t\treturn *this;\n\t}\n\n\tdifference_type operator-(const this_type& rhs) const { return mIterator - rhs.mIterator; }\n\tbool operator<(const this_type& rhs) const { return mIterator < rhs.mIterator; }\n\tbool operator>(const this_type& rhs) const { return mIterator > rhs.mIterator; }\n\tbool operator>=(const this_type& rhs) const { return mIterator >= rhs.mIterator; }\n\tbool operator<=(const this_type& rhs) const { return mIterator <= rhs.mIterator; }\n\n\treference operator[](difference_type n) const { return *(*this + n); }\n\nprivate:\n\treference MakeReference() const\n\t{\n\t\treturn reference(eastl::move(((Ts*)mIterator.mpData[Indices])[mIterator.mIndex])...);\n\t}\n\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // 'is_iterator_wrapper': was declared deprecated\n\t// Unwrapping interface, not part of the public API.\n\tEASTL_REMOVE_AT_2024_SEPT iterator_type unwrap() const { return mIterator; }\n\n\t// The unwrapper helpers need access to unwrap().\n\tfriend is_iterator_wrapper_helper<this_type, true>;\n\tfriend is_iterator_wrapper<this_type>;\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n};\n\ntemplate <typename AllocatorA, typename AllocatorB, typename Indices, typename... Ts>\ninline bool operator==(const TupleVecInternal::TupleVecImpl<AllocatorA, Indices, Ts...>& a,\n\t\t\t\t\t   const TupleVecInternal::TupleVecImpl<AllocatorB, Indices, Ts...>& b)\n{\n\treturn ((a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin()));\n}\n\ntemplate <typename AllocatorA, typename AllocatorB, typename Indices, typename... Ts>\ninline bool operator!=(const TupleVecInternal::TupleVecImpl<AllocatorA, Indices, Ts...>& a,\n\t\t\t\t\t   const TupleVecInternal::TupleVecImpl<AllocatorB, Indices, Ts...>& b)\n{\n\treturn ((a.size() != b.size()) || !eastl::equal(a.begin(), a.end(), b.begin()));\n}\n\ntemplate <typename AllocatorA, typename AllocatorB, typename Indices, typename... Ts>\ninline bool operator<(const TupleVecInternal::TupleVecImpl<AllocatorA, Indices, Ts...>& a,\n\t\t\t\t\t  const TupleVecInternal::TupleVecImpl<AllocatorB, Indices, Ts...>& b)\n{\n\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n}\n\ntemplate <typename AllocatorA, typename AllocatorB, typename Indices, typename... Ts>\ninline bool operator>(const TupleVecInternal::TupleVecImpl<AllocatorA, Indices, Ts...>& a,\n\t\t\t\t\t  const TupleVecInternal::TupleVecImpl<AllocatorB, Indices, Ts...>& b)\n{\n\treturn b < a;\n}\n\ntemplate <typename AllocatorA, typename AllocatorB, typename Indices, typename... Ts>\ninline bool operator<=(const TupleVecInternal::TupleVecImpl<AllocatorA, Indices, Ts...>& a,\n\t\t\t\t\t   const TupleVecInternal::TupleVecImpl<AllocatorB, Indices, Ts...>& b)\n{\n\treturn !(b < a);\n}\n\ntemplate <typename AllocatorA, typename AllocatorB, typename Indices, typename... Ts>\ninline bool operator>=(const TupleVecInternal::TupleVecImpl<AllocatorA, Indices, Ts...>& a,\n\t\t\t\t\t   const TupleVecInternal::TupleVecImpl<AllocatorB, Indices, Ts...>& b)\n{\n\treturn !(a < b);\n}\n\ntemplate <typename AllocatorA, typename AllocatorB, typename Indices, typename... Ts>\ninline void swap(TupleVecInternal::TupleVecImpl<AllocatorA, Indices, Ts...>& a,\n\t\t\t\tTupleVecInternal::TupleVecImpl<AllocatorB, Indices, Ts...>& b)\n{\n\ta.swap(b);\n}\n\n// A customization of swap is made for r-values of tuples-of-references - \n// normally, swapping rvalues doesn't make sense, but in this case, we do want to \n// swap the contents of what the tuple-of-references are referring to\n//\n// This is required due to TupleVecIter returning a value-type for its dereferencing,\n// as opposed to an actual real reference of some sort\ntemplate<typename... Ts>\ninline\ntypename enable_if<conjunction<is_swappable<Ts>...>::value>::type\nswap(tuple<Ts&...>&& a, tuple<Ts&...>&& b)\n{\n\ta.swap(b);\n}\n\ntemplate<typename... Ts>\ninline\ntypename enable_if<!conjunction<is_swappable<Ts>...>::value>::type\nswap(tuple<Ts&...>&& a, tuple<Ts&...>&& b) = delete;\n\n\n// External interface of tuple_vector\ntemplate <typename... Ts>\nclass tuple_vector : public TupleVecInternal::TupleVecImpl<EASTLAllocatorType, make_index_sequence<sizeof...(Ts)>, Ts...>\n{\n\ttypedef tuple_vector<Ts...> this_type;\n\ttypedef TupleVecInternal::TupleVecImpl<EASTLAllocatorType, make_index_sequence<sizeof...(Ts)>, Ts...> base_type;\n\tusing base_type::base_type;\n\npublic:\n\tthis_type& operator=(std::initializer_list<typename base_type::value_tuple> iList) \n\t{\n\t\tbase_type::operator=(iList);\n\t\treturn *this;\n\t}\n};\n\n// Variant of tuple_vector that allows a user-defined allocator type (can't mix default template params with variadics)\ntemplate <typename AllocatorType, typename... Ts>\nclass tuple_vector_alloc\n\t: public TupleVecInternal::TupleVecImpl<AllocatorType, make_index_sequence<sizeof...(Ts)>, Ts...>\n{\n\ttypedef tuple_vector_alloc<AllocatorType, Ts...> this_type;\n\ttypedef TupleVecInternal::TupleVecImpl<AllocatorType, make_index_sequence<sizeof...(Ts)>, Ts...> base_type;\n\tusing base_type::base_type;\n\npublic:\n\n\tthis_type& operator=(std::initializer_list<typename base_type::value_tuple> iList)\n\t{\n\t\tbase_type::operator=(iList);\n\t\treturn *this;\n\t}\n};\n\n}  // namespace eastl\n\nEA_RESTORE_VC_WARNING()\nEA_RESTORE_VC_WARNING()\nEA_RESTORE_VC_WARNING()\nEA_RESTORE_VC_WARNING()\n\n#endif  // EASTL_TUPLEVECTOR_H\n"
  },
  {
    "path": "include/EASTL/chrono.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the eastl::chrono specification which is part of the\n// standard STL date and time library.  eastl::chrono implements all the\n// mechanisms required to capture and manipulate times retrieved from the\n// provided clocks.  It implements the all of the features to allow type safe\n// durations to be used in code.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_CHRONO_H\n#define EASTL_CHRONO_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once \n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/numeric_limits.h>\n#include <EASTL/ratio.h>\n\n\n// TODO:  move to platform specific cpp or header file\n#if  defined EA_PLATFORM_MICROSOFT\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\n\t#ifndef WIN32_LEAN_AND_MEAN\n\t\t#define WIN32_LEAN_AND_MEAN\n\t#endif\n\n\t#undef NOMINMAX\n\t#define NOMINMAX\n\n\t#include <Windows.h>\n\n\t#ifdef min\n\t\t#undef min\n\t#endif\n\t#ifdef max\n\t\t#undef max\n\t#endif\n\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\n#if defined(EA_PLATFORM_MICROSOFT) && !defined(EA_PLATFORM_MINGW)\n\t// Nothing to do\n#elif defined(EA_PLATFORM_SONY)\n\t#include <Dinkum/threads/xtimec.h>\n\t#include <kernel.h>\n#elif defined(EA_PLATFORM_APPLE)\n\t#include <mach/mach_time.h>\n#elif defined(EA_PLATFORM_POSIX) || defined(EA_PLATFORM_MINGW) || defined(EA_PLATFORM_ANDROID) \n\t// Posix means Linux, Unix, and Macintosh OSX, among others (including Linux-based mobile platforms).\n\t#if defined(EA_PLATFORM_MINGW)\n\t\t#include <pthread_time.h>\n\t#endif\n\t#include <time.h>\n\t#if (defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC))\n\t\t#include <errno.h>\n\t#else\n\t\t#include <sys/time.h>\n\t\t#include <unistd.h>\n\t#endif\n#endif\n\n\nnamespace eastl\n{\nnamespace chrono\n{\n\t///////////////////////////////////////////////////////////////////////////////\n\t// treat_as_floating_point\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <class Rep>\n\tstruct treat_as_floating_point : is_floating_point<Rep> {};\n\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.4, duration_values\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <class Rep>\n\tstruct duration_values\n\t{\n\tpublic:\n\t\tEASTL_FORCE_INLINE static EA_CONSTEXPR Rep zero() { return Rep(0); }\n\t\tEASTL_FORCE_INLINE static EA_CONSTEXPR Rep max()  { return eastl::numeric_limits<Rep>::max(); }\n\t\tEASTL_FORCE_INLINE static EA_CONSTEXPR Rep min()  { return eastl::numeric_limits<Rep>::lowest(); }\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// duration fwd_decl\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename Rep, typename Period = ratio<1>>\n\tclass duration;\n\n\n\tnamespace Internal\n\t{\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// IsRatio \n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\ttemplate <typename> struct IsRatio                                           : eastl::false_type {};\n\t\ttemplate <intmax_t N, intmax_t D> struct IsRatio<ratio<N, D>>                : eastl::true_type {};\n\t\ttemplate <intmax_t N, intmax_t D> struct IsRatio<const ratio<N, D>>          : eastl::true_type {};\n\t\ttemplate <intmax_t N, intmax_t D> struct IsRatio<volatile ratio<N, D>>       : eastl::true_type {};\n\t\ttemplate <intmax_t N, intmax_t D> struct IsRatio<const volatile ratio<N, D>> : eastl::true_type {};\n\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// IsDuration \n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\ttemplate<typename> struct IsDuration                                                            : eastl::false_type{};\n\t\ttemplate<typename Rep, typename Period> struct IsDuration<duration<Rep, Period>>                : eastl::true_type{};\n\t\ttemplate<typename Rep, typename Period> struct IsDuration<const duration<Rep, Period>>          : eastl::true_type{};\n\t\ttemplate<typename Rep, typename Period> struct IsDuration<volatile duration<Rep, Period>>       : eastl::true_type{};\n\t\ttemplate<typename Rep, typename Period> struct IsDuration<const volatile duration<Rep, Period>> : eastl::true_type{};\n\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// RatioGCD \n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\ttemplate <class Period1, class Period2>\n\t\tstruct RatioGCD\n\t\t{\n\t\t\tstatic_assert(IsRatio<Period1>::value, \"Period1 is not a eastl::ratio type\");\n\t\t\tstatic_assert(IsRatio<Period2>::value, \"Period2 is not a eastl::ratio type\");\n\n\t\t\ttypedef ratio<eastl::Internal::gcd<Period1::num, Period2::num>::value,\n\t\t\t              eastl::Internal::lcm<Period1::den, Period2::den>::value> type;\n\t\t};\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.5.7, duration_cast\n\t///////////////////////////////////////////////////////////////////////////////\n\tnamespace Internal\n\t{\n\t\ttemplate <typename FromDuration,\n\t\t          typename ToDuration,\n\t\t          typename CommonPeriod =\n\t\t              typename ratio_divide<typename FromDuration::period, typename ToDuration::period>::type,\n\t\t          typename CommonRep = typename eastl::decay<typename eastl::common_type<typename ToDuration::rep,\n\t\t                                                                                 typename FromDuration::rep,\n\t\t                                                                                 intmax_t>::type>::type,\n\t\t          bool = CommonPeriod::num == 1,\n\t\t          bool = CommonPeriod::den == 1>\n\t\tstruct DurationCastImpl;\n\n\t\ttemplate <typename FromDuration, typename ToDuration, typename CommonPeriod, typename CommonRep>\n\t\tstruct DurationCastImpl<FromDuration, ToDuration, CommonPeriod, CommonRep, true, true>\n\t\t{\n\t\t\tinline static ToDuration DoCast(const FromDuration& fd)\n\t\t\t{\n\t\t\t\treturn ToDuration(static_cast<typename ToDuration::rep>(fd.count()));\n\t\t\t}\n\t\t};\n\n\t\ttemplate <typename FromDuration, typename ToDuration, typename CommonPeriod, typename CommonRep>\n\t\tstruct DurationCastImpl<FromDuration, ToDuration, CommonPeriod, CommonRep, false, true>\n\t\t{\n\t\t\tinline static ToDuration DoCast(const FromDuration& d)\n\t\t\t{\n\t\t\t\treturn ToDuration(static_cast<typename ToDuration::rep>(static_cast<CommonRep>(d.count()) *\n\t\t\t\t                                                        static_cast<CommonRep>(CommonPeriod::num)));\n\t\t\t}\n\t\t};\n\n\t\ttemplate <typename FromDuration, typename ToDuration, typename CommonPeriod, typename CommonRep>\n\t\tstruct DurationCastImpl<FromDuration, ToDuration, CommonPeriod, CommonRep, true, false>\n\t\t{\n\t\t\tinline static ToDuration DoCast(const FromDuration& d)\n\t\t\t{\n\t\t\t\treturn ToDuration(static_cast<typename ToDuration::rep>(static_cast<CommonRep>(d.count()) /\n\t\t\t\t                                                        static_cast<CommonRep>(CommonPeriod::den)));\n\t\t\t}\n\t\t};\n\n\t\ttemplate <typename FromDuration, typename ToDuration, typename CommonPeriod, typename CommonRep>\n\t\tstruct DurationCastImpl<FromDuration, ToDuration, CommonPeriod, CommonRep, false, false>\n\t\t{\n\t\t\tinline static ToDuration DoCast(const FromDuration& d)\n\t\t\t{\n\t\t\t\treturn ToDuration(static_cast<typename ToDuration::rep>(static_cast<CommonRep>(d.count()) *\n\t\t\t\t                                                        static_cast<CommonRep>(CommonPeriod::num) /\n\t\t\t\t                                                        static_cast<CommonRep>(CommonPeriod::den)));\n\t\t\t}\n\t\t};\n\t}; // namespace Internal\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// duration_cast \n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename ToDuration, typename Rep, typename Period>\n\tinline typename eastl::enable_if<Internal::IsDuration<ToDuration>::value, ToDuration>::type \n\tduration_cast(const duration<Rep, Period>& d)\n\t{\n\t\ttypedef typename duration<Rep, Period>::this_type FromDuration;\n\t\treturn Internal::DurationCastImpl<FromDuration, ToDuration>::DoCast(d);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// duration \n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <class Rep, class Period>\n\tclass duration\n\t{\n\t\tRep mRep;\t\n\n\tpublic:\n\t\ttypedef Rep rep;\n\t\ttypedef Period period;\n\t\ttypedef duration<Rep, Period> this_type;\n\n    #if defined(EA_COMPILER_NO_DEFAULTED_FUNCTIONS)\n\t\tEA_CONSTEXPR duration() \n\t\t\t: mRep() {}\n\n\t\tduration(const duration& other)\n\t\t\t: mRep(Rep(other.mRep)) {}\n\n\t\tduration& operator=(const duration& other)\n\t\t\t{ mRep = other.mRep; return *this; }\n\t#else\n\t\tEA_CONSTEXPR duration() = default;\n\t\tduration(const duration&) = default;\n\t\tduration& operator=(const duration&) = default;\n    #endif\n\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// conversion constructors \n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\ttemplate <class Rep2>\n\t\tinline EA_CONSTEXPR explicit duration(\n\t\t    const Rep2& rep2,\n\t\t    typename eastl::enable_if<eastl::is_convertible<Rep2, Rep>::value &&\n\t\t                              (treat_as_floating_point<Rep>::value ||\n\t\t                               !treat_as_floating_point<Rep2>::value)>::type** = 0)\n\t\t    : mRep(static_cast<Rep>(rep2)) {}\n\n\n\t\ttemplate <class Rep2, class Period2>\n\t\tEA_CONSTEXPR duration(const duration<Rep2, Period2>& d2,\n\t\t                      typename eastl::enable_if<treat_as_floating_point<Rep>::value ||\n\t\t                                                    (eastl::ratio_divide<Period2, Period>::type::den == 1 &&\n\t\t                                                     !treat_as_floating_point<Rep2>::value),\n\t\t                                                void>::type** = 0)\n\t\t    : mRep(duration_cast<duration>(d2).count()) {}\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// returns the count of ticks \n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\tEA_CONSTEXPR Rep count() const { return mRep; }\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// static accessors of special duration values \n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\tEA_CONSTEXPR inline static duration zero() { return duration(duration_values<Rep>::zero()); }\n\t\tEA_CONSTEXPR inline static duration min()  { return duration(duration_values<Rep>::min()); }\n\t\tEA_CONSTEXPR inline static duration max()  { return duration(duration_values<Rep>::max()); }\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// const arithmetic operations\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\tEA_CONSTEXPR inline duration operator+() const { return *this; }\n\t\tEA_CONSTEXPR inline duration operator-() const { return duration(0-mRep); }\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// arithmetic operations\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\tinline duration operator++(int)                  { return duration(mRep++); }\n\t\tinline duration operator--(int)                  { return duration(mRep--); }\n\t\tinline duration& operator++()                    { ++mRep; return *this; }\n\t\tinline duration& operator--()                    { --mRep; return *this; }\n\t\tinline duration& operator+=(const duration& d)   { mRep += d.count(); return *this; }\n\t\tinline duration& operator-=(const duration& d)   { mRep -= d.count(); return *this; }\n\t\tinline duration& operator*=(const Rep& rhs)      { mRep *= rhs; return *this; }\n\t\tinline duration& operator/=(const Rep& rhs)      { mRep /= rhs; return *this; }\n\t\tinline duration& operator%=(const Rep& rhs)      { mRep %= rhs; return *this; }\n\t\tinline duration& operator%=(const duration& d)   { mRep %= d.count(); return *this; }\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.5.5, arithmetic operations with durations as arguments\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\ttypename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type EASTL_FORCE_INLINE\n\toperator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef typename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type common_duration_t;\n\t\treturn common_duration_t(common_duration_t(lhs).count() + common_duration_t(rhs).count());\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\ttypename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type EASTL_FORCE_INLINE\n\toperator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef typename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type common_duration_t;\n\t\treturn common_duration_t(common_duration_t(lhs).count() - common_duration_t(rhs).count());\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2>\n\tduration<typename eastl::common_type<Rep1, Rep2>::type, Period1> EASTL_FORCE_INLINE\n\toperator*(const duration<Rep1, Period1>& lhs, const Rep2& rhs)\n\t{\n\t\ttypedef duration<typename eastl::common_type<Rep1, Rep2>::type, Period1> common_duration_t;\n\t\treturn common_duration_t(common_duration_t(lhs).count() * rhs);\n\t}\n\n\ttemplate <typename Rep1, typename Rep2, typename Period2>\n\tduration<typename eastl::common_type<Rep1, Rep2>::type, Period2> EASTL_FORCE_INLINE\n\toperator*(const Rep1& lhs, const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef duration<typename eastl::common_type<Rep1, Rep2>::type, Period2> common_duration_t;\n\t\treturn common_duration_t(lhs * common_duration_t(rhs).count());\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2>\n\tduration<typename eastl::common_type<Rep1, Rep2>::type, Period1> EASTL_FORCE_INLINE\n\toperator/(const duration<Rep1, Period1>& lhs, const Rep2& rhs)\n\t{\n\t\ttypedef duration<typename eastl::common_type<Rep1, Rep2>::type, Period1> common_duration_t;\n\t\treturn common_duration_t(common_duration_t(lhs).count() / rhs);\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\ttypename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type EASTL_FORCE_INLINE\n\toperator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef typename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type common_duration_t;\n\t\treturn common_duration_t(common_duration_t(lhs).count() / common_duration_t(rhs).count());\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2>\n\tduration<typename eastl::common_type<Rep1, Rep2>::type, Period1> EASTL_FORCE_INLINE\n\toperator%(const duration<Rep1, Period1>& lhs, const Rep2& rhs)\n\t{\n\t\ttypedef duration<typename eastl::common_type<Rep1, Rep2>::type, Period1> common_duration_t;\n\t\treturn common_duration_t(common_duration_t(lhs).count() % rhs);\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\ttypename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type EASTL_FORCE_INLINE\n\toperator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef typename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type common_duration_t;\n\t\treturn common_duration_t(common_duration_t(lhs).count() % common_duration_t(rhs).count());\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.5.6, compares two durations\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\tEASTL_FORCE_INLINE bool operator==(const duration<Rep1, Period1>& lhs,\n\t                                                const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef typename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type common_duration_t;\n\t\treturn common_duration_t(lhs).count() == common_duration_t(rhs).count();\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\tEASTL_FORCE_INLINE bool operator<(const duration<Rep1, Period1>& lhs,\n\t                                               const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef typename eastl::common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type common_duration_t;\n\t\treturn common_duration_t(lhs).count() < common_duration_t(rhs).count();\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\tEASTL_FORCE_INLINE bool operator!=(const duration<Rep1, Period1>& lhs,\n\t                                                const duration<Rep2, Period2>& rhs)\n\t{\n\t\treturn !(lhs == rhs);\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\tEASTL_FORCE_INLINE bool operator<=(const duration<Rep1, Period1>& lhs,\n\t                                                const duration<Rep2, Period2>& rhs)\n\t{\n\t\treturn !(rhs < lhs);\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\tEASTL_FORCE_INLINE bool operator>(const duration<Rep1, Period1>& lhs,\n\t                                               const duration<Rep2, Period2>& rhs)\n\t{\n\t\treturn rhs < lhs;\n\t}\n\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\tEASTL_FORCE_INLINE bool operator>=(const duration<Rep1, Period1>& lhs,\n\t                                                const duration<Rep2, Period2>& rhs)\n\t{\n\t\treturn !(lhs < rhs);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// standard duration units\n\t///////////////////////////////////////////////////////////////////////////////\n    typedef duration<long long, nano> nanoseconds;\n    typedef duration<long long, micro> microseconds;\n    typedef duration<long long, milli> milliseconds;\n    typedef duration<long long> seconds;\n    typedef duration<int, ratio<60>> minutes;\n    typedef duration<int, ratio<3600>> hours;\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.6, time_point\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename Clock, typename Duration = typename Clock::duration> \n\tclass time_point\n\t{\n\t\tDuration mDuration;\n\n\tpublic:\n\t\ttypedef Clock clock;\n\t\ttypedef Duration duration;\n\t\ttypedef typename Duration::rep rep;\n\t\ttypedef typename Duration::period period;\n\n\t\tinline EA_CONSTEXPR time_point() : mDuration(Duration::zero()) {}\n\t\tEA_CONSTEXPR explicit time_point(const Duration& other) : mDuration(other) {}\n\n\t\ttemplate <typename Duration2>\n\t\tinline EA_CONSTEXPR time_point(\n\t\t    const time_point<Clock, Duration2>& t,\n\t\t    typename eastl::enable_if<eastl::is_convertible<Duration2, Duration>::value>::type** = 0)\n\t\t    : mDuration(t.time_since_epoch()) {}\n\n\t\tEA_CONSTEXPR Duration time_since_epoch() const { return mDuration; }\n\n\t\ttime_point& operator+=(const Duration& d) { mDuration += d; return *this; } \n\t\ttime_point& operator-=(const Duration& d) { mDuration -= d; return *this; }\n\n\t\tstatic EA_CONSTEXPR time_point min() { return time_point(Duration::min()); }\n\t\tstatic EA_CONSTEXPR time_point max() { return time_point(Duration::max()); }\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.6.5, time_point arithmetic\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <class Clock, class Duration1, class Rep2, class Period2>\n\tinline EA_CONSTEXPR time_point<Clock, typename eastl::common_type<Duration1, duration<Rep2, Period2>>::type>\n\toperator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef time_point<Clock, typename eastl::common_type<Duration1, duration<Rep2, Period2>>::type> common_timepoint_t;\n\t\treturn common_timepoint_t(lhs.time_since_epoch() + rhs);\n\t}\n\n\ttemplate <class Rep1, class Period1, class Clock, class Duration2>\n\tinline EA_CONSTEXPR time_point<Clock, typename eastl::common_type<Duration2, duration<Rep1, Period1>>::type>\n\toperator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs)\n\t{\n\t\ttypedef time_point<Clock, typename eastl::common_type<Duration2, duration<Rep1, Period1>>::type> common_timepoint_t;\n\t\treturn common_timepoint_t(lhs + rhs.time_since_epoch());\n\t}\n\n\ttemplate <class Clock, class Duration1, class Rep2, class Period2>\n\tinline EA_CONSTEXPR time_point<Clock, typename eastl::common_type<Duration1, duration<Rep2, Period2>>::type>\n\toperator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs)\n\t{\n\t\ttypedef time_point<Clock, typename eastl::common_type<Duration1, duration<Rep2, Period2>>::type> common_timepoint_t;\n\t\treturn common_timepoint_t(lhs.time_since_epoch() - rhs);\n\t}\n\n\ttemplate <class Clock, class Duration1, class Duration2>\n\tinline EA_CONSTEXPR typename eastl::common_type<Duration1, Duration2>::type operator-(\n\t    const time_point<Clock, Duration1>& lhs,\n\t    const time_point<Clock, Duration2>& rhs)\n\t{\n\t\treturn lhs.time_since_epoch() - rhs.time_since_epoch();\n\t}\n\n\ttemplate <class Clock, class Duration1, class Duration2>\n\tinline EA_CONSTEXPR bool operator==(const time_point<Clock, Duration1>& lhs,\n\t                                    const time_point<Clock, Duration2>& rhs)\n\t{\n\t\treturn lhs.time_since_epoch() == rhs.time_since_epoch();\n\t}\n\n\ttemplate <class Clock, class Duration1, class Duration2>\n\tinline EA_CONSTEXPR bool operator!=(const time_point<Clock, Duration1>& lhs,\n\t                                    const time_point<Clock, Duration2>& rhs)\n\t{\n\t\treturn !(lhs == rhs);\n\t}\n\n\ttemplate <class Clock, class Duration1, class Duration2>\n\tinline EA_CONSTEXPR bool operator<(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)\n\t{\n\t\treturn lhs.time_since_epoch() < rhs.time_since_epoch();\n\t}\n\n\ttemplate <class Clock, class Duration1, class Duration2>\n\tinline EA_CONSTEXPR bool operator<=(const time_point<Clock, Duration1>& lhs,\n\t                                    const time_point<Clock, Duration2>& rhs)\n\t{\n\t\treturn !(rhs < lhs);\n\t}\n\n\ttemplate <class Clock, class Duration1, class Duration2>\n\tinline EA_CONSTEXPR bool operator>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)\n\t{\n\t\treturn rhs < lhs;\n\t}\n\n\ttemplate <class Clock, class Duration1, class Duration2>\n\tinline EA_CONSTEXPR bool operator>=(const time_point<Clock, Duration1>& lhs,\n\t                                    const time_point<Clock, Duration2>& rhs)\n\t{\n\t\treturn !(lhs < rhs);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.6.7, time_point_cast\n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename ToDuration, typename Clock, typename Duration>\n\tEA_CONSTEXPR time_point<Clock, ToDuration> time_point_cast(\n\t    const time_point<Clock, Duration>& t,\n\t    typename eastl::enable_if<Internal::IsDuration<ToDuration>::value>::type** = 0)\n\t{\n\t\treturn time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch()));\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 20.12.7, clocks\n\t///////////////////////////////////////////////////////////////////////////////\n\n\tnamespace Internal\n\t{\n\t\t#if defined(EA_PLATFORM_MICROSOFT) && !defined(EA_PLATFORM_MINGW)\n\t\t\t#define EASTL_NS_PER_TICK 1 \n\t\t#elif defined EA_PLATFORM_SONY\n\t\t\t#define EASTL_NS_PER_TICK 1\n\t\t#elif defined EA_PLATFORM_POSIX\n\t\t\t#define EASTL_NS_PER_TICK _XTIME_NSECS_PER_TICK\n\t\t#else\n\t\t\t#define EASTL_NS_PER_TICK 100\n\t\t#endif\n\n\t\t#if defined(EA_PLATFORM_POSIX) \n\t\t\ttypedef chrono::nanoseconds::period SystemClock_Period;\n\t\t\ttypedef chrono::nanoseconds::period SteadyClock_Period;\n\t\t#else\n\t\t\ttypedef eastl::ratio_multiply<eastl::ratio<EASTL_NS_PER_TICK, 1>, nano>::type SystemClock_Period; \n\t\t\ttypedef eastl::ratio_multiply<eastl::ratio<EASTL_NS_PER_TICK, 1>, nano>::type SteadyClock_Period; \n\t\t#endif\n\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t// Internal::GetTicks \n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\tinline uint64_t GetTicks()\n\t\t{\n\t\t#if defined EA_PLATFORM_MICROSOFT\n\t\t\tauto queryFrequency = []\n\t\t\t{\n\t\t\t\tLARGE_INTEGER frequency;\n\t\t\t\tQueryPerformanceFrequency(&frequency);\n\t\t\t\treturn double(1000000000.0L / (long double)frequency.QuadPart);  // nanoseconds per tick\n\t\t\t};\n\n\t\t\tauto queryCounter = []\n\t\t\t{\n\t\t\t\tLARGE_INTEGER counter;\n\t\t\t\tQueryPerformanceCounter(&counter);\n\t\t\t\treturn counter.QuadPart;\n\t\t\t};\n\n\t\t\tEA_DISABLE_VC_WARNING(4640)  // warning C4640: construction of local static object is not thread-safe (VS2013)\n\t\t\tstatic auto frequency = queryFrequency(); // cache cpu frequency on first call\n\t\t\tEA_RESTORE_VC_WARNING()\n\t\t\treturn uint64_t(frequency * (double)queryCounter());\n\t\t#elif defined EA_PLATFORM_SONY\n\t\t\tauto queryFrequency = []\n\t\t\t{\n\t\t\t\t// nanoseconds/seconds / ticks/seconds\n\t\t\t\treturn double(1000000000.0L / (long double)sceKernelGetProcessTimeCounterFrequency());  // nanoseconds per tick\n\t\t\t};\n\n\t\t\tauto queryCounter = []\n\t\t\t{\n\t\t\t\treturn sceKernelGetProcessTimeCounter();\n\t\t\t};\n\n\t\t\tEA_DISABLE_VC_WARNING(4640)  // warning C4640: construction of local static object is not thread-safe (VS2013)\n\t\t\tstatic auto frequency = queryFrequency(); // cache cpu frequency on first call\n\t\t\tEA_RESTORE_VC_WARNING()\n\t\t\treturn uint64_t(frequency * (double)queryCounter());\n\t\t#elif defined(EA_PLATFORM_APPLE)\n\t\t\tauto queryTimeInfo = []\n\t\t\t{\n\t\t\t\tmach_timebase_info_data_t info;\n\t\t\t\tmach_timebase_info(&info);\n\t\t\t\treturn info;\n\t\t\t};\n\t\t\t\n\t\t\tstatic auto timeInfo = queryTimeInfo();\n\t\t\tuint64_t t = mach_absolute_time();\n\t\t\tt *= timeInfo.numer;\n\t\t\tt /= timeInfo.denom;\n\t\t\treturn t;\n\t\t#elif defined(EA_PLATFORM_POSIX) // Posix means Linux, Unix, and Macintosh OSX, among others (including Linux-based mobile platforms).\n\t\t\t#if (defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC))\n\t\t\t\ttimespec ts;\n\t\t\t\tint result = clock_gettime(CLOCK_MONOTONIC, &ts);\n\n\t\t\t\tif (result == -1 && errno == EINVAL)\n\t\t\t\t\tresult = clock_gettime(CLOCK_REALTIME, &ts);\n\n\t\t\t\tconst uint64_t nNanoseconds = (uint64_t)ts.tv_nsec + ((uint64_t)ts.tv_sec * UINT64_C(1000000000));\n\t\t\t\treturn nNanoseconds;\n\t\t\t#else\n\t\t\t\tstruct timeval tv;\n\t\t\t\tgettimeofday(&tv, NULL);\n\t\t\t\tconst uint64_t nMicroseconds = (uint64_t)tv.tv_usec + ((uint64_t)tv.tv_sec * 1000000);\n\t\t\t\treturn nMicroseconds;\n\t\t\t#endif\n        #else\n\t\t\t#error \"chrono not implemented for platform\"\n\t\t#endif\n\t\t}\n\t} // namespace Internal\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// system_clock \n\t///////////////////////////////////////////////////////////////////////////////\n\tclass system_clock\n\t{\n\tpublic:\n\t\ttypedef long long rep; // signed arithmetic type representing the number of ticks in the clock's duration\n\t\ttypedef Internal::SystemClock_Period period;\n\t\ttypedef chrono::duration<rep, period> duration; // duration<rep, period>, capable of representing negative durations\n\t\ttypedef chrono::time_point<system_clock> time_point;\n\n\t\t// true if the time between ticks is always increases monotonically\n\t\tEA_CONSTEXPR_OR_CONST static bool is_steady = false;\n\n\t\t// returns a time point representing the current point in time.\n\t\tstatic time_point now() EA_NOEXCEPT \n\t\t{ \n\t\t\treturn time_point(duration(Internal::GetTicks())); \n\t\t}\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// steady_clock \n\t///////////////////////////////////////////////////////////////////////////////\n\tclass steady_clock\n\t{\n\tpublic:\n\t\ttypedef long long rep; // signed arithmetic type representing the number of ticks in the clock's duration\n\t\ttypedef Internal::SteadyClock_Period period;\n\t\ttypedef chrono::duration<rep, period> duration; // duration<rep, period>, capable of representing negative durations\n\t\ttypedef chrono::time_point<steady_clock> time_point;\n\n\t\t// true if the time between ticks is always increases monotonically\n\t\tEA_CONSTEXPR_OR_CONST static bool is_steady = true;\n\n\t\t// returns a time point representing the current point in time.\n\t\tstatic time_point now() EA_NOEXCEPT \n\t\t{ \n\t\t\treturn time_point(duration(Internal::GetTicks())); \n\t\t}\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// high_resolution_clock \n\t///////////////////////////////////////////////////////////////////////////////\n\ttypedef system_clock high_resolution_clock;\n\n\n} // namespace chrono \n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// duration common_type specialization \n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename Rep1, typename Period1, typename Rep2, typename Period2>\n\tstruct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>>\n\t{\n\t    typedef chrono::duration<typename eastl::decay<typename eastl::common_type<Rep1, Rep2>::type>::type,\n\t                             typename chrono::Internal::RatioGCD<Period1, Period2>::type> type;\n    };\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// time_point common_type specialization \n\t///////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename Clock, typename Duration1, typename Duration2>\n\tstruct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>>\n\t{\n\t\ttypedef chrono::time_point<Clock, typename eastl::common_type<Duration1, Duration2>::type> type;\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// chrono_literals  \n\t///////////////////////////////////////////////////////////////////////////////\n\t#if EASTL_USER_LITERALS_ENABLED && EASTL_INLINE_NAMESPACES_ENABLED\n\t\t// Disabling the Clang/GCC/MSVC warning about using user\n\t\t// defined literals without a leading '_' as they are reserved\n\t\t// for standard libary usage.\n\t\tEA_DISABLE_VC_WARNING(4455)\n\t\tEA_DISABLE_CLANG_WARNING(-Wuser-defined-literals)\n\t\tEA_DISABLE_GCC_WARNING(-Wliteral-suffix)\n\t\tinline namespace literals\n\t\t{\n\t\t\tinline namespace chrono_literals\n\t\t\t{\n\t\t\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t\t\t// integer chrono literals\n\t\t\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t\t\tEA_CONSTEXPR chrono::hours operator\"\" h(unsigned long long h) { return chrono::hours(h); }\n\t\t\t\tEA_CONSTEXPR chrono::minutes operator\"\" min(unsigned long long m) { return chrono::minutes(m); }\n\t\t\t\tEA_CONSTEXPR chrono::seconds operator\"\" s(unsigned long long s) { return chrono::seconds(s); }\n\t\t\t\tEA_CONSTEXPR chrono::milliseconds operator\"\" ms(unsigned long long ms) { return chrono::milliseconds(ms); }\n\t\t\t\tEA_CONSTEXPR chrono::microseconds operator\"\" us(unsigned long long us) { return chrono::microseconds(us); }\n\t\t\t\tEA_CONSTEXPR chrono::nanoseconds operator\"\" ns(unsigned long long ns) { return chrono::nanoseconds(ns); }\n\n\t\t\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t\t\t// float chrono literals\n\t\t\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t\t\tEA_CONSTEXPR chrono::duration<long double, ratio<3600, 1>> operator\"\" h(long double h)\n\t\t\t\t\t{ return chrono::duration<long double, ratio<3600, 1>>(h); }\n\t\t\t\tEA_CONSTEXPR chrono::duration<long double, ratio<60, 1>> operator\"\" min(long double m)\n\t\t\t\t\t{ return chrono::duration<long double, ratio<60, 1>>(m); }\n\t\t\t\tEA_CONSTEXPR chrono::duration<long double> operator\"\" s(long double s)\n\t\t\t\t\t{ return chrono::duration<long double>(s); }\n\t\t\t\tEA_CONSTEXPR chrono::duration<float, milli> operator\"\" ms(long double ms)\n\t\t\t\t\t{ return chrono::duration<long double, milli>(ms); }\n\t\t\t\tEA_CONSTEXPR chrono::duration<float, micro> operator\"\" us(long double us)\n\t\t\t\t\t{ return chrono::duration<long double, micro>(us); }\n\t\t\t\tEA_CONSTEXPR chrono::duration<float, nano> operator\"\" ns(long double ns)\n\t\t\t\t\t{ return chrono::duration<long double, nano>(ns); }\n\n\t\t\t} // namespace chrono_literals\n\t\t}// namespace literals\n\t\tEA_RESTORE_GCC_WARNING()\t// -Wliteral-suffix\n\t\tEA_RESTORE_CLANG_WARNING()\t// -Wuser-defined-literals\n\t\tEA_RESTORE_VC_WARNING()\t\t// warning: 4455\n\t#endif\n\n} // namespace eastl\n\n\n#if EASTL_USER_LITERALS_ENABLED && EASTL_INLINE_NAMESPACES_ENABLED\nnamespace chrono\n{\n\tusing namespace eastl::literals::chrono_literals;\n} // namespace chrono\n#endif\n\n\n#endif \n"
  },
  {
    "path": "include/EASTL/compare.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_COMPARE_H\n#define EASTL_COMPARE_H\n\n\n#include <EABase/eabase.h>\n\nnamespace eastl\n{\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\tstruct synth_three_way\n\t{\n\t\ttemplate <typename T, typename U>\n\t\tconstexpr auto operator()(const T& t, const U& u) const requires requires\n\t\t{\n\t\t\t{t < u}->std::convertible_to<bool>;\n\t\t\t{u < t}->std::convertible_to<bool>;\n\t\t}\n\t\t{\n\t\t\tif constexpr (std::three_way_comparable_with<T, U>)\n\t\t\t{\n\t\t\t\treturn t <=> u;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn (t < u) ? std::weak_ordering::less :\n\t\t\t\t       (u < t) ? std::weak_ordering::greater :\n                                 std::weak_ordering::equivalent;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate <typename T, typename U=T>\n\tusing synth_three_way_result = decltype(synth_three_way{}(declval<T&>(), declval<U&>()));\n#endif\n\n} // namespace eastl\n\n\n#endif // Header include guard"
  },
  {
    "path": "include/EASTL/core_allocator.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_CORE_ALLOCATOR_H\n#define EASTL_CORE_ALLOCATOR_H\n\n#if EASTL_CORE_ALLOCATOR_ENABLED\n\n#include <coreallocator/icoreallocator.h>\n\nnamespace EA\n{\n\tnamespace Allocator\n\t{\n\t\t/// EASTLCoreAllocatorImpl\n\t\t///\n\t\t/// EASTL provides an out of the box implementation of the\n\t\t/// ICoreAllocator interface.  This is provided as a convenience for\n\t\t/// users who wish to provide ICoreAllocator implementations for EASTL to use.  \n\t\t///\n\t\t/// EASTL has a dependency on coreallocator so to provide an out of \n\t\t/// the box implementation for EASTLCoreAlloctor and EASTLCoreDeleter \n\t\t/// that can be used and tested.  Historically we could not test \n\t\t/// ICoreAllocator interface because we relied on the code being linked \n\t\t/// in user code.\n\t\t///\n\n\t\tclass EASTLCoreAllocatorImpl : public ICoreAllocator\n\t\t{\n\t\tpublic:\n\t\t\tvirtual void* Alloc(size_t size, const char* name, unsigned int flags)\n\t\t\t{\n\t\t\t\treturn ::operator new[](size, name, flags, 0, __FILE__, __LINE__);\n\t\t\t}\n\n\t\t\tvirtual void* Alloc(size_t size, const char* name, unsigned int flags, unsigned int alignment, unsigned int alignOffset = 0)\n\t\t\t{\n\t\t\t\treturn ::operator new[](size, alignment, alignOffset, name, flags, 0, __FILE__, __LINE__);\n\t\t\t}\n\n\t\t\tvirtual void Free(void* ptr, size_t size = 0)\n\t\t\t{\n\t\t\t\t::operator delete(static_cast<char*>(ptr));\n\t\t\t}\n\n\t\t\tvirtual void* AllocDebug(size_t size, const DebugParams debugParams, unsigned int flags)\n\t\t\t{\n\t\t\t\treturn Alloc(size, debugParams.mName, flags);\n\t\t\t}\n\n\t\t\tvirtual void* AllocDebug(size_t size, const DebugParams debugParams, unsigned int flags, unsigned int align, unsigned int alignOffset = 0)\n\t\t\t{\n\t\t\t\treturn Alloc(size, debugParams.mName, flags, align, alignOffset);\n\t\t\t}\n\n\t\t\tstatic EASTLCoreAllocatorImpl* GetDefaultAllocator();\n\t\t};\n\n\t\tinline EASTLCoreAllocatorImpl* EASTLCoreAllocatorImpl::GetDefaultAllocator()\n\t\t{\n\t\t\tstatic EASTLCoreAllocatorImpl allocator;\n\t\t\treturn &allocator;\n\t\t}\n\t}\n}\n\n#endif // EASTL_CORE_ALLOCATOR_ENABLED\n#endif // EASTL_CORE_ALLOCATOR_H\n\n"
  },
  {
    "path": "include/EASTL/core_allocator_adapter.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Implements an EASTL allocator that uses an ICoreAllocator.\n// However, this header file is not dependent on ICoreAllocator or its package.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_CORE_ALLOCATOR_ADAPTER_H\n#define EASTL_CORE_ALLOCATOR_ADAPTER_H\n\n#if EASTL_CORE_ALLOCATOR_ENABLED\n\n\n#include <EASTL/internal/config.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n/// EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR\n///\n/// This allows the application to override the default name for the default global core allocator.\n/// However, you must be careful in your usage of this, as if this file is shared between uses then \n/// you will need to be careful that your override of this doesn't conflict with others. \n///\n#ifndef EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR\n\t#define EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR AllocatorType::GetDefaultAllocator\n#endif\n\n\n\nnamespace EA\n{\n\tnamespace Allocator\n\t{\n\t\t/// CoreAllocatorAdapter\n\t\t///\n\t\t/// Implements the EASTL allocator interface.\n\t\t/// Allocates memory from an instance of ICoreAllocator or another class with an equivalent interface.\n\t\t/// ICoreAllocator is a pure-virtual memory allocation interface used by a number of EA games and \n\t\t/// shared libraries. It's completely unrelated to EASTL, but it's prevalent enough that it's useful\n\t\t/// for EASTL to have a built-in adapter for this interface. ICoreAllocator is declared in the \n\t\t/// CoreAllocator package icoreallocator_interface.h header, but CoreAllocatorAdapter can work with\n\t\t/// any equivalent interface, as defined below.\n\t\t///\n\t\t/// Expected interface:\n\t\t///     enum AllocFlags {\n\t\t///         kFlagTempMemory = 0,\n\t\t///         kFlagPermMemory = 1\n\t\t///     };\n\t\t///     \n\t\t///     struct CoreAllocator {\n\t\t///         void* Alloc(size_t size, const char* name, unsigned int allocFlags);\n\t\t///         void* Alloc(size_t size, const char* name, unsigned int allocFlags,     // Not required unless you are working with types that require custom alignment.\n\t\t///                      unsigned int align, unsigned int alignOffset = 0);\n\t\t///         void Free(void* block, size_t size = 0);\n\t\t///         static CoreAllocator* GetDefaultAllocator();\n\t\t///     };\n\t\t///\n\t\t/// Example usage:\n\t\t///     #include <coreallocator/icoreallocator_interface.h>\n\t\t///     typedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter;\n\t\t///     eastl::list<Widget, Adapter> widgetList(Adapter(\"UI/WidgetList\", pSomeCoreAllocator));\n\t\t///     widgetList.push_back(Widget());\n\t\t///\n\t\t/// Example usage:\n\t\t///     #include <MyEquivalentCoreAllocatorInterface.h>\n\t\t///     eastl::list<Widget, CoreAllocatorAdapter<MyCoreAllocatorInterface> > widgetList;\n\t\t///     widgetList.push_back(Widget());\n\t\t///\n\t\t/// Example usage:\n\t\t///     #include <coreallocator/icoreallocator_interface.h>\n\t\t///     typedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter;\n\t\t///     typedef eastl::list<Widget, Adapter> WidgetList;\n\t\t///     CoreAllocatorFixed<WidgetList::node_type> widgetCoreAllocator(pFixedAllocatorForWidgetListValueType); // CoreAllocatorFixed is a hypothetical implementation of the ICoreAllocator interface.\n\t\t///     WidgetList widgetList(Adapter(\"UI/WidgetList\", &widgetCoreAllocator));                                // Note that the widgetCoreAllocator is declared before and thus destroyed after the widget list.\n\t\t///\n\t\ttemplate<class AllocatorType>\n\t\tclass CoreAllocatorAdapter\n\t\t{\n\t\tpublic:\n\t\t\ttypedef CoreAllocatorAdapter<AllocatorType> this_type;\n\n\t\tpublic:\n\t\t\t// To do: Make this constructor explicit, when there is no known code dependent on it being otherwise.\n\t\t\tCoreAllocatorAdapter(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME), AllocatorType* pAllocator = EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR());\n\t\t\tCoreAllocatorAdapter(const char* pName, AllocatorType* pAllocator, int flags);\n\t\t\tCoreAllocatorAdapter(const CoreAllocatorAdapter& x);\n\t\t\tCoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* pName);\n\n\t\t\tCoreAllocatorAdapter& operator=(const CoreAllocatorAdapter& x);\n\n\t\t\tvoid* allocate(size_t n, int flags = 0);\n\t\t\tvoid* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);\n\t\t\tvoid  deallocate(void* p, size_t n);\n\n\t\t\tAllocatorType* get_allocator() const;\n\t\t\tvoid           set_allocator(AllocatorType* pAllocator);\n\n\t\t\tint  get_flags() const;\n\t\t\tvoid set_flags(int flags);\n\n\t\t\tconst char* get_name() const;\n\t\t\tvoid        set_name(const char* pName);\n\n\t\tpublic: // Public because otherwise VC++ generates (possibly invalid) warnings about inline friend template specializations.\n\t\t\tAllocatorType* mpCoreAllocator;\n\t\t\tint            mnFlags;    // Allocation flags. See ICoreAllocator/AllocFlags.\n\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tconst char* mpName; // Debug name, used to track memory.\n\t\t\t#endif\n\t\t};\n\n\t\ttemplate<class AllocatorType>\n\t\tbool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b);\n\n\t\ttemplate<class AllocatorType>\n\t\tbool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b);\n\n\n\n\t\t/// EASTLICoreAllocator\n\t\t///\n\t\t/// Provides a standardized typedef for ICoreAllocator;\n\t\t/// \n\t\t/// Example usage:\n\t\t///     eastl::list<Widget, EASTLICoreAllocator> widgetList(\"UI/WidgetList\", pSomeCoreAllocator);\n\t\t///     widgetList.push_back(Widget());\n\t\t///\n\t\tclass ICoreAllocator;\n\t\tclass EASTLCoreAllocatorImpl;\n\n\t\ttypedef CoreAllocatorAdapter<ICoreAllocator> EASTLICoreAllocatorAdapter;\n\t\ttypedef CoreAllocatorAdapter<EASTLCoreAllocatorImpl> EASTLCoreAllocatorAdapter;\n\t\ttypedef EASTLICoreAllocatorAdapter EASTLICoreAllocator;  // for backwards compatibility\n\n\n\n\t\t/// EASTLICoreDeleter\n\t\t///\n\t\t/// Implements a functor which can free memory from the specified\n\t\t/// ICoreAllocator interface.  This is a convenience object provided for\n\t\t/// users who wish to have EASTL containers deallocate memory obtained from\n\t\t/// ICoreAllocator interfaces.\n\t\t///\n\t\ttemplate <class AllocatorType>\n\t\tclass CoreDeleterAdapter\n\t\t{\n\t\tpublic:\n\t\t\ttypedef CoreDeleterAdapter<AllocatorType> this_type;\n\t\t\tAllocatorType* mpCoreAllocator;\n\n\t\tpublic:\n\t\t\tCoreDeleterAdapter(AllocatorType* pAllocator = EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR()) EA_NOEXCEPT \n\t\t\t: mpCoreAllocator(pAllocator) {}\n\n\t\t\t~CoreDeleterAdapter() EA_NOEXCEPT {}\n\n\t\t\ttemplate <typename T>\n\t\t\tvoid operator()(T* p)\n\t\t\t{\n\t\t\t\tp->~T();\n\t\t\t\tmpCoreAllocator->Free(p);\n\t\t\t}\n\n\t\t\tCoreDeleterAdapter(const CoreDeleterAdapter& in) { mpCoreAllocator = in.mpCoreAllocator; }\n\n\t\t\tCoreDeleterAdapter(CoreDeleterAdapter&& in)\n\t\t\t{\n\t\t\t\tmpCoreAllocator = in.mpCoreAllocator;\n\t\t\t\tin.mpCoreAllocator = nullptr;\n\t\t\t}\n\n\t\t\tCoreDeleterAdapter& operator=(const CoreDeleterAdapter& in)\n\t\t\t{\n\t\t\t\tmpCoreAllocator = in.mpCoreAllocator;\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\tCoreDeleterAdapter& operator=(CoreDeleterAdapter&& in)\n\t\t\t{\n\t\t\t\tmpCoreAllocator = in.mpCoreAllocator;\n\t\t\t\tin.mpCoreAllocator = nullptr;\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\n\n\n\t\t/// EASTLICoreDeleter\n\t\t///\n\t\t/// Provides a standardized typedef for ICoreAllocator implementations.\n\t\t///\n\t\t/// Example usage: \n\t\t///     eastl::shared_ptr<A> foo(pA, EASTLCoreDeleter());\n\t\t///\n\t\ttypedef CoreDeleterAdapter<ICoreAllocator> EASTLICoreDeleterAdapter;\n\t\ttypedef CoreDeleterAdapter<EASTLCoreAllocatorImpl> EASTLCoreDeleterAdapter;\n\n\t} // namespace Allocator\n\n} // namespace EA\n\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Inlines\n///////////////////////////////////////////////////////////////////////////////\n\nnamespace EA\n{\n\tnamespace Allocator\n\t{\n\t\ttemplate<class AllocatorType>\n\t\tinline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator)\n\t\t\t: mpCoreAllocator(pCoreAllocator), mnFlags(0)\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n\t\t\t#endif\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator, int flags)\n\t\t\t: mpCoreAllocator(pCoreAllocator), mnFlags(flags)\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n\t\t\t#endif\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x)\n\t\t\t: mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags)\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = x.mpName;\n\t\t\t#endif\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* EASTL_NAME(pName))\n\t\t\t: mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags)\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;\n\t\t\t#endif\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline CoreAllocatorAdapter<AllocatorType>& CoreAllocatorAdapter<AllocatorType>::operator=(const CoreAllocatorAdapter& x)\n\t\t{\n\t\t\tmpCoreAllocator = x.mpCoreAllocator;\n\t\t\tmnFlags         = x.mnFlags;\n\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = x.mpName;\n\t\t\t#endif\n\t\t\t\t\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, int /*flags*/)\n\t\t{\n\t\t\t// It turns out that EASTL itself doesn't use the flags parameter, \n\t\t\t// whereas the user here might well want to specify a flags \n\t\t\t// parameter. So we use ours instead of the one passed in.\n\t\t\treturn mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags);\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, size_t alignment, size_t offset, int /*flags*/)\n\t\t{\n\t\t\t// It turns out that EASTL itself doesn't use the flags parameter, \n\t\t\t// whereas the user here might well want to specify a flags \n\t\t\t// parameter. So we use ours instead of the one passed in.\n\t\t\treturn mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags, (unsigned)alignment, (unsigned)offset);\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline void CoreAllocatorAdapter<AllocatorType>::deallocate(void* p, size_t n)\n\t\t{\n\t\t\treturn mpCoreAllocator->Free(p, n);\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline AllocatorType* CoreAllocatorAdapter<AllocatorType>::get_allocator() const\n\t\t{\n\t\t\treturn mpCoreAllocator;\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline void CoreAllocatorAdapter<AllocatorType>::set_allocator(AllocatorType* pAllocator)\n\t\t{\n\t\t\tmpCoreAllocator = pAllocator;\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline int CoreAllocatorAdapter<AllocatorType>::get_flags() const\n\t\t{\n\t\t\treturn mnFlags;\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline void CoreAllocatorAdapter<AllocatorType>::set_flags(int flags)\n\t\t{\n\t\t\tmnFlags = flags;\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline const char* CoreAllocatorAdapter<AllocatorType>::get_name() const\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\treturn mpName;\n\t\t\t#else\n\t\t\t\treturn EASTL_ALLOCATOR_DEFAULT_NAME;\n\t\t\t#endif\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline void CoreAllocatorAdapter<AllocatorType>::set_name(const char* pName)\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tmpName = pName;\n\t\t\t#else\n\t\t\t\t(void)pName;\n\t\t\t#endif\n\t\t}\n\n\n\n\t\ttemplate<class AllocatorType>\n\t\tinline bool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b)\n\t\t{\n\t\t\treturn (a.mpCoreAllocator == b.mpCoreAllocator) &&\n\t\t\t\t   (a.mnFlags         == b.mnFlags);\n\t\t}\n\n\t\ttemplate<class AllocatorType>\n\t\tinline bool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b)\n\t\t{\n\t\t\treturn (a.mpCoreAllocator != b.mpCoreAllocator) ||\n\t\t\t\t   (a.mnFlags         != b.mnFlags);\n\t\t}\n\n\n\t} // namespace Allocator\n\n} // namespace EA\n\n\n#endif // EASTL_CORE_ALLOCATOR_ENABLED\n#endif // Header include guard\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/deque.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////////\n// deque design\n//\n// A deque (pronounced \"deck\") is a double-ended queue, though this is partially \n// of a misnomer. A deque does indeed let you add and remove values from both ends\n// of the container, but it's not usually used for such a thing and instead is used\n// as a more flexible version of a vector. It provides operator[] (random access) \n// and can insert items anywhere and not just at the front and back.\n// \n// While you can implement a double-ended queue via a doubly-linked list, deque is \n// instead implemented as a list of arrays. The benefit of this is that memory usage \n// is lower and that random access can be had with decent efficiency. \n// \n// Our implementation of deque is just like every other implementation of deque,\n// as the C++ standard all but dictates that you make it work this way. Below \n// we have a depiction of an array (or vector) of 48 items, with each node being \n// a '+' character and extra capacity being a '-' character. What we have is one \n// contiguous block of memory:\n// \n//     ++++++++++++++++++++++++++++++++++++++++++++++++-----------------\n//     0                                              47\n// \n// With a deque, the same array of 48 items would be implemented as multiple smaller\n// arrays of contiguous memory, each of fixed size. We will call these \"sub-arrays.\"\n// In the case here, we have six arrays of 8 nodes:\n// \n//     ++++++++ ++++++++ ++++++++ ++++++++ ++++++++ ++++++++\n// \n// With an vector, item [0] is the first item and item [47] is the last item. With a \n// deque, item [0] is usually not the first item and neither is item [47]. There is \n// extra capacity on both the front side and the back side of the deque. So a deque\n// (of 24 items) actually looks like this:\n// \n//     -------- -----+++ ++++++++ ++++++++ +++++--- --------\n//                   0                         23\n// \n// To insert items at the front, you move into the capacity on the left, and to insert\n// items at the back, you append items on the right. As you can see, inserting an item\n// at the front doesn't require allocating new memory nor does it require moving any \n// items in the container. It merely involves moving the pointer to the [0] item to\n// the left by one node.\n// \n// We keep track of these sub-arrays by having an array of pointers, with each array \n// entry pointing to each of the sub-arrays. We could alternatively use a linked\n// list of pointers, but it turns out we can implement our deque::operator[] more \n// efficiently if we use an array of pointers instead of a list of pointers.\n//\n// To implement deque::iterator, we could keep a struct which is essentially this:\n//     struct iterator {\n//        int subArrayIndex;\n//        int subArrayOffset;\n//     }\n//\n// In practice, we implement iterators a little differently, but in reality our \n// implementation isn't much different from the above. It turns out that it's most\n// simple if we also manage the location of item [0] and item [end] by using these\n// same iterators.\n//\n// To consider: Implement the deque as a circular deque instead of a linear one.\n//              This would use a similar subarray layout but iterators would\n//              wrap around when they reached the end of the subarray pointer list.\n//\n//////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_DEQUE_H\n#define EASTL_DEQUE_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/memory.h>\n#include <EASTL/initializer_list.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <new>\n#include <stddef.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <stdexcept> // std::out_of_range, std::length_error, std::logic_error.\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\n\n// 4267 - 'argument' : conversion from 'size_t' to 'const uint32_t', possible loss of data. This is a bogus warning resulting from a bug in VC++.\n// 4345 - Behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized\n// 4480 - nonstandard extension used: specifying underlying type for enum\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\nEA_DISABLE_VC_WARNING(4267 4345 4480 4530 4571);\n\n#if EASTL_EXCEPTIONS_ENABLED\n\t// 4703 - potentially uninitialized local pointer variable used. VC++ is mistakenly analyzing the possibility of uninitialized variables, though it's not easy for it to do so.\n\t// 4701 - potentially uninitialized local variable used.\n\tEA_DISABLE_VC_WARNING(4703 4701)\n#endif\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\nnamespace eastl\n{\n\n\t/// EASTL_DEQUE_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_DEQUE_DEFAULT_NAME\n\t\t#define EASTL_DEQUE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" deque\" // Unless the user overrides something, this is \"EASTL deque\".\n\t#endif\n\n\n\t/// EASTL_DEQUE_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_DEQUE_DEFAULT_ALLOCATOR\n\t\t#define EASTL_DEQUE_DEFAULT_ALLOCATOR allocator_type(EASTL_DEQUE_DEFAULT_NAME)\n\t#endif\n\n\n\t/// DEQUE_DEFAULT_SUBARRAY_SIZE\n\t///\n\t/// Defines the default number of items in a subarray.\n\t/// Note that the user has the option of specifying the subarray size\n\t/// in the deque template declaration.\n\t///\n\t#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x can't handle the declaration below.\n\t\t#define DEQUE_DEFAULT_SUBARRAY_SIZE(T) ((sizeof(T) <= 4) ? 64 : ((sizeof(T) <= 8) ? 32 : ((sizeof(T) <= 16) ? 16 : ((sizeof(T) <= 32) ? 8 : 4))))\n\t#else\n\t\t#define DEQUE_DEFAULT_SUBARRAY_SIZE(T) 16\n\t#endif\n\n\n\n\t/// DequeIterator\n\t///\n\t/// The DequeIterator provides both const and non-const iterators for deque. \n\t/// It also is used for the tracking of the begin and end for the deque.\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tstruct DequeIterator\n\t{\n\t\ttypedef DequeIterator<T, Pointer, Reference, kDequeSubarraySize>  this_type;\n\t\ttypedef DequeIterator<T, T*, T&, kDequeSubarraySize>              iterator;\n\t\ttypedef DequeIterator<T, const T*, const T&, kDequeSubarraySize>  const_iterator;\n\t\ttypedef ptrdiff_t                                                 difference_type;\n\t\ttypedef eastl::random_access_iterator_tag                  iterator_category;\n\t\ttypedef T                                                         value_type;\n\t\ttypedef T*                                                        pointer;\n\t\ttypedef T&                                                        reference;\n\n\tpublic:\n\t\tDequeIterator();\n\t\tDequeIterator(const iterator& x);\n\t\tDequeIterator& operator=(const iterator& x);\n\n\t\tpointer   operator->() const;\n\t\treference operator*() const;\n\n\t\tthis_type& operator++();\n\t\tthis_type  operator++(int);\n\n\t\tthis_type& operator--();\n\t\tthis_type  operator--(int);\n\n\t\tthis_type& operator+=(difference_type n);\n\t\tthis_type& operator-=(difference_type n);\n\n\t\tthis_type operator+(difference_type n) const;\n\t\tthis_type operator-(difference_type n) const;\n\n\tprotected:\n\t\ttemplate <typename, typename, typename, unsigned>\n\t\tfriend struct DequeIterator;\n\n\t\ttemplate <typename, typename, unsigned>\n\t\tfriend struct DequeBase;\n\n\t\ttemplate <typename, typename, unsigned>\n\t\tfriend class deque;\n\n\t\ttemplate <typename U, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySizeU>\n\t\tfriend bool operator==(const DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>&, \n\t\t\t\t\t\t\t   const DequeIterator<U, PointerB, ReferenceB, kDequeSubarraySizeU>&);\n\n\t\ttemplate <typename U, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySizeU>\n\t\tfriend bool operator!=(const DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>&, \n\t\t\t\t\t\t\t   const DequeIterator<U, PointerB, ReferenceB, kDequeSubarraySizeU>&);\n\n\t\ttemplate <typename U, typename PointerU, typename ReferenceU, unsigned kDequeSubarraySizeU>\n\t\tfriend bool operator!=(const DequeIterator<U, PointerU, ReferenceU, kDequeSubarraySizeU>& a, \n\t\t\t\t\t\t\t   const DequeIterator<U, PointerU, ReferenceU, kDequeSubarraySizeU>& b);\n\n\t\ttemplate <typename U, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySizeU>\n\t\tfriend bool operator< (const DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>&, \n\t\t\t\t\t\t\t   const DequeIterator<U, PointerB, ReferenceB, kDequeSubarraySizeU>&);\n\n\t\ttemplate <typename U, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySizeU>\n\t\tfriend bool operator> (const DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>&, \n\t\t\t\t\t\t\t   const DequeIterator<U, PointerB, ReferenceB, kDequeSubarraySizeU>&);\n\n\t\ttemplate <typename U, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySizeU>\n\t\tfriend bool operator<=(const DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>&, \n\t\t\t\t\t\t\t   const DequeIterator<U, PointerB, ReferenceB, kDequeSubarraySizeU>&);\n\n\t\ttemplate <typename U, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySizeU>\n\t\tfriend bool operator>=(const DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>&, \n\t\t\t\t\t\t\t   const DequeIterator<U, PointerB, ReferenceB, kDequeSubarraySizeU>&);\n\n\t\ttemplate <typename U, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySizeU>\n\t\tfriend typename DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>::difference_type\n\t\toperator-(const DequeIterator<U, PointerA, ReferenceA, kDequeSubarraySizeU>& a,\n\t\t\t\t  const DequeIterator<U, PointerB, ReferenceB, kDequeSubarraySizeU>& b);\n\n\tprotected:\n\t\tT*  mpCurrent;          // Where we currently point. Declared first because it's used most often.\n\t\tT*  mpBegin;            // The beginning of the current subarray.\n\t\tT*  mpEnd;              // The end of the current subarray. To consider: remove this member, as it is always equal to 'mpBegin + kDequeSubarraySize'. Given that deque subarrays usually consist of hundreds of bytes, this isn't a massive win. Also, now that we are implementing a zero-allocation new deque policy, mpEnd may in fact not be equal to 'mpBegin + kDequeSubarraySize'.\n\t\tT** mpCurrentArrayPtr;  // Pointer to current subarray. We could alternatively implement this as a list node iterator if the deque used a linked list.\n\n\t\tstruct Increment {};\n\t\tstruct Decrement {};\n\t\tstruct FromConst {};\n\n\t\tDequeIterator(T** pCurrentArrayPtr, T* pCurrent);\n\t\tDequeIterator(const const_iterator& x, FromConst) : mpCurrent(x.mpCurrent), mpBegin(x.mpBegin), mpEnd(x.mpEnd), mpCurrentArrayPtr(x.mpCurrentArrayPtr){}\n\t\tDequeIterator(const iterator&       x, Increment);\n\t\tDequeIterator(const iterator&       x, Decrement);\n\n\t\tthis_type move(const iterator& first, const iterator& last, true_type);  // true means that value_type has the type_trait is_trivially_copyable,\n\t\tthis_type move(const iterator& first, const iterator& last, false_type); // false means it does not. \n\n\t\tvoid move_backward(const iterator& first, const iterator& last, true_type);  // true means that value_type has the type_trait is_trivially_copyable,\n\t\tvoid move_backward(const iterator& first, const iterator& last, false_type); // false means it does not.\n\n\t\tvoid SetSubarray(T** pCurrentArrayPtr);\n\t};\n\n\n\n\n\t/// DequeBase\n\t///\n\t/// The DequeBase implements memory allocation for deque.\n\t/// See VectorBase (class vector) for an explanation of why we \n\t/// create this separate base class.\n\t///\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tstruct DequeBase\n\t{\n\t\ttypedef T                                                        value_type;\n\t\ttypedef Allocator                                                allocator_type;\n\t\ttypedef eastl_size_t                                             size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                                difference_type;\n\t\ttypedef DequeIterator<T, T*, T&, kDequeSubarraySize>             iterator;\n\t\ttypedef DequeIterator<T, const T*, const T&, kDequeSubarraySize> const_iterator;\n\n\t\tstatic const size_type npos     = (size_type)-1;      /// 'npos' means non-valid position or simply non-position.\n\t\tstatic const size_type kMaxSize = (size_type)-2;      /// -1 is reserved for 'npos'. It also happens to be slightly beneficial that kMaxSize is a value less than -1, as it helps us deal with potential integer wraparound issues.\n\n\t\tenum\n\t\t{\n\t\t\tkMinPtrArraySize = 8,                               /// A new empty deque has a ptrArraySize of 0, but any allocated ptrArrays use this min size.\n\t\t\tkSubarraySize    = kDequeSubarraySize               /// \n\t\t  //kNodeSize        = kDequeSubarraySize * sizeof(T)   /// Disabled because it prevents the ability to do this: struct X{ eastl::deque<X, EASTLAllocatorType, 16> mDequeOfSelf; };\n\t\t};\n\n\tprotected:\n\t\tenum Side       /// Defines the side of the deque: front or back.\n\t\t{\n\t\t\tkSideFront, /// Identifies the front side of the deque.\n\t\t\tkSideBack   /// Identifies the back side of the deque.\n\t\t};\n\n\t\tT**             mpPtrArray;         // Array of pointers to subarrays.\n\t\tsize_type       mnPtrArraySize;     // Possibly we should store this as T** mpArrayEnd.\n\t\titerator        mItBegin;           // Where within the subarrays is our beginning.\n\t\titerator        mItEnd;             // Where within the subarrays is our end.\n\t\tallocator_type  mAllocator;         // To do: Use base class optimization to make this go away.\n\n\tpublic:\n\t\tDequeBase(const allocator_type& allocator);\n\t\tDequeBase(size_type n);\n\t\tDequeBase(size_type n, const allocator_type& allocator);\n\t   ~DequeBase();\n\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT;\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT;\n\t\tvoid                  set_allocator(const allocator_type& allocator);\n\n\tprotected:\n\t\tT*       DoAllocateSubarray();\n\t\tvoid     DoFreeSubarray(T* p);\n\t\tvoid     DoFreeSubarrays(T** pBegin, T** pEnd);\n\n\t\tT**      DoAllocatePtrArray(size_type n);\n\t\tvoid     DoFreePtrArray(T** p, size_t n);\n\n\t\titerator DoReallocSubarray(size_type nAdditionalCapacity, Side allocationSide);\n\t\tvoid     DoReallocPtrArray(size_type nAdditionalCapacity, Side allocationSide);\n\n\t\tvoid     DoInit(size_type n);\n\n\t}; // DequeBase\n\n\n\n\n\t/// deque\n\t///\n\t/// Implements a conventional C++ double-ended queue. The implementation used here\n\t/// is very much like any other deque implementations you may have seen, as it \n\t/// follows the standard algorithm for deque design. \n\t///\n\t/// Note:\n\t/// As of this writing, deque does not support zero-allocation initial emptiness.\n\t/// A newly created deque with zero elements will still allocate a subarray\n\t/// pointer set. We are looking for efficient and clean ways to get around this,\n\t/// but current efforts have resulted in less efficient and more fragile code.\n\t/// The logic of this class doesn't lend itself to a clean implementation. \n\t/// It turns out that deques are one of the least likely classes you'd want this\n\t/// behaviour in, so until this functionality becomes very important to somebody,\n\t/// we will leave it as-is. It can probably be solved by adding some extra code to\n\t/// the Do* functions and adding good comments explaining the situation.\n\t/// \n\ttemplate <typename T, typename Allocator = EASTLAllocatorType, unsigned kDequeSubarraySize = DEQUE_DEFAULT_SUBARRAY_SIZE(T)>\n\tclass deque : public DequeBase<T, Allocator, kDequeSubarraySize>\n\t{\n\tpublic:\n\t\ttypedef DequeBase<T, Allocator, kDequeSubarraySize>              base_type;\n\t\ttypedef deque<T, Allocator, kDequeSubarraySize>                  this_type;\n\t\ttypedef T                                                        value_type;\n\t\ttypedef T*                                                       pointer;\n\t\ttypedef const T*                                                 const_pointer;\n\t\ttypedef T&                                                       reference;\n\t\ttypedef const T&                                                 const_reference;\n\t\ttypedef DequeIterator<T, T*, T&, kDequeSubarraySize>             iterator;\n\t\ttypedef DequeIterator<T, const T*, const T&, kDequeSubarraySize> const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>                        reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>                  const_reverse_iterator;\n\t\ttypedef typename base_type::size_type                            size_type;\n\t\ttypedef typename base_type::difference_type                      difference_type;\n\t\ttypedef typename base_type::allocator_type                       allocator_type;\n\n\t\tusing base_type::npos;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"deque<T>::value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"deque<T>::value_type must be non-volatile.\");\n\n\tprotected:\n\t\tusing base_type::kSideFront;\n\t\tusing base_type::kSideBack;\n\t\tusing base_type::mpPtrArray;\n\t\tusing base_type::mnPtrArraySize;\n\t\tusing base_type::mItBegin;\n\t\tusing base_type::mItEnd;\n\t\tusing base_type::mAllocator;\n\t\tusing base_type::DoAllocateSubarray;\n\t\tusing base_type::DoFreeSubarray;\n\t\tusing base_type::DoFreeSubarrays;\n\t\tusing base_type::DoAllocatePtrArray;\n\t\tusing base_type::DoFreePtrArray;\n\t\tusing base_type::DoReallocSubarray;\n\t\tusing base_type::DoReallocPtrArray;\n\n\tpublic:\n\t\tdeque();\n\t\texplicit deque(const allocator_type& allocator);\n\t\texplicit deque(size_type n, const allocator_type& allocator = EASTL_DEQUE_DEFAULT_ALLOCATOR);\n\t\tdeque(size_type n, const value_type& value, const allocator_type& allocator = EASTL_DEQUE_DEFAULT_ALLOCATOR);\n\t\tdeque(const this_type& x);\n\t\tdeque(this_type&& x);\n\t\tdeque(this_type&& x, const allocator_type& allocator);\n\t\tdeque(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_DEQUE_DEFAULT_ALLOCATOR);\n\n\t\t// note: this has pre-C++11 semantics:\n\t\t// this constructor is equivalent to the constructor deque(static_cast<size_type>(first), static_cast<value_type>(last)) if InputIterator is an integral type.\n\t\ttemplate <typename InputIterator>\n\t\tdeque(InputIterator first, InputIterator last); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t   ~deque();\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid assign(size_type n, const value_type& value);\n\t\tvoid assign(std::initializer_list<value_type> ilist);\n\n\t\ttemplate <typename InputIterator>                       // It turns out that the C++ std::deque<int, int> specifies a two argument\n\t\tvoid assign(InputIterator first, InputIterator last);   // version of assign that takes (int size, int value). These are not \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// iterators, so we need to do a template compiler trick to do the right thing.\n\n\t\titerator       begin() EA_NOEXCEPT;\n\t\tconst_iterator begin() const EA_NOEXCEPT;\n\t\tconst_iterator cbegin() const EA_NOEXCEPT;\n\n\t\titerator       end() EA_NOEXCEPT;\n\t\tconst_iterator end() const EA_NOEXCEPT;\n\t\tconst_iterator cend() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rbegin() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crbegin() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rend() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rend() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crend() const EA_NOEXCEPT;\n\n\t\tbool      empty() const EA_NOEXCEPT; \n\t\tsize_type size() const EA_NOEXCEPT;\n\n\t\tvoid resize(size_type n, const value_type& value);\n\t\tvoid resize(size_type n);\n\n\t\tvoid shrink_to_fit();\n\t\tvoid set_capacity(size_type n = base_type::npos);\n\n\t\treference       operator[](size_type n);\n\t\tconst_reference operator[](size_type n) const;\n\n\t\treference       at(size_type n);\n\t\tconst_reference at(size_type n) const;\n\n\t\treference       front();\n\t\tconst_reference front() const;\n\n\t\treference       back();\n\t\tconst_reference back() const;\n\n\t\tvoid      push_front(const value_type& value);\n\t\treference push_front();\n\t\tvoid      push_front(value_type&& value);\n\n\t\tvoid      push_back(const value_type& value);\n\t\treference push_back();\n\t\tvoid      push_back(value_type&& value);\n\n\t\tvoid pop_front();\n\t\tvoid pop_back();\n\n\t\ttemplate<class... Args>\n\t\titerator emplace(const_iterator position, Args&&... args);\n\n\t\ttemplate<class... Args>\n\t\treference emplace_front(Args&&... args);\n\n\t\ttemplate<class... Args>\n\t\treference emplace_back(Args&&... args);\n\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\titerator insert(const_iterator position, value_type&& value);\n\t\titerator insert(const_iterator position, size_type n, const value_type& value);\n\t\titerator insert(const_iterator position, std::initializer_list<value_type> ilist);\n\n\t\t// note: this has pre-C++11 semantics:\n\t\t// this function is equivalent to insert(const_iterator position, static_cast<size_type>(first), static_cast<value_type>(last)) if InputIterator is an integral type.\n\t\t// ie. same as insert(const_iterator position, size_type n, const value_type& value)\n\t\ttemplate <typename InputIterator>\n\t\titerator insert(const_iterator position, InputIterator first, InputIterator last);\n\n\t\titerator         erase(const_iterator position);\n\t\titerator         erase(const_iterator first, const_iterator last);\n\t\treverse_iterator erase(reverse_iterator position);\n\t\treverse_iterator erase(reverse_iterator first, reverse_iterator last);\n\n\t\tvoid clear();\n\t\t//void reset_lose_memory(); // Disabled until it can be implemented efficiently and cleanly.  // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\tprotected:\n\t\ttemplate <typename Integer>\n\t\tvoid DoInit(Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoInit(InputIterator first, InputIterator last, false_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoInitFromIterator(InputIterator first, InputIterator last, eastl::input_iterator_tag);\n\n\t\ttemplate <typename ForwardIterator>\n\t\tvoid DoInitFromIterator(ForwardIterator first, ForwardIterator last, eastl::forward_iterator_tag);\n\n\t\tvoid DoFillInit(const value_type& value);\n\n\t\ttemplate <typename Integer>\n\t\tvoid DoAssign(Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoAssign(InputIterator first, InputIterator last, false_type);\n\n\t\tvoid DoAssignValues(size_type n, const value_type& value);\n\n\t\ttemplate <typename Integer>\n\t\titerator DoInsert(const const_iterator& position, Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\titerator DoInsert(const const_iterator& position, const InputIterator& first, const InputIterator& last, false_type);\n\n\t\ttemplate <typename InputIterator>\n\t\titerator DoInsertFromIterator(const_iterator position, const InputIterator& first, const InputIterator& last, eastl::input_iterator_tag);\n\n\t\ttemplate <typename ForwardIterator>\n\t\titerator DoInsertFromIterator(const_iterator position, const ForwardIterator& first, const ForwardIterator& last, eastl::forward_iterator_tag);\n\n\t\titerator DoInsertValues(const_iterator position, size_type n, const value_type& value);\n\n\t\tvoid DoSwap(this_type& x);\n\t}; // class deque\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// DequeBase\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tDequeBase<T, Allocator, kDequeSubarraySize>::DequeBase(const allocator_type& allocator)\n\t\t: mpPtrArray(NULL),\n\t\t  mnPtrArraySize(0),\n\t\t  mItBegin(),\n\t\t  mItEnd(),\n\t\t  mAllocator(allocator)\n\t{\n\t\t// It is assumed here that the deque subclass will init us when/as needed.\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tDequeBase<T, Allocator, kDequeSubarraySize>::DequeBase(size_type n)\n\t\t: mpPtrArray(NULL),\n\t\t  mnPtrArraySize(0),\n\t\t  mItBegin(),\n\t\t  mItEnd(),\n\t\t  mAllocator(EASTL_DEQUE_DEFAULT_NAME)\n\t{\n\t\t// It's important to note that DoInit creates space for elements and assigns \n\t\t// mItBegin/mItEnd to point to them, but these elements are not constructed. \n\t\t// You need to immediately follow this constructor with code that constructs the values.\n\t\tDoInit(n); \n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tDequeBase<T, Allocator, kDequeSubarraySize>::DequeBase(size_type n, const allocator_type& allocator)\n\t\t: mpPtrArray(NULL),\n\t\t  mnPtrArraySize(0),\n\t\t  mItBegin(),\n\t\t  mItEnd(),\n\t\t  mAllocator(allocator)\n\t{\n\t\t// It's important to note that DoInit creates space for elements and assigns \n\t\t// mItBegin/mItEnd to point to them, but these elements are not constructed. \n\t\t// You need to immediately follow this constructor with code that constructs the values.\n\t\tDoInit(n); \n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tDequeBase<T, Allocator, kDequeSubarraySize>::~DequeBase()\n\t{\n\t\tif(mpPtrArray)\n\t\t{\n\t\t\tDoFreeSubarrays(mItBegin.mpCurrentArrayPtr, mItEnd.mpCurrentArrayPtr + 1);\n\t\t\tDoFreePtrArray(mpPtrArray, mnPtrArraySize);\n\t\t\tmpPtrArray = nullptr;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tconst typename DequeBase<T, Allocator, kDequeSubarraySize>::allocator_type&\n\tDequeBase<T, Allocator, kDequeSubarraySize>::get_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename DequeBase<T, Allocator, kDequeSubarraySize>::allocator_type&\n\tDequeBase<T, Allocator, kDequeSubarraySize>::get_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid DequeBase<T, Allocator, kDequeSubarraySize>::set_allocator(const allocator_type& allocator)\n\t{\n\t\t// The only time you can set an allocator is with an empty unused container, such as right after construction.\n\t\tif(EASTL_LIKELY(mAllocator != allocator))\n\t\t{\n\t\t\t// our deque implementation always has allocations for mpPtrArray. this set_allocator() is unlike other container's set_allocator() member function\n\t\t\t// in that it actually frees allocations when assigning the allocator. this lack of consistency is unfortunate.\n\t\t\tif(EASTL_LIKELY(mpPtrArray && (mItBegin.mpCurrent == mItEnd.mpCurrent))) // is the container empty?\n\t\t\t{\n\t\t\t\tDoFreeSubarrays(mItBegin.mpCurrentArrayPtr, mItEnd.mpCurrentArrayPtr + 1);\n\t\t\t\tDoFreePtrArray(mpPtrArray, mnPtrArraySize);\n\n\t\t\t\tmAllocator = allocator;\n\t\t\t\tDoInit(0);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"deque::set_allocator -- attempt to change allocator after inserting elements.\");\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tT* DequeBase<T, Allocator, kDequeSubarraySize>::DoAllocateSubarray()\n\t{\n\t\tT* p = (T*)allocate_memory(mAllocator, kDequeSubarraySize * sizeof(T), EASTL_ALIGN_OF(T), 0);\n\t\tEASTL_ASSERT_MSG(p != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\t#if EASTL_DEBUG\n\t\t\tmemset((void*)p, 0, kDequeSubarraySize * sizeof(T));\n\t\t#endif\n\n\t\treturn (T*)p;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid DequeBase<T, Allocator, kDequeSubarraySize>::DoFreeSubarray(T* p)\n\t{\n\t\tif(p)\n\t\t\tEASTLFree(mAllocator, p, kDequeSubarraySize * sizeof(T)); \n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid DequeBase<T, Allocator, kDequeSubarraySize>::DoFreeSubarrays(T** pBegin, T** pEnd)\n\t{\n\t\twhile(pBegin < pEnd)\n\t\t\tDoFreeSubarray(*pBegin++);\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tT** DequeBase<T, Allocator, kDequeSubarraySize>::DoAllocatePtrArray(size_type n)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= 0x80000000))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::DoAllocatePtrArray -- improbably large request.\");\n\t\t#endif\n\n\t\tT** pp = (T**)allocate_memory(mAllocator, n * sizeof(T*), EASTL_ALIGN_OF(T), 0);\n\t\tEASTL_ASSERT_MSG(pp != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\t#if EASTL_DEBUG\n\t\t\tmemset((void*)pp, 0, n * sizeof(T*));\n\t\t#endif\n\n\t\treturn pp;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid DequeBase<T, Allocator, kDequeSubarraySize>::DoFreePtrArray(T** pp, size_t n)\n\t{\n\t\tif(pp)\n\t\t\tEASTLFree(mAllocator, pp, n * sizeof(T*)); \n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename DequeBase<T, Allocator, kDequeSubarraySize>::iterator\n\tDequeBase<T, Allocator, kDequeSubarraySize>::DoReallocSubarray(size_type nAdditionalCapacity, Side allocationSide)\n\t{\n\t\t// nAdditionalCapacity refers to the amount of additional space we need to be \n\t\t// able to store in this deque. Typically this function is called as part of \n\t\t// an insert or append operation. This is the function that makes sure there\n\t\t// is enough capacity for the new elements to be copied into the deque.\n\t\t// The new capacity here is always at the front or back of the deque.\n\t\t// This function returns an iterator to that points to the new begin or\n\t\t// the new end of the deque space, depending on allocationSide.\n\n\t\tif(allocationSide == kSideFront)\n\t\t{\n\t\t\t// There might be some free space (nCurrentAdditionalCapacity) at the front of the existing subarray.\n\t\t\tconst size_type nCurrentAdditionalCapacity = (size_type)(mItBegin.mpCurrent - mItBegin.mpBegin);\n\n\t\t\tif(EASTL_UNLIKELY(nCurrentAdditionalCapacity < nAdditionalCapacity)) // If we need to grow downward into a new subarray...\n\t\t\t{\n\t\t\t\tconst difference_type nSubarrayIncrease = (difference_type)(((nAdditionalCapacity - nCurrentAdditionalCapacity) + kDequeSubarraySize - 1) / kDequeSubarraySize);\n\t\t\t\tdifference_type i;\n\n\t\t\t\tif(nSubarrayIncrease > (mItBegin.mpCurrentArrayPtr - mpPtrArray)) // If there are not enough pointers in front of the current (first) one...\n\t\t\t\t\tDoReallocPtrArray((size_type)(nSubarrayIncrease - (mItBegin.mpCurrentArrayPtr - mpPtrArray)), kSideFront);\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t#endif\n\t\t\t\t\t\tfor(i = 1; i <= nSubarrayIncrease; ++i)\n\t\t\t\t\t\t\tmItBegin.mpCurrentArrayPtr[-i] = DoAllocateSubarray();\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor(difference_type j = 1; j < i; ++j)\n\t\t\t\t\t\t\tDoFreeSubarray(mItBegin.mpCurrentArrayPtr[-j]);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\treturn mItBegin - (difference_type)nAdditionalCapacity;\n\t\t}\n\t\telse // else kSideBack\n\t\t{\n\t\t\tconst size_type nCurrentAdditionalCapacity = (size_type)((mItEnd.mpEnd - 1) - mItEnd.mpCurrent);\n\n\t\t\tif(EASTL_UNLIKELY(nCurrentAdditionalCapacity < nAdditionalCapacity)) // If we need to grow forward into a new subarray...\n\t\t\t{\n\t\t\t\tconst difference_type nSubarrayIncrease = (difference_type)(((nAdditionalCapacity - nCurrentAdditionalCapacity) + kDequeSubarraySize - 1) / kDequeSubarraySize);\n\t\t\t\tdifference_type i;\n\n\t\t\t\tif(nSubarrayIncrease > ((mpPtrArray + mnPtrArraySize) - mItEnd.mpCurrentArrayPtr) - 1)  // If there are not enough pointers after the current (last) one...\n\t\t\t\t\tDoReallocPtrArray((size_type)(nSubarrayIncrease - (((mpPtrArray + mnPtrArraySize) - mItEnd.mpCurrentArrayPtr) - 1)), kSideBack);\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t#endif\n\t\t\t\t\t\tfor(i = 1; i <= nSubarrayIncrease; ++i)\n\t\t\t\t\t\t\tmItEnd.mpCurrentArrayPtr[i] = DoAllocateSubarray();\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor(difference_type j = 1; j < i; ++j)\n\t\t\t\t\t\t\tDoFreeSubarray(mItEnd.mpCurrentArrayPtr[j]);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\treturn mItEnd + (difference_type)nAdditionalCapacity;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid DequeBase<T, Allocator, kDequeSubarraySize>::DoReallocPtrArray(size_type nAdditionalCapacity, Side allocationSide)\n\t{\n\t\t// This function is not called unless the capacity is known to require a resize.\n\t\t//\n\t\t// We have an array of pointers (mpPtrArray), of which a segment of them are in use and \n\t\t// at either end of the array are zero or more unused pointers. This function is being\n\t\t// called because we need to extend the capacity on either side of this array by \n\t\t// nAdditionalCapacity pointers. However, it's possible that if the user is continually\n\t\t// using push_back and pop_front then the pointer array will continue to be extended \n\t\t// on the back side and unused on the front side. So while we are doing this resizing \n\t\t// here we also take the opportunity to recenter the pointers and thus be balanced.\n\t\t// It man turn out that we don't even need to reallocate the pointer array in order\n\t\t// to increase capacity on one side, as simply moving the pointers to the center may\n\t\t// be enough to open up the requires space.\n\t\t//\n\t\t// Balanced pointer array     Unbalanced pointer array (unused space at front, no free space at back)\n\t\t// ----++++++++++++----        ---------+++++++++++\n\n\t\tconst size_type nUnusedPtrCountAtFront = (size_type)(mItBegin.mpCurrentArrayPtr - mpPtrArray);\n\t\tconst size_type nUsedPtrCount          = (size_type)(mItEnd.mpCurrentArrayPtr - mItBegin.mpCurrentArrayPtr) + 1;\n\t\tconst size_type nUsedPtrSpace          = nUsedPtrCount * sizeof(void*);\n\t\tconst size_type nUnusedPtrCountAtBack  = (mnPtrArraySize - nUnusedPtrCountAtFront) - nUsedPtrCount;\n\t\tvalue_type**    pPtrArrayBegin;\n\n\t\tif((allocationSide == kSideBack) && (nAdditionalCapacity <= nUnusedPtrCountAtFront))  // If we can take advantage of unused pointers at the front without doing any reallocation...\n\t\t{\n\t\t\tif(nAdditionalCapacity < (nUnusedPtrCountAtFront / 2))  // Possibly use more space than required, if there's a lot of extra space.\n\t\t\t\tnAdditionalCapacity = (nUnusedPtrCountAtFront / 2);\n\n\t\t\tpPtrArrayBegin = mpPtrArray + (nUnusedPtrCountAtFront - nAdditionalCapacity);\n\t\t\tmemmove(pPtrArrayBegin, mItBegin.mpCurrentArrayPtr, nUsedPtrSpace);\n\n\t\t\t#if EASTL_DEBUG\n\t\t\t\tmemset(pPtrArrayBegin + nUsedPtrCount, 0, (size_t)(mpPtrArray + mnPtrArraySize) - (size_t)(pPtrArrayBegin + nUsedPtrCount));\n\t\t\t#endif\n\t\t}\n\t\telse if((allocationSide == kSideFront) && (nAdditionalCapacity <= nUnusedPtrCountAtBack)) // If we can take advantage of unused pointers at the back without doing any reallocation...\n\t\t{\n\t\t\tif(nAdditionalCapacity < (nUnusedPtrCountAtBack / 2))  // Possibly use more space than required, if there's a lot of extra space.\n\t\t\t\tnAdditionalCapacity = (nUnusedPtrCountAtBack / 2);\n\n\t\t\tpPtrArrayBegin = mItBegin.mpCurrentArrayPtr + nAdditionalCapacity;\n\t\t\tmemmove(pPtrArrayBegin, mItBegin.mpCurrentArrayPtr, nUsedPtrSpace);\n\n\t\t\t#if EASTL_DEBUG\n\t\t\t\tmemset(mpPtrArray, 0, (size_t)((uintptr_t)pPtrArrayBegin - (uintptr_t)mpPtrArray));\n\t\t\t#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// In this case we will have to do a reallocation.\n\t\t\tconst size_type    nNewPtrArraySize = mnPtrArraySize + eastl::max_alt(mnPtrArraySize, nAdditionalCapacity) + 2;  // Allocate extra capacity.\n\t\t\tvalue_type** const pNewPtrArray     = DoAllocatePtrArray(nNewPtrArraySize);\n\n\t\t\tpPtrArrayBegin = pNewPtrArray + (mItBegin.mpCurrentArrayPtr - mpPtrArray) + ((allocationSide == kSideFront) ? nAdditionalCapacity : 0);\n\n\t\t\t// The following is equivalent to: eastl::copy(mItBegin.mpCurrentArrayPtr, mItEnd.mpCurrentArrayPtr + 1, pPtrArrayBegin);\n\t\t\t// It's OK to use memcpy instead of memmove because the destination is guaranteed to non-overlap the source.\n\t\t\tif(mpPtrArray) // Could also say: 'if(mItBegin.mpCurrentArrayPtr)' \n\t\t\t\tmemcpy(pPtrArrayBegin, mItBegin.mpCurrentArrayPtr, nUsedPtrSpace);\n\n\t\t\tDoFreePtrArray(mpPtrArray, mnPtrArraySize);\n\n\t\t\tmpPtrArray     = pNewPtrArray;\n\t\t\tmnPtrArraySize = nNewPtrArraySize;\n\t\t}\n\n\t\t// We need to reset the begin and end iterators, as code that calls this expects them to *not* be invalidated.\n\t\tmItBegin.SetSubarray(pPtrArrayBegin);\n\t\tmItEnd.SetSubarray((pPtrArrayBegin + nUsedPtrCount) - 1);\n\t}\n\t\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid DequeBase<T, Allocator, kDequeSubarraySize>::DoInit(size_type n)\n\t{\n\t\t// This code is disabled because it doesn't currently work properly.\n\t\t// We are trying to make it so that a deque can have a zero allocation \n\t\t// initial empty state, but we (OK, I) am having a hard time making\n\t\t// this elegant and efficient. \n\t\t//if(n)\n\t\t//{\n\t\t\tconst size_type nNewPtrArraySize = (size_type)((n / kDequeSubarraySize) + 1); // Always have at least one, even if n is zero.\n\t\t\tconst size_type kMinPtrArraySize_ = kMinPtrArraySize;\n\n\t\t\tmnPtrArraySize = eastl::max_alt(kMinPtrArraySize_, (nNewPtrArraySize + 2)); \n\t\t\tmpPtrArray     = DoAllocatePtrArray(mnPtrArraySize);\n\n\t\t\tvalue_type** const pPtrArrayBegin   = (mpPtrArray + ((mnPtrArraySize - nNewPtrArraySize) / 2)); // Try to place it in the middle.\n\t\t\tvalue_type** const pPtrArrayEnd     = pPtrArrayBegin + nNewPtrArraySize;\n\t\t\tvalue_type**       pPtrArrayCurrent = pPtrArrayBegin;\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\t\twhile(pPtrArrayCurrent < pPtrArrayEnd)\n\t\t\t\t\t\t\t*pPtrArrayCurrent++ = DoAllocateSubarray();\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tDoFreeSubarrays(pPtrArrayBegin, pPtrArrayCurrent);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tDoFreePtrArray(mpPtrArray, mnPtrArraySize);\n\t\t\t\t\tmpPtrArray     = NULL;\n\t\t\t\t\tmnPtrArraySize = 0;\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\tmItBegin.SetSubarray(pPtrArrayBegin);\n\t\t\tmItBegin.mpCurrent = mItBegin.mpBegin;\n\n\t\t\tmItEnd.SetSubarray(pPtrArrayEnd - 1);\n\t\t\tmItEnd.mpCurrent = mItEnd.mpBegin + (difference_type)(n % kDequeSubarraySize);\n\t\t//}\n\t\t//else // Else we do a zero-allocation initialization.\n\t\t//{\n\t\t//    mpPtrArray     = NULL;\n\t\t//    mnPtrArraySize = 0;\n\t\t//\n\t\t//    mItBegin.mpCurrentArrayPtr = NULL;\n\t\t//    mItBegin.mpBegin           = NULL;\n\t\t//    mItBegin.mpEnd             = NULL; // We intentionally create a situation whereby the subarray that has no capacity.\n\t\t//    mItBegin.mpCurrent         = NULL;\n\t\t//\n\t\t//    mItEnd = mItBegin;\n\t\t//}\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// DequeIterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::DequeIterator()\n\t\t: mpCurrent(NULL), mpBegin(NULL), mpEnd(NULL), mpCurrentArrayPtr(NULL)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::DequeIterator(T** pCurrentArrayPtr, T* pCurrent)\n\t\t: mpCurrent(pCurrent), mpBegin(*pCurrentArrayPtr), mpEnd(pCurrent + kDequeSubarraySize), mpCurrentArrayPtr(pCurrentArrayPtr)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::DequeIterator(const iterator& x)\n\t\t: mpCurrent(x.mpCurrent), mpBegin(x.mpBegin), mpEnd(x.mpEnd), mpCurrentArrayPtr(x.mpCurrentArrayPtr)\n\t{\n\t\t// Empty\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>& DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator=(const iterator& x)\n\t{\n\t\tmpCurrent = x.mpCurrent;\n\t\tmpBegin = x.mpBegin;\n\t\tmpEnd = x.mpEnd;\n\t\tmpCurrentArrayPtr = x.mpCurrentArrayPtr;\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::DequeIterator(const iterator& x, Increment)\n\t\t: mpCurrent(x.mpCurrent), mpBegin(x.mpBegin), mpEnd(x.mpEnd), mpCurrentArrayPtr(x.mpCurrentArrayPtr)\n\t{\n\t\toperator++();\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::DequeIterator(const iterator& x, Decrement)\n\t\t: mpCurrent(x.mpCurrent), mpBegin(x.mpBegin), mpEnd(x.mpEnd), mpCurrentArrayPtr(x.mpCurrentArrayPtr)\n\t{\n\t\toperator--();\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::pointer\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator->() const\n\t{\n\t\treturn mpCurrent;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::reference\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator*() const\n\t{\n\t\treturn *mpCurrent;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type&\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator++()\n\t{\n\t\tif(EASTL_UNLIKELY(++mpCurrent == mpEnd))\n\t\t{\n\t\t\tmpBegin   = *++mpCurrentArrayPtr;\n\t\t\tmpEnd     = mpBegin + kDequeSubarraySize;\n\t\t\tmpCurrent = mpBegin;\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator++(int)\n\t{\n\t\tconst this_type temp(*this);\n\t\toperator++();\n\t\treturn temp;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type&\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator--()\n\t{\n\t\tif(EASTL_UNLIKELY(mpCurrent == mpBegin))\n\t\t{\n\t\t\tmpBegin   = *--mpCurrentArrayPtr;\n\t\t\tmpEnd     = mpBegin + kDequeSubarraySize;\n\t\t\tmpCurrent = mpEnd; // fall through...\n\t\t}\n\t\t--mpCurrent;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator--(int)\n\t{\n\t\tconst this_type temp(*this);\n\t\toperator--();\n\t\treturn temp;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type&\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator+=(difference_type n)\n\t{\n\t\tconst difference_type subarrayPosition = (mpCurrent - mpBegin) + n;\n\n\t\t// Cast from signed to unsigned (size_t) in order to obviate the need to compare to < 0. \n\t\tif((size_t)subarrayPosition < (size_t)kDequeSubarraySize) // If the new position is within the current subarray (i.e. >= 0 && < kSubArraySize)...\n\t\t\tmpCurrent += n;\n\t\telse\n\t\t{\n\t\t\t// This implementation is a branchless version which works by offsetting \n\t\t\t// the math to always be in the positive range. Much of the values here\n\t\t\t// reduce to constants and both the multiplication and division are of \n\t\t\t// power of two sizes and so this calculation ends up compiling down to \n\t\t\t// just one addition, one shift and one subtraction. This algorithm has \n\t\t\t// a theoretical weakness in that on 32 bit systems it will fail if the \n\t\t\t// value of n is >= (2^32 - 2^24) or 4,278,190,080 of if kDequeSubarraySize\n\t\t\t// is >= 2^24 or 16,777,216.\n\t\t\tEASTL_CT_ASSERT((kDequeSubarraySize & (kDequeSubarraySize - 1)) == 0); // Verify that it is a power of 2.\n\t\t\tconst difference_type subarrayIndex = (((16777216 + subarrayPosition) / (difference_type)kDequeSubarraySize)) - (16777216 / (difference_type)kDequeSubarraySize);\n\n\t\t\tSetSubarray(mpCurrentArrayPtr + subarrayIndex);\n\t\t\tmpCurrent = mpBegin + (subarrayPosition - (subarrayIndex * (difference_type)kDequeSubarraySize));\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type&\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator-=(difference_type n)\n\t{\n\t\treturn (*this).operator+=(-n);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator+(difference_type n) const\n\t{\n\t\treturn this_type(*this).operator+=(n);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::operator-(difference_type n) const\n\t{\n\t\treturn this_type(*this).operator+=(-n);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::move(const iterator& first, const iterator& last, true_type)\n\t{\n\t\t// To do: Implement this as a loop which does memcpys between subarrays appropriately.\n\t\t//        Currently we only do memcpy if the entire operation occurs within a single subarray.\n\t\tif((first.mpBegin == last.mpBegin) && (first.mpBegin == mpBegin)) // If all operations are within the same subarray, implement the operation as a memmove.\n\t\t{\n\t\t\tmemmove(mpCurrent, first.mpCurrent, (size_t)((uintptr_t)last.mpCurrent - (uintptr_t)first.mpCurrent));\n\t\t\treturn *this + (last.mpCurrent - first.mpCurrent);\n\t\t}\n\t\treturn eastl::move(first, last, *this);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\ttypename DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::this_type\n\tDequeIterator<T, Pointer, Reference, kDequeSubarraySize>::move(const iterator& first, const iterator& last, false_type)\n\t{\n\t\treturn eastl::move(first, last, *this);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tvoid DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::move_backward(const iterator& first, const iterator& last, true_type)\n\t{\n\t\t// To do: Implement this as a loop which does memmoves between subarrays appropriately.\n\t\t//        Currently we only do memcpy if the entire operation occurs within a single subarray.\n\t\tif((first.mpBegin == last.mpBegin) && (first.mpBegin == mpBegin)) // If all operations are within the same subarray, implement the operation as a memcpy.\n\t\t\tmemmove(mpCurrent - (last.mpCurrent - first.mpCurrent), first.mpCurrent, (size_t)((uintptr_t)last.mpCurrent - (uintptr_t)first.mpCurrent));\n\t\telse\n\t\t\teastl::move_backward(first, last, *this);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tvoid DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::move_backward(const iterator& first, const iterator& last, false_type)\n\t{\n\t\teastl::move_backward(first, last, *this);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tvoid DequeIterator<T, Pointer, Reference, kDequeSubarraySize>::SetSubarray(T** pCurrentArrayPtr)\n\t{\n\t\tmpCurrentArrayPtr = pCurrentArrayPtr;\n\t\tmpBegin           = *pCurrentArrayPtr;\n\t\tmpEnd             = mpBegin + kDequeSubarraySize;\n\t}\n\n\n\t// The C++ defect report #179 requires that we support comparisons between const and non-const iterators.\n\t// Thus we provide additional template paremeters here to support this. The defect report does not\n\t// require us to support comparisons between reverse_iterators and const_reverse_iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySize>\n\tinline bool operator==(const DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>& a, \n\t\t\t\t\t\t   const DequeIterator<T, PointerB, ReferenceB, kDequeSubarraySize>& b)\n\t{\n\t\treturn a.mpCurrent == b.mpCurrent;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySize>\n\tinline bool operator!=(const DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>& a, \n\t\t\t\t\t\t   const DequeIterator<T, PointerB, ReferenceB, kDequeSubarraySize>& b)\n\t{\n\t\treturn a.mpCurrent != b.mpCurrent;\n\t}\n\n\n\t// We provide a version of operator!= for the case where the iterators are of the \n\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tinline bool operator!=(const DequeIterator<T, Pointer, Reference, kDequeSubarraySize>& a, \n\t\t\t\t\t\t   const DequeIterator<T, Pointer, Reference, kDequeSubarraySize>& b)\n\t{\n\t\treturn a.mpCurrent != b.mpCurrent;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySize>\n\tinline bool operator<(const DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>& a, \n\t\t\t\t\t\t  const DequeIterator<T, PointerB, ReferenceB, kDequeSubarraySize>& b)\n\t{\n\t\treturn (a.mpCurrentArrayPtr == b.mpCurrentArrayPtr) ? (a.mpCurrent < b.mpCurrent) : (a.mpCurrentArrayPtr < b.mpCurrentArrayPtr);\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySize>\n\tinline bool operator>(const DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>& a, \n\t\t\t\t\t\t  const DequeIterator<T, PointerB, ReferenceB, kDequeSubarraySize>& b)\n\t{\n\t\treturn (a.mpCurrentArrayPtr == b.mpCurrentArrayPtr) ? (a.mpCurrent > b.mpCurrent) : (a.mpCurrentArrayPtr > b.mpCurrentArrayPtr);\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySize>\n\tinline bool operator<=(const DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>& a, \n\t\t\t\t\t\t   const DequeIterator<T, PointerB, ReferenceB, kDequeSubarraySize>& b)\n\t{\n\t\treturn (a.mpCurrentArrayPtr == b.mpCurrentArrayPtr) ? (a.mpCurrent <= b.mpCurrent) : (a.mpCurrentArrayPtr <= b.mpCurrentArrayPtr);\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySize>\n\tinline bool operator>=(const DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>& a, \n\t\t\t\t\t\t   const DequeIterator<T, PointerB, ReferenceB, kDequeSubarraySize>& b)\n\t{\n\t\treturn (a.mpCurrentArrayPtr == b.mpCurrentArrayPtr) ? (a.mpCurrent >= b.mpCurrent) : (a.mpCurrentArrayPtr >= b.mpCurrentArrayPtr);\n\t}\n\n\n\t// Random access iterators must support operator + and operator -.\n\t// You can only add an integer to an iterator, and you cannot add two iterators.\n\ttemplate <typename T, typename Pointer, typename Reference, unsigned kDequeSubarraySize>\n\tinline DequeIterator<T, Pointer, Reference, kDequeSubarraySize>\n\toperator+(ptrdiff_t n, const DequeIterator<T, Pointer, Reference, kDequeSubarraySize>& x)\n\t{\n\t\treturn x + n; // Implement (n + x) in terms of (x + n).\n\t}\n\n\n\t// You can only add an integer to an iterator, but you can subtract two iterators.\n\t// The C++ defect report #179 mentioned above specifically refers to \n\t// operator - and states that we support the subtraction of const and non-const iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB, unsigned kDequeSubarraySize>\n\tinline typename DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>::difference_type\n\toperator-(const DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>& a,\n\t\t\t  const DequeIterator<T, PointerB, ReferenceB, kDequeSubarraySize>& b)\n\t{\n\t\t// This is a fairly clever algorithm that has been used in STL deque implementations since the original HP STL:\n\t\ttypedef typename DequeIterator<T, PointerA, ReferenceA, kDequeSubarraySize>::difference_type difference_type;\n\n\t\treturn ((difference_type)kDequeSubarraySize * ((a.mpCurrentArrayPtr - b.mpCurrentArrayPtr) - 1)) + (a.mpCurrent - a.mpBegin) + (b.mpEnd - b.mpCurrent);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// deque\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque()\n\t\t: base_type((size_type)0)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(const allocator_type& allocator)\n\t\t: base_type((size_type)0, allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(size_type n, const allocator_type& allocator)\n\t\t: base_type(n, allocator)\n\t{\n\t\tDoFillInit(value_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(size_type n, const value_type& value, const allocator_type& allocator)\n\t\t: base_type(n, allocator)\n\t{\n\t\tDoFillInit(value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(const this_type& x)\n\t\t: base_type(x.size(), x.mAllocator)\n\t{\n\t\teastl::uninitialized_copy(x.mItBegin, x.mItEnd, mItBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(this_type&& x)\n\t  : base_type((size_type)0, x.mAllocator)\n\t{\n\t\tswap(x);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(this_type&& x, const allocator_type& allocator)\n\t  : base_type((size_type)0, allocator)\n\t{\n\t\tswap(x); // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInit(ilist.begin(), ilist.end(), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\tinline deque<T, Allocator, kDequeSubarraySize>::deque(InputIterator first, InputIterator last)\n\t\t: base_type(EASTL_DEQUE_DEFAULT_ALLOCATOR) // Call the empty base constructor, which does nothing. We need to do all the work in our own DoInit.\n\t{\n\t\tDoInit(first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline deque<T, Allocator, kDequeSubarraySize>::~deque()\n\t{\n\t\t// Call destructors. Parent class will free the memory.\n\t\tfor(iterator itCurrent(mItBegin); itCurrent != mItEnd; ++itCurrent)\n\t\t\titCurrent.mpCurrent->~value_type();\n\t} \n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::this_type& \n\tdeque<T, Allocator, kDequeSubarraySize>::operator=(const this_type& x)\n\t{\n\t\tif(&x != this) // If not assigning to ourselves...\n\t\t{\n\t\t\t// If (EASTL_ALLOCATOR_COPY_ENABLED == 1) and the current contents are allocated by an \n\t\t\t// allocator that's unequal to x's allocator, we need to reallocate our elements with \n\t\t\t// our current allocator and reallocate it with x's allocator. If the allocators are \n\t\t\t// equal then we can use a more optimal algorithm that doesn't reallocate our elements\n\t\t\t// but instead can copy them in place.\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tbool bSlowerPathwayRequired = (mAllocator != x.mAllocator);\n\t\t\t#else\n\t\t\t\tbool bSlowerPathwayRequired = false;\n\t\t\t#endif\n\n\t\t\tif(bSlowerPathwayRequired)\n\t\t\t{\n\t\t\t\t// We can't currently use set_capacity(0) or shrink_to_fit, because they \n\t\t\t\t// leave a remaining allocation with our old allocator. So we do a similar \n\t\t\t\t// thing but set our allocator to x.mAllocator while doing so.\n\t\t\t\tthis_type temp(x.mAllocator);\n\t\t\t\tDoSwap(temp);\n\t\t\t\t// Now we have an empty container with an allocator equal to x.mAllocator, ready to assign from x.\n\t\t\t}\n\n\t\t\tDoAssign(x.begin(), x.end(), eastl::false_type());\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::this_type& \n\tdeque<T, Allocator, kDequeSubarraySize>::operator=(this_type&& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tthis_type temp(mAllocator);\n\t\t\tswap(temp);\n\t\t\tswap(x);         // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t\t}\n\t\treturn *this; \n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::this_type& \n\tdeque<T, Allocator, kDequeSubarraySize>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tDoAssign(ilist.begin(), ilist.end(), false_type());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::assign(size_type n, const value_type& value)\n\t{\n\t\tDoAssignValues(n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::assign(std::initializer_list<value_type> ilist)\n\t{\n\t\tDoAssign(ilist.begin(), ilist.end(), false_type());\n\t}\n\n\n\t// It turns out that the C++ std::deque specifies a two argument\n\t// version of assign that takes (int size, int value). These are not\n\t// iterators, so we need to do a template compiler trick to do the right thing. \n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::assign(InputIterator first, InputIterator last)\n\t{\n\t\tDoAssign(first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::iterator \n\tdeque<T, Allocator, kDequeSubarraySize>::begin() EA_NOEXCEPT\n\t{\n\t\treturn mItBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::const_iterator \n\tdeque<T, Allocator, kDequeSubarraySize>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn mItBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::const_iterator \n\tdeque<T, Allocator, kDequeSubarraySize>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn mItBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::iterator \n\tdeque<T, Allocator, kDequeSubarraySize>::end() EA_NOEXCEPT\n\t{\n\t\treturn mItEnd;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::const_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::end() const EA_NOEXCEPT\n\t{\n\t\treturn mItEnd;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::const_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn mItEnd;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(mItEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::const_reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mItEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::const_reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mItEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(mItBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::const_reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mItBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline typename deque<T, Allocator, kDequeSubarraySize>::const_reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mItBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool deque<T, Allocator, kDequeSubarraySize>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn mItBegin.mpCurrent == mItEnd.mpCurrent;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::size_type\n\tinline deque<T, Allocator, kDequeSubarraySize>::size() const EA_NOEXCEPT\n\t{\n\t\treturn (size_type)(mItEnd - mItBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::resize(size_type n, const value_type& value)\n\t{\n\t\tconst size_type nSizeCurrent = size();\n\n\t\tif(n > nSizeCurrent) // We expect that more often than not, resizes will be upsizes.\n\t\t\tinsert(mItEnd, n - nSizeCurrent, value);\n\t\telse\n\t\t\terase(mItBegin + (difference_type)n, mItEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::resize(size_type n)\n\t{\n\t\tresize(n, value_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::shrink_to_fit()\n\t{\n\t\tthis_type x(eastl::make_move_iterator(begin()), eastl::make_move_iterator(end()));\n\t\tswap(x);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::set_capacity(size_type n)\n\t{\n\t\t// Currently there isn't a way to remove all allocations from a deque, as it \n\t\t// requires a single starting allocation for the subarrays. So we can't just\n\t\t// free all memory without leaving it in a bad state. So the best means of \n\t\t// implementing set_capacity() is to do what we do below.\n\n\t\tif(n == 0)\n\t\t{\n\t\t\tthis_type temp(mAllocator);\n\t\t\tDoSwap(temp);\n\t\t}\n\t\telse if(n < size())\n\t\t{\n\t\t\t// We currently ignore the request to reduce capacity. To do: Implement this\n\t\t\t// and do it in a way that doesn't result in temporarily ~doubling our memory usage.\n\t\t\t// That might involve trimming unused subarrays from the front or back of \n\t\t\t// the container.\n\t\t\tresize(n);\n\t\t}        \n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference\n\tdeque<T, Allocator, kDequeSubarraySize>::operator[](size_type n)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(n >= (size_type)(mItEnd - mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::operator[] -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t// We allow taking a reference to deque[0]\n\t\t\tif (EASTL_UNLIKELY((n != 0) && n >= (size_type)(mItEnd - mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::operator[] -- out of range\");\n\t\t#endif\n\n\t\t// See DequeIterator::operator+=() for an explanation of the code below.\n\t\titerator it(mItBegin);\n\n\t\tconst difference_type subarrayPosition = (difference_type)((it.mpCurrent - it.mpBegin) + (difference_type)n);\n\t\tconst difference_type subarrayIndex    = (((16777216 + subarrayPosition) / (difference_type)kDequeSubarraySize)) - (16777216 / (difference_type)kDequeSubarraySize);\n\n\t\treturn *(*(it.mpCurrentArrayPtr + subarrayIndex) + (subarrayPosition - (subarrayIndex * (difference_type)kDequeSubarraySize)));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::const_reference\n\tdeque<T, Allocator, kDequeSubarraySize>::operator[](size_type n) const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(n >= (size_type)(mItEnd - mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::operator[] -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t// We allow the user to use a reference to deque[0] of an empty container.\n\t\t\tif (EASTL_UNLIKELY((n != 0) && n >= (size_type)(mItEnd - mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::operator[] -- out of range\");\n\t\t#endif\n\n\t\t// See DequeIterator::operator+=() for an explanation of the code below.\n\t\titerator it(mItBegin);\n\n\t\tconst difference_type subarrayPosition = (it.mpCurrent - it.mpBegin) + (difference_type)n;\n\t\tconst difference_type subarrayIndex    = (((16777216 + subarrayPosition) / (difference_type)kDequeSubarraySize)) - (16777216 / (difference_type)kDequeSubarraySize);\n\n\t\treturn *(*(it.mpCurrentArrayPtr + subarrayIndex) + (subarrayPosition - (subarrayIndex * (difference_type)kDequeSubarraySize)));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference\n\tdeque<T, Allocator, kDequeSubarraySize>::at(size_type n)\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(n >= (size_type)(mItEnd - mItBegin))\n\t\t\t\tthrow std::out_of_range(\"deque::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(n >= (size_type)(mItEnd - mItBegin))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::at -- out of range\");\n\t\t#endif\n\t\treturn *(mItBegin.operator+((difference_type)n));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::const_reference\n\tdeque<T, Allocator, kDequeSubarraySize>::at(size_type n) const\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(n >= (size_type)(mItEnd - mItBegin))\n\t\t\t\tthrow std::out_of_range(\"deque::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(n >= (size_type)(mItEnd - mItBegin))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::at -- out of range\");\n\t\t#endif\n\t\treturn *(mItBegin.operator+((difference_type)n));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference\n\tdeque<T, Allocator, kDequeSubarraySize>::front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::front -- empty deque\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn *mItBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::const_reference\n\tdeque<T, Allocator, kDequeSubarraySize>::front() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::front -- empty deque\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn *mItBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference\n\tdeque<T, Allocator, kDequeSubarraySize>::back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t// Decrementing an iterator with an empty container will result in undefined behaviour.\n\t\t\t// specifically: the iterator decrement will apply pointer arithmetic to a nullptr (depending on the situation either mpCurrentArrayPtr or mpBegin).\n\t\t\tif (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::back -- empty deque\");\n\t\t#endif\n\n\t\treturn *iterator(mItEnd, typename iterator::Decrement());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::const_reference\n\tdeque<T, Allocator, kDequeSubarraySize>::back() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t// Decrementing an iterator with an empty container will result in undefined behaviour.\n\t\t\t// specifically: the iterator decrement will apply pointer arithmetic to a nullptr (depending on the situation either mpCurrentArrayPtr or mpBegin).\n\t\t\tif (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::back -- empty deque\");\n\t\t#endif\n\n\t\treturn *iterator(mItEnd, typename iterator::Decrement());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::push_front(const value_type& value)\n\t{\n\t\templace_front(value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::push_front(value_type&& value)\n\t{\n\t\templace_front(eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference\n\tdeque<T, Allocator, kDequeSubarraySize>::push_front()\n\t{\n\t\templace_front(value_type());\n\t\treturn *mItBegin;   // Same as return front();\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::push_back(const value_type& value)\n\t{\n\t\templace_back(value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::push_back(value_type&& value)\n\t{\n\t\templace_back(eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference\n\tdeque<T, Allocator, kDequeSubarraySize>::push_back()\n\t{\n\t\templace_back(value_type());\n\t\treturn *iterator(mItEnd, typename iterator::Decrement()); // Same thing as return back();\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::pop_front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((size_type)(mItEnd == mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::pop_front -- empty deque\");\n\t\t#endif\n\n\t\tif((mItBegin.mpCurrent + 1) != mItBegin.mpEnd) // If the operation is very simple...\n\t\t\t(mItBegin.mpCurrent++)->~value_type();\n\t\telse\n\t\t{\n\t\t\t// This is executed only when we are popping the end (last) item off the front-most subarray.\n\t\t\t// In this case we need to free the subarray and point mItBegin to the next subarray.\n\t\t\t#ifdef EA_DEBUG\n\t\t\t\tvalue_type** pp = mItBegin.mpCurrentArrayPtr;\n\t\t\t#endif\n\n\t\t\tmItBegin.mpCurrent->~value_type(); // mpCurrent == mpEnd - 1\n\t\t\tDoFreeSubarray(mItBegin.mpBegin);\n\t\t\tmItBegin.SetSubarray(mItBegin.mpCurrentArrayPtr + 1);\n\t\t\tmItBegin.mpCurrent = mItBegin.mpBegin;\n\n\t\t\t#ifdef EA_DEBUG\n\t\t\t\t*pp = NULL;\n\t\t\t#endif\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::pop_back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((size_type)(mItEnd == mItBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::pop_back -- empty deque\");\n\t\t#endif\n\n\t\tif(mItEnd.mpCurrent != mItEnd.mpBegin) // If the operation is very simple...\n\t\t\t(--mItEnd.mpCurrent)->~value_type();\n\t\telse\n\t\t{\n\t\t\t// This is executed only when we are popping the first item off the last subarray.\n\t\t\t// In this case we need to free the subarray and point mItEnd to the previous subarray.\n\t\t\t#ifdef EA_DEBUG\n\t\t\t\tvalue_type** pp = mItEnd.mpCurrentArrayPtr;\n\t\t\t#endif\n\n\t\t\tDoFreeSubarray(mItEnd.mpBegin);\n\t\t\tmItEnd.SetSubarray(mItEnd.mpCurrentArrayPtr - 1);\n\t\t\tmItEnd.mpCurrent = mItEnd.mpEnd - 1;        // Recall that mItEnd points to one-past the last item in the container.\n\t\t\tmItEnd.mpCurrent->~value_type();            // Thus we need to call the destructor on the item *before* that last item.\n\n\t\t\t#ifdef EA_DEBUG\n\t\t\t\t*pp = NULL;\n\t\t\t#endif\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate<class... Args>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::emplace(const_iterator position, Args&&... args)\n\t{\n\t\tif(EASTL_UNLIKELY(position.mpCurrent == mItEnd.mpCurrent)) // If we are doing the same thing as push_back...\n\t\t{\n\t\t\templace_back(eastl::forward<Args>(args)...);\n\t\t\treturn iterator(mItEnd, typename iterator::Decrement()); // Unfortunately, we need to make an iterator here, as the above push_back is an operation that can invalidate existing iterators.\n\t\t}\n\t\telse if(EASTL_UNLIKELY(position.mpCurrent == mItBegin.mpCurrent)) // If we are doing the same thing as push_front...\n\t\t{\n\t\t\templace_front(eastl::forward<Args>(args)...);\n\t\t\treturn mItBegin;\n\t\t}\n\n\t\titerator              itPosition(position, typename iterator::FromConst());\n\t\tvalue_type  valueSaved(eastl::forward<Args>(args)...); // We need to save this because value may come from within our container. It would be somewhat tedious to make a workaround that could avoid this.\n\t\tconst difference_type i(itPosition - mItBegin);\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tEASTL_ASSERT(!empty()); // The push_front and push_back calls below assume that we are non-empty. It turns out this is never called unless so.\n\n\t\t\tif(EASTL_UNLIKELY(!(validate_iterator(itPosition) & isf_valid)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::emplace -- invalid iterator\");\n\t\t#endif\n\n\t\tif(i < (difference_type)(size() / 2)) // Should we insert at the front or at the back? We divide the range in half.\n\t\t{\n\t\t\templace_front(eastl::move(*mItBegin)); // This operation potentially invalidates all existing iterators and so we need to assign them anew relative to mItBegin below.\n\n\t\t\titPosition = mItBegin + i;\n\n\t\t\tconst iterator newPosition  (itPosition, typename iterator::Increment());\n\t\t\t\t  iterator oldBegin     (mItBegin,   typename iterator::Increment());\n\t\t\tconst iterator oldBeginPlus1(oldBegin,   typename iterator::Increment());\n\n\t\t\toldBegin.move(oldBeginPlus1, newPosition, eastl::is_trivially_copyable<value_type>());\n\t\t}\n\t\telse\n\t\t{\n\t\t\templace_back(eastl::move(*iterator(mItEnd, typename iterator::Decrement())));\n\n\t\t\titPosition = mItBegin + i;\n\n\t\t\t\t  iterator oldBack      (mItEnd,  typename iterator::Decrement());\n\t\t\tconst iterator oldBackMinus1(oldBack, typename iterator::Decrement());\n\n\t\t\toldBack.move_backward(itPosition, oldBackMinus1, eastl::is_trivially_copyable<value_type>());\n\t\t}\n\n\t\t*itPosition = eastl::move(valueSaved);\n\n\t\treturn itPosition;\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate<class... Args>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference deque<T, Allocator, kDequeSubarraySize>::emplace_front(Args&&... args)\n\t{\n\t\tif(mItBegin.mpCurrent != mItBegin.mpBegin)                                         // If we have room in the first subarray... we hope that usually this 'new' pathway gets executed, as it is slightly faster.\n\t\t\tdetail::allocator_construct(mAllocator, --mItBegin.mpCurrent, eastl::forward<Args>(args)...);\n\t\telse\n\t\t{\n\t\t\t// To consider: Detect if value isn't coming from within this container and handle that efficiently.\n\t\t\tvalue_type  valueSaved(eastl::forward<Args>(args)...);                          // We need to make a temporary, because args may be a value_type that comes from within our container and the operations below may change the container. But we can use move instead of copy.\n\n\t\t\tif(mItBegin.mpCurrentArrayPtr == mpPtrArray)                                   // If there are no more pointers in front of the current (first) one...\n\t\t\t\tDoReallocPtrArray(1, kSideFront);\n\n\t\t\tmItBegin.mpCurrentArrayPtr[-1] = DoAllocateSubarray();\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\tmItBegin.SetSubarray(mItBegin.mpCurrentArrayPtr - 1);\n\t\t\t\t\tmItBegin.mpCurrent = mItBegin.mpEnd - 1;\n\t\t\t\t\tdetail::allocator_construct(mAllocator, mItBegin.mpCurrent, eastl::move(valueSaved));\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\t++mItBegin; // The exception could only occur in the new operation above, after we have incremented mItBegin. So we need to undo it.\n\t\t\t\t\tDoFreeSubarray(mItBegin.mpCurrentArrayPtr[-1]);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\n\t\treturn *mItBegin; // Same as return front();\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate<class... Args>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reference deque<T, Allocator, kDequeSubarraySize>::emplace_back(Args&&... args)\n\t{\n\t\tif ((mItEnd.mpCurrent + 1) != mItEnd.mpEnd)                                       // If we have room in the last subarray... we hope that usually this 'new' pathway gets executed, as it is slightly faster.\n\t\t{\n\t\t\treference back = *mItEnd.mpCurrent;\n\t\t\tdetail::allocator_construct(mAllocator, mItEnd.mpCurrent++, eastl::forward<Args>(args)...);\n\t\t\treturn back;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// To consider: Detect if value isn't coming from within this container and handle that efficiently.\n\t\t\tvalue_type  valueSaved(eastl::forward<Args>(args)...);                          // We need to make a temporary, because args may be a value_type that comes from within our container and the operations below may change the container. But we can use move instead of copy.\n\t\t\tif(((mItEnd.mpCurrentArrayPtr - mpPtrArray) + 1) >= (difference_type)mnPtrArraySize) // If there are no more pointers after the current (last) one.\n\t\t\t\tDoReallocPtrArray(1, kSideBack);\n\n\t\t\tmItEnd.mpCurrentArrayPtr[1] = DoAllocateSubarray();\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\tdetail::allocator_construct(mAllocator, mItEnd.mpCurrent, eastl::move(valueSaved));\n\t\t\t\t\tmItEnd.SetSubarray(mItEnd.mpCurrentArrayPtr + 1);\n\t\t\t\t\tmItEnd.mpCurrent = mItEnd.mpBegin;\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\t// No need to execute '--mItEnd', as the exception could only occur in the new operation above before we set mItEnd.\n\t\t\t\t\tDoFreeSubarray(mItEnd.mpCurrentArrayPtr[1]);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\treturn *iterator(mItEnd, typename iterator::Decrement()); // Same as return back();\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::insert(const_iterator position, const value_type& value)\n\t{\n\t\treturn emplace(position, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::insert(const_iterator position, value_type&& value)\n\t{\n\t\treturn emplace(position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::insert(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\treturn DoInsertValues(position, n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::insert(const_iterator position, InputIterator first, InputIterator last)\n\t{\n\t\treturn DoInsert(position, first, last, is_integral<InputIterator>()); // The C++ standard requires this sort of behaviour, as InputIterator might actually be Integer and 'first' is really 'count' and 'last' is really 'value'.\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::insert(const_iterator position, std::initializer_list<value_type> ilist)\n\t{\n\t\tconst difference_type i(position - mItBegin);\n\t\tDoInsert(position, ilist.begin(), ilist.end(), false_type());\n\t\treturn (mItBegin + i);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::erase(const_iterator position)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(!(validate_iterator(position) & isf_valid)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::erase -- invalid iterator\");\n\n\t\t\tif(EASTL_UNLIKELY(position == end()))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::erase -- end() iterator is an invalid iterator for erase\");\n\t\t#endif\n\n\t\titerator itPosition(position, typename iterator::FromConst());\n\t\titerator itNext(itPosition, typename iterator::Increment());\n\t\tconst difference_type i(itPosition - mItBegin);\n\n\t\tif(i < (difference_type)(size() / 2)) // Should we move the front entries forward or the back entries backward? We divide the range in half.\n\t\t{\n\t\t\titNext.move_backward(mItBegin, itPosition, eastl::is_trivially_copyable<value_type>());\n\t\t\tpop_front();\n\t\t}\n\t\telse\n\t\t{\n\t\t\titPosition.move(itNext, mItEnd, eastl::is_trivially_copyable<value_type>());\n\t\t\tpop_back();\n\t\t}\n\n\t\treturn mItBegin + i;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::erase(const_iterator first, const_iterator last)\n\t{\n\t\titerator itFirst(first, typename iterator::FromConst());\n\t\titerator itLast(last, typename iterator::FromConst());\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(!(validate_iterator(itFirst) & isf_valid)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::erase -- invalid iterator\");\n\t\t\tif(EASTL_UNLIKELY(!(validate_iterator(itLast) & isf_valid)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::erase -- invalid iterator\");\n\t\t#endif\n\n\t\tif((itFirst != mItBegin) || (itLast != mItEnd)) // If not erasing everything... (We expect that the user won't call erase(begin, end) because instead the user would just call clear.)\n\t\t{\n\t\t\tconst difference_type n(itLast - itFirst);\n\t\t\tconst difference_type i(itFirst - mItBegin);\n\n\t\t\tif(i < (difference_type)((size() - n) / 2)) // Should we move the front entries forward or the back entries backward? We divide the range in half.\n\t\t\t{\n\t\t\t\tconst iterator itNewBegin(mItBegin + n);\n\t\t\t\tvalue_type** const pPtrArrayBegin = mItBegin.mpCurrentArrayPtr;\n\n\t\t\t\titLast.move_backward(mItBegin, itFirst, eastl::is_trivially_copyable<value_type>());\n\n\t\t\t\tfor(; mItBegin != itNewBegin; ++mItBegin) // Question: If value_type is a POD type, will the compiler generate this loop at all?\n\t\t\t\t\tmItBegin.mpCurrent->~value_type();    //           If so, then we need to make a specialization for destructing PODs.\n\n\t\t\t\tDoFreeSubarrays(pPtrArrayBegin, itNewBegin.mpCurrentArrayPtr);\n\n\t\t\t\t// mItBegin = itNewBegin; <-- Not necessary, as the above loop makes it so already.\n\t\t\t}\n\t\t\telse // Else we will be moving back entries backward.\n\t\t\t{\n\t\t\t\titerator itNewEnd(mItEnd - n);\n\t\t\t\tvalue_type** const pPtrArrayEnd = itNewEnd.mpCurrentArrayPtr + 1;\n\n\t\t\t\titFirst.move(itLast, mItEnd, eastl::is_trivially_copyable<value_type>());\n\n\t\t\t\tfor(iterator itTemp(itNewEnd); itTemp != mItEnd; ++itTemp)\n\t\t\t\t\titTemp.mpCurrent->~value_type();\n\n\t\t\t\tDoFreeSubarrays(pPtrArrayEnd, mItEnd.mpCurrentArrayPtr + 1);\n\n\t\t\t\tmItEnd = itNewEnd;\n\t\t\t}\n\n\t\t\treturn mItBegin + i;\n\t\t}\n\n\t\tclear();\n\t\treturn mItEnd;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::erase(reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::reverse_iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::erase(reverse_iterator first, reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase(last.base(), first.base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::clear()\n\t{\n\t\t// Destroy all values and all subarrays they belong to, except for the first one, \n\t\t// as we need to reserve some space for a valid mItBegin/mItEnd.\n\t\tif(mItBegin.mpCurrentArrayPtr != mItEnd.mpCurrentArrayPtr) // If there are multiple subarrays (more often than not, this will be so)...\n\t\t{\n\t\t\tfor(value_type* p1 = mItBegin.mpCurrent; p1 < mItBegin.mpEnd; ++p1)\n\t\t\t\tp1->~value_type();\n\t\t\tfor(value_type* p2 = mItEnd.mpBegin; p2 < mItEnd.mpCurrent; ++p2)\n\t\t\t\tp2->~value_type();\n\t\t\tDoFreeSubarray(mItEnd.mpBegin); // Leave mItBegin with a valid subarray.\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(value_type* p = mItBegin.mpCurrent; p < mItEnd.mpCurrent; ++p)\n\t\t\t\tp->~value_type();\n\t\t\t// Don't free the one existing subarray, as we need it for mItBegin/mItEnd.\n\t\t}\n\n\t\tfor(value_type** pPtrArray = mItBegin.mpCurrentArrayPtr + 1; pPtrArray < mItEnd.mpCurrentArrayPtr; ++pPtrArray)\n\t\t{\n\t\t\tfor(value_type* p = *pPtrArray, *pEnd = *pPtrArray + kDequeSubarraySize; p < pEnd; ++p)\n\t\t\t\tp->~value_type();\n\t\t\tDoFreeSubarray(*pPtrArray);\n\t\t}\n\n\t\tmItEnd = mItBegin; // mItBegin/mItEnd will not be dereferencable.\n\t}\n\n\n\t//template <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\t//void deque<T, Allocator, kDequeSubarraySize>::reset_lose_memory()\n\t//{\n\t//    // The reset_lose_memory function is a special extension function which unilaterally \n\t//    // resets the container to an empty state without freeing the memory of \n\t//    // the contained objects. This is useful for very quickly tearing down a \n\t//    // container built into scratch memory.\n\t//\n\t//    // Currently we are unable to get this reset_lose_memory operation to work correctly \n\t//    // as we haven't been able to find a good way to have a deque initialize\n\t//    // without allocating memory. We can lose the old memory, but DoInit \n\t//    // would necessarily do a ptrArray allocation. And this is not within\n\t//    // our definition of how reset_lose_memory works.\n\t//    base_type::DoInit(0);\n\t//\n\t//}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::swap(deque& x)\n\t{\n\t#if defined(EASTL_DEQUE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR) && EASTL_DEQUE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t\tif(mAllocator == x.mAllocator) // If allocators are equivalent...\n\t\t\tDoSwap(x);\n\t\telse // else swap the contents.\n\t\t{\n\t\t\tconst this_type temp(*this); // Can't call eastl::swap because that would\n\t\t\t*this = x;                   // itself call this member swap function.\n\t\t\tx     = temp;\n\t\t}\n\t#else\n\t\t// NOTE(rparolin): The previous implementation required T to be copy-constructible in the fall-back case where\n\t\t// allocators with unique instances copied elements.  This was an unnecessary restriction and prevented the common\n\t\t// usage of deque with non-copyable types (eg. eastl::deque<non_copyable> or eastl::deque<unique_ptr>). \n\t\t// \n\t\t// The previous implementation violated the following requirements of deque::swap so the fall-back code has\n\t\t// been removed.  EASTL implicitly defines 'propagate_on_container_swap = true' therefore the fall-back case is\n\t\t// not required.  We simply swap the contents and the allocator as that is the common expectation of\n\t\t// users and does not put the container into an invalid state since it can not free its memory via its current\n\t\t// allocator instance.\n\t\t//\n\t\tDoSwap(x);\n\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename Integer>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoInit(Integer n, Integer value, true_type)\n\t{\n\t\tbase_type::DoInit(n);  // Call the base uninitialized init function. \n\t\tDoFillInit(value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoInit(InputIterator first, InputIterator last, false_type)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\tDoInitFromIterator(first, last, IC());\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoInitFromIterator(InputIterator first, InputIterator last, eastl::input_iterator_tag)\n\t{\n\t\tbase_type::DoInit(0); // Call the base uninitialized init function, but don't actually allocate any values.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\t// We have little choice but to iterate through the source iterator and call \n\t\t\t\t// push_back for each item. It can be slow because it will keep reallocating the \n\t\t\t\t// container memory as we go (every kDequeSubarraySize elements). We are not allowed to use distance() on an InputIterator.\n\t\t\t\tfor(; first != last; ++first)   // InputIterators by definition actually only allow you to iterate through them once.\n\t\t\t\t{                               // Thus the standard *requires* that we do this (inefficient) implementation.  \n\t\t\t\t\tpush_back(*first);          // Luckily, InputIterators are in practice almost never used, so this code will likely never get executed.\n\t\t\t\t}\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tclear();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename ForwardIterator>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoInitFromIterator(ForwardIterator first, ForwardIterator last, eastl::forward_iterator_tag)\n\t{\n\t\ttypedef typename eastl::remove_const<ForwardIterator>::type non_const_iterator_type; // If T is a const type (e.g. const int) then we need to initialize it as if it were non-const.\n\t\ttypedef typename eastl::remove_const<value_type>::type      non_const_value_type;\n\n\t\tconst size_type n = (size_type)eastl::distance(first, last);\n\t\tvalue_type** pPtrArrayCurrent;\n\n\t\tbase_type::DoInit(n); // Call the base uninitialized init function.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tfor(pPtrArrayCurrent = mItBegin.mpCurrentArrayPtr; pPtrArrayCurrent < mItEnd.mpCurrentArrayPtr; ++pPtrArrayCurrent) // Copy to the known-to-be-completely-used subarrays.\n\t\t\t\t{\n\t\t\t\t\t// We implment an algorithm here whereby we use uninitialized_copy() and advance() instead of just iterating from first to last and constructing as we go.\n\t\t\t\t\t// The reason for this is that we can take advantage of trivially copyable data types and implement construction as memcpy operations.\n\t\t\t\t\tForwardIterator current(first); // To do: Implement a specialization of this algorithm for non-trivially copyable types which eliminates the need for 'current'.\n\n\t\t\t\t\teastl::advance(current, kDequeSubarraySize);\n\t\t\t\t\teastl::uninitialized_copy((non_const_iterator_type)first, (non_const_iterator_type)current, (non_const_value_type*)*pPtrArrayCurrent);\n\t\t\t\t\tfirst = current;\n\t\t\t\t}\n\n\t\t\t\teastl::uninitialized_copy((non_const_iterator_type)first, (non_const_iterator_type)last, (non_const_value_type*)mItEnd.mpBegin);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tfor(iterator itCurrent(mItBegin), itEnd(pPtrArrayCurrent, *pPtrArrayCurrent); itCurrent != itEnd; ++itCurrent)\n\t\t\t\t\titCurrent.mpCurrent->~value_type();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoFillInit(const value_type& value)\n\t{\n\t\tvalue_type** pPtrArrayCurrent = mItBegin.mpCurrentArrayPtr;\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\twhile(pPtrArrayCurrent < mItEnd.mpCurrentArrayPtr)\n\t\t\t\t{\n\t\t\t\t\teastl::uninitialized_fill(*pPtrArrayCurrent, *pPtrArrayCurrent + kDequeSubarraySize, value);\n\t\t\t\t\t++pPtrArrayCurrent;\n\t\t\t\t}\n\t\t\t\teastl::uninitialized_fill(mItEnd.mpBegin, mItEnd.mpCurrent, value);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tfor(iterator itCurrent(mItBegin), itEnd(pPtrArrayCurrent, *pPtrArrayCurrent); itCurrent != itEnd; ++itCurrent)\n\t\t\t\t\titCurrent.mpCurrent->~value_type();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename Integer>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoAssign(Integer n, Integer value, true_type) // false_type means this is the integer version instead of iterator version.\n\t{\n\t\tDoAssignValues(static_cast<size_type>(n), static_cast<value_type>(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoAssign(InputIterator first, InputIterator last, false_type) // false_type means this is the iterator version instead of integer version.\n\t{\n\t\t// Actually, the implementation below requires first/last to be a ForwardIterator and not just an InputIterator.\n\t\t// But Paul Pedriana if you somehow need to work with an InputIterator and we can deal with it.\n\t\tconst size_type n     = (size_type)eastl::distance(first, last);\n\t\tconst size_type nSize = size();\n\n\t\tif(n > nSize) // If we are increasing the size...\n\t\t{\n\t\t\tInputIterator atEnd(first);\n\n\t\t\teastl::advance(atEnd, (difference_type)nSize);\n\t\t\teastl::copy(first, atEnd, mItBegin);\n\t\t\tinsert(mItEnd, atEnd, last);\n\t\t}\n\t\telse // n is <= size.\n\t\t{\n\t\t\titerator itEnd(eastl::copy(first, last, mItBegin));\n\n\t\t\tif(n < nSize) // If we need to erase any trailing elements...\n\t\t\t\terase(itEnd, mItEnd);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tvoid deque<T, Allocator, kDequeSubarraySize>::DoAssignValues(size_type n, const value_type& value)\n\t{\n\t\tconst size_type nSize = size();\n\n\t\tif(n > nSize) // If we are increasing the size...\n\t\t{\n\t\t\teastl::fill(mItBegin, mItEnd, value);\n\t\t\tinsert(mItEnd, n - nSize, value);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terase(mItBegin + (difference_type)n, mItEnd);\n\t\t\teastl::fill(mItBegin, mItEnd, value);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename Integer>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::DoInsert(const const_iterator& position, Integer n, Integer value, true_type)\n\t{\n\t\treturn DoInsertValues(position, (size_type)n, (value_type)value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::DoInsert(const const_iterator& position, const InputIterator& first, const InputIterator& last, false_type)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\treturn DoInsertFromIterator(position, first, last, IC());\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename InputIterator>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::DoInsertFromIterator(const_iterator position, const InputIterator& first, const InputIterator& last, eastl::input_iterator_tag)\n\t{\n\t\tconst difference_type index = eastl::distance(cbegin(), position);\n#if EASTL_EXCEPTIONS_ENABLED\n\t\ttry\n\t\t{\n#endif\n\t\t\t// We have little choice but to iterate through the source iterator and call\n\t\t\t// insert for each item. It can be slow because it will keep reallocating the\n\t\t\t// container memory as we go (every kDequeSubarraySize elements). We are not\n\t\t\t// allowed to use distance() on an InputIterator. InputIterators by definition\n\t\t\t// actually only allow you to iterate through them once. Thus the standard\n\t\t\t// *requires* that we do this (inefficient) implementation. Luckily,\n\t\t\t// InputIterators are in practice almost never used, so this code will likely\n\t\t\t// never get executed.\n\t\t\tfor (InputIterator iter = first; iter != last; ++iter)\n\t\t\t{\n\t\t\t\tposition = insert(position, *iter) + 1;\n\t\t\t}\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\terase(cbegin() + index, position);\n\t\t\tthrow;\n\t\t}\n#endif\n\n\t\treturn begin() + index;\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttemplate <typename ForwardIterator>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::DoInsertFromIterator(const_iterator position, const ForwardIterator& first, const ForwardIterator& last, eastl::forward_iterator_tag)\n\t{\n\t\tconst size_type n = (size_type)eastl::distance(first, last);\n\n\t\t// This implementation is nearly identical to DoInsertValues below. \n\t\t// If you make a bug fix to one, you will likely want to fix the other.\n\t\tif(position.mpCurrent == mItBegin.mpCurrent) // If inserting at the beginning or into an empty container...\n\t\t{\n\t\t\titerator itNewBegin(DoReallocSubarray(n, kSideFront)); // itNewBegin to mItBegin refers to memory that isn't initialized yet; so it's not truly a valid iterator. Or at least not a dereferencable one.\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\t// We would like to use move here instead of copy when possible, which would be useful for \n\t\t\t\t\t// when inserting from a std::initializer_list, for example.\n\t\t\t\t\t// To do: solve this by having a template or runtime parameter which specifies move vs copy.\n\t\t\t\t\teastl::uninitialized_copy(first, last, itNewBegin);\n\t\t\t\t\tmItBegin = itNewBegin;\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tDoFreeSubarrays(itNewBegin.mpCurrentArrayPtr, mItBegin.mpCurrentArrayPtr);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\treturn mItBegin;\n\t\t}\n\t\telse if(EASTL_UNLIKELY(position.mpCurrent == mItEnd.mpCurrent)) // If inserting at the end (i.e. appending)...\n\t\t{\n\t\t\tconst iterator itNewEnd(DoReallocSubarray(n, kSideBack)); // mItEnd to itNewEnd refers to memory that isn't initialized yet; so it's not truly a valid iterator. Or at least not a dereferencable one.\n\t\t\tconst iterator itFirstInserted(mItEnd);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\t// We would like to use move here instead of copy when possible, which would be useful for \n\t\t\t\t\t// when inserting from a std::initializer_list, for example.\n\t\t\t\t\t// To do: solve this by having a template or runtime parameter which specifies move vs copy.\n\t\t\t\t\teastl::uninitialized_copy(first, last, mItEnd);\n\t\t\t\t\tmItEnd = itNewEnd;\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tDoFreeSubarrays(mItEnd.mpCurrentArrayPtr + 1, itNewEnd.mpCurrentArrayPtr + 1);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\treturn itFirstInserted;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst difference_type nInsertionIndex = position - mItBegin;\n\t\t\tconst size_type       nSize           = size();\n\n\t\t\tif(nInsertionIndex < (difference_type)(nSize / 2)) // If the insertion index is in the front half of the deque... grow the deque at the front.\n\t\t\t{\n\t\t\t\tconst iterator itNewBegin(DoReallocSubarray(n, kSideFront)); // itNewBegin to mItBegin refers to memory that isn't initialized yet; so it's not truly a valid iterator. Or at least not a dereferencable one.\n\t\t\t\tconst iterator itOldBegin(mItBegin);\n\t\t\t\tconst iterator itPosition(mItBegin + nInsertionIndex); // We need to reset this value because the reallocation above can invalidate iterators.\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t#endif\n\t\t\t\t\t\t// We have a problem here: we would like to use move instead of copy, but it may be that the range to be inserted comes from\n\t\t\t\t\t\t// this container and comes from the segment we need to move. So we can't use move operations unless we are careful to handle\n\t\t\t\t\t\t// that situation. The newly inserted contents must be contents that were moved to and not moved from. To do: solve this.\n\t\t\t\t\t\tif(nInsertionIndex >= (difference_type)n) // If the newly inserted items will be entirely within the old area...\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titerator itUCopyEnd(mItBegin + (difference_type)n);\n\n\t\t\t\t\t\t\teastl::uninitialized_copy(mItBegin, itUCopyEnd, itNewBegin); // This can throw.\n\t\t\t\t\t\t\titUCopyEnd = eastl::copy(itUCopyEnd, itPosition, itOldBegin); // Recycle 'itUCopyEnd' to mean something else.\n\t\t\t\t\t\t\teastl::copy(first, last, itUCopyEnd);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse // Else the newly inserted items are going within the newly allocated area at the front.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tForwardIterator mid(first);\n\n\t\t\t\t\t\t\teastl::advance(mid, (difference_type)n - nInsertionIndex);\n\t\t\t\t\t\t\teastl::uninitialized_copy_copy(mItBegin, itPosition, first, mid, itNewBegin); // This can throw.\n\t\t\t\t\t\t\teastl::copy(mid, last, itOldBegin);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmItBegin = itNewBegin;\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tDoFreeSubarrays(itNewBegin.mpCurrentArrayPtr, mItBegin.mpCurrentArrayPtr);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconst iterator        itNewEnd(DoReallocSubarray(n, kSideBack));\n\t\t\t\tconst iterator        itOldEnd(mItEnd);\n\t\t\t\tconst difference_type nPushedCount = (difference_type)nSize - nInsertionIndex;\n\t\t\t\tconst iterator        itPosition(mItEnd - nPushedCount); // We need to reset this value because the reallocation above can invalidate iterators.\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t#endif\n\t\t\t\t\t\t// We have a problem here: we would like to use move instead of copy, but it may be that the range to be inserted comes from\n\t\t\t\t\t\t// this container and comes from the segment we need to move. So we can't use move operations unless we are careful to handle\n\t\t\t\t\t\t// that situation. The newly inserted contents must be contents that were moved to and not moved from. To do: solve this.\n\t\t\t\t\t\tif(nPushedCount > (difference_type)n)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst iterator itUCopyEnd(mItEnd - (difference_type)n);\n\n\t\t\t\t\t\t\teastl::uninitialized_copy(itUCopyEnd, mItEnd, mItEnd);\n\t\t\t\t\t\t\teastl::copy_backward(itPosition, itUCopyEnd, itOldEnd);\n\t\t\t\t\t\t\teastl::copy(first, last, itPosition);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tForwardIterator mid(first);\n\n\t\t\t\t\t\t\teastl::advance(mid, nPushedCount);\n\t\t\t\t\t\t\teastl::uninitialized_copy_copy(mid, last, itPosition, mItEnd, mItEnd);\n\t\t\t\t\t\t\teastl::copy(first, mid, itPosition);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmItEnd = itNewEnd;\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tDoFreeSubarrays(mItEnd.mpCurrentArrayPtr + 1, itNewEnd.mpCurrentArrayPtr + 1);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\treturn iterator(mItBegin + nInsertionIndex);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\ttypename deque<T, Allocator, kDequeSubarraySize>::iterator\n\tdeque<T, Allocator, kDequeSubarraySize>::DoInsertValues(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(!(validate_iterator(position) & isf_valid)))\n\t\t\t\tEASTL_FAIL_MSG(\"deque::insert -- invalid iterator\");\n\t\t#endif\n\n\t\t// This implementation is nearly identical to DoInsertFromIterator above. \n\t\t// If you make a bug fix to one, you will likely want to fix the other.\n\t\tif(position.mpCurrent == mItBegin.mpCurrent) // If inserting at the beginning...\n\t\t{\n\t\t\tconst iterator itNewBegin(DoReallocSubarray(n, kSideFront));\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\t// Note that we don't make a temp copy of 'value' here. This is because in a \n\t\t\t\t\t// deque, insertion at either the front or back doesn't cause a reallocation\n\t\t\t\t\t// or move of data in the middle. That's a key feature of deques, in fact.\n\t\t\t\t\teastl::uninitialized_fill(itNewBegin, mItBegin, value);\n\t\t\t\t\tmItBegin = itNewBegin;\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tDoFreeSubarrays(itNewBegin.mpCurrentArrayPtr, mItBegin.mpCurrentArrayPtr);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\treturn mItBegin;\n\t\t}\n\t\telse if(EASTL_UNLIKELY(position.mpCurrent == mItEnd.mpCurrent)) // If inserting at the end (i.e. appending)...\n\t\t{\n\t\t\tconst iterator itNewEnd(DoReallocSubarray(n, kSideBack));\n\t\t\tconst iterator itFirstInserted(mItEnd);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\t// Note that we don't make a temp copy of 'value' here. This is because in a \n\t\t\t\t\t// deque, insertion at either the front or back doesn't cause a reallocation\n\t\t\t\t\t// or move of data in the middle. That's a key feature of deques, in fact.\n\t\t\t\t\teastl::uninitialized_fill(mItEnd, itNewEnd, value);\n\t\t\t\t\tmItEnd = itNewEnd;\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tDoFreeSubarrays(mItEnd.mpCurrentArrayPtr + 1, itNewEnd.mpCurrentArrayPtr + 1);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\n\t\t\treturn itFirstInserted;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// A key purpose of a deque is to implement insertions and removals more efficiently \n\t\t\t// than with a vector. We are inserting into the middle of the deque here. A quick and \n\t\t\t// dirty implementation of this would be to reallocate the subarrays and simply push \n\t\t\t// all values in the middle upward like you would do with a vector. Instead we implement\n\t\t\t// the minimum amount of reallocations needed but may need to do some value moving, \n\t\t\t// as the subarray sizes need to remain constant and can have no holes in them.\n\t\t\tconst difference_type nInsertionIndex = position - mItBegin;\n\t\t\tconst size_type       nSize = size();\n\t\t\tconst value_type      valueSaved(value);\n\n\t\t\tif(nInsertionIndex < (difference_type)(nSize / 2)) // If the insertion index is in the front half of the deque... grow the deque at the front.\n\t\t\t{\n\t\t\t\tconst iterator itNewBegin(DoReallocSubarray(n, kSideFront));\n\t\t\t\tconst iterator itOldBegin(mItBegin);\n\t\t\t\tconst iterator itPosition(mItBegin + nInsertionIndex); // We need to reset this value because the reallocation above can invalidate iterators.\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t#endif\n\t\t\t\t\t\tif(nInsertionIndex >= (difference_type)n) // If the newly inserted items will be entirely within the old area...\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titerator itUCopyEnd(mItBegin + (difference_type)n);\n\n\t\t\t\t\t\t\teastl::uninitialized_move_if_noexcept(mItBegin, itUCopyEnd, itNewBegin); // This can throw.\n\t\t\t\t\t\t\titUCopyEnd = eastl::move(itUCopyEnd, itPosition, itOldBegin); // Recycle 'itUCopyEnd' to mean something else.\n\t\t\t\t\t\t\teastl::fill(itUCopyEnd, itPosition, valueSaved);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse // Else the newly inserted items are going within the newly allocated area at the front.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teastl::uninitialized_move_fill(mItBegin, itPosition, itNewBegin, mItBegin, valueSaved); // This can throw.\n\t\t\t\t\t\t\teastl::fill(itOldBegin, itPosition, valueSaved);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmItBegin = itNewBegin;\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tDoFreeSubarrays(itNewBegin.mpCurrentArrayPtr, mItBegin.mpCurrentArrayPtr);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\treturn iterator(mItBegin + nInsertionIndex);\n\t\t\t}\n\t\t\telse // Else the insertion index is in the back half of the deque, so grow the deque at the back.\n\t\t\t{\n\t\t\t\tconst iterator        itNewEnd(DoReallocSubarray(n, kSideBack));\n\t\t\t\tconst iterator        itOldEnd(mItEnd);\n\t\t\t\tconst difference_type nPushedCount = (difference_type)nSize - nInsertionIndex;\n\t\t\t\tconst iterator        itPosition(mItEnd - nPushedCount); // We need to reset this value because the reallocation above can invalidate iterators.\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t#endif\n\t\t\t\t\t\tif(nPushedCount > (difference_type)n) // If the newly inserted items will be entirely within the old area...\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titerator itUCopyEnd(mItEnd - (difference_type)n);\n\n\t\t\t\t\t\t\teastl::uninitialized_move_if_noexcept(itUCopyEnd, mItEnd, mItEnd); // This can throw.\n\t\t\t\t\t\t\titUCopyEnd = eastl::move_backward(itPosition, itUCopyEnd, itOldEnd); // Recycle 'itUCopyEnd' to mean something else.\n\t\t\t\t\t\t\teastl::fill(itPosition, itUCopyEnd, valueSaved);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse // Else the newly inserted items are going within the newly allocated area at the back.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teastl::uninitialized_fill_move(mItEnd, itPosition + (difference_type)n, valueSaved, itPosition, mItEnd); // This can throw.\n\t\t\t\t\t\t\teastl::fill(itPosition, itOldEnd, valueSaved);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmItEnd = itNewEnd;\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tDoFreeSubarrays(mItEnd.mpCurrentArrayPtr + 1, itNewEnd.mpCurrentArrayPtr + 1);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\treturn iterator(mItBegin + nInsertionIndex);\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void deque<T, Allocator, kDequeSubarraySize>::DoSwap(this_type& x)\n\t{\n\t\teastl::swap(mpPtrArray,     x.mpPtrArray);\n\t\teastl::swap(mnPtrArraySize, x.mnPtrArraySize);\n\t\teastl::swap(mItBegin,       x.mItBegin);\n\t\teastl::swap(mItEnd,         x.mItEnd);\n\t\teastl::swap(mAllocator,     x.mAllocator);  // We do this even if EASTL_ALLOCATOR_COPY_ENABLED is 0.\n\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool deque<T, Allocator, kDequeSubarraySize>::validate() const\n\t{\n\t\t// To do: More detailed validation.\n\t\t// To do: Try to make the validation resistant to crashes if the data is invalid.\n\t\tif((end() - begin()) < 0)\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline int deque<T, Allocator, kDequeSubarraySize>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: We don't currently track isf_current, will need to make it do so.\n\t\t// To do: Fix the validation below, as it will not catch all invalid iterators.\n\t\tif((i - begin()) < 0)\n\t\t\treturn isf_none;\n\n\t\tif((end() - i) < 0)\n\t\t\treturn isf_none;\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current);\n\n\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool operator==(const deque<T, Allocator, kDequeSubarraySize>& a, const deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t\treturn ((a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin()));\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline synth_three_way_result<T> operator<=>(const deque<T, Allocator, kDequeSubarraySize>& a, const deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t    return eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n\n#else\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool operator!=(const deque<T, Allocator, kDequeSubarraySize>& a, const deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t\treturn ((a.size() != b.size()) || !eastl::equal(a.begin(), a.end(), b.begin()));\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool operator<(const deque<T, Allocator, kDequeSubarraySize>& a, const deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool operator>(const deque<T, Allocator, kDequeSubarraySize>& a, const deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool operator<=(const deque<T, Allocator, kDequeSubarraySize>& a, const deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline bool operator>=(const deque<T, Allocator, kDequeSubarraySize>& a, const deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n#endif\n\n\ttemplate <typename T, typename Allocator, unsigned kDequeSubarraySize>\n\tinline void swap(deque<T, Allocator, kDequeSubarraySize>& a, deque<T, Allocator, kDequeSubarraySize>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase / erase_if\n\t//\n\t// https://en.cppreference.com/w/cpp/container/deque/erase2\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class T, class Allocator, class U>\n\ttypename deque<T, Allocator>::size_type erase(deque<T, Allocator>& c, const U& value)\n\t{\n\t\t// Erases all elements that compare equal to value from the container. \n\t\tauto origEnd = c.end();\n\t\tauto newEnd = eastl::remove(c.begin(), origEnd, value);\n\t\tauto numRemoved = eastl::distance(newEnd, origEnd);\n\t\tc.erase(newEnd, origEnd);\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the deque\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename deque<T, Allocator>::size_type>(numRemoved);\n\t}\n\n\ttemplate <class T, class Allocator, class Predicate>\n\ttypename deque<T, Allocator>::size_type erase_if(deque<T, Allocator>& c, Predicate predicate)\n\t{\n\t\t// Erases all elements that satisfy the predicate pred from the container. \n\t\tauto origEnd = c.end();\n\t\tauto newEnd = eastl::remove_if(c.begin(), origEnd, predicate);\n\t\tauto numRemoved = eastl::distance(newEnd, origEnd);\n\t\tc.erase(newEnd, origEnd);\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the deque\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename deque<T, Allocator>::size_type>(numRemoved);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_unsorted\n\t//\n\t// This serves a similar purpose as erase above but with the difference\n\t// that it doesn't preserve the relative order of what is left in the\n\t// deque.\n\t//\n\t// Effects: Removes all elements equal to value from the deque while\n\t// optimizing for speed with the potential reordering of elements as a\n\t// side effect.\n\t//\n\t// Complexity: Linear\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class T, class Allocator, unsigned SubArraySize, class U>\n\ttypename deque<T, Allocator, SubArraySize>::size_type erase_unsorted(deque<T, Allocator, SubArraySize>& c, const U& value)\n\t{\n\t\tauto itRemove = c.begin();\n\t\tauto ritMove = c.rbegin();\n\n\t\twhile(true)\n\t\t{\n\t\t\titRemove = eastl::find(itRemove, ritMove.base(), value);\n\t\t\tif (itRemove == ritMove.base()) // any elements to remove?\n\t\t\t\tbreak;\n\n\t\t\tritMove = eastl::find_if(ritMove, eastl::make_reverse_iterator(itRemove), [&value](const T& elem) { return elem != value; });\n\t\t\tif (itRemove == ritMove.base()) // any elements that can be moved into place?\n\t\t\t\tbreak;\n\n\t\t\t*itRemove = eastl::move(*ritMove);\n\t\t\t++itRemove;\n\t\t\t++ritMove;\n\t\t}\n\n\t\t// now all elements in the range [itRemove, c.end()) are either to be removed or have already been moved from.\n\n\t\tauto origEnd = end(c);\n\t\tauto numRemoved = distance(itRemove, origEnd);\n\t\tc.erase(itRemove, origEnd);\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the deque\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename deque<T, Allocator>::size_type>(numRemoved);\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_unsorted_if\n\t//\n\t// This serves a similar purpose as erase_if above but with the\n\t// difference that it doesn't preserve the relative order of what is\n\t// left in the deque.\n\t//\n\t// Effects: Removes all elements that return true for the predicate\n\t// while optimizing for speed with the potential reordering of elements\n\t// as a side effect.\n\t//\n\t// Complexity: Linear\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class T, class Allocator, class Predicate, unsigned SubArraySize>\n\ttypename deque<T, Allocator, SubArraySize>::size_type erase_unsorted_if(deque<T, Allocator, SubArraySize>& c, Predicate predicate)\n\t{\n\t\t// Erases all elements that satisfy predicate from the container. \n\t\tauto itRemove = c.begin();\n\t\tauto ritMove = c.rbegin();\n\n\t\twhile(true)\n\t\t{\n\t\t\titRemove = eastl::find_if(itRemove, ritMove.base(), predicate);\n\t\t\tif (itRemove == ritMove.base()) // any elements to remove?\n\t\t\t\tbreak;\n\n\t\t\tritMove = eastl::find_if(ritMove, eastl::make_reverse_iterator(itRemove), not_fn(predicate));\n\t\t\tif (itRemove == ritMove.base()) // any elements that can be moved into place?\n\t\t\t\tbreak;\n\n\t\t\t*itRemove = eastl::move(*ritMove);\n\t\t\t++itRemove;\n\t\t\t++ritMove;\n\t\t}\n\n\t\t// now all elements in the range [itRemove, c.end()) are either to be removed or have already been moved from.\n\n\t\tauto origEnd = end(c);\n\t\tauto numRemoved = distance(itRemove, origEnd);\n\t\tc.erase(itRemove, origEnd);\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the deque\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename deque<T, Allocator>::size_type>(numRemoved);\n\t}\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n#if EASTL_EXCEPTIONS_ENABLED\n\tEA_RESTORE_VC_WARNING();\n#endif\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/expected.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n#pragma once\n\n// We use a few c++17 features in the implementation of eastl::expceted, so we only provide\n// it from c++17 onwards.\n#if EA_COMPILER_CPP17_ENABLED\n\n#include <EABase/eabase.h>\n\nEA_DISABLE_VC_WARNING(4623) // warning C4623: default constructor was implicitly defined as deleted\nEA_DISABLE_VC_WARNING(4625) // warning C4625: copy constructor was implicitly defined as deleted\nEA_DISABLE_VC_WARNING(4510) // warning C4510: default constructor could not be generated\n\n#include <EASTL/internal/special_member_functions_expected.h>\n#include <EASTL/internal/in_place_t.h>\n#include <EASTL/memory.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/utility.h>\n\n#include <initializer_list> // for std::initializer_list\n\n#if EASTL_EXCEPTIONS_ENABLED\n#include <exception> // for std::exception in bad_exception_access.\n#endif\n\nnamespace eastl\n{\n\ttemplate <class T, class E>\n\tclass expected;\n\n\ttemplate <class E>\n\tclass unexpected;\n\n\t// Some helper type traits:\n\tnamespace internal\n\t{\n\t\t// TODO: move this somewhere else? It doesn't handle\n\t\t// templates with non-type template parameters so it isn't\n\t\t// really generic...\n\t\ttemplate <class T, template <class...> class Template>\n\t\tstruct is_specialization : eastl::false_type\n\t\t{\n\t\t};\n\n\t\ttemplate <template <class...> class Template, class... Args>\n\t\tstruct is_specialization<Template<Args...>, Template> : eastl::true_type\n\t\t{\n\t\t};\n\n\t\t// Used in the SFINAE expression for a constructor in the expected class.\n\t\ttemplate <class T, class U>\n\t\tstatic constexpr bool converts_from_any_cvref_v =\n\t\t    is_constructible_v<T, U&> || is_convertible_v<U&, T> || is_constructible_v<T, U> ||\n\t\t    is_convertible_v<U, T> || is_constructible_v<T, const U> || is_convertible_v<const U, T> ||\n\t\t    is_constructible_v<T, const U&> || is_convertible_v<const U&, T>;\n\n\t\ttemplate <class T, class E, class U>\n\t\tstatic constexpr bool generic_constructor_constraint_v =\n\t\t    !is_same_v<remove_cvref_t<U>, in_place_t> && !is_same_v<expected<T, E>, remove_cvref_t<U>> &&\n\t\t    !internal::is_specialization<remove_cvref_t<U>, unexpected>::value && is_constructible_v<T, U> &&\n\t\t    (!is_same_v<remove_cv<T>, bool> || !internal::is_specialization<remove_cvref_t<U>, expected>::value);\n\n\t\ttemplate <class T, class E, class U, class G, class UF, class GF>\n\t\tstatic constexpr bool expected_to_expected_ctor_constraint_v =\n\t\t    is_constructible_v<T, UF> && is_constructible_v<E, GF> &&\n\t\t    !is_constructible_v<unexpected<E>, expected<U, G>&> && !is_constructible_v<unexpected<E>, expected<U, G>> &&\n\t\t    !is_constructible_v<unexpected<E>, const expected<U, G>&> &&\n\t\t    !is_constructible_v<unexpected<E>, const expected<U, G>> &&\n\t\t    (!is_same_v<remove_cv<T>, bool> || !internal::converts_from_any_cvref_v<T, expected<U, G>>);\n\n\t} // namespace internal\n\n\ttemplate <class E>\n\tclass unexpected\n\t{\n\tpublic:\n\t\t// constructors\n\t\tconstexpr unexpected(const unexpected&) = default;\n\t\tconstexpr unexpected(unexpected&&) = default;\n\n\t\ttemplate <class Err,\n\t\t          typename = enable_if_t<!is_same_v<remove_cvref_t<Err>, unexpected<E>> &&\n\t\t                                 !is_same_v<remove_cvref_t<Err>, in_place_t> && is_constructible_v<E, Err>>>\n\t\tconstexpr explicit unexpected(Err&& e) : mError(eastl::forward<Err>(e)){};\n\n\t\ttemplate <class... Args, enable_if_t<is_constructible_v<E, Args...>, int> = 0>\n\t\tconstexpr explicit unexpected(in_place_t, Args&&... args) : mError(eastl::forward<Args>(args)...){};\n\n\t\ttemplate <class U,\n\t\t          class... Args,\n\t\t          enable_if_t<is_constructible_v<E, std::initializer_list<U>&, Args...>, int> = 0>\n\t\tconstexpr explicit unexpected(in_place_t, std::initializer_list<U> il, Args&&... args)\n\t\t    : mError(il, eastl::forward<Args>(args)...){};\n\n\t\tconstexpr unexpected& operator=(const unexpected&) = default;\n\t\tconstexpr unexpected& operator=(unexpected&&) = default;\n\n\t\tconstexpr const E& error() const& noexcept { return mError; };\n\t\tconstexpr E& error() & noexcept { return mError; };\n\t\tconstexpr const E&& error() const&& noexcept { return eastl::move(mError); };\n\t\tconstexpr E&& error() && noexcept { return eastl::move(mError); };\n\n\t\tconstexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v<E>)\n\t\t{\n\t\t\tstatic_assert(is_swappable_v<E>, \"unexpected<E> swap requires E to be swappable\");\n\t\t\tusing eastl::swap;\n\t\t\tswap(mError, other.mError);\n\t\t};\n\n\t\tfriend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)))\n\t\t{\n\t\t\tstatic_assert(is_swappable_v<E>, \"unexpected<E> swap requires E to be swappable\");\n\t\t\tx.swap(y);\n\t\t}\n\n\t\t// equality operator\n\t\ttemplate <class E2>\n\t\tfriend constexpr bool operator==(const unexpected& x, const unexpected<E2>& y)\n\t\t{\n\t\t\treturn x.mError == y.mError;\n\t\t}\n\n\tprivate:\n\t\tE mError;\n\n\t\t// The standard specifies these are ill-formed.\n\t\tstatic_assert(is_object_v<E> && !is_array_v<E> && !is_const_v<E> && !is_volatile_v<E> &&\n\t\t                  !internal::is_specialization<E, unexpected>::value,\n\t\t              \"This type is not supported by a conforming implementation of unexpected.\");\n\t};\n\n\ttemplate <class E>\n\tunexpected(E) -> unexpected<E>;\n\n\n#if EASTL_EXCEPTIONS_ENABLED\n\ttemplate <class E>\n\tclass bad_expected_access;\n\n\ttemplate <>\n\tclass bad_expected_access<void> : public std::exception\n\t{\n\tpublic:\n\t\tconst char* what() const noexcept override { return \"Bad expected access.\"; };\n\n\tprotected:\n\t\tbad_expected_access() noexcept = default;\n\t\tbad_expected_access(const bad_expected_access&) = default;\n\t\tbad_expected_access(bad_expected_access&&) = default;\n\t\tbad_expected_access& operator=(const bad_expected_access&) = default;\n\t\tbad_expected_access& operator=(bad_expected_access&&) = default;\n\t\t~bad_expected_access() = default;\n\t};\n\n\ttemplate <class E>\n\tclass bad_expected_access : public bad_expected_access<void>\n\t{\n\tpublic:\n\t\texplicit bad_expected_access(E e) : mError(eastl::move(e)){};\n\n\t\t// just use the base class' what(), no need to override this.\n\t\t// const char* what() const noexcept override;\n\n\t\tE& error() & noexcept { return mError; };\n\t\tconst E& error() const& noexcept { return mError; };\n\t\tE&& error() && noexcept { return eastl::move(mError); };\n\t\tconst E&& error() const&& noexcept { return eastl::move(mError); };\n\n\tprivate:\n\t\tE mError;\n\t};\n#endif // EASTL_EXCEPTIONS_ENABLED\n\n\t// in-place construction of unexpected values\n\tstruct unexpect_t\n\t{\n\t\texplicit unexpect_t() = default;\n\t};\n\tinline constexpr unexpect_t unexpect{};\n\n\tnamespace internal\n\t{\n\t\t///////\n\t\t// ExpectedDestructLayer handles the triviality of the destructor\n\t\t//\n\t\t// The general case when both T and E are trivially destructible.\n\t\ttemplate <class T, class E, bool = is_trivially_destructible_v<T> && is_trivially_destructible_v<E>>\n\t\tstruct ExpectedDestructLayer\n\t\t{\n\t\t\t// Note: we deliberately don't initialize anything here, member initailization for\n\t\t\t// the default conxtructoris done in the `expected` class.\n\t\t\tconstexpr ExpectedDestructLayer(){};\n\n\t\t\tunion\n\t\t\t{\n\t\t\t\tT mValue;\n\t\t\t\tE mError;\n\t\t\t};\n\t\t\tbool mHasValue;\n\t\t};\n\t\t//\n\t\t// The case where one of T or E is not trivially destructible.\n\t\ttemplate <class T, class E>\n\t\tstruct ExpectedDestructLayer<T, E, false>\n\t\t{\n\t\t\t~ExpectedDestructLayer()\n\t\t\t{\n\t\t\t\tif (mHasValue)\n\t\t\t\t{\n\t\t\t\t\teastl::destroy_at(&mValue);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teastl::destroy_at(&mError);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Note: we deliberately don't initialize anything here, member initailization for\n\t\t\t// the default conxtructoris done in the `expected` class.\n\t\t\tconstexpr ExpectedDestructLayer(){};\n\n\t\t\tunion\n\t\t\t{\n\t\t\t\tT mValue;\n\t\t\t\tE mError;\n\t\t\t};\n\t\t\tbool mHasValue;\n\t\t};\n\n\n\t\t///////\n\t\t// ExpectedConstructLayer handles the implemenation of the copy/move constructor/assignment\n\t\t//\n\t\ttemplate <class T, class E>\n\t\tstruct ExpectedConstructLayer : ExpectedDestructLayer<T, E>\n\t\t{\n\t\t\tusing ExpectedDestructLayer<T, E>::ExpectedDestructLayer;\n\n\t\t\tvoid ConstructFrom(const ExpectedConstructLayer& other)\n\t\t\t{\n\t\t\t\tthis->mHasValue = other.mHasValue;\n\t\t\t\tif (this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\teastl::construct_at(eastl::addressof(this->mValue), other.mValue);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teastl::construct_at(eastl::addressof(this->mError), other.mError);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvoid ConstructFrom(ExpectedConstructLayer&& other)\n\t\t\t{\n\t\t\t\tthis->mHasValue = other.mHasValue;\n\t\t\t\tif (this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\teastl::construct_at(eastl::addressof(this->mValue), eastl::move(other.mValue));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(other.mError));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvoid AssignFrom(const ExpectedConstructLayer& other)\n\t\t\t{\n\t\t\t\tif (this->mHasValue && other.mHasValue)\n\t\t\t\t{\n\t\t\t\t\tthis->mValue = other.mValue;\n\t\t\t\t}\n\t\t\t\telse if (this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\tReInit(this->mError, this->mValue, other.mError);\n\t\t\t\t\tthis->mHasValue = false;\n\t\t\t\t}\n\t\t\t\telse if (other.mHasValue)\n\t\t\t\t{\n\t\t\t\t\tReInit(this->mValue, this->mError, other.mValue);\n\t\t\t\t\tthis->mHasValue = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthis->mError = other.mError;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvoid AssignFrom(ExpectedConstructLayer&& other)\n\t\t\t{\n\t\t\t\tif (this->mHasValue && other.mHasValue)\n\t\t\t\t{\n\t\t\t\t\tthis->mValue = eastl::move(other.mValue);\n\t\t\t\t}\n\t\t\t\telse if (this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\tReInit(this->mError, this->mValue, eastl::move(other.mError));\n\t\t\t\t\tthis->mHasValue = false;\n\t\t\t\t}\n\t\t\t\telse if (other.mHasValue)\n\t\t\t\t{\n\t\t\t\t\tReInit(this->mValue, this->mError, eastl::move(other.mValue));\n\t\t\t\t\tthis->mHasValue = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthis->mError = eastl::move(other.mError);\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\ttemplate <class NewVal, class OldVal, class... Args>\n\t\t\tvoid ReInit(NewVal& newval, OldVal& oldval, Args&&... args)\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tif constexpr (is_nothrow_constructible_v<NewVal, Args...>)\n\t\t\t\t{\n\t\t\t\t\teastl::destroy_at(&oldval);\n\t\t\t\t\teastl::construct_at(eastl::addressof(newval), eastl::forward<Args>(args)...);\n\t\t\t\t}\n\t\t\t\telse if constexpr (is_nothrow_move_constructible_v<NewVal>)\n\t\t\t\t{\n\t\t\t\t\tNewVal tmp(eastl::forward<Args>(args)...);\n\t\t\t\t\teastl::destroy_at(&oldval);\n\t\t\t\t\teastl::construct_at(eastl::addressof(newval), eastl::move(tmp));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tOldVal tmp(eastl::move(oldval));\n\t\t\t\t\teastl::destroy_at(&oldval);\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t\t\teastl::construct_at(eastl::addressof(newval), eastl::forward<Args>(args)...);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (...)\n\t\t\t\t\t{\n\t\t\t\t\t\teastl::construct_at(eastl::addressof(oldval), eastl::move(tmp));\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t}\n#else\n\t\t\t\teastl::destroy_at(&oldval);\n\t\t\t\teastl::construct_at(&newval, eastl::forward<Args>(args)...);\n#endif\n\t\t\t}\n\t\t};\n\n\t} // namespace internal\n\n\t// TODO: we've marked member functions and constructors as constexpr when the standard\n\t// dictates it, but in reality a lot of these functions do now work at constant evaluation\n\t// time becuase they use facilities like `eastl::addressof` and `eastl::construct_at` which\n\t// are currently not constexpr.\n\ttemplate <class T, class E>\n\tclass expected : internal::EnableExpectedSpecialMemberFunctions<internal::ExpectedConstructLayer<T, E>, T, E>\n\t{\n\tprivate:\n\t\tusing LayeredBase = internal::EnableExpectedSpecialMemberFunctions<internal::ExpectedConstructLayer<T, E>, T, E>;\n\n\tpublic:\n\t\tusing value_type = T;\n\t\tusing error_type = E;\n\t\tusing unexpected_type = unexpected<E>;\n\n\n\t\ttemplate <class U>\n\t\tusing rebind = expected<U, error_type>;\n\n\t\ttemplate <bool Requires = is_default_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr expected()\n\t\t{\n\t\t\tthis->mHasValue = true;\n\t\t\teastl::construct_at(eastl::addressof(this->mValue));\n\t\t};\n\n\t\t// non-explicit version for when is_convertible_v<U, T> is true.\n\t\ttemplate <class U,\n\t\t          enable_if_t<is_convertible_v<U, T> && internal::generic_constructor_constraint_v<T, E, U>, int> = 0>\n\t\tconstexpr expected(U&& v)\n\t\t{\n\t\t\tthis->mHasValue = true;\n\t\t\teastl::construct_at(eastl::addressof(this->mValue), eastl::forward<U>(v));\n\t\t}\n\n\t\t// explicit version for when is_convertible_v<U, T> is false\n\t\ttemplate <class U,\n\t\t          enable_if_t<!is_convertible_v<U, T> && internal::generic_constructor_constraint_v<T, E, U>, int> = 0>\n\t\tconstexpr explicit expected(U&& v)\n\t\t{\n\t\t\tthis->mHasValue = true;\n\t\t\teastl::construct_at(eastl::addressof(this->mValue), eastl::forward<U>(v));\n\t\t}\n\n\t\ttemplate <class T1,\n\t\t          class E1,\n\t\t          enable_if_t<internal::expected_to_expected_ctor_constraint_v<T, E, T1, E1, const T1&, const E1&> &&\n\t\t                          (!is_convertible_v<const T1&, T> || !is_convertible_v<const E1&, E>),\n\t\t                      int> = 0>\n\t\tconstexpr explicit expected(const expected<T1, E1>& other)\n\t\t{\n\t\t\tthis->mHasValue = other.has_value();\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mValue), other.value());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), other.error());\n\t\t\t}\n\t\t}\n\n\t\t// Same as above except this is implicit when is_convertible_v<const T1&, T> && is_convertible_v<const E1&, E>.\n\t\ttemplate <class T1,\n\t\t          class E1,\n\t\t          enable_if_t<internal::expected_to_expected_ctor_constraint_v<T, E, T1, E1, const T1&, const E1&> &&\n\t\t                          (is_convertible_v<const T1&, T> && is_convertible_v<const E1&, E>),\n\t\t                      int> = 0>\n\t\tconstexpr expected(const expected<T1, E1>& other)\n\t\t{\n\t\t\tthis->mHasValue = other.has_value();\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mValue), other.value());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), other.error());\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class T1,\n\t\t          class E1,\n\t\t          enable_if_t<internal::expected_to_expected_ctor_constraint_v<T, E, T1, E1, T1, E1> &&\n\t\t                          (!is_convertible_v<T1, T> || !is_convertible_v<E1, E>),\n\t\t                      int> = 0>\n\t\tconstexpr explicit expected(expected<T1, E1>&& other)\n\t\t{\n\t\t\tthis->mHasValue = other.has_value();\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mValue), eastl::move(other).value());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(other).error());\n\t\t\t}\n\t\t}\n\n\t\t// Same as above except this is implicit when (is_convertible_v<T1, T> && is_convertible_v<E1, E>)\n\t\ttemplate <class T1,\n\t\t          class E1,\n\t\t          enable_if_t<internal::expected_to_expected_ctor_constraint_v<T, E, T1, E1, T1, E1> &&\n\t\t                          (is_convertible_v<T1, T> && is_convertible_v<E1, E>),\n\t\t                      int> = 0>\n\t\tconstexpr expected(expected<T1, E1>&& other)\n\t\t{\n\t\t\tthis->mHasValue = other.has_value();\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mValue), eastl::move(other).value());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(other).error());\n\t\t\t}\n\t\t}\n\n\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, const G&> && !is_convertible_v<const G&, E>, int> = 0>\n\t\tconstexpr explicit expected(const unexpected<G>& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), unex.error());\n\t\t}\n\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, const G&> && is_convertible_v<const G&, E>, int> = 0>\n\t\tconstexpr expected(const unexpected<G>& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), unex.error());\n\t\t}\n\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, G> && !is_convertible_v<G, E>, int> = 0>\n\t\tconstexpr explicit expected(unexpected<G>&& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(unex.error()));\n\t\t}\n\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, G> && is_convertible_v<G, E>, int> = 0>\n\t\tconstexpr expected(unexpected<G>&& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(unex.error()));\n\t\t}\n\n\t\ttemplate <class... Args, enable_if_t<is_constructible_v<T, Args...>, int> = 0>\n\t\tconstexpr explicit expected(in_place_t, Args&&... args)\n\t\t{\n\t\t\tthis->mHasValue = true;\n\t\t\teastl::construct_at(eastl::addressof(this->mValue), eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <class U,\n\t\t          class... Args,\n\t\t          enable_if_t<is_constructible_v<T, std::initializer_list<U>&, Args...>, int> = 0>\n\t\tconstexpr explicit expected(in_place_t, std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\tthis->mHasValue = true;\n\t\t\teastl::construct_at(eastl::addressof(this->mValue), il, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <class... Args, enable_if_t<is_constructible_v<E, Args...>, int> = 0>\n\t\tconstexpr explicit expected(unexpect_t, Args&&... args)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <class U,\n\t\t          class... Args,\n\t\t          enable_if_t<is_constructible_v<E, std::initializer_list<U>&, Args...>, int> = 0>\n\t\tconstexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), il, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\t// copy/move assignments are done by means of ExpectedConstructLayer::AssignFrom, and the\n\t\t// special function layers the assignments are deleted when they should be.\n\t\t//\n\t\t// constexpr expected& operator=(const expected&);\n\t\t// constexpr expected& operator=(expected&&) noexcept(/* see description */);\n\t\t//\n\t\t///////\n\n\t\t// Note: The default template parameter is in the standard, the nothrow constraints are\n\t\t// also in the standard.\n\t\ttemplate <class U = T,\n\t\t          enable_if_t<!is_same_v<expected, remove_cvref_t<U>> &&\n\t\t                          !internal::is_specialization<remove_cvref_t<U>, unexpected>::value &&\n\t\t                          is_constructible_v<T, U> && is_assignable_v<T&, U> &&\n\t\t                          (is_nothrow_constructible_v<T, U> || is_nothrow_move_constructible_v<T> ||\n\t\t                           is_nothrow_move_constructible_v<E>),\n\t\t                      int> = 0>\n\t\tconstexpr expected& operator=(U&& x)\n\t\t{\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\tthis->mValue = eastl::forward<U>(x);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->ReInit(this->mValue, this->mError, eastl::forward<U>(x));\n\t\t\t\tthis->mHasValue = true;\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <class G,\n\t\t          enable_if_t<is_constructible_v<E, const G&> && is_assignable_v<E&, const G&> &&\n\t\t                          (is_nothrow_constructible_v<E, const G&> || is_nothrow_move_constructible_v<T> ||\n\t\t                           is_nothrow_move_constructible_v<E>),\n\t\t                      int> = 0>\n\t\tconstexpr expected& operator=(const unexpected<G>& unex)\n\t\t{\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\tthis->ReInit(this->mError, this->mValue, unex.error());\n\t\t\t\tthis->mHasValue = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->mError = unex.error();\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <class G,\n\t\t          enable_if_t<is_constructible_v<E, G> && is_assignable_v<E&, G> &&\n\t\t                          (is_nothrow_constructible_v<E, G> || is_nothrow_move_constructible_v<T> ||\n\t\t                           is_nothrow_move_constructible_v<E>),\n\t\t                      int> = 0>\n\t\tconstexpr expected& operator=(unexpected<G>&& unex)\n\t\t{\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\tthis->ReInit(this->mError, this->mValue, eastl::move(unex).error());\n\t\t\t\tthis->mHasValue = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->mError = eastl::move(unex).error();\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\t// Note: this only works if the constructor is noexcept, kind of strict but that's what the standard dictates...\n\t\ttemplate <class... Args, enable_if_t<is_nothrow_constructible_v<T, Args...>, int> = 0>\n\t\tconstexpr T& emplace(Args&&... args) noexcept\n\t\t{\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::destroy_at(&this->mValue);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\teastl::destroy_at(&this->mError);\n\t\t\t\tthis->mHasValue = true;\n\t\t\t}\n\t\t\treturn *eastl::construct_at(eastl::addressof(this->mValue), eastl::forward<Args>(args)...);\n\t\t}\n\n\t\t// Note: this only works if the constructor is noexcept, kind of strict but that's what the standard dictates...\n\t\ttemplate <class U,\n\t\t          class... Args,\n\t\t          enable_if_t<is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>, int> = 0>\n\t\tconstexpr T& emplace(std::initializer_list<U> il, Args&&... args) noexcept\n\t\t{\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::destroy_at(&this->mValue);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\teastl::destroy_at(&this->mError);\n\t\t\t\tthis->mHasValue = true;\n\t\t\t}\n\t\t\treturn *eastl::construct_at(eastl::addressof(this->mValue), il, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\t// swap\n\t\ttemplate <bool Requires = is_swappable_v<T> && is_swappable_v<E> && is_move_constructible_v<T> &&\n\t\t                          is_move_constructible_v<E> &&\n\t\t                          (is_nothrow_move_assignable_v<E> || is_nothrow_move_assignable_v<T>),\n\t\t          enable_if_t<Requires, int> = 0,\n\t\t          bool NoExcept = is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T> &&\n\t\t                          is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>>\n\t\tEA_CPP20_CONSTEXPR void swap(expected& other) noexcept(NoExcept)\n\t\t{\n\t\t\tusing eastl::swap;\n\t\t\tif (other.mHasValue)\n\t\t\t{\n\t\t\t\tif (this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\tswap(this->mValue, other.mValue);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tother.swap(*this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse // other.mHasValue is false\n\t\t\t{\n\t\t\t\tif (!this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\tswap(this->mError, other.mError);\n\t\t\t\t}\n\t\t\t\telse // `other` has an error and `this` has a value, we need to swap them around.\n\t\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tif constexpr (NoExcept)\n\t\t\t\t\t{\n#endif\n\t\t\t\t\t\t// Note that is_nothrow_swappable_v implies the destructors cannot throw.\n\t\t\t\t\t\t// The definition of NoExcept implies the constructions here cannot throw.\n\t\t\t\t\t\t// So notheng here throws.\n\t\t\t\t\t\tE tmp(eastl::move(other.mError));\n\t\t\t\t\t\teastl::destroy_at(&other.mError);\n\t\t\t\t\t\teastl::construct_at(eastl::addressof(other.mValue), eastl::move(this->mValue));\n\t\t\t\t\t\teastl::destroy_at(&this->mValue);\n\t\t\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(tmp));\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\telse if constexpr (is_nothrow_move_constructible_v<E>)\n\t\t\t\t\t{\n\t\t\t\t\t\tE tmp(eastl::move(other.mError));\n\t\t\t\t\t\teastl::destroy_at(&other.mError);\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// this may throw\n\t\t\t\t\t\t\teastl::construct_at(eastl::addressof(other.mValue), eastl::move(this->mValue));\n\n\t\t\t\t\t\t\teastl::destroy_at(&this->mValue);\n\t\t\t\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(tmp));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (...)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// We need to reconstruct other.mError.\n\t\t\t\t\t\t\teastl::construct_at(eastl::addressof(other.mError), eastl::move(tmp));\n\t\t\t\t\t\t\tthrow;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse // T is nothrow_move_constructible (see sfinae condition for swap)\n\t\t\t\t\t{\n\t\t\t\t\t\tT tmp(eastl::move(this->mValue));\n\n\t\t\t\t\t\teastl::destroy_at(&this->mValue);\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// this may throw\n\t\t\t\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(other.mError));\n\n\t\t\t\t\t\t\teastl::destroy_at(&other.mError);\n\t\t\t\t\t\t\teastl::construct_at(eastl::addressof(other.mValue), eastl::move(tmp));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (...)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// We need to reconstruct this->mValue\n\t\t\t\t\t\t\teastl::construct_at(eastl::addressof(this->mValue), eastl::move(tmp));\n\t\t\t\t\t\t\tthrow;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tthis->mHasValue = false;\n\t\t\t\t\tother.mHasValue = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfriend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))) { x.swap(y); }\n\n\t\t// These all assume has_value() is true. Otherwise, calling them is UB (as per the\n\t\t// standard).  When asserts are enabled, we've decided to assert the precondition\n\t\t// similar to what would be done in a hardened library implementation.\n\t\tconstexpr const T* operator->() const noexcept\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(),\n\t\t\t                 \"Pre-condition failed! Accessing an expected value while containing an error.\");\n\t\t\treturn eastl::addressof(this->mValue);\n\t\t}\n\t\tconstexpr T* operator->() noexcept\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(),\n\t\t\t                 \"Pre-condition failed! Accessing an expected value while containing an error.\");\n\t\t\treturn eastl::addressof(this->mValue);\n\t\t}\n\t\tconstexpr const T& operator*() const& noexcept\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(),\n\t\t\t                 \"Pre-condition failed! Accessing an expected value while containing an error.\");\n\t\t\treturn this->mValue;\n\t\t}\n\t\tconstexpr T& operator*() & noexcept\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(),\n\t\t\t                 \"Pre-condition failed! Accessing an expected value while containing an error.\");\n\t\t\treturn this->mValue;\n\t\t}\n\t\tconstexpr const T&& operator*() const&& noexcept\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(),\n\t\t\t                 \"Pre-condition failed! Accessing an expected value while containing an error.\");\n\t\t\treturn eastl::move(this->mValue);\n\t\t}\n\t\tconstexpr T&& operator*() && noexcept\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(),\n\t\t\t                 \"Pre-condition failed! Accessing an expected value while containing an error.\");\n\t\t\treturn eastl::move(this->mValue);\n\t\t}\n\n\t\tconstexpr explicit operator bool() const noexcept { return this->mHasValue; }\n\t\tconstexpr bool has_value() const noexcept { return this->mHasValue; };\n\n\t\tconstexpr const T& value() const&\n\t\t{\n\t\t\tif (!has_value())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow(eastl::bad_expected_access(this->mError));\n#else\n\t\t\t\tEASTL_FAIL_MSG(\"Calling `value()` when expected contains no value.\");\n#endif\n\t\t\t}\n\t\t\treturn this->mValue;\n\t\t}\n\t\tconstexpr T& value() &\n\t\t{\n\t\t\tif (!has_value())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow(eastl::bad_expected_access(this->mError));\n#else\n\t\t\t\tEASTL_FAIL_MSG(\"Calling `value()` when expected contains no value.\");\n#endif\n\t\t\t}\n\t\t\treturn this->mValue;\n\t\t}\n\t\tconstexpr const T&& value() const&&\n\t\t{\n\t\t\tif (!has_value())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow(eastl::bad_expected_access(eastl::move(this->mError)));\n#else\n\t\t\t\tEASTL_FAIL_MSG(\"Calling `value()` when expected contains no value.\");\n#endif\n\t\t\t}\n\t\t\treturn eastl::move(this->mValue);\n\t\t}\n\t\tconstexpr T&& value() &&\n\t\t{\n\t\t\tif (!has_value())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow(eastl::bad_expected_access(eastl::move(this->mError)));\n#else\n\t\t\t\tEASTL_FAIL_MSG(\"Calling `value()` when expected contains no value.\");\n#endif\n\t\t\t}\n\t\t\treturn eastl::move(this->mValue);\n\t\t}\n\n\t\t// These all assume has_value() is false. Otherwise, calling them is UB (as per the\n\t\t// standard).  When asserts are enabled, we've decided to assert the precondition\n\t\t// similar to what would be done in a hardened library implementation.\n\t\tconstexpr const E& error() const&\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(!has_value(), \"Pre-condition failed! Calling error() while containing a value.\");\n\t\t\treturn this->mError;\n\t\t};\n\t\tconstexpr E& error() &\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(!has_value(), \"Pre-condition failed! Calling error() while containing a value.\");\n\t\t\treturn this->mError;\n\t\t};\n\t\tconstexpr const E&& error() const&&\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(!has_value(), \"Pre-condition failed! Calling error() while containing a value.\");\n\t\t\treturn eastl::move(this->mError);\n\t\t};\n\t\tconstexpr E&& error() &&\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(!has_value(), \"Pre-condition failed! Calling error() while containing a value.\");\n\t\t\treturn eastl::move(this->mError);\n\t\t};\n\n\t\ttemplate <class U>\n\t\tconstexpr T value_or(U&& alt) const&\n\t\t{\n\t\t\tstatic_assert(is_copy_constructible_v<T> && is_convertible_v<U, T>);\n\t\t\treturn has_value() ? this->mValue : static_cast<T>(eastl::forward<U>(alt));\n\t\t}\n\n\t\ttemplate <class U>\n\t\tconstexpr T value_or(U&& alt) &&\n\t\t{\n\t\t\tstatic_assert(is_move_constructible_v<T> && is_convertible_v<U, T>);\n\t\t\treturn has_value() ? eastl::move(this->mValue) : static_cast<T>(eastl::forward<U>(alt));\n\t\t}\n\n\t\ttemplate <class U>\n\t\tconstexpr E error_or(U&& alt) const&\n\t\t{\n\t\t\tstatic_assert(is_copy_constructible_v<E> && is_convertible_v<U, E>);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::forward<U>(alt);\n\t\t\t}\n\t\t\treturn this->mError;\n\t\t}\n\n\t\ttemplate <class U>\n\t\tconstexpr E error_or(U&& alt) &&\n\t\t{\n\t\t\tstatic_assert(is_move_constructible_v<E> && is_convertible_v<U, E>);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::forward<U>(alt);\n\t\t\t}\n\t\t\treturn eastl::move(this->mError);\n\t\t}\n\n\t\t// Note: the constraint in the standard is is_constructible_v<E, decltype(error())>\n\t\t// here and is_constructible_v<E, decltype(std::move(error()))> in the && qualified\n\t\t// versions, we're just explicitly spellig the decltype in our implementations since we\n\t\t// can't put the member call in the template argument. declval doesn't really help us\n\t\t// much since it always returns an rvalue reference, and `expected` is an incomplete\n\t\t// type at this point.\n\t\ttemplate <class F, bool Requires = is_constructible_v<E, E&>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) &\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F, decltype(value())>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), value());\n\t\t\t}\n\t\t\treturn U(unexpect, error());\n\t\t}\n\n\t\t// See note about constraint above.\n\t\ttemplate <class F, bool Requires = is_constructible_v<E, const E&>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) const&\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F, decltype(value())>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), value());\n\t\t\t}\n\t\t\treturn U(unexpect, error());\n\t\t}\n\n\t\t// See note about constraint above.\n\t\ttemplate <class F, bool Requires = is_constructible_v<E, E&&>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) &&\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F, decltype(eastl::move(value()))>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(value()));\n\t\t\t}\n\t\t\treturn U(unexpect, eastl::move(error()));\n\t\t}\n\n\t\t// See note about constraint above.\n\t\ttemplate <class F, bool Requires = is_constructible_v<E, const E&&>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) const&&\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F, decltype(eastl::move(value()))>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(value()));\n\t\t\t}\n\t\t\treturn U(unexpect, eastl::move(error()));\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto or_else(F&& f) &\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, T> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G(in_place, value());\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), error());\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto or_else(F&& f) const&\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, T> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G(in_place, value());\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), error());\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto or_else(F&& f) &&\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, T> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G(in_place, eastl::move(value()));\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(error()));\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto or_else(F&& f) const&&\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, T> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G(in_place, eastl::move(value()));\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(error()));\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) &\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F, decltype(value())>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, error());\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f), value());\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f), value()));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) const&\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F, decltype(value())>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, error());\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f), value());\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f), value()));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) &&\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F, decltype(eastl::move(value()))>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, eastl::move(error()));\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f), eastl::move(value()));\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f), eastl::move(value())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) const&&\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F, decltype(eastl::move(value()))>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, eastl::move(error()));\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f), eastl::move(value()));\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f), eastl::move(value())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform_error(F&& f) &\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<T, G>(in_place, value());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<T, G>(unexpect, eastl::invoke(eastl::forward<F>(f), error()));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform_error(F&& f) const&\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<T, G>(in_place, value());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<T, G>(unexpect, eastl::invoke(eastl::forward<F>(f), error()));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform_error(F&& f) &&\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<T, G>(in_place, eastl::move(value()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<T, G>(unexpect, eastl::invoke(eastl::forward<F>(f), eastl::move(error())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<T>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform_error(F&& f) const&&\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<T, G>(in_place, eastl::move(value()));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<T, G>(unexpect, eastl::invoke(eastl::forward<F>(f), eastl::move(error())));\n\t\t\t}\n\t\t}\n\n\t\t// equality operators\n\t\ttemplate <class T2, class E2>\n\t\tfriend constexpr bool operator==(const expected& x, const expected<T2, E2>& y)\n\t\t{\n\t\t\tif (x.has_value() != y.has_value())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (x.has_value())\n\t\t\t{\n\t\t\t\treturn *x == *y;\n\t\t\t}\n\t\t\treturn x.error() == y.error();\n\t\t}\n\n\t\ttemplate <class T2>\n\t\tfriend constexpr bool operator==(const expected& x, const T2& y)\n\t\t{\n\t\t\treturn x.has_value() && static_cast<bool>(*x == y);\n\t\t}\n\n\t\ttemplate <class E2>\n\t\tfriend constexpr bool operator==(const expected& x, const unexpected<E2>& y)\n\t\t{\n\t\t\treturn !x.has_value() && static_cast<bool>(x.error() == y.error());\n\t\t}\n\n\tprivate:\n\t\tstatic_assert(is_same_v<remove_cv_t<T>, void> ||\n\t\t                  (is_object_v<remove_cv_t<T>> && !is_array_v<remove_cv_t<T>> &&\n\t\t                   !is_same_v<remove_cv_t<T>, in_place_t> && !is_same_v<remove_cv_t<T>, unexpect_t> &&\n\t\t                   !internal::is_specialization<remove_cv_t<T>, unexpected>::value),\n\t\t              \"Invalid type for eastl::expected.\");\n\n\n\t\t// TODO: When T is not cv void, it shall meet the\n\t\t// Cpp17Destructible requirements. E shall meet the\n\t\t// Cpp17Destructible requirements. Can we statically assert this?\n\t};\n\n\tnamespace internal\n\t{\n\t\t// Used as a fake \"Value\" type in the void specialization of expected so it can be default\n\t\t// constructible and so we can use all the other machinery we have for value/error pairs.\n\t\tstruct ExpectedEmptyUnionMember\n\t\t{\n\t\t\tconstexpr ExpectedEmptyUnionMember() noexcept {\n\t\t\t    // Provide default constructor to avoid zero-initialization when objects are value-initialized.\n\t\t\t};\n\t\t};\n\t} // namespace internal\n\n\t// TODO: The standard has specializations for all cv-qualified void, but we're only doing\n\t// it for non-qualified void.\n\ttemplate <class E>\n\tclass expected<void, E>\n\t    : internal::EnableExpectedSpecialMemberFunctions<internal::ExpectedConstructLayer<internal::ExpectedEmptyUnionMember, E>,\n\t                                           E>\n\t{\n\tprivate:\n\t\tusing LayeredBase = internal::\n\t\t\tEnableExpectedSpecialMemberFunctions<internal::ExpectedConstructLayer<internal::ExpectedEmptyUnionMember, E>, E>;\n\n\tpublic:\n\t\tusing value_type = void;\n\t\tusing error_type = E;\n\t\tusing unexpected_type = unexpected<E>;\n\n\t\ttemplate <class U>\n\t\tusing rebind = expected<U, error_type>;\n\n\t\tconstexpr expected() noexcept { this->mHasValue = true; }\n\t\tconstexpr expected(in_place_t) noexcept { this->mHasValue = true; }\n\n\t\t// Copy/move constructors and the destructor are handled by the layers.\n\n\t\ttemplate <class U,\n\t\t          class G,\n\t\t          enable_if_t<is_void_v<U> && is_constructible_v<E, const G&> &&\n\t\t                          !is_constructible_v<unexpected<E>, expected<U, G>&> &&\n\t\t                          !is_constructible_v<unexpected<E>, expected<U, G>> &&\n\t\t                          !is_constructible_v<unexpected<E>, const expected<U, G>&> &&\n\t\t                          !is_constructible_v<unexpected<E>, const expected<U, G>>,\n\t\t                      int> = 0>\n\t\t// TODO: More SFINAE for the explicit vs not explicit version...\n\t\t// explicit(!is_convertible_v<const G&, E>)\n\t\tconstexpr expected(const expected<U, G>& other)\n\t\t{\n\t\t\tthis->mHasValue = other.has_value();\n\t\t\tif (!this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), other.error());\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class U,\n\t\t          class G,\n\t\t          enable_if_t<is_void_v<U> && is_constructible_v<E, G> &&\n\t\t                          !is_constructible_v<unexpected<E>, expected<U, G>&> &&\n\t\t                          !is_constructible_v<unexpected<E>, expected<U, G>> &&\n\t\t                          !is_constructible_v<unexpected<E>, const expected<U, G>&> &&\n\t\t                          !is_constructible_v<unexpected<E>, const expected<U, G>>,\n\t\t                      int> = 0>\n\t\t// TODO: More SFINAE for the explicit vs not explicit version...\n\t\t// explicit(!is_convertible_v<T1, T> || !is_convertible_v<E1, E>)\n\t\tconstexpr expected(expected<U, G>&& other)\n\t\t{\n\t\t\tthis->mHasValue = other.has_value();\n\t\t\tif (!this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(other).error());\n\t\t\t}\n\t\t}\n\n\n\t\t// Conversion from unexpected lvalue explicit version.\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, const G&> && !is_convertible_v<const G&, E>, int> = 0>\n\t\tconstexpr explicit expected(const unexpected<G>& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), unex.error());\n\t\t}\n\n\t\t// Conversion from unexpected lvalue non-explicit version.\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, const G&> && is_convertible_v<const G&, E>, int> = 0>\n\t\tconstexpr expected(const unexpected<G>& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), unex.error());\n\t\t}\n\n\t\t// Conversion from unexpected rvalue explicit version.\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, G> && !is_convertible_v<G, E>, int> = 0>\n\t\tconstexpr explicit expected(unexpected<G>&& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(unex.error()));\n\t\t}\n\n\t\t// Conversion from unexpected rvalue non-explicit version.\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, G> && is_convertible_v<G, E>, int> = 0>\n\t\tconstexpr expected(unexpected<G>&& unex)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(unex.error()));\n\t\t}\n\n\t\ttemplate <class... Args, enable_if_t<is_constructible_v<E, Args...>, int> = 0>\n\t\tconstexpr explicit expected(unexpect_t, Args&&... args)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <class U,\n\t\t          class... Args,\n\t\t          enable_if_t<is_constructible_v<E, std::initializer_list<U>&, Args...>, int> = 0>\n\t\tconstexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\tthis->mHasValue = false;\n\t\t\teastl::construct_at(eastl::addressof(this->mError), il, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\t////////\n\t\t//\n\t\t// copy/move assignments are done by means of ExpectedConstructLayer::AssignFrom, and the\n\t\t// special function layers so the assignments are deleted when they should be.\n\t\t//\n\t\t// constexpr expected& operator=(const expected&);\n\t\t// constexpr expected& operator=(expected&&) noexcept(/* see description */);\n\t\t//\n\t\t///////\n\n\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, const G&> && is_assignable_v<E&, const G&>, int> = 0>\n\t\tconstexpr expected& operator=(const unexpected<G>& unex)\n\t\t{\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), unex.error());\n\t\t\t\tthis->mHasValue = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->mError = unex.error();\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <class G, enable_if_t<is_constructible_v<E, const G&> && is_assignable_v<E&, G>, int> = 0>\n\t\tconstexpr expected& operator=(unexpected<G>&& unex)\n\t\t{\n\t\t\tif (this->mHasValue)\n\t\t\t{\n\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(unex.error()));\n\t\t\t\tthis->mHasValue = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis->mError = unex.error();\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <bool Requires = is_swappable_v<E> && is_move_constructible_v<E>,\n\t\t          enable_if_t<Requires, int> = 0,\n\t\t          bool NoExcept = is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>>\n\t\tEA_CPP20_CONSTEXPR void swap(expected& other) noexcept(NoExcept)\n\t\t{\n\t\t\tusing eastl::swap;\n\t\t\tif (other.mHasValue)\n\t\t\t{\n\t\t\t\tif (this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tother.swap(*this);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse // other.mHasValue is false\n\t\t\t{\n\t\t\t\tif (!this->mHasValue)\n\t\t\t\t{\n\t\t\t\t\tswap(this->mError, other.mError);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// other has an error and this has a value, we need to swap them around.\n\t\t\t\t\teastl::construct_at(eastl::addressof(this->mError), eastl::move(other.mError));\n\t\t\t\t\teastl::destroy_at(&other.mError);\n\n\t\t\t\t\tthis->mHasValue = false;\n\t\t\t\t\tother.mHasValue = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfriend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))) { x.swap(y); }\n\n\t\tconstexpr explicit operator bool() const noexcept { return this->mHasValue; }\n\n\t\tconstexpr bool has_value() const noexcept { return this->mHasValue; };\n\n\t\tconstexpr void operator*() const noexcept {}\n\n\t\tconstexpr void value() const&\n\t\t{\n\t\t\tif (!has_value())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow(eastl::bad_expected_access(eastl::move(this->mError)));\n#else\n\t\t\t\tEASTL_FAIL_MSG(\"Calling `value()` when expected contains no value.\");\n#endif\n\t\t\t}\n\t\t}\n\n\t\tconstexpr void value() &&\n\t\t{\n\t\t\tif (!has_value())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow(eastl::bad_expected_access(eastl::move(this->mError)));\n#else\n\t\t\t\tEASTL_FAIL_MSG(\"Calling `value()` when expected contains no value.\");\n#endif\n\t\t\t}\n\t\t}\n\n\t\t// These assume has_value() is false, otherwise this is UB, as per the standard.\n\t\tconstexpr const E& error() const& noexcept { return this->mError; };\n\t\tconstexpr E& error() & noexcept { return this->mError; };\n\t\tconstexpr const E&& error() const&& noexcept { return eastl::move(this->mError); };\n\t\tconstexpr E&& error() && noexcept { return eastl::move(this->mError); };\n\n\t\ttemplate <class U = E>\n\t\tconstexpr E error_or(U&& alt) const&\n\t\t{\n\t\t\tstatic_assert(is_copy_constructible_v<E> && is_convertible_v<U, E>);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::forward<U>(alt);\n\t\t\t}\n\t\t\treturn this->mError;\n\t\t}\n\n\t\ttemplate <class U = E>\n\t\tconstexpr E error_or(U&& alt) &&\n\t\t{\n\t\t\tstatic_assert(is_move_constructible_v<E> && is_convertible_v<U, E>);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::forward<U>(alt);\n\t\t\t}\n\t\t\treturn eastl::move(this->mError);\n\t\t}\n\n\t\t///////////////////////\n\t\t// Monadic operations\n\t\t///////////////////////\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) &\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f));\n\t\t\t}\n\t\t\treturn U(unexpect, error());\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) const&\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f));\n\t\t\t}\n\t\t\treturn U(unexpect, error());\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) &&\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f));\n\t\t\t}\n\t\t\treturn U(unexpect, eastl::move(error()));\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto and_then(F&& f) const&&\n\t\t{\n\t\t\tusing U = remove_cvref_t<invoke_result_t<F, decltype(eastl::move(value()))>>;\n\t\t\tstatic_assert(is_same_v<typename U::error_type, E> && internal::is_specialization<U, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f));\n\t\t\t}\n\t\t\treturn U(unexpect, eastl::move(error()));\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto or_else(F&& f) &\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, void> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G();\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), error());\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto or_else(F&& f) const&\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, void> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G();\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), error());\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto or_else(F&& f) &&\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, void> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G();\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(error()));\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto or_else(F&& f) const&&\n\t\t{\n\t\t\tusing G = remove_cvref_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tstatic_assert(is_same_v<typename G::value_type, void> && internal::is_specialization<G, expected>::value);\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn G();\n\t\t\t}\n\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(error()));\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) &\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, error());\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f));\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f)));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_copy_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) const&\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, error());\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f));\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f)));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) &&\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, eastl::move(error()));\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f));\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f), eastl::move(value())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F, bool Requires = is_move_constructible_v<E>, enable_if_t<Requires, int> = 0>\n\t\tconstexpr auto transform(F&& f) const&&\n\t\t{\n\t\t\tusing U = remove_cv_t<invoke_result_t<F>>;\n\t\t\tif (!has_value())\n\t\t\t{\n\t\t\t\treturn expected<U, E>(unexpect, eastl::move(error()));\n\t\t\t}\n\n\t\t\tif constexpr (is_void_v<U>)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<F>(f));\n\t\t\t\treturn expected<U, E>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<U, E>(eastl::invoke(eastl::forward<F>(f), eastl::move(value())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto transform_error(F&& f) &\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<void, G>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<void, G>(unexpect, eastl::invoke(eastl::forward<F>(f), error()));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto transform_error(F&& f) const&\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(error())>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<void, G>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<void, G>(unexpect, eastl::invoke(eastl::forward<F>(f), error()));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto transform_error(F&& f) &&\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<void, G>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<void, G>(unexpect, eastl::invoke(eastl::forward<F>(f), eastl::move(error())));\n\t\t\t}\n\t\t}\n\n\t\ttemplate <class F>\n\t\tconstexpr auto transform_error(F&& f) const&&\n\t\t{\n\t\t\tusing G = remove_cv_t<invoke_result_t<F, decltype(eastl::move(error()))>>;\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn expected<void, G>();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn expected<void, G>(unexpect, eastl::invoke(eastl::forward<F>(f), eastl::move(error())));\n\t\t\t}\n\t\t}\n\n\t\t// equality operators\n\t\ttemplate <class T2, class E2, bool Requires = is_void_v<T2>, enable_if_t<Requires, int> = 0>\n\t\tfriend constexpr bool operator==(const expected& x, const expected<T2, E2>& y)\n\t\t{\n\t\t\tif (x.has_value() != y.has_value())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn x.has_value() || static_cast<bool>(x.error() == y.error());\n\t\t}\n\n\t\ttemplate <class E2>\n\t\tfriend constexpr bool operator==(const expected& x, const unexpected<E2>& y)\n\t\t{\n\t\t\treturn !x.has_value() && static_cast<bool>(x.error() == y.error());\n\t\t}\n\t};\n\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING() EA_RESTORE_VC_WARNING() EA_RESTORE_VC_WARNING()\n\n#endif\n"
  },
  {
    "path": "include/EASTL/finally.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// eastl::finally is an implementation of the popular cpp idiom RAII - Resource\n// Acquisition Is Initialization. eastl::finally guarantees that the user\n// provided callable will be executed upon whatever mechanism is used to leave\n// the current scope. This can guard against user errors but this is a popular\n// technique to write robust code in execution environments that have exceptions\n// enabled.\n//\n// Example:\n//     void foo()\n//     {\n//         void* p = malloc(128);\n//         auto _ = eastl::make_finally([&] { free(p); });\n//\n//         // Code that may throw an exception...\n//         \n//     }  // eastl::finally guaranteed to call 'free' at scope exit.\n//\n// References:\n// * https://www.bfilipek.com/2017/04/finalact.html\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FINALLY_H\n#define EASTL_FINALLY_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/type_traits.h>\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////\n\t// finally\n\t//\n\t// finally is the type that calls the users callback on scope exit.\n\t//\n\ttemplate <typename Functor>\n\tclass EA_NODISCARD finally\n\t{\n\t\tstatic_assert(!eastl::is_lvalue_reference_v<Functor>, \"eastl::finally requires the callable is passed as an rvalue reference.\");\n\n\t\tFunctor m_functor;\n\t\tbool m_engaged = false;\n\n\tpublic:\n\t\tfinally(Functor f) : m_functor(eastl::move(f)), m_engaged(true) {}\n\n\t\tfinally(finally&& other) : m_functor(eastl::move(other.m_functor)), m_engaged(other.m_engaged)\n\t\t{\n\t\t\tother.dismiss();\n\t\t}\n\n\t\t~finally() { execute(); }\n\n\t\tfinally(const finally&) = delete;\n\t\tfinally& operator=(const finally&) = delete;\n\t\tfinally& operator=(finally&&) = delete;\n\n\t\tinline void dismiss() { m_engaged = false; }\n\n\t\tinline void execute()\n\t\t{\n\t\t\tif (m_engaged)\n\t\t\t\tm_functor();\n\n\t\t\tdismiss();\n\t\t}\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// make_finally\n\t//\n\t// this utility function is the standard mechansim to perform the required\n\t// type deduction on the users provided callback inorder to create a\n\t// 'finally' object.\n\t//\n\ttemplate <typename F>\n\tauto make_finally(F&& f)\n\t{\n\t\treturn finally<F>(eastl::forward<F>(f));\n\t}\n}\n\n#endif // EASTL_FINALLY_H\n"
  },
  {
    "path": "include/EASTL/fixed_allocator.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the following\n//     fixed_allocator\n//     fixed_allocator_with_overflow\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_ALLOCATOR_H\n#define EASTL_FIXED_ALLOCATOR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/fixed_pool.h>\n#include <EASTL/functional.h>\n#include <EASTL/memory.h>\n#include <EASTL/allocator.h>\n#include <EASTL/type_traits.h>\n\nEA_DISABLE_ALL_VC_WARNINGS();\n\n#include <new>\n\nEA_RESTORE_ALL_VC_WARNINGS();\n\nEA_DISABLE_VC_WARNING(4275); // non dll-interface class used as base for DLL-interface classkey 'identifier'\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_allocator\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_allocator\n\t///\n\t/// Implements an allocator which allocates a single fixed size where \n\t/// the size, alignment, and memory used for the pool is defined at \n\t/// runtime by the user. This is different from fixed containers \n\t/// such as fixed_list whereby the size and alignment are determined\n\t/// at compile time and the memory is directly built into the container's\n\t/// member data.\n\t///\n\t/// If the pool's memory is exhausted or was never initialized, the \n\t/// allocate function returns NULL. Consider the fixed_allocator_with_overflow \n\t/// class as an alternative in order to deal with this situation.\n\t///\n\t/// This class requires the user to call container.get_allocator().init() \n\t/// after constructing the container. There currently isn't a way to \n\t/// construct the container with the initialization parameters, though\n\t/// with some effort such a thing could probably be made possible. \n\t/// It's not as simple as it might first seem, due to the non-copyable\n\t/// nature of fixed allocators. A side effect of this limitation is that\n\t/// you cannot copy-construct a container using fixed_allocators.\n\t///\n\t/// Another side-effect is that you cannot swap two containers using\n\t/// a fixed_allocator, as a swap requires temporary memory allocated by\n\t/// an equivalent allocator, and such a thing cannot be done implicitly.\n\t/// A workaround for the swap limitation is that you can implement your\n\t/// own swap whereby you provide an explicitly created temporary object.\n\t///\n\t/// Note: Be careful to set the allocator's node size to the size of the \n\t/// container node and not the size of the contained object. Note that the \n\t/// example code below uses IntListNode.\n\t///\n\t/// Example usage:\n\t///     typedef eastl::list<int, fixed_allocator> IntList;\n\t///     typedef IntList::node_type                IntListNode;\n\t///\n\t///     IntListNode buffer[200];\n\t///     IntList     intList;\n\t///     intList.get_allocator().init(buffer, sizeof(buffer), sizeof(IntListNode), __alignof(IntListNode));\n\t///\n\tclass EASTL_API fixed_allocator : public fixed_pool_base\n\t{\n\tpublic:\n\t\t/// fixed_allocator\n\t\t///\n\t\t/// Default constructor. The user usually will need to call init() after  \n\t\t/// constructing via this constructor. \n\t\t///\n\t\tfixed_allocator(const char* /*pName*/ = EASTL_FIXED_POOL_DEFAULT_NAME)\n\t\t\t: fixed_pool_base(NULL)\n\t\t{\n\t\t}\n\n\n\t\t/// fixed_allocator\n\t\t///\n\t\t/// Copy constructor. The user usually will need to call init() after  \n\t\t/// constructing via this constructor. By their nature, fixed-allocators\n\t\t/// cannot be copied in any useful way, as by their nature the user\n\t\t/// must manually initialize them.\n\t\t///\n\t\tfixed_allocator(const fixed_allocator&)\n\t\t\t: fixed_pool_base(NULL)\n\t\t{\n\t\t}\n\n\n\t\t/// operator=\n\t\t///\n\t\t/// By their nature, fixed-allocators cannot be copied in any \n\t\t/// useful way, as by their nature the user must manually \n\t\t/// initialize them.\n\t\t///\n\t\tfixed_allocator& operator=(const fixed_allocator&)\n\t\t{\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t// init\n\t\t//\n\t\t// No init here, as the base class version is sufficient.\n\t\t//\n\t\t//void init(void* pMemory, size_t memorySize, size_t nodeSize,\n\t\t//            size_t alignment, size_t alignmentOffset = 0);\n\n\n\t\t/// allocate\n\t\t///\n\t\t/// Allocates a new object of the size specified upon class initialization.\n\t\t/// Returns NULL if there is no more memory. \n\t\t///\n\t\tvoid* allocate(size_t n, int /*flags*/ = 0)\n\t\t{\n\t\t\t// To consider: Verify that 'n' is what the user initialized us with.\n\n\t\t\tLink* pLink = mpHead;\n\n\t\t\tif(pLink) // If we have space...\n\t\t\t{\n\t\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t\tif(++mnCurrentSize > mnPeakSize)\n\t\t\t\t\t\tmnPeakSize = mnCurrentSize;\n\t\t\t\t#endif\n\n\t\t\t\tmpHead = pLink->mpNext;\n\t\t\t\treturn pLink;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If there's no free node in the free list, just\n\t\t\t\t// allocate another from the reserved memory area\n\n\t\t\t\tif(mpNext != mpCapacity)\n\t\t\t\t{\n\t\t\t\t\tpLink = mpNext;\n\t\t\t\t\t\n\t\t\t\t\tmpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + n);\n\n\t\t\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t\t\tif(++mnCurrentSize > mnPeakSize)\n\t\t\t\t\t\t\tmnPeakSize = mnCurrentSize;\n\t\t\t\t\t#endif\n\n\t\t\t\t\treturn pLink;\n\t\t\t\t}\n\n\t\t\t\t// EASTL_ASSERT(false); To consider: enable this assert. However, we intentionally disable it because this isn't necessarily an assertable error.\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t}\n\n\n\t\t/// allocate\n\t\t///\n\t\tvoid* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0)\n\t\t{\n\t\t\treturn allocate(n, flags);\n\t\t}\n\n\n\t\t/// deallocate\n\t\t///\n\t\t/// Frees the given object which was allocated by allocate(). \n\t\t/// If the given node was not allocated by allocate() then the behaviour \n\t\t/// is undefined.\n\t\t///\n\t\tvoid deallocate(void* p, size_t)\n\t\t{\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t--mnCurrentSize;\n\t\t\t#endif\n\n\t\t\t((Link*)p)->mpNext = mpHead;\n\t\t\tmpHead = ((Link*)p);\n\t\t}\n\n\n\t\tusing fixed_pool_base::can_allocate;\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn EASTL_FIXED_POOL_DEFAULT_NAME;\n\t\t}\n\n\n\t\tvoid set_name(const char*)\n\t\t{\n\t\t\t// Nothing to do. We don't allocate memory.\n\t\t}\n\n\t}; // fixed_allocator\n\n\tbool operator==(const fixed_allocator& a, const fixed_allocator& b);\n\tbool operator!=(const fixed_allocator& a, const fixed_allocator& b);\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_allocator_with_overflow\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_allocator_with_overflow\n\t///\n\t/// Implements an allocator which allocates a single fixed size where \n\t/// the size, alignment, and memory used for the pool is defined at \n\t/// runtime by the user. This is different from fixed containers \n\t/// such as fixed_list whereby the size and alignment are determined\n\t/// at compile time and the memory is directly built into the container's\n\t/// member data.\n\t///\n\t/// Note: Be careful to set the allocator's node size to the size of the \n\t/// container node and not the size of the contained object. Note that the \n\t/// example code below uses IntListNode.\n\t///\n\t/// This class requires the user to call container.get_allocator().init() \n\t/// after constructing the container. There currently isn't a way to \n\t/// construct the container with the initialization parameters, though\n\t/// with some effort such a thing could probably be made possible. \n\t/// It's not as simple as it might first seem, due to the non-copyable\n\t/// nature of fixed allocators. A side effect of this limitation is that\n\t/// you cannot copy-construct a container using fixed_allocators.\n\t///\n\t/// Another side-effect is that you cannot swap two containers using\n\t/// a fixed_allocator, as a swap requires temporary memory allocated by\n\t/// an equivalent allocator, and such a thing cannot be done implicitly.\n\t/// A workaround for the swap limitation is that you can implement your\n\t/// own swap whereby you provide an explicitly created temporary object.\n\t///\n\t/// Example usage:\n\t///     typedef eastl::list<int, fixed_allocator_with_overflow> IntList;\n\t///     typedef IntList::node_type                              IntListNode;\n\t///\n\t///     IntListNode buffer[200];\n\t///     IntList     intList;\n\t///     intList.get_allocator().init(buffer, sizeof(buffer), sizeof(IntListNode), __alignof(IntListNode));\n\t///\n\tclass EASTL_API fixed_allocator_with_overflow : public fixed_pool_base\n\t{\n\tpublic:\n\t\t/// fixed_allocator_with_overflow\n\t\t///\n\t\t/// Default constructor. The user usually will need to call init() after  \n\t\t/// constructing via this constructor. \n\t\t///\n\t\tfixed_allocator_with_overflow(const char* pName = EASTL_FIXED_POOL_DEFAULT_NAME)\n\t\t\t: fixed_pool_base(NULL)\n\t\t\t, mOverflowAllocator(pName)\n\t\t\t, mpPoolBegin(nullptr)\n\t\t\t, mpPoolEnd(nullptr)\n\t\t\t, mnNodeSize(0)\n\t\t{\n\t\t}\n\n\n\t\t/// fixed_allocator_with_overflow\n\t\t///\n\t\t/// Copy constructor. The user usually will need to call init() after  \n\t\t/// constructing via this constructor. By their nature, fixed-allocators\n\t\t/// cannot be copied in any useful way, as by their nature the user\n\t\t/// must manually initialize them.\n\t\t///\n\t\tfixed_allocator_with_overflow(const fixed_allocator_with_overflow&)\n\t\t\t: fixed_pool_base(NULL)\n\t\t\t, mpPoolBegin(nullptr)\n\t\t\t, mpPoolEnd(nullptr)\n\t\t\t, mnNodeSize(0)\n\t\t{\n\t\t}\n\n\n\t\t/// operator=\n\t\t///\n\t\t/// By their nature, fixed-allocators cannot be copied in any \n\t\t/// useful way, as by their nature the user must manually \n\t\t/// initialize them.\n\t\t///\n\t\tfixed_allocator_with_overflow& operator=(const fixed_allocator_with_overflow& x)\n\t\t{\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tmOverflowAllocator = x.mOverflowAllocator;\n\t\t\t#else\n\t\t\t\t(void)x;\n\t\t\t#endif\n\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// init\n\t\t///\n\t\tvoid init(void* pMemory, size_t memorySize, size_t nodeSize,\n\t\t\t\t\tsize_t alignment, size_t alignmentOffset = 0)\n\t\t{\n\t\t\tfixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset);\n\n\t\t\tmpPoolBegin = pMemory;\n\t\t\tmpPoolEnd   = (void*)((uintptr_t)pMemory + memorySize);\n\t\t\tmnNodeSize  = (eastl_size_t)nodeSize;\n\t\t}\n\n\n\t\t/// allocate\n\t\t///\n\t\t/// Allocates a new object of the size specified upon class initialization.\n\t\t/// Returns NULL if there is no more memory. \n\t\t///\n\t\tvoid* allocate(size_t /*n*/, int /*flags*/ = 0)\n\t\t{\n\t\t\t// To consider: Verify that 'n' is what the user initialized us with.\n\n\t\t\tvoid* p;\n\n\t\t\tif(mpHead) // If we have space...\n\t\t\t{\n\t\t\t\tp      = mpHead;\n\t\t\t\tmpHead = mpHead->mpNext;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If there's no free node in the free list, just\n\t\t\t\t// allocate another from the reserved memory area\n\n\t\t\t\tif (mpNext != mpCapacity)\n\t\t\t\t{\n\t\t\t\t\tp = mpNext;\n\t\t\t\t\tmpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + mnNodeSize);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tp = mOverflowAllocator.allocate(mnNodeSize);\n\t\t\t}\n\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\tif(p && (++mnCurrentSize > mnPeakSize))\n\t\t\t\t\tmnPeakSize = mnCurrentSize;\n\t\t\t#endif\n\n\t\t\treturn p;\n\t\t}\n\n\n\t\t/// allocate\n\t\t///\n\t\tvoid* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0)\n\t\t{\n\t\t\treturn allocate(n, flags);\n\t\t}\n\n\n\t\t/// deallocate\n\t\t///\n\t\t/// Frees the given object which was allocated by allocate(). \n\t\t/// If the given node was not allocated by allocate() then the behaviour \n\t\t/// is undefined.\n\t\t///\n\t\tvoid deallocate(void* p, size_t)\n\t\t{\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t--mnCurrentSize;\n\t\t\t#endif\n\n\t\t\tif((p >= mpPoolBegin) && (p < mpPoolEnd))\n\t\t\t{\n\t\t\t\t((Link*)p)->mpNext = mpHead;\n\t\t\t\tmpHead = ((Link*)p);\n\t\t\t}\n\t\t\telse\n\t\t\t\tmOverflowAllocator.deallocate(p, (size_t)mnNodeSize);\n\t\t}\n\n\n\t\tusing fixed_pool_base::can_allocate;\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn mOverflowAllocator.get_name();\n\t\t}\n\n\n\t\tvoid set_name(const char* pName)\n\t\t{\n\t\t\tmOverflowAllocator.set_name(pName);\n\t\t}\n\n\tprotected:\n\t\tEASTLAllocatorType mOverflowAllocator;  // To consider: Allow the user to define the type of this, presumably via a template parameter.\n\t\tvoid*              mpPoolBegin;         // To consider: We have these member variables and ideally we shouldn't need them. The problem is that \n\t\tvoid*              mpPoolEnd;           //              the information about the pool buffer and object size is stored in the owning container \n\t\teastl_size_t       mnNodeSize;          //              and we can't have access to it without increasing the amount of code we need and by templating \n\t\t\t\t\t\t\t\t\t\t\t\t//              more code. It may turn out that simply storing data here is smaller in the end.\n\t}; // fixed_allocator_with_overflow         //              Granted, this class is usually used for debugging purposes, but perhaps there is an elegant solution.\n\n\tbool operator==(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b);\n\tbool operator!=(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b);\n\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\tinline bool operator==(const fixed_allocator&, const fixed_allocator&)\n\t{\n\t\treturn false;\n\t}\n\n\tinline bool operator!=(const fixed_allocator&, const fixed_allocator&)\n\t{\n\t\treturn false;\n\t}\n\n\tinline bool operator==(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&)\n\t{\n\t\treturn false;\n\t}\n\n\tinline bool operator!=(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&)\n\t{\n\t\treturn false;\n\t}\n\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/fixed_function.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FIXED_FUNCTION_H\n#define EASTL_FIXED_FUNCTION_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/function_detail.h>\n\nnamespace eastl\n{\n\ttemplate <int, typename>\n\tclass fixed_function;\n\n\tnamespace internal\n\t{\n\t\ttemplate <typename>\n\t\tstruct is_fixed_function\n\t\t\t: public eastl::false_type {};\n\n\t\ttemplate <int SIZE_IN_BYTES, typename R, typename... Args>\n\t\tstruct is_fixed_function<eastl::fixed_function<SIZE_IN_BYTES, R(Args...)>>\n\t\t\t: public eastl::true_type {};\n\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_fixed_function_v = is_fixed_function<T>::value;\n\t}\n\n\t#define EASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(TYPE)\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tstatic_assert(sizeof(eastl::decay_t<TYPE>) <= sizeof(typename Base::FunctorStorageType),\t\t\\\n\t\t\t\t\t\"fixed_function local buffer is not large enough to hold the callable object.\");\t\\\n\t\tstatic_assert(alignof(eastl::internal::functor_storage_alignment) % alignof(eastl::decay_t<TYPE>) == 0,\t\\\n\t\t\t\t\t\"object alignment too large to fit into fixed_function alignment\");\n\n    #define EASTL_INTERNAL_FIXED_FUNCTION_OTHER_SIZE_STATIC_ASSERT(OTHER_SIZE_IN_BYTES) \\\n\t\tstatic_assert(SIZE_IN_BYTES >= OTHER_SIZE_IN_BYTES,\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t \"fixed_function local buffer is not large enough to hold the new fixed_function type.\")\n\n\ttemplate <typename Functor>\n\tusing EASTL_DISABLE_OVERLOAD_IF_FIXED_FUNCTION =\n\t    eastl::disable_if_t<internal::is_fixed_function_v<eastl::decay_t<Functor>>>;\n\n\n\t// fixed_function\n\t//\n\ttemplate <int SIZE_IN_BYTES, typename R, typename... Args>\n\tclass fixed_function<SIZE_IN_BYTES, R(Args...)> : public internal::function_detail<SIZE_IN_BYTES, R(Args...)>\n\t{\n\t\tusing Base = internal::function_detail<SIZE_IN_BYTES, R(Args...)>;\n\n\tpublic:\n\t\tusing typename Base::result_type;\n\n\t\tfixed_function() EA_NOEXCEPT = default;\n\t\tfixed_function(std::nullptr_t p) EA_NOEXCEPT\n\t\t\t: Base(p)\n\t\t{\n\t\t}\n\n\t\tfixed_function(const fixed_function& other)\n\t\t\t: Base(other)\n\t\t{\n\t\t}\n\n\t\tfixed_function(fixed_function&& other)\n\t\t\t: Base(eastl::move(other))\n\t\t{\n\t\t}\n\n\t\ttemplate <typename Functor,\n\t\t          typename = EASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(Functor, R, Args..., Base, fixed_function),\n\t\t          typename = EASTL_DISABLE_OVERLOAD_IF_FIXED_FUNCTION<Functor>>\n\t\tfixed_function(Functor&& functor)\n\t\t    : Base(eastl::forward<Functor>(functor))\n\t\t{\n\t\t\tEASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(Functor);\n\t\t}\n\n\t\ttemplate<int OTHER_SIZE_IN_BYTES>\n\t\tfixed_function(const fixed_function<OTHER_SIZE_IN_BYTES, R(Args...)>& other)\n\t\t    : Base(static_cast<const internal::function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>&>(other))\n\t\t{\n\t\t\tEASTL_INTERNAL_FIXED_FUNCTION_OTHER_SIZE_STATIC_ASSERT(OTHER_SIZE_IN_BYTES);\n\t\t}\n\n\t\ttemplate<int OTHER_SIZE_IN_BYTES>\n\t\tfixed_function(fixed_function<OTHER_SIZE_IN_BYTES, R(Args...)>&& other)\n\t\t    : Base(static_cast<internal::function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>&&>(other))\n\t\t{\n\t\t\tEASTL_INTERNAL_FIXED_FUNCTION_OTHER_SIZE_STATIC_ASSERT(OTHER_SIZE_IN_BYTES);\n\t\t}\n\n\t\t~fixed_function() EA_NOEXCEPT = default;\n\n\t\tfixed_function& operator=(const fixed_function& other)\n\t\t{\n\t\t\tBase::operator=(other);\n\t\t\treturn *this;\n\t\t}\n\n\t\tfixed_function& operator=(fixed_function&& other)\n\t\t{\n\t\t\tBase::operator=(eastl::move(other));\n\t\t\treturn *this;\n\t\t}\n\n\t\tfixed_function& operator=(std::nullptr_t p) EA_NOEXCEPT\n\t\t{\n\t\t\tBase::operator=(p);\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate<int OTHER_SIZE_IN_BYTES>\n\t\tfixed_function& operator=(const fixed_function<OTHER_SIZE_IN_BYTES, R(Args...)>& other)\n\t\t{\n\t\t\tEASTL_INTERNAL_FIXED_FUNCTION_OTHER_SIZE_STATIC_ASSERT(OTHER_SIZE_IN_BYTES);\n\n\t\t\tBase::operator=(static_cast<const internal::function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>&>(other));\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate<int OTHER_SIZE_IN_BYTES>\n\t\tfixed_function& operator=(fixed_function<OTHER_SIZE_IN_BYTES, R(Args...)>&& other)\n\t\t{\n\t\t\tEASTL_INTERNAL_FIXED_FUNCTION_OTHER_SIZE_STATIC_ASSERT(OTHER_SIZE_IN_BYTES);\n\n\t\t\tBase::operator=(static_cast<internal::function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>&&>(other));\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename Functor,\n\t\t          typename = EASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(Functor, R, Args..., Base, fixed_function),\n\t\t          typename = EASTL_DISABLE_OVERLOAD_IF_FIXED_FUNCTION<Functor>>\n\t\tfixed_function& operator=(Functor&& functor)\n\t\t{\n\t\t\tEASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(eastl::decay_t<Functor>);\n\t\t\tBase::operator=(eastl::forward<Functor>(functor));\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename Functor>\n\t\tfixed_function& operator=(eastl::reference_wrapper<Functor> f) EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(eastl::reference_wrapper<Functor>);\n\t\t\tBase::operator=(f);\n\t\t\treturn *this;\n\t\t}\n\n\t\tvoid swap(fixed_function& other) EA_NOEXCEPT\n\t\t{\n\t\t\tBase::swap(other);\n\t\t}\n\n\t\texplicit operator bool() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::operator bool();\n\t\t}\n\n\t\tR operator ()(Args... args) const\n\t\t{\n\t\t\treturn Base::operator ()(eastl::forward<Args>(args)...);\n\t\t}\n\n\t#if EASTL_RTTI_ENABLED\n\t\tconst std::type_info& target_type() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::target_type();\n\t\t}\n\n\t\ttemplate <typename Functor>\n\t\tFunctor* target() EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::target();\n\t\t}\n\n\t\ttemplate <typename Functor>\n\t\tconst Functor* target() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::target();\n\t\t}\n\t#endif\n\t};\n\n\ttemplate <int S, typename R, typename... Args>\n\tbool operator==(const fixed_function<S, R(Args...)>& f, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !f;\n\t}\n\n\ttemplate <int S, typename R, typename... Args>\n\tbool operator==(std::nullptr_t, const fixed_function<S, R(Args...)>& f) EA_NOEXCEPT\n\t{\n\t\treturn !f;\n\t}\n\n\ttemplate <int S, typename R, typename... Args>\n\tbool operator!=(const fixed_function<S, R(Args...)>& f, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !!f;\n\t}\n\n\ttemplate <int S, typename R, typename... Args>\n\tbool operator!=(std::nullptr_t, const fixed_function<S, R(Args...)>& f) EA_NOEXCEPT\n\t{\n\t\treturn !!f;\n\t}\n\n\ttemplate <int S, typename R, typename... Args>\n\tvoid swap(fixed_function<S, R(Args...)>& lhs, fixed_function<S, R(Args...)>& rhs)\n\t{\n\t\tlhs.swap(rhs);\n\t}\n\n} // namespace eastl\n\n#endif // EASTL_FIXED_FUNCTION_H\n"
  },
  {
    "path": "include/EASTL/fixed_hash_map.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a hash_map and hash_multimap which use a fixed size \n// memory pool for its buckets and nodes. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_HASH_MAP_H\n#define EASTL_FIXED_HASH_MAP_H\n\n\n#include <EASTL/hash_map.h>\n#include <EASTL/internal/fixed_pool.h>\n\nEA_DISABLE_VC_WARNING(4127) // Conditional expression is constant\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_HASH_MAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_HASH_MAP_DEFAULT_NAME\n\t\t#define EASTL_FIXED_HASH_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_hash_map\" // Unless the user overrides something, this is \"EASTL fixed_hash_map\".\n\t#endif\n\n\t#ifndef EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME\n\t\t#define EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_hash_multimap\" // Unless the user overrides something, this is \"EASTL fixed_hash_multimap\".\n\t#endif\n\n\n\t/// EASTL_FIXED_HASH_MAP_DEFAULT_ALLOCATOR\n\t/// EASTL_FIXED_HASH_MULTIMAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_HASH_MAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_HASH_MAP_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_HASH_MAP_DEFAULT_NAME)\n\t#endif\n\n\t#ifndef EASTL_FIXED_HASH_MULTIMAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_HASH_MULTIMAP_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// fixed_hash_map\n\t///\n\t/// Implements a hash_map with a fixed block of memory identified by the nodeCount and bucketCount\n\t/// template parameters. \n\t///\n\t/// Template parameters:\n\t///     Key                    The key type for the map. This is a map of Key to T (value).\n\t///     T                      The value type for the map.\n\t///     nodeCount              The max number of objects to contain. This value must be >= 1.\n\t///     bucketCount            The number of buckets to use. This value must be >= 2.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Hash                   hash_set hash function. See hash_set.\n\t///     Predicate              hash_set equality testing function. See hash_set.\n\t///\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,\n\t\t\t  typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>, bool bCacheHashCode = false, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_hash_map : public hash_map<Key, \n\t\t\t\t\t\t\t\t\t\t   T,\n\t\t\t\t\t\t\t\t\t\t   Hash,\n\t\t\t\t\t\t\t\t\t\t   Predicate,\n\t\t\t\t\t\t\t\t\t\t   fixed_hashtable_allocator<\n\t\t\t\t\t\t\t\t\t\t\t\tbucketCount + 1,\n\t\t\t\t\t\t\t\t\t\t\t\tsizeof(typename hash_map<Key, T, Hash, Predicate, OverflowAllocator, bCacheHashCode>::node_type), \n\t\t\t\t\t\t\t\t\t\t\t\tnodeCount,\n\t\t\t\t\t\t\t\t\t\t\t\tEASTL_ALIGN_OF(eastl::pair<Key, T>), \n\t\t\t\t\t\t\t\t\t\t\t\t0, \n\t\t\t\t\t\t\t\t\t\t\t\tbEnableOverflow,\n\t\t\t\t\t\t\t\t\t\t\t\tOverflowAllocator>, \n\t\t\t\t\t\t\t\t\t\t   bCacheHashCode>\n\t{\n\tpublic:\n\t\ttypedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_map<Key, T, Hash, Predicate, \n\t\t\t\t\t\tOverflowAllocator, bCacheHashCode>::node_type), nodeCount, EASTL_ALIGN_OF(eastl::pair<Key, T>), 0,\n\t\t\t\t\t\tbEnableOverflow, OverflowAllocator>                                                                         fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                                                              overflow_allocator_type;\n\t\ttypedef hash_map<Key, T, Hash, Predicate, fixed_allocator_type, bCacheHashCode>                                             base_type;\n\t\ttypedef fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator> this_type;\n\t\ttypedef typename base_type::value_type                                                                                      value_type;\n\t\ttypedef typename base_type::node_type                                                                                       node_type;\n\t\ttypedef typename base_type::size_type                                                                                       size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::clear;\n\n\tprotected:\n\t\tusing base_type::mAllocator;\n\n\t\tnode_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.\n\t\tchar        mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\tpublic:\n\t\texplicit fixed_hash_map(const overflow_allocator_type& overflowAllocator);\n\n\t\texplicit fixed_hash_map(const Hash& hashFunction = Hash(), \n\t\t\t\t\t\t\t\tconst Predicate& predicate = Predicate());\n\n\t\tfixed_hash_map(const Hash& hashFunction, \n\t\t\t\t\t   const Predicate& predicate,\n\t\t\t\t\t   const overflow_allocator_type& overflowAllocator);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_hash_map(InputIterator first, InputIterator last, \n\t\t\t\t\t\tconst Hash& hashFunction = Hash(), \n\t\t\t\t\t\tconst Predicate& predicate = Predicate());\n\n\t\tfixed_hash_map(const this_type& x);\n\t\tfixed_hash_map(this_type&& x);\n\t\tfixed_hash_map(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_hash_map(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_MAP_DEFAULT_ALLOCATOR);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\n\t\tvoid clear(bool clearBuckets); \n\t}; // fixed_hash_map\n\n\n\n\n\n\t/// fixed_hash_multimap\n\t///\n\t/// Implements a hash_multimap with a fixed block of memory identified by the nodeCount and bucketCount\n\t/// template parameters. \n\t///\n\t/// Template parameters:\n\t///     Key                    The key type for the map. This is a map of Key to T (value).\n\t///     T                      The value type for the map.\n\t///     nodeCount              The max number of objects to contain. This value must be >= 1.\n\t///     bucketCount            The number of buckets to use. This value must be >= 2.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Hash                   hash_set hash function. See hash_set.\n\t///     Predicate              hash_set equality testing function. See hash_set.\n\t///\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,\n\t\t\t  typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>, bool bCacheHashCode = false, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_hash_multimap : public hash_multimap<Key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t T,\n\t\t\t\t\t\t\t\t\t\t\t\t\t Hash,\n\t\t\t\t\t\t\t\t\t\t\t\t\t Predicate,\n\t\t\t\t\t\t\t\t\t\t\t\t\t fixed_hashtable_allocator<\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbucketCount + 1, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsizeof(typename hash_multimap<Key, T, Hash, Predicate, OverflowAllocator, bCacheHashCode>::node_type), \n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnodeCount,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tEASTL_ALIGN_OF(eastl::pair<Key, T>),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbEnableOverflow,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tOverflowAllocator>, \n\t\t\t\t\t\t\t\t\t\t\t\t\t bCacheHashCode>\n\t{\n\tpublic:\n\t\ttypedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_multimap<Key, T, Hash, Predicate, \n\t\t\t\t\t\tOverflowAllocator, bCacheHashCode>::node_type), nodeCount, EASTL_ALIGN_OF(eastl::pair<Key, T>), 0, \n\t\t\t\t\t\tbEnableOverflow, OverflowAllocator>                                                                              fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                                                                   overflow_allocator_type;\n\t\ttypedef hash_multimap<Key, T, Hash, Predicate, fixed_allocator_type, bCacheHashCode>                                             base_type;\n\t\ttypedef fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator> this_type;\n\t\ttypedef typename base_type::value_type                                                                                           value_type;\n\t\ttypedef typename base_type::node_type                                                                                            node_type;\n\t\ttypedef typename base_type::size_type                                                                                            size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::clear;\n\n\tprotected:\n\t\tusing base_type::mAllocator;\n\n\t\tnode_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.\n\t\tchar        mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\tpublic:\n\t\texplicit fixed_hash_multimap(const overflow_allocator_type& overflowAllocator);\n\n\t\texplicit fixed_hash_multimap(const Hash& hashFunction = Hash(), \n\t\t\t\t\t\t\t\t\t\tconst Predicate& predicate = Predicate());\n\n\t\tfixed_hash_multimap(const Hash& hashFunction,\n\t\t\t\t\t\t\tconst Predicate& predicate,\n\t\t\t\t\t\t\tconst overflow_allocator_type& overflowAllocator);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_hash_multimap(InputIterator first, InputIterator last, \n\t\t\t\t\t\tconst Hash& hashFunction = Hash(), \n\t\t\t\t\t\tconst Predicate& predicate = Predicate());\n\n\t\tfixed_hash_multimap(const this_type& x);\n\t\tfixed_hash_multimap(this_type&& x);\n\t\tfixed_hash_multimap(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_hash_multimap(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_MULTIMAP_DEFAULT_ALLOCATOR);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\n\t\tvoid clear(bool clearBuckets); \n\t}; // fixed_hash_multimap\n\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_hash_map\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), Hash(), \n\t\t\t\t\tPredicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(const Hash& hashFunction, \n\t\t\t\t   const Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif (!bEnableOverflow)\n\t\t{\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\t\t}\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(const Hash& hashFunction, \n\t\t\t\t   const Predicate& predicate,\n\t\t\t\t   const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif (!bEnableOverflow)\n\t\t{\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\t\t}\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(InputIterator first, InputIterator last, \n\t\t\t\t\tconst Hash& hashFunction, \n\t\t\t\t\tconst Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(first, last);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(const this_type& x)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(), \n\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(this_type&& x)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(), \n\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(), \n\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_map(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), Hash(), \n\t\t\t\t\tPredicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tswap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\treset_lose_memory()\n\t{\n\t\tbase_type::mnBucketCount = (size_type)base_type::mRehashPolicy.GetPrevBucketCount((uint32_t)bucketCount);\n\t\tbase_type::mnElementCount = 0;\n\t\tbase_type::mRehashPolicy.mnNextResize = 0;\n\t\tbase_type::get_allocator().reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::size_type \n\tfixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline const typename fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tset_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tclear(bool clearBuckets)\n\t{\n\t\tbase_type::DoFreeNodes(base_type::mpBucketArray, base_type::mnBucketCount);\n\t\tif(clearBuckets)\n\t\t{\n\t\t\tbase_type::DoFreeBuckets(base_type::mpBucketArray, base_type::mnBucketCount);\n\t\t\treset_lose_memory();\n\t\t}\n\t\tbase_type::mpBucketArray = (node_type**)mBucketBuffer;\n\t\tbase_type::mnElementCount = 0;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>\n\tinline void swap(fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a, \n\t\t\t\t\t fixed_hash_map<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_hash_multimap\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), Hash(), \n\t\t\t\t\tPredicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif (!bEnableOverflow)\n\t\t{\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\t\t}\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(const Hash& hashFunction, \n\t\t\t\t\t\tconst Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(const Hash& hashFunction,\n\t\t\t\t\t\tconst Predicate& predicate,\n\t\t\t\t\t\tconst overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(InputIterator first, InputIterator last, \n\t\t\t\t\t\tconst Hash& hashFunction, \n\t\t\t\t\t\tconst Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(first, last);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(const this_type& x)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(), \n\t\t\t\t\tx.key_eq(),fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(this_type&& x)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(), \n\t\t\t\t\tx.key_eq(),fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(), \n\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multimap(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), Hash(), \n\t\t\t\t\tPredicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tswap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\treset_lose_memory()\n\t{\n\t\tbase_type::mnBucketCount = (size_type)base_type::mRehashPolicy.GetPrevBucketCount((uint32_t)bucketCount);\n\t\tbase_type::mnElementCount = 0;\n\t\tbase_type::mRehashPolicy.mnNextResize = 0;\n\t\tbase_type::get_allocator().reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::size_type\n\tfixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline const typename fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tclear(bool clearBuckets)\n\t{\n\t\tbase_type::DoFreeNodes(base_type::mpBucketArray, base_type::mnBucketCount);\n\t\tif(clearBuckets)\n\t\t{\n\t\t\tbase_type::DoFreeBuckets(base_type::mpBucketArray, base_type::mnBucketCount);\n\t\t\treset_lose_memory();\n\t\t}\n\t\tbase_type::mpBucketArray = (node_type**)mBucketBuffer;\n\t\tbase_type::mnElementCount = 0;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>\n\tinline void swap(fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a, \n\t\t\t\t\t fixed_hash_multimap<Key, T, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING()\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/fixed_hash_set.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a hash_set which uses a fixed size memory pool for \n// its buckets and nodes. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_HASH_SET_H\n#define EASTL_FIXED_HASH_SET_H\n\n\n#include <EASTL/hash_set.h>\n#include <EASTL/internal/fixed_pool.h>\n\nEA_DISABLE_VC_WARNING(4127) // Conditional expression is constant\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_HASH_SET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_HASH_SET_DEFAULT_NAME\n\t\t#define EASTL_FIXED_HASH_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_hash_set\" // Unless the user overrides something, this is \"EASTL fixed_hash_set\".\n\t#endif\n\n\t#ifndef EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME\n\t\t#define EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_hash_multiset\" // Unless the user overrides something, this is \"EASTL fixed_hash_multiset\".\n\t#endif\n\n\n\t/// EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR\n\t/// EASTL_FIXED_HASH_MULTISET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_HASH_SET_DEFAULT_NAME)\n\t#endif\n\n\t#ifndef EASTL_FIXED_HASH_MULTISET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_HASH_MULTISET_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// fixed_hash_set\n\t///\n\t/// Implements a hash_set with a fixed block of memory identified by the nodeCount and bucketCount\n\t/// template parameters. \n\t///\n\t/// Template parameters:\n\t///     Value                  The type of object the hash_set holds.\n\t///     nodeCount              The max number of objects to contain. This value must be >= 1.\n\t///     bucketCount            The number of buckets to use. This value must be >= 2.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Hash                   hash_set hash function. See hash_set.\n\t///     Predicate              hash_set equality testing function. See hash_set.\n\t///\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,\n\t\t\t  typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>, bool bCacheHashCode = false, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_hash_set : public hash_set<Value,\n\t\t\t\t\t\t\t\t\t\t   Hash,\n\t\t\t\t\t\t\t\t\t\t   Predicate,\n\t\t\t\t\t\t\t\t\t\t   fixed_hashtable_allocator<\n\t\t\t\t\t\t\t\t\t\t\t\tbucketCount + 1, \n\t\t\t\t\t\t\t\t\t\t\t\tsizeof(typename hash_set<Value, Hash, Predicate, OverflowAllocator, bCacheHashCode>::node_type), \n\t\t\t\t\t\t\t\t\t\t\t\tnodeCount, \n\t\t\t\t\t\t\t\t\t\t\t\tEASTL_ALIGN_OF(typename hash_set<Value, Hash, Predicate, OverflowAllocator, bCacheHashCode>::node_type),\n\t\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t\t\tbEnableOverflow,\n\t\t\t\t\t\t\t\t\t\t\t\tOverflowAllocator>, \n\t\t\t\t\t\t\t\t\t\t   bCacheHashCode>\n\t{\n\tpublic:\n\t\ttypedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_set<Value, Hash, Predicate, \n\t\t\t\t\t\tOverflowAllocator, bCacheHashCode>::node_type), nodeCount, \n\t\t\t\t\t\tEASTL_ALIGN_OF(typename hash_set<Value, Hash, Predicate, OverflowAllocator, bCacheHashCode>::node_type),\n\t\t\t\t\t\t0,\tbEnableOverflow, OverflowAllocator>                                                                    fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                                                             overflow_allocator_type;\n\t\ttypedef fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator> this_type;\n\t\ttypedef hash_set<Value, Hash, Predicate, fixed_allocator_type, bCacheHashCode>                                             base_type;\n\t\ttypedef typename base_type::value_type                                                                                     value_type;\n\t\ttypedef typename base_type::node_type                                                                                      node_type;\n\t\ttypedef typename base_type::size_type                                                                                      size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\tprotected:\n\t\tusing base_type::mAllocator;\n\n\t\tnode_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.\n\t\tchar        mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\tpublic:\n\t\texplicit fixed_hash_set(const overflow_allocator_type& overflowAllocator);\n\n\t\texplicit fixed_hash_set(const Hash& hashFunction = Hash(), \n\t\t\t\t\t\t\t\tconst Predicate& predicate = Predicate());\n\n\t\tfixed_hash_set(const Hash& hashFunction, \n\t\t\t\t\t   const Predicate& predicate,\n\t\t\t\t\t   const overflow_allocator_type& overflowAllocator);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_hash_set(InputIterator first, InputIterator last,\n\t\t\t\t\t   const Hash& hashFunction = Hash(),\n\t\t\t\t\t   const Predicate& predicate = Predicate());\n\n\t\tfixed_hash_set(const this_type& x);\n\t\tfixed_hash_set(this_type&& x);\n\t\tfixed_hash_set(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\n\t\tfixed_hash_set(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\t}; // fixed_hash_set\n\n\n\n\n\n\n\t/// fixed_hash_multiset\n\t///\n\t/// Implements a hash_multiset with a fixed block of memory identified by the nodeCount and bucketCount\n\t/// template parameters. \n\t///\n\t///     Value                  The type of object the hash_set holds.\n\t///     nodeCount              The max number of objects to contain. This value must be >= 1.\n\t///     bucketCount            The number of buckets to use. This value must be >= 2.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Hash                   hash_set hash function. See hash_set.\n\t///     Predicate              hash_set equality testing function. See hash_set.\n\t///\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount = nodeCount + 1, bool bEnableOverflow = true,\n\t\t\t  typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>, bool bCacheHashCode = false, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_hash_multiset : public hash_multiset<Value,\n\t\t\t\t\t\t\t\t\t\t\t\t\t Hash,\n\t\t\t\t\t\t\t\t\t\t\t\t\t Predicate,\n\t\t\t\t\t\t\t\t\t\t\t\t\t fixed_hashtable_allocator<\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbucketCount + 1, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsizeof(typename hash_multiset<Value, Hash, Predicate, OverflowAllocator, bCacheHashCode>::node_type),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnodeCount,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tEASTL_ALIGN_OF(typename hash_multiset<Value, Hash, Predicate, OverflowAllocator, bCacheHashCode>::node_type),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbEnableOverflow,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tOverflowAllocator>,\n\t\t\t\t\t\t\t\t\t\t\t\t\t bCacheHashCode>\n\t{\n\tpublic:\n\t\ttypedef fixed_hashtable_allocator<bucketCount + 1, sizeof(typename hash_multiset<Value, Hash, Predicate, \n\t\t\t\t\tOverflowAllocator, bCacheHashCode>::node_type), nodeCount, EASTL_ALIGN_OF(typename hash_multiset<Value, Hash, Predicate,\n\t\t\t\t\tOverflowAllocator, bCacheHashCode>::node_type), 0,\n\t\t\t\t\tbEnableOverflow, OverflowAllocator>                                                                                 fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                                                                  overflow_allocator_type;\n\t\ttypedef hash_multiset<Value, Hash, Predicate, fixed_allocator_type, bCacheHashCode>                                             base_type;\n\t\ttypedef fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator> this_type;\n\t\ttypedef typename base_type::value_type                                                                                          value_type;\n\t\ttypedef typename base_type::node_type                                                                                           node_type;\n\t\ttypedef typename base_type::size_type                                                                                           size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\tprotected:\n\t\tusing base_type::mAllocator;\n\n\t\tnode_type** mBucketBuffer[bucketCount + 1]; // '+1' because the hash table needs a null terminating bucket.\n\t\tchar        mNodeBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\tpublic:\n\t\texplicit fixed_hash_multiset(const overflow_allocator_type& overflowAllocator);\n\n\t\texplicit fixed_hash_multiset(const Hash& hashFunction = Hash(), \n\t\t\t\t\t\t\t\t\t const Predicate& predicate = Predicate());\n\n\t\tfixed_hash_multiset(const Hash& hashFunction, \n\t\t\t\t\t\t\tconst Predicate& predicate,\n\t\t\t\t\t\t\tconst overflow_allocator_type& overflowAllocator);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_hash_multiset(InputIterator first, InputIterator last, \n\t\t\t\t\t\t\tconst Hash& hashFunction = Hash(), \n\t\t\t\t\t\t\tconst Predicate& predicate = Predicate());\n\n\t\tfixed_hash_multiset(const this_type& x);\n\t\tfixed_hash_multiset(this_type&& x);\n\t\tfixed_hash_multiset(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_hash_multiset(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_MULTISET_DEFAULT_ALLOCATOR);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\t}; // fixed_hash_multiset\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_hash_set\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_set(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), \n\t\t\t\t\tHash(), Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif (!bEnableOverflow)\n\t\t{\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\t\t}\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_set(const Hash& hashFunction, \n\t\t\t\t   const Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), \n\t\t\t\t\thashFunction, predicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_set(const Hash& hashFunction, \n\t\t\t\t   const Predicate& predicate,\n\t\t\t\t   const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), \n\t\t\t\t\thashFunction, predicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif (!bEnableOverflow)\n\t\t{\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\t\t}\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_set(InputIterator first, InputIterator last,\n\t\t\t\t   const Hash& hashFunction,\n\t\t\t\t   const Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t{\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\t\t}\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(first, last);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_set(const this_type& x)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(),\n\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_set<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::fixed_hash_set(this_type&& x)\n\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(),\n\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_set<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::fixed_hash_set(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), \n\t\t\t\t\tx.hash_function(), x.key_eq(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_set<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_set(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), Hash(), \n\t\t\t\t\tPredicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\ttypename fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_set<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_set<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\toperator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_set<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_set<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tswap(this_type& x)\n\t{\n\t\t// We must do a brute-force swap, because fixed containers cannot share memory allocations.\n\t\t// Note that we create a temp value on the stack. This approach may fail if the size of the \n\t\t// container is too large. We have a rule against allocating memory from the heap, and so \n\t\t// if the user wants to swap two large objects of this class, the user will currently need \n\t\t// to implement it manually. To consider: add code to allocate a temporary buffer if the \n\t\t// size of the container is too large for the stack.\n\t\tEASTL_ASSERT(sizeof(x) < EASTL_MAX_STACK_USAGE); // It is dangerous to try to create objects that are too big for the stack.\n\n\t\tconst this_type temp(*this); // Can't call eastl::swap because that would\n\t\t*this = x;                   // itself call this member swap function.\n\t\tx     = temp;\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tvoid fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\treset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tbase_type::get_allocator().reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::size_type \n\tfixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline const typename fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tset_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>\n\tinline void swap(fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a, \n\t\t\t\t\t fixed_hash_set<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_hash_multiset\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multiset(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), Hash(), \n\t\t\t\t\tPredicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multiset(const Hash& hashFunction, \n\t\t\t\t\t\tconst Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multiset(const Hash& hashFunction, \n\t\t\t\t\t\tconst Predicate& predicate,\n\t\t\t\t\t\tconst overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tinline fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multiset(InputIterator first, InputIterator last, \n\t\t\t\t\t\tconst Hash& hashFunction, \n\t\t\t\t\t\tconst Predicate& predicate)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), hashFunction, \n\t\t\t\t\tpredicate, fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(first, last);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multiset(const this_type& x)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(), \n\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multiset<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::fixed_hash_multiset(this_type&& x)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), x.hash_function(),\n\t\t\t\t\t\tx.key_eq(), fixed_allocator_type(NULL, mBucketBuffer))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multiset<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::fixed_hash_multiset(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), \n\t\t\t\t\tx.hash_function(), x.key_eq(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\t// This implementation is the same as above. If we could rely on using C++11 delegating constructor support then we could just call that here.\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline fixed_hash_multiset<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tfixed_hash_multiset(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(prime_rehash_policy::GetPrevBucketCountOnly(bucketCount), Hash(), \n\t\t\t\t\tPredicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator))\n\t{\n\t\tEASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2));\n\n\t\tif(!bEnableOverflow)\n\t\t\tbase_type::set_max_load_factor(10000.f); // Set it so that we will never resize.\n\n\t\tmAllocator.reset(mNodeBuffer);\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multiset<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_multiset<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multiset<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::this_type& \n\tfixed_hash_multiset<Key, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tbase_type::insert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tswap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\treset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tbase_type::get_allocator().reset(mNodeBuffer);\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::size_type \n\tfixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline const typename fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline typename fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::overflow_allocator_type& \n\tfixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode, typename OverflowAllocator>\n\tinline void fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode, OverflowAllocator>::\n\tset_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, size_t nodeCount, size_t bucketCount, bool bEnableOverflow, typename Hash, typename Predicate, bool bCacheHashCode>\n\tinline void swap(fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& a, \n\t\t\t\t\t fixed_hash_multiset<Value, nodeCount, bucketCount, bEnableOverflow, Hash, Predicate, bCacheHashCode>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING()\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/fixed_list.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a list which uses a fixed size memory pool for its nodes. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_LIST_H\n#define EASTL_FIXED_LIST_H\n\n\n#include <EASTL/list.h>\n#include <EASTL/internal/fixed_pool.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_LIST_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_LIST_DEFAULT_NAME\n\t\t#define EASTL_FIXED_LIST_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_list\" // Unless the user overrides something, this is \"EASTL fixed_list\".\n\t#endif\n\n\n\t/// EASTL_FIXED_LIST_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_LIST_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_LIST_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_LIST_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// fixed_list\n\t///\n\t/// fixed_list is a list which uses a single block of contiguous memory \n\t/// for its nodes. The purpose of this is to reduce memory usage relative\n\t/// to a conventional memory allocation system (with block headers), to \n\t/// increase allocation speed (often due to avoidance of mutex locks),\n\t/// to increase performance (due to better memory locality), and to decrease\n\t/// memory fragmentation due to the way that fixed block allocators work.\n\t///\n\t/// The primary downside to a fixed_list is that the number of nodes it\n\t/// can contain is fixed upon its declaration. If you want a fixed_list\n\t/// that doesn't have this limitation, then you probably don't want a\n\t/// fixed_list. You can always create your own memory allocator that works\n\t/// the way you want.\n\t///\n\t/// Template parameters:\n\t///     T                      The type of object the list holds.\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the overflow heap if our object pool is exhausted.\n\t///     OverflowAllocator      Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow = true, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_list : public list<T, fixed_node_allocator<sizeof(typename list<T>::node_type),\n\t\t\t\t\t\t\t\t   nodeCount, EASTL_ALIGN_OF(typename list<T>::node_type), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_node_allocator<sizeof(typename list<T>::node_type), nodeCount,\n\t\t\t\t\t EASTL_ALIGN_OF(typename list<T>::node_type), 0, bEnableOverflow, OverflowAllocator> fixed_allocator_type;\n\t\ttypedef OverflowAllocator                                              overflow_allocator_type;\n\t\ttypedef list<T, fixed_allocator_type>                                  base_type;\n\t\ttypedef fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>   this_type;\n\t\ttypedef typename base_type::size_type                                  size_type;\n\t\ttypedef typename base_type::value_type                                 value_type;\n\t\ttypedef typename base_type::node_type                                  node_type;\n\t\ttypedef typename base_type::iterator                                   iterator;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::assign;\n\t\tusing base_type::resize;\n\t\tusing base_type::insert;\n\t\tusing base_type::size;\n\t\tusing base_type::get_allocator;\n\n\tprotected:\n\t\tchar mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\t\tusing base_type::internalAllocator;\n\n\tpublic:\n\t\tfixed_list();\n\t\texplicit fixed_list(const overflow_allocator_type& overflowAllocator); // Only applicable if bEnableOverflow is true.\n\t\texplicit fixed_list(size_type n);                                      // Currently we don't support overflowAllocator specification for other constructors, for simplicity.\n\t\tfixed_list(size_type n, const value_type& value);\n\t\tfixed_list(const this_type& x);\n\t\tfixed_list(this_type&& x);\n\t\tfixed_list(this_type&&, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_list(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_LIST_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_list(InputIterator first, InputIterator last);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid      swap(this_type& x);\n\t\tvoid      reset_lose_memory();      // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\t\tsize_type max_size() const;         // Returns the max fixed size, which is the user-supplied nodeCount parameter.\n\t\tbool      full() const;             // Returns true if the fixed space has been fully allocated. Note that if overflow is enabled, the container size can be greater than nodeCount but full() could return true because the fixed space may have a recently freed slot. \n\t\tbool      has_overflowed() const;   // Returns true if the allocations spilled over into the overflow allocator. Meaningful only if overflow is enabled.\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; } // Returns the value of the bEnableOverflow template parameter.\n\n\t\t// OverflowAllocator\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\t}; // fixed_list\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_list\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list()\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(size_type n)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);\n\t\t#endif\n\n\t\tresize(n);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(size_type n, const value_type& value)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);\n\t\t#endif\n\n\t\tresize(n, value);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(const this_type& x)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\tinternalAllocator().copy_overflow_allocator(x.internalAllocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(x.internalAllocator().get_name());\n\t\t#endif\n\n\t\tassign(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(this_type&& x)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t// Since we are a fixed_list, we can't normally swap pointers unless both this and \n\t\t// x are using using overflow and the overflow allocators are equal. To do:\n\t\t//if(has_overflowed() && x.has_overflowed() && (get_overflow_allocator() == x.get_overflow_allocator()))\n\t\t//{\n\t\t//    We can swap contents and may need to swap the allocators as well.\n\t\t//}\n\n\t\t// The following is currently identical to the fixed_vector(const this_type& x) code above. If it stays that\n\t\t// way then we may want to make a shared implementation.\n\t\tinternalAllocator().copy_overflow_allocator(x.internalAllocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(x.internalAllocator().get_name());\n\t\t#endif\n\n\t\tassign(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\t// See comments above.\n\t\tinternalAllocator().copy_overflow_allocator(x.internalAllocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(x.internalAllocator().get_name());\n\t\t#endif\n\n\t\tassign(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tassign(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(InputIterator first, InputIterator last)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);\n\t\t#endif\n\n\t\tassign(first, last);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&\n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tbase_type::clear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tinternalAllocator() = x.internalAllocator(); // The primary effect of this is to copy the overflow allocator.\n\t\t\t#endif\n\n\t\t\tbase_type::assign(x.begin(), x.end()); // It would probably be better to implement this like list::operator=.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&\n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\treturn operator=(x);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&\n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tbase_type::assign(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tget_allocator().reset(mBuffer);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::size_type\n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::full() const\n\t{\n\t\t// Note: This implementation isn't right in the case of bEnableOverflow = true because it will return \n\t\t// false for the case that  there are free nodes from the buffer but also nodes from the dynamic heap. \n\t\t// This can happen if the container exceeds the fixed size and then frees some of the nodes from the fixed buffer.\n\t\t// The only simple fix for this is to take on another member variable which tracks whether this overflow\n\t\t// has occurred at some point in the past.\n\t\treturn !internalAllocator().can_allocate(); // This is the quickest way of detecting this. has_overflowed uses a different method because it can't use this quick method.\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::has_overflowed() const\n\t{\n\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED // If we can use this faster pathway (as size() may be slow)...\n\t\t\treturn (internalAllocator().mPool.mnPeakSize > kMaxSize);\n\t\t#else\n\t\t\treturn (size() > kMaxSize);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline const typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type& \n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type& \n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void \n\tfixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tinternalAllocator().set_overflow_allocator(allocator);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void swap(fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/fixed_map.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a map and multimap which use a fixed size memory \n// pool for their nodes. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_MAP_H\n#define EASTL_FIXED_MAP_H\n\n\n#include <EASTL/map.h>\n#include <EASTL/fixed_set.h> // Included because fixed_rbtree_base resides here.\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_MAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_MAP_DEFAULT_NAME\n\t\t#define EASTL_FIXED_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_map\" // Unless the user overrides something, this is \"EASTL fixed_map\".\n\t#endif\n\n\t#ifndef EASTL_FIXED_MULTIMAP_DEFAULT_NAME\n\t\t#define EASTL_FIXED_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_multimap\" // Unless the user overrides something, this is \"EASTL fixed_multimap\".\n\t#endif\n\n\n\t/// EASTL_FIXED_MAP_DEFAULT_ALLOCATOR\n\t/// EASTL_FIXED_MULTIMAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_MAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_MAP_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_MAP_DEFAULT_NAME)\n\t#endif\n\n\t#ifndef EASTL_FIXED_MULTIMAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_MULTIMAP_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_MULTIMAP_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// fixed_map\n\t///\n\t/// Implements a map with a fixed block of memory identified by the \n\t/// nodeCount template parameter. \n\t///\n\t///     Key                    The key object (key in the key/value pair).\n\t///     T                      The mapped object (value in the key/value pair).\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Compare                Compare function/object for set ordering.\n\t///     OverflowAllocator              Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_map : public map<Key, T, Compare, fixed_node_allocator<sizeof(typename map<Key, T>::node_type), \n\t\tnodeCount, EASTL_ALIGN_OF(eastl::pair<Key, T>), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_node_allocator<sizeof(typename map<Key, T>::node_type), nodeCount, \n\t\t\t\t\t EASTL_ALIGN_OF(eastl::pair<Key, T>), 0, bEnableOverflow, OverflowAllocator>                           fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                                                     overflow_allocator_type;\n\t\ttypedef fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>                                  this_type;\n\t\ttypedef map<Key, T, Compare, fixed_allocator_type>                                                                 base_type;\n\t\ttypedef typename base_type::value_type                                                                             value_type;\n\t\ttypedef typename base_type::node_type                                                                              node_type;\n\t\ttypedef typename base_type::size_type                                                                              size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\t\t   \n\t\tusing base_type::insert;\n\n\tprotected:\n\t\tchar mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\t\tusing base_type::mAllocator;\n\n\tpublic:\n\t\tfixed_map();\n\t\texplicit fixed_map(const overflow_allocator_type& overflowAllocator);\n\t\texplicit fixed_map(const Compare& compare);\n\t\tfixed_map(const this_type& x);\n\t\tfixed_map(this_type&& x);\n\t\tfixed_map(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_map(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_MAP_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_map(InputIterator first, InputIterator last);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\t}; // fixed_map\n\n\n\n\n\t/// fixed_multimap\n\t///\n\t/// Implements a multimap with a fixed block of memory identified by the \n\t/// nodeCount template parameter. \n\t///\n\t///     Key                    The key object (key in the key/value pair).\n\t///     T                      The mapped object (value in the key/value pair).\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Compare                Compare function/object for set ordering.\n\t///     OverflowAllocator              Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_multimap : public multimap<Key, T, Compare, fixed_node_allocator<sizeof(typename multimap<Key, T>::node_type), \n\t\t\t\t\t\t\t\t\t\t   nodeCount, EASTL_ALIGN_OF(eastl::pair<Key, T>), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_node_allocator<sizeof(typename multimap<Key, T>::node_type), nodeCount, \n\t\t\t\t\tEASTL_ALIGN_OF(eastl::pair<Key, T>), 0, bEnableOverflow, OverflowAllocator>                                      fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                                                               overflow_allocator_type;\n\t\ttypedef multimap<Key, T, Compare, fixed_allocator_type>                                                                      base_type;\n\t\ttypedef fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>                                       this_type;\n\t\ttypedef typename base_type::value_type                                                                                       value_type;\n\t\ttypedef typename base_type::node_type                                                                                        node_type;\n\t\ttypedef typename base_type::size_type                                                                                        size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::insert;\n\n\tprotected:\n\t\tchar mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\t\tusing base_type::mAllocator;\n\t\tusing base_type::get_compare;\n\n\tpublic:\n\t\tfixed_multimap();\n\t\tfixed_multimap(const overflow_allocator_type& overflowAllocator);\n\t\texplicit fixed_multimap(const Compare& compare);\n\t\tfixed_multimap(const this_type& x);\n\t\tfixed_multimap(this_type&& x);\n\t\tfixed_multimap(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_multimap(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_MULTIMAP_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_multimap(InputIterator first, InputIterator last);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\t}; // fixed_multimap\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_map\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map()\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MAP_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map(const Compare& compare)\n\t\t: base_type(compare, fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MAP_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map(const this_type& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map(this_type&& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_map(InputIterator first, InputIterator last)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MAP_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tbase_type::get_allocator().reset(mBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::size_type\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline const typename fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type&\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type&\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void\n\tfixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void swap(fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& a, \n\t\t\t\t\t fixed_map<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_multimap\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multimap()\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MULTIMAP_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multimap(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multimap(const Compare& compare)\n\t\t: base_type(compare, fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MULTIMAP_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multimap(const this_type& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multimap(this_type&& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multimap(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multimap(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::\n\tfixed_multimap(InputIterator first, InputIterator last)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MULTIMAP_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type& \n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tbase_type::get_allocator().reset(mBuffer);\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::size_type \n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline const typename fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type&\n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type&\n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void\n\tfixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void swap(fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& a, \n\t\t\t\t\t fixed_multimap<Key, T, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/fixed_set.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a set and multiset which use a fixed size memory \n// pool for their nodes. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_SET_H\n#define EASTL_FIXED_SET_H\n\n\n#include <EASTL/set.h>\n#include <EASTL/internal/fixed_pool.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_SET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_SET_DEFAULT_NAME\n\t\t#define EASTL_FIXED_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_set\" // Unless the user overrides something, this is \"EASTL fixed_set\".\n\t#endif\n\n\t#ifndef EASTL_FIXED_MULTISET_DEFAULT_NAME\n\t\t#define EASTL_FIXED_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_multiset\" // Unless the user overrides something, this is \"EASTL fixed_multiset\".\n\t#endif\n\n\n\t/// EASTL_FIXED_SET_DEFAULT_ALLOCATOR\n\t/// EASTL_FIXED_MULTISET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_SET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_SET_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_SET_DEFAULT_NAME)\n\t#endif\n\n\t#ifndef EASTL_FIXED_MULTISET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_MULTISET_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_MULTISET_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// fixed_set\n\t///\n\t/// Implements a set with a fixed block of memory identified by the \n\t/// nodeCount template parameter. \n\t///\n\t/// Template parameters:\n\t///     Key                    The type of object the set holds (a.k.a. value).\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Compare                Compare function/object for set ordering.\n\t///     OverflowAllocator              Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_set : public set<Key, Compare, fixed_node_allocator<sizeof(typename set<Key>::node_type), \n\t\t\t\t\t\t\t\t nodeCount, EASTL_ALIGN_OF(Key), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_node_allocator<sizeof(typename set<Key>::node_type), nodeCount, \n\t\t\t\t\tEASTL_ALIGN_OF(Key), 0, bEnableOverflow, OverflowAllocator>            fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                     overflow_allocator_type;\n\t\ttypedef set<Key, Compare, fixed_allocator_type>                                    base_type;\n\t\ttypedef fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>     this_type;\n\t\ttypedef typename base_type::value_type                                             value_type;\n\t\ttypedef typename base_type::node_type                                              node_type;\n\t\ttypedef typename base_type::size_type                                              size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::insert;\n\n\tprotected:\n\t\tchar mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\t\tusing base_type::mAllocator;\n\t\tusing base_type::get_compare;\n\n\tpublic:\n\t\tfixed_set();\n\t\tfixed_set(const overflow_allocator_type& overflowAllocator);\n\t\texplicit fixed_set(const Compare& compare);\n\t\tfixed_set(const this_type& x);\n\t\tfixed_set(this_type&& x);\n\t\tfixed_set(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_set(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_SET_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_set(InputIterator first, InputIterator last);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\t}; // fixed_set\n\n\n\n\n\n\n\t/// fixed_multiset\n\t///\n\t/// Implements a multiset with a fixed block of memory identified by the \n\t/// nodeCount template parameter. \n\t///\n\t///     Key                    The type of object the set holds (a.k.a. value).\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the global heap if our object pool is exhausted.\n\t///     Compare                Compare function/object for set ordering.\n\t///     OverflowAllocator              Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow = true, typename Compare = eastl::less<Key>, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_multiset : public multiset<Key, Compare, fixed_node_allocator<sizeof(typename multiset<Key>::node_type), \n\t\t\t\t\t\t\t\t\t\t   nodeCount, EASTL_ALIGN_OF(Key), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_node_allocator<sizeof(typename multiset<Key>::node_type), nodeCount, \n\t\t\t\t\t EASTL_ALIGN_OF(Key), 0, bEnableOverflow, OverflowAllocator>                fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type                          overflow_allocator_type;\n\t\ttypedef multiset<Key, Compare, fixed_allocator_type>                                    base_type;\n\t\ttypedef fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>     this_type;\n\t\ttypedef typename base_type::value_type                                                  value_type;\n\t\ttypedef typename base_type::node_type                                                   node_type;\n\t\ttypedef typename base_type::size_type                                                   size_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::insert;\n\n\tprotected:\n\t\tchar mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\t\tusing base_type::mAllocator;\n\n\tpublic:\n\t\tfixed_multiset();\n\t\tfixed_multiset(const overflow_allocator_type& overflowAllocator);\n\t\texplicit fixed_multiset(const Compare& compare);\n\t\tfixed_multiset(const this_type& x);\n\t\tfixed_multiset(this_type&& x);\n\t\tfixed_multiset(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_multiset(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_MULTISET_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_multiset(InputIterator first, InputIterator last);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type max_size() const;\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; }\n\t}; // fixed_multiset\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_set\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set()\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_SET_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set(const Compare& compare)\n\t\t: base_type(compare, fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_SET_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set(const this_type& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set(this_type&& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_set(InputIterator first, InputIterator last)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_SET_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type& \n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tbase_type::get_allocator().reset(mBuffer);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::size_type \n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline const typename fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type& \n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type& \n\tfixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void swap(fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& a, \n\t\t\t\t\t fixed_set<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_multiset\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset()\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MULTISET_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset(const Compare& compare)\n\t\t: base_type(compare, fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MULTISET_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset(const this_type& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset(this_type&& x)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(x.get_compare(), fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tmAllocator.copy_overflow_allocator(x.mAllocator);\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(x.mAllocator.get_name());\n\t\t#endif\n\n\t\tbase_type::operator=(x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::fixed_multiset(InputIterator first, InputIterator last)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tmAllocator.set_name(EASTL_FIXED_MULTISET_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type& \n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::this_type&\n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tbase_type::get_allocator().reset(mBuffer);\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::size_type \n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline const typename fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type& \n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline typename fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::overflow_allocator_type& \n\tfixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator.get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tmAllocator.set_overflow_allocator(allocator);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, size_t nodeCount, bool bEnableOverflow, typename Compare, typename OverflowAllocator>\n\tinline void swap(fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& a, \n\t\t\t\t\t fixed_multiset<Key, nodeCount, bEnableOverflow, Compare, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/fixed_slist.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements an slist which uses a fixed size memory pool for its nodes. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_SLIST_H\n#define EASTL_FIXED_SLIST_H\n\n\n#include <EASTL/slist.h>\n#include <EASTL/internal/fixed_pool.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_SLIST_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_SLIST_DEFAULT_NAME\n\t\t#define EASTL_FIXED_SLIST_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_slist\" // Unless the user overrides something, this is \"EASTL fixed_slist\".\n\t#endif\n\n\n\t/// EASTL_FIXED_SLIST_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_SLIST_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_SLIST_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_SLIST_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// fixed_slist\n\t///\n\t/// fixed_slist is an slist which uses a single block of contiguous memory \n\t/// for its nodes. The purpose of this is to reduce memory usage relative\n\t/// to a conventional memory allocation system (with block headers), to \n\t/// increase allocation speed (often due to avoidance of mutex locks),\n\t/// to increase performance (due to better memory locality), and to decrease\n\t/// memory fragmentation due to the way that fixed block allocators work.\n\t///\n\t/// The primary downside to a fixed_slist is that the number of nodes it\n\t/// can contain is fixed upon its declaration. If you want a fixed_slist\n\t/// that doesn't have this limitation, then you probably don't want a\n\t/// fixed_slist. You can always create your own memory allocator that works\n\t/// the way you want.\n\t///\n\t/// Template parameters:\n\t///     T                      The type of object the slist holds.\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the overflow heap if our object pool is exhausted.\n\t///     OverflowAllocator      Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow = true, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_slist : public slist<T, fixed_node_allocator<sizeof(typename slist<T>::node_type),\n\t\t\t\t\t\t\t\t\t nodeCount, EASTL_ALIGN_OF(typename slist<T>::node_type), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_node_allocator<sizeof(typename slist<T>::node_type), nodeCount,\n\t\t\t\t\t EASTL_ALIGN_OF(typename slist<T>::node_type), 0, bEnableOverflow, OverflowAllocator> fixed_allocator_type;\n\t\ttypedef OverflowAllocator                                              overflow_allocator_type;\n\t\ttypedef slist<T, fixed_allocator_type>                                 base_type;\n\t\ttypedef fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>  this_type;\n\t\ttypedef typename base_type::size_type                                  size_type;\n\t\ttypedef typename base_type::value_type                                 value_type;\n\t\ttypedef typename base_type::node_type                                  node_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::assign;\n\t\tusing base_type::resize;\n\t\tusing base_type::size;\n\n\tprotected:\n\t\tchar mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.\n\n\t\tusing base_type::internalAllocator;\n\n\tpublic:\n\t\tfixed_slist();\n\t\texplicit fixed_slist(const overflow_allocator_type& overflowAllocator);             // Only applicable if bEnableOverflow is true.\n\t\texplicit fixed_slist(size_type n);                                                  // Currently we don't support overflowAllocator specification for other constructors, for simplicity.\n\t\tfixed_slist(size_type n, const value_type& value);\n\t\tfixed_slist(const this_type& x);\n\t\tfixed_slist(this_type&& x);\n\t\tfixed_slist(this_type&&, const overflow_allocator_type&);\n\t\tfixed_slist(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_SLIST_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_slist(InputIterator first, InputIterator last);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid      swap(this_type& x);\n\t\tvoid      reset_lose_memory();      // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\t\tsize_type max_size() const;         // Returns the max fixed size, which is the user-supplied nodeCount parameter.\n\t\tbool      full() const;             // Returns true if the fixed space has been fully allocated. Note that if overflow is enabled, the container size can be greater than nodeCount but full() could return true because the fixed space may have a recently freed slot. \n\t\tbool      has_overflowed() const;   // Returns true if the allocations spilled over into the overflow allocator. Meaningful only if overflow is enabled.\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; } // Returns the value of the bEnableOverflow template parameter.\n\n\t\t// OverflowAllocator\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\t}; // fixed_slist\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// slist\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist()\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_SLIST_DEFAULT_NAME);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(size_type n)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_SLIST_DEFAULT_NAME);\n\t\t#endif\n\n\t\tresize(n);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(size_type n, const value_type& value)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_SLIST_DEFAULT_NAME);\n\t\t#endif\n\n\t\tresize(n, value);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(const this_type& x)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\tinternalAllocator().copy_overflow_allocator(x.internalAllocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(x.internalAllocator().get_name());\n\t\t#endif\n\n\t\tassign(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(this_type&& x)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t// Since we are a fixed_list, we can't normally swap pointers unless both this and \n\t\t// x are using using overflow and the overflow allocators are equal. To do:\n\t\t//if(has_overflowed() && x.has_overflowed() && (get_overflow_allocator() == x.get_overflow_allocator()))\n\t\t//{\n\t\t//    We can swap contents and may need to swap the allocators as well.\n\t\t//}\n\n\t\t// The following is currently identical to the fixed_vector(const this_type& x) code above. If it stays that\n\t\t// way then we may want to make a shared implementation.\n\t\tinternalAllocator().copy_overflow_allocator(x.internalAllocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(x.internalAllocator().get_name());\n\t\t#endif\n\n\t\tassign(x.begin(), x.end());\n\t}\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\t// See comments above.\n\t\tinternalAllocator().copy_overflow_allocator(x.internalAllocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(x.internalAllocator().get_name());\n\t\t#endif\n\n\t\tassign(x.begin(), x.end());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer, overflowAllocator))\n\t{\n\t\tassign(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_slist(InputIterator first, InputIterator last)\n\t\t: base_type(fixed_allocator_type(mBuffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tinternalAllocator().set_name(EASTL_FIXED_SLIST_DEFAULT_NAME);\n\t\t#endif\n\n\t\tassign(first, last);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&\n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tbase_type::clear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tinternalAllocator() = x.internalAllocator(); // The primary effect of this is to copy the overflow allocator.\n\t\t\t#endif\n\n\t\t\tbase_type::assign(x.begin(), x.end()); // It would probably be better to implement this like slist::operator=.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&\n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\treturn operator=(x);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&\n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tbase_type::assign(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tbase_type::reset_lose_memory();\n\t\tbase_type::get_allocator().reset(mBuffer);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::size_type\n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::full() const\n\t{\n\t\t// Note: This implementation isn't right in the case of bEnableOverflow = true because it will return \n\t\t// false for the case that  there are free nodes from the buffer but also nodes from the dynamic heap. \n\t\t// This can happen if the container exceeds the fixed size and then frees some of the nodes from the fixed buffer.\n\t\treturn !internalAllocator().can_allocate(); // This is the quickest way of detecting this. has_overflowed uses a different method because it can't use this quick method.\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::has_overflowed() const\n\t{\n\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED // If we can use this faster pathway (as size() may be slow)...\n\t\t\treturn (internalAllocator().mPool.mnPeakSize > kMaxSize);\n\t\t#else\n\t\t\treturn (size() > kMaxSize);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline const typename fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type& \n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type& \n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void \n\tfixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tinternalAllocator().set_overflow_allocator(allocator);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void swap(fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t fixed_slist<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/fixed_string.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a string which uses a fixed size memory pool.\n// The bEnableOverflow template parameter allows the container to resort to\n// heap allocations if the memory pool is exhausted.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_STRING_H\n#define EASTL_FIXED_STRING_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/string.h>\n#include <EASTL/internal/fixed_pool.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_STRING_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations.\n\t///\n\t#ifndef EASTL_FIXED_STRING_DEFAULT_NAME\n\t\t#define EASTL_FIXED_STRING_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_string\" // Unless the user overrides something, this is \"EASTL fixed_string\".\n\t#endif\n\n\t/// EASTL_FIXED_STRING_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_STRING_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_STRING_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_STRING_DEFAULT_NAME)\n\t#endif\n\n\n\t/// fixed_string\n\t///\n\t/// A fixed_string with bEnableOverflow == true is identical to a regular\n\t/// string in terms of its behavior. All the expectations of regular string\n\t/// apply to it and no additional expectations come from it. When bEnableOverflow\n\t/// is false, fixed_string behaves like regular string with the exception that\n\t/// its capacity can never increase. All operations you do on such a fixed_string\n\t/// which require a capacity increase will result in undefined behavior or an\n\t/// C++ allocation exception, depending on the configuration of EASTL.\n\t///\n\t/// Note: The nodeCount value is the amount of characters to allocate, which needs to\n\t/// take into account a terminating zero. Thus if you want to store strings with a strlen\n\t/// of 30, the nodeCount value must be at least 31.\n\t///\n\t/// Template parameters:\n\t///     T                      The type of object the string holds (char, wchar_t, char8_t, char16_t, char32_t).\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the overflow heap if our object pool is exhausted.\n\t///     OverflowAllocator              Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\t/// Notes:\n\t///     The nodeCount value must be at least 2, one for a character and one for a terminating 0.\n\t///\n\t///     As of this writing, the string class necessarily reallocates when an insert of\n\t///     self is done into self. As a result, the fixed_string class doesn't support\n\t///     inserting self into self unless the bEnableOverflow template parameter is true.\n\t///\n\t/// Example usage:\n\t///    fixed_string<char, 128 + 1, true> fixedString(\"hello world\"); // Can hold up to a strlen of 128.\n\t///\n\t///    fixedString = \"hola mundo\";\n\t///    fixedString.clear();\n\t///    fixedString.resize(200);\n\t///    fixedString.sprintf(\"%f\", 1.5f);\n\t///\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow = true, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_string : public basic_string<T, fixed_vector_allocator<sizeof(T), nodeCount, EASTL_ALIGN_OF(T), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_vector_allocator<sizeof(T), nodeCount, EASTL_ALIGN_OF(T),\n\t\t\t\t\t\t\t0, bEnableOverflow, OverflowAllocator>              fixed_allocator_type;\n\t\ttypedef typename fixed_allocator_type::overflow_allocator_type          overflow_allocator_type;\n\t\ttypedef basic_string<T, fixed_allocator_type>                           base_type;\n\t\ttypedef fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>  this_type;\n\t\ttypedef typename base_type::size_type                                   size_type;\n\t\ttypedef typename base_type::value_type                                  value_type;\n\t\ttypedef typename base_type::CtorDoNotInitialize                         CtorDoNotInitialize;\n\t\ttypedef typename base_type::CtorSprintf                                 CtorSprintf;\n\t\ttypedef aligned_buffer<nodeCount * sizeof(T), EASTL_ALIGN_OF(T)>        aligned_buffer_type;\n\n\t\tenum { kMaxSize = nodeCount - 1 }; // -1 because we need to save one element for the silent terminating null.\n\n\t\tusing base_type::npos;\n\t\tusing base_type::append;\n\t\tusing base_type::resize;\n\t\tusing base_type::clear;\n\t\tusing base_type::capacity;\n\t\tusing base_type::size;\n\t\tusing base_type::sprintf_va_list;\n\t\tusing base_type::get_allocator;\n\n\tprotected:\n\t\tusing base_type::mPair;\n\t\tusing base_type::DoAllocate;\n\t\tusing base_type::DoFree;\n\t\tusing base_type::internalLayout;\n\n\t\tunion // We define a union in order to avoid strict pointer aliasing issues with compilers like GCC.\n\t\t{\n\t\t\tvalue_type          mArray[1];\n\t\t\taligned_buffer_type mBuffer;     // Question: Why are we doing this aligned_buffer thing? Why not just do an array of value_type, given that we are using just strings of char types.\n\t\t};\n\n\tpublic:\n\t\tfixed_string();\n\t\texplicit fixed_string(const overflow_allocator_type& overflowAllocator);             // Only applicable if bEnableOverflow is true.\n\t\tfixed_string(const base_type& x, size_type position, size_type n = base_type::npos); // Currently we don't support overflowAllocator specification for other constructors, for simplicity.\n\t\tfixed_string(const value_type* p, size_type n);\n\t\tfixed_string(const value_type* p);\n\t\tfixed_string(size_type n, const value_type& value);\n\t\tfixed_string(const this_type& x);\n\t\tfixed_string(const this_type& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_string(const base_type& x);\n\t\tfixed_string(const value_type* pBegin, const value_type* pEnd);\n\t\tfixed_string(CtorDoNotInitialize, size_type n);\n\t\tfixed_string(CtorSprintf, const value_type* pFormat, ...);\n\t\tfixed_string(std::initializer_list<T> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_STRING_DEFAULT_ALLOCATOR);\n\t\tfixed_string(this_type&& x);\n\t\tfixed_string(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(const base_type& x);\n\t\tthis_type& operator=(const value_type* p);\n\t\tthis_type& operator=(const value_type c);\n\t\tthis_type& operator=(std::initializer_list<T> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid      set_capacity(size_type n);\n\t\tvoid      reset_lose_memory();          // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\t\tsize_type max_size() const;\n\t\tbool      full() const;                 // Returns true if the fixed space has been fully allocated. Note that if overflow is enabled, the container size can be greater than nodeCount but full() could return true because the fixed space may have a recently freed slot.\n\t\tbool      has_overflowed() const;       // Returns true if the allocations spilled over into the overflow allocator. Meaningful only if overflow is enabled.\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; } // Returns the value of the bEnableOverflow template parameter.\n\n\t\t// The inherited versions of substr/left/right call the basic_string constructor,\n\t\t// which will call the overflow allocator and fail if bEnableOverflow == false\n\t\tthis_type substr(size_type position, size_type n) const;\n\t\tthis_type left(size_type n) const;\n\t\tthis_type right(size_type n) const;\n\n\t\t// OverflowAllocator\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\t}; // fixed_string\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_string\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string()\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_STRING_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t   internalLayout().SetHeapBeginPtr(mArray);\n\t   internalLayout().SetHeapCapacity(nodeCount - 1);\n\t   internalLayout().SetHeapSize(0);\n\n\t   *internalLayout().HeapBeginPtr() = 0;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const this_type& x)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\tget_allocator().copy_overflow_allocator(x.get_allocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(x);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const this_type& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\tget_allocator().copy_overflow_allocator(x.get_allocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(x);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const base_type& x)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(x);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const base_type& x, size_type position, size_type n)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(x, position, n);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const value_type* p, size_type n)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_STRING_DEFAULT_NAME);\n\t\t#endif\n\n\t   internalLayout().SetHeapBeginPtr(mArray);\n\t   internalLayout().SetHeapCapacity(nodeCount - 1);\n\t   internalLayout().SetHeapSize(0);\n\n\t   *internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(p, n);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const value_type* p)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_STRING_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(p); // There better be enough space to hold the assigned string.\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(size_type n, const value_type& value)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_STRING_DEFAULT_NAME);\n\t\t#endif\n\n\t   internalLayout().SetHeapBeginPtr(mArray);\n\t   internalLayout().SetHeapCapacity(nodeCount - 1);\n\t   internalLayout().SetHeapSize(0);\n\n\t   *internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(n, value); // There better be enough space to hold the assigned string.\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(const value_type* pBegin, const value_type* pEnd)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_STRING_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(pBegin, pEnd);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(CtorDoNotInitialize, size_type n)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_STRING_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\n\t\tif(n < nodeCount)\n\t\t{\n\t\t\tinternalLayout().SetHeapSize(n);\n\t\t\t*internalLayout().HeapEndPtr() = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinternalLayout().SetHeapSize(0);\n\t\t\t*internalLayout().HeapEndPtr() = 0;\n\n\t\t\tresize(n);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(CtorSprintf, const value_type* pFormat, ...)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_STRING_DEFAULT_NAME);\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tva_list arguments;\n\t\tva_start(arguments, pFormat);\n\t\tsprintf_va_list(pFormat, arguments);\n\t\tva_end(arguments);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(std::initializer_list<T> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(this_type&& x)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t// We copy from x instead of trade with it. We need to do so because fixed_ containers use local memory buffers.\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t#endif\n\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(x); // Let x destruct its own items.\n\t}\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_string(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t\tinternalLayout().SetHeapSize(0);\n\n\t\t*internalLayout().HeapBeginPtr() = 0;\n\n\t\tappend(x); // Let x destruct its own items.\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tget_allocator() = x.get_allocator();\n\t\t\t#endif\n\n\t\t\tappend(x);\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type& fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const base_type& x)\n\t{\n\t\tif(static_cast<base_type*>(this) != &x)\n\t\t{\n\t\t\tclear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tget_allocator() = x.get_allocator();\n\t\t\t#endif\n\n\t\t\tappend(x);\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type& fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const value_type* p)\n\t{\n\t\tif(internalLayout().HeapBeginPtr() != p)\n\t\t{\n\t\t\tclear();\n\t\t\tappend(p);\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type& fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const value_type c)\n\t{\n\t\tclear();\n\t\tappend((size_type)1, c);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type& fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(std::initializer_list<T> ilist)\n\t{\n\t\tclear();\n\t\tappend(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type& fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\t// We copy from x instead of trade with it. We need to do so because fixed_ containers use local memory buffers.\n\n\t\t// if(static_cast<base_type*>(this) != &x) This should be impossible, so we disable it until proven otherwise.\n\t\t{\n\t\t\tclear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tget_allocator() = x.get_allocator();\n\t\t\t#endif\n\n\t\t\tappend(x); // Let x destruct its own items.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(*this, x);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::set_capacity(size_type n)\n\t{\n\t\tconst size_type nPrevSize     = internalLayout().GetSize();\n\t\tconst size_type nPrevCapacity = capacity();\n\n\t\tif(n == npos)       // If the user means to set the capacity so that it equals the size (i.e. free excess capacity)...\n\t\t\tn = nPrevSize;\n\n\t\tif(n != nPrevCapacity)  // If the request results in a capacity change...\n\t\t{\n\t\t\tconst size_type allocSize = (n + 1); // +1 because the terminating 0 isn't included in the supplied capacity value. So now n refers the amount of memory we need.\n\n\t\t\tif(can_overflow() && (((uintptr_t)internalLayout().HeapBeginPtr() != (uintptr_t)mBuffer.buffer) || (allocSize > kMaxSize))) // If we are or would be using dynamically allocated memory instead of our fixed-size member buffer...\n\t\t\t{\n\t\t\t\tT* const pNewData = (allocSize <= kMaxSize) ? (T*)&mBuffer.buffer[0] : DoAllocate(allocSize);\n\t\t\t\tT* const pCopyEnd = (n < nPrevSize) ? (internalLayout().HeapBeginPtr() + n) : internalLayout().HeapEndPtr();\n\t\t\t\tCharStringUninitializedCopy(internalLayout().HeapBeginPtr(), pCopyEnd, pNewData);  // Copy [internalLayout().heap.mpBegin, pCopyEnd) to pNewData.\n\t\t\t\tif((uintptr_t)internalLayout().HeapBeginPtr() != (uintptr_t)mBuffer.buffer)\n\t\t\t\t\tDoFree(internalLayout().HeapBeginPtr(), internalLayout().GetHeapCapacity() + 1);\n\n\t\t\t\tinternalLayout().SetHeapSize((size_type)(pCopyEnd - internalLayout().HeapBeginPtr()));\n\t\t\t\tinternalLayout().SetHeapBeginPtr(pNewData);\n\t\t\t\tinternalLayout().SetHeapCapacity(allocSize - 1);\n\t\t\t} // Else the new capacity would be within our fixed buffer.\n\t\t\telse if(n < nPrevSize) // If the newly requested capacity is less than our size, we do what vector::set_capacity does and resize, even though we actually aren't reducing the capacity.\n\t\t\t\tresize(n);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tinternalLayout().SetHeapBeginPtr(mArray);\n\t\tinternalLayout().SetHeapSize(0);\n\t\tinternalLayout().SetHeapCapacity(nodeCount - 1);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tsize_type fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::full() const\n\t{\n\t\t// If size >= capacity, then we are definitely full.\n\t\t// Also, if our size is smaller but we've switched away from mBuffer due to a previous overflow, then we are considered full.\n\t\treturn ((size_t)(internalLayout().HeapEndPtr() - internalLayout().HeapBeginPtr()) >= kMaxSize) || ((void*)internalLayout().HeapBeginPtr() != (void*)mBuffer.buffer);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::has_overflowed() const\n\t{\n\t\t// This will be incorrect for the case that bOverflowEnabled is true and the container was resized\n\t\t// down to a small size where the fixed buffer could take over ownership of the data again.\n\t\t// The only simple fix for this is to take on another member variable which tracks whether this overflow\n\t\t// has occurred at some point in the past.\n\t\treturn ((void*)internalLayout().HeapBeginPtr() != (void*)mBuffer.buffer);\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::substr(size_type position, size_type n) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(position > internalLayout().GetSize())\n\t\t\t\tbase_type::ThrowRangeException();\n\t\t#endif\n\n\t\t\treturn fixed_string(internalLayout().HeapBeginPtr() + position,\n\t\t\t\t\t\t\t\tinternalLayout().HeapBeginPtr() + position + eastl::min_alt(n, internalLayout().GetSize() - position));\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::left(size_type n) const\n\t{\n\t\tconst size_type nLength = size();\n\t\tif(n < nLength)\n\t\t\treturn fixed_string(internalLayout().HeapBeginPtr(), internalLayout().HeapBeginPtr() + n);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\tthis_type fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::right(size_type n) const\n\t{\n\t\tconst size_type nLength = size();\n\t\tif(n < nLength)\n\t\t\treturn fixed_string(internalLayout().HeapEndPtr() - n, internalLayout().HeapEndPtr());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline const typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\toverflow_allocator_type& fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn get_allocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::\n\toverflow_allocator_type& fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn get_allocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tget_allocator().set_overflow_allocator(allocator);\n\t}\n\n\ttemplate <class T>\n\tinline size_t hash_string(const T* p)\n\t{\n\t\tunsigned int c, result = 2166136261U;\n\t\twhile ((c = *p++) != 0) // To consider: limit p to at most 256 chars.\n\t\t\tresult = (result * 16777619) ^ c;\n\t\treturn (size_t)result;\n\t}\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tstruct hash<fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>>\n\t{\n\t\tsize_t operator()(const fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& x) const\n\t\t{\n\t\t\treturn hash_string(x.c_str());\n\t\t}\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\n\t// Operator +\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(const fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& a,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t const fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\t// We have a problem here because need to return an fixed_string by value. This will typically result in it\n\t\t// using stack space equal to its size. That size may be too large to be workable.\n\t\ttypedef fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> this_type;\n\n\t\tthis_type result(const_cast<this_type&>(a).get_overflow_allocator());\n\t\tresult.append(a);\n\t\tresult.append(b);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(const typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::value_type* p,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t const fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\ttypedef fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> this_type;\n\n\t\tconst typename this_type::size_type n = (typename this_type::size_type)CharStrlen(p);\n\t\tthis_type result(const_cast<this_type&>(b).get_overflow_allocator());\n\t\tresult.append(p, p + n);\n\t\tresult.append(b);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::value_type c,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\ttypedef fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> this_type;\n\n\t\tthis_type result(const_cast<this_type&>(b).get_overflow_allocator());\n\t\tresult.push_back(c);\n\t\tresult.append(b);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(const fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& a,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::value_type* p)\n\t{\n\t\ttypedef fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> this_type;\n\n\t\tconst typename this_type::size_type n = (typename this_type::size_type)CharStrlen(p);\n\t\tthis_type result(const_cast<this_type&>(a).get_overflow_allocator());\n\t\tresult.append(a);\n\t\tresult.append(p, p + n);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(const fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& a,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::value_type c)\n\t{\n\t\ttypedef fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> this_type;\n\n\t\tthis_type result(const_cast<this_type&>(a).get_overflow_allocator());\n\t\tresult.append(a);\n\t\tresult.push_back(c);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>&& a,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>&& b)\n\t{\n\t\ta.append(b); // Using an rvalue by name results in it becoming an lvalue.\n\t\treturn eastl::move(a);\n\t}\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>&& a,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   const fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\ta.append(b);\n\t\treturn eastl::move(a);\n\t}\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(const typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::value_type* p,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>&& b)\n\t{\n\t\tb.insert(0, p);\n\t\treturn eastl::move(b);\n\t}\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>&& a,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  const typename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::value_type* p)\n\t{\n\t\ta.append(p);\n\t\treturn eastl::move(a);\n\t}\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tfixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator> operator+(fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>&& a,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttypename fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>::value_type c)\n\t{\n\t\ta.push_back(c);\n\t\treturn eastl::move(a);\n\t}\n\n\n\t// operator ==, !=, <, >, <=, >= come from the string implementations.\n\n\ttemplate <typename T, int nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void swap(fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& a,\n\t\t\t\t\t fixed_string<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n} // namespace eastl\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/fixed_substring.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_SUBSTRING_H\n#define EASTL_FIXED_SUBSTRING_H\n\n\n#include <EASTL/string.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// fixed_substring\n\t///\n\t/// Implements a string which is a reference to a segment of characters.\n\t/// This class is efficient because it allocates no memory and copies no\n\t/// memory during construction and assignment, but rather refers directly\n\t/// to the segment of chracters. A common use of this is to have a\n\t/// fixed_substring efficiently refer to a substring within another string.\n\t///\n\t/// You cannot directly resize a fixed_substring (e.g. via resize, insert,\n\t/// append, erase), but you can assign a different substring to it.\n\t/// You can modify the characters within a substring in place.\n\t/// As of this writing, in the name of being lean and simple it is the\n\t/// user's responsibility to not call unsupported resizing functions\n\t/// such as those listed above. A detailed listing of the functions which\n\t/// are not supported is given below in the class declaration.\n\t///\n\t/// The c_str function doesn't act as one might hope, as it simply\n\t/// returns the pointer to the beginning of the string segment and the\n\t/// 0-terminator may be beyond the end of the segment. If you want to\n\t/// always be able to use c_str as expected, use the fixed string solution\n\t/// we describe below.\n\t///\n\t/// Another use of fixed_substring is to provide C++ string-like functionality\n\t/// with a C character array. This allows you to work on a C character array\n\t/// as if it were a C++ string as opposed using the C string API. Thus you\n\t/// can do this:\n\t///\n\t///    void DoSomethingForUser(char* timeStr, size_t timeStrCapacity)\n\t///    {\n\t///        fixed_substring tmp(timeStr, timeStrCapacity);\n\t///        tmp  = \"hello \";\n\t///        tmp += \"world\";\n\t///    }\n\t///\n\t/// Note that this class constructs and assigns from const string pointers\n\t/// and const string objects, yet this class does not declare its member\n\t/// data as const. This is a concession in order to allow this implementation\n\t/// to be simple and lean. It is the user's responsibility to make sure\n\t/// that strings that should not or can not be modified are either not\n\t/// used by fixed_substring or are not modified by fixed_substring.\n\t///\n\t/// A more flexible alternative to fixed_substring is fixed_string.\n\t/// fixed_string has none of the functional limitations that fixed_substring\n\t/// has and like fixed_substring it doesn't allocate memory. However,\n\t/// fixed_string makes a *copy* of the source string and uses local\n\t/// memory to store that copy. Also, fixed_string objects on the stack\n\t/// are going to have a limit as to their maximum size.\n\t///\n\t/// Notes:\n\t///     As of this writing, the string class necessarily reallocates when\n\t///     an insert of self is done into self. As a result, the fixed_substring\n\t///     class doesn't support inserting self into self.\n\t///\n\t/// Example usage:\n\t///     basic_string<char>    str(\"hello world\");\n\t///     fixed_substring<char> sub(str, 2, 5);      // sub == \"llo w\"\n\t///\n\ttemplate <typename T>\n\tclass fixed_substring : public basic_string<T>\n\t{\n\tpublic:\n\t\ttypedef basic_string<T>                     base_type;\n\t\ttypedef fixed_substring<T>                  this_type;\n\t\ttypedef typename base_type::size_type       size_type;\n\t\ttypedef typename base_type::value_type      value_type;\n\t\ttypedef typename base_type::iterator        iterator;\n\t\ttypedef typename base_type::const_iterator  const_iterator;\n\n\t\tusing base_type::npos;\n\t\tusing base_type::get_allocator;\n\n\tprivate:\n\t\tusing base_type::mPair;\n\t\tusing base_type::AllocateSelf;\n\t\tusing base_type::internalLayout;\n\n\t\tvoid SetInternalHeapLayout(value_type* pBeginPtr, size_type nSize, size_type nCap)\n\t\t{\n\t\t\tinternalLayout().SetHeapBeginPtr(pBeginPtr);\n\t\t\tinternalLayout().SetHeapSize(nSize);\n\t\t\tinternalLayout().SetHeapCapacity(nCap);\n\t\t}\n\n\n\tpublic:\n\t\tfixed_substring()\n\t\t\t: base_type()\n\t\t{\n\t\t}\n\n\t\tfixed_substring(const fixed_substring& x)\n\t\t\t: fixed_substring(static_cast<const base_type&>(x))\n\t\t{}\n\n\t\tfixed_substring(const base_type& x)\n\t\t\t: base_type()\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t\t#endif\n\n\t\t\tassign(x);\n\t\t}\n\n\t\t// We gain no benefit from having an rvalue move constructor or assignment operator,\n\t\t// as this class is a const class.\n\n\t\tfixed_substring(const base_type& x, size_type position, size_type n = base_type::npos)\n\t\t\t: base_type()\n\t\t{\n\t\t\t#if EASTL_NAME_ENABLED\n\t\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t\t#endif\n\n\t\t\tassign(x, position, n);\n\t\t}\n\n\t\tfixed_substring(const value_type* p, size_type n)\n\t\t\t: base_type()\n\t\t{\n\t\t\tassign(p, n);\n\t\t}\n\n\t\tfixed_substring(const value_type* p)\n\t\t\t: base_type()\n\t\t{\n\t\t\t assign(p);\n\t\t}\n\n\t\tfixed_substring(const value_type* pBegin, const value_type* pEnd)\n\t\t\t: base_type()\n\t\t{\n\t\t\tassign(pBegin, pEnd);\n\t\t}\n\n\t\t~fixed_substring()\n\t\t{\n\t\t\t// We need to reset, as otherwise the parent destructor will\n\t\t\t// attempt to free our memory.\n\t\t\tAllocateSelf();\n\t\t}\n\n\t\tthis_type& operator=(const this_type& x)\n\t\t{\n\t\t\tassign(x);\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& operator=(const base_type& x)\n\t\t{\n\t\t\tassign(x);\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& operator=(const value_type* p)\n\t\t{\n\t\t\tassign(p);\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& assign(const base_type& x)\n\t\t{\n\t\t\t// By design, we need to cast away const-ness here.\n\t\t\tSetInternalHeapLayout(const_cast<value_type*>(x.data()), x.size(), x.size());\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& assign(const base_type& x, size_type position, size_type n)\n\t\t{\n\t\t\t// By design, we need to cast away const-ness here.\n\t\t\tSetInternalHeapLayout(const_cast<value_type*>(x.data()) + position, n, n);\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& assign(const value_type* p, size_type n)\n\t\t{\n\t\t\t// By design, we need to cast away const-ness here.\n\t\t\tSetInternalHeapLayout(const_cast<value_type*>(p), n, n);\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& assign(const value_type* p)\n\t\t{\n\t\t\t// By design, we need to cast away const-ness here.\n\t\t\tSetInternalHeapLayout(const_cast<value_type*>(p), (size_type)CharStrlen(p), (size_type)CharStrlen(p));\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& assign(const value_type* pBegin, const value_type* pEnd)\n\t\t{\n\t\t\t// By design, we need to cast away const-ness here.\n\t\t\tSetInternalHeapLayout(const_cast<value_type*>(pBegin), (size_type)(pEnd - pBegin), (size_type)(pEnd - pBegin));\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t// Partially supported functionality\n\t\t//\n\t\t// When using fixed_substring on a character sequence that is within another\n\t\t// string, the following functions may do one of two things:\n\t\t//     1 Attempt to reallocate\n\t\t//     2 Write a 0 char at the end of the fixed_substring\n\t\t//\n\t\t// Item #1 will result in a crash, due to the attempt by the underlying\n\t\t// string class to free the substring memory. Item #2 will result in a 0\n\t\t// char being written to the character array. Item #2 may or may not be\n\t\t// a problem, depending on how you use fixed_substring. Thus the following\n\t\t// functions cannot be used safely.\n\n\t\t#if 0 // !defined(EA_COMPILER_NO_DELETED_FUNCTIONS) We may want to enable these deletions after some investigation of possible user impact.\n\t\t\tthis_type&  operator=(value_type c) = delete;\n\t\t\tvoid        resize(size_type n, value_type c) = delete;\n\t\t\tvoid        resize(size_type n) = delete;\n\t\t\tvoid        reserve(size_type = 0) = delete;\n\t\t\tvoid        set_capacity(size_type n) = delete;\n\t\t\tvoid        clear() = delete;\n\t\t\tthis_type&  operator+=(const base_type& x) = delete;\n\t\t\tthis_type&  operator+=(const value_type* p) = delete;\n\t\t\tthis_type&  operator+=(value_type c) = delete;\n\t\t\tthis_type&  append(const base_type& x) = delete;\n\t\t\tthis_type&  append(const base_type& x, size_type position, size_type n) = delete;\n\t\t\tthis_type&  append(const value_type* p, size_type n) = delete;\n\t\t\tthis_type&  append(const value_type* p) = delete;\n\t\t\tthis_type&  append(size_type n) = delete;\n\t\t\tthis_type&  append(size_type n, value_type c) = delete;\n\t\t\tthis_type&  append(const value_type* pBegin, const value_type* pEnd) = delete;\n\t\t\tthis_type&  append_sprintf_va_list(const value_type* pFormat, va_list arguments) = delete;\n\t\t\tthis_type&  append_sprintf(const value_type* pFormat, ...) = delete;\n\t\t\tvoid        push_back(value_type c) = delete;\n\t\t\tvoid        pop_back() = delete;\n\t\t\tthis_type&  assign(size_type n, value_type c) = delete;\n\t\t\tthis_type&  insert(size_type position, const base_type& x) = delete;\n\t\t\tthis_type&  insert(size_type position, const base_type& x, size_type beg, size_type n) = delete;\n\t\t\tthis_type&  insert(size_type position, const value_type* p, size_type n) = delete;\n\t\t\tthis_type&  insert(size_type position, const value_type* p) = delete;\n\t\t\tthis_type&  insert(size_type position, size_type n, value_type c) = delete;\n\t\t\titerator    insert(const_iterator p, value_type c) = delete;\n\t\t\tvoid        insert(const_iterator p, size_type n, value_type c) = delete;\n\t\t\tvoid        insert(const_iterator p, const value_type* pBegin, const value_type* pEnd) = delete;\n\t\t\tthis_type&  erase(size_type position = 0, size_type n = npos) = delete;\n\t\t\titerator    erase(const_iterator p) = delete;\n\t\t\titerator    erase(const_iterator pBegin, const_iterator pEnd) = delete;\n\t\t\tvoid        swap(base_type& x) = delete;\n\t\t\tthis_type&  sprintf_va_list(const value_type* pFormat, va_list arguments) = delete;\n\t\t\tthis_type&  sprintf(const value_type* pFormat, ...) = delete;\n\t\t#endif\n\n\t}; // fixed_substring\n\n\n} // namespace eastl\n\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/fixed_vector.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a vector which uses a fixed size memory pool. \n// The bEnableOverflow template parameter allows the container to resort to\n// heap allocations if the memory pool is exhausted.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_FIXED_VECTOR_H\n#define EASTL_FIXED_VECTOR_H\n\n\n#include <EASTL/vector.h>\n#include <EASTL/internal/fixed_pool.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// EASTL_FIXED_VECTOR_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t/// In the case of fixed-size containers, the allocator name always refers\n\t/// to overflow allocations. \n\t///\n\t#ifndef EASTL_FIXED_VECTOR_DEFAULT_NAME\n\t\t#define EASTL_FIXED_VECTOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_vector\" // Unless the user overrides something, this is \"EASTL fixed_vector\".\n\t#endif\n\n\n\t/// EASTL_FIXED_VECTOR_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_FIXED_VECTOR_DEFAULT_ALLOCATOR\n\t\t#define EASTL_FIXED_VECTOR_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_VECTOR_DEFAULT_NAME)\n\t#endif\n\n\n\t/// fixed_vector\n\t///\n\t/// A fixed_vector with bEnableOverflow == true is identical to a regular \n\t/// vector in terms of its behavior. All the expectations of regular vector\n\t/// apply to it and no additional expectations come from it. When bEnableOverflow\n\t/// is false, fixed_vector behaves like regular vector with the exception that \n\t/// its capacity can never increase. All operations you do on such a fixed_vector\n\t/// which require a capacity increase will result in undefined behavior or an \n\t/// C++ allocation exception, depending on the configuration of EASTL.\n\t///\n\t/// Template parameters:\n\t///     T                      The type of object the vector holds.\n\t///     nodeCount              The max number of objects to contain.\n\t///     bEnableOverflow        Whether or not we should use the overflow heap if our object pool is exhausted.\n\t///     OverflowAllocator              Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\t/// Note: The nodeCount value must be at least 1.\n\t///\n\t/// Example usage:\n\t///    fixed_vector<Widget, 128, true> fixedVector);\n\t///\n\t///    fixedVector.push_back(Widget());\n\t///    fixedVector.resize(200);\n\t///    fixedVector.clear();\n\t///\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow = true, typename OverflowAllocator = typename eastl::conditional<bEnableOverflow, EASTLAllocatorType, EASTLDummyAllocatorType>::type>\n\tclass fixed_vector : public vector<T, fixed_vector_allocator<sizeof(T), nodeCount, EASTL_ALIGN_OF(T), 0, bEnableOverflow, OverflowAllocator> >\n\t{\n\tpublic:\n\t\ttypedef fixed_vector_allocator<sizeof(T), nodeCount, EASTL_ALIGN_OF(T), \n\t\t\t\t\t\t\t0, bEnableOverflow, OverflowAllocator>              fixed_allocator_type;\n\t\ttypedef OverflowAllocator                                               overflow_allocator_type;\n\t\ttypedef vector<T, fixed_allocator_type>                                 base_type;\n\t\ttypedef fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>  this_type;\n\t\ttypedef typename base_type::size_type                                   size_type;\n\t\ttypedef typename base_type::value_type                                  value_type;\n\t\ttypedef typename base_type::reference                                   reference;\n\t\ttypedef typename base_type::iterator                                    iterator;\n\t\ttypedef typename base_type::const_iterator                              const_iterator;\n\t\ttypedef aligned_buffer<nodeCount * sizeof(T), EASTL_ALIGN_OF(T)>        aligned_buffer_type;\n\n\t\tenum { kMaxSize = nodeCount };\n\n\t\tusing base_type::get_allocator;\n\t\tusing base_type::resize;\n\t\tusing base_type::clear;\n\t\tusing base_type::size;\n\t\tusing base_type::assign;\n\t\tusing base_type::npos;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"fixed_vector<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"fixed_vector<T> value_type must be non-volatile.\");\n\n\tprotected:\n\t\taligned_buffer_type mBuffer;\n\n\t\tusing base_type::mpBegin;\n\t\tusing base_type::mpEnd;\n\t\tusing base_type::internalCapacityPtr;\n\t\tusing base_type::DoAllocate;\n\t\tusing base_type::DoFree;\n\t\tusing base_type::DoAssign;\n\n\tpublic:\n\t\tfixed_vector();\n\t\texplicit fixed_vector(const overflow_allocator_type& overflowAllocator); // Only applicable if bEnableOverflow is true.\n\t\texplicit fixed_vector(size_type n);                                      // Currently we don't support overflowAllocator specification for other constructors, for simplicity.\n\t\tfixed_vector(size_type n, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_vector(size_type n, const value_type& value);\n\t\tfixed_vector(size_type n, const value_type& value, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_vector(const this_type& x);\n\t\tfixed_vector(this_type&& x) EA_NOEXCEPT;\n\t\tfixed_vector(this_type&& x, const overflow_allocator_type& overflowAllocator);\n\t\tfixed_vector(std::initializer_list<T> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_VECTOR_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tfixed_vector(InputIterator first, InputIterator last);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<T> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid      set_capacity(size_type n);\n\t\tvoid      clear(bool freeOverflow);\n\t\tvoid      reset_lose_memory();          // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\t\tsize_type max_size() const;             // Returns the max fixed size, which is the user-supplied nodeCount parameter.\n\t\tbool      full() const;                 // Returns true if the fixed space has been fully allocated. Note that if overflow is enabled, the container size can be greater than nodeCount but full() could return true because the fixed space may have a recently freed slot. \n\t\tbool      has_overflowed() const;       // Returns true if the allocations spilled over into the overflow allocator. Meaningful only if overflow is enabled.\n\t\tstatic constexpr bool can_overflow() { return bEnableOverflow; } // Returns the value of the bEnableOverflow template parameter.\n\n\t\tvoid*     push_back_uninitialized();\n\t\tvoid      push_back(const value_type& value);   // We implement push_back here because we have a specialization that's \n\t\treference push_back();                          // smaller for the case of overflow being disabled.\n\t\tvoid      push_back(value_type&& value);\n\n\t\t// OverflowAllocator\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;\n\t\toverflow_allocator_type&       get_overflow_allocator() EA_NOEXCEPT;\n\t\tvoid                           set_overflow_allocator(const overflow_allocator_type& allocator);\n\n\tprotected:\n\t\tvoid*     DoPushBackUninitialized(true_type);\n\t\tvoid*     DoPushBackUninitialized(false_type);\n\n\t\tvoid      DoPushBack(true_type, const value_type& value);\n\t\tvoid      DoPushBack(false_type, const value_type& value);\n\n\t\tvoid      DoPushBackMove(true_type, value_type&& value);\n\t\tvoid      DoPushBackMove(false_type, value_type&& value);\n\n\t\treference DoPushBack(false_type);\n\t\treference DoPushBack(true_type);\n\n\t}; // fixed_vector\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// fixed_vector\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector()\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t}\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t}\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(size_type n)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tresize(n);\n\t}\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(size_type n, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tresize(n);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(size_type n, const value_type& value)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tresize(n, value);\n\t}\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(size_type n, const value_type& value, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tresize(n, value);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(const this_type& x)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\tget_allocator().copy_overflow_allocator(x.get_allocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t#endif\n\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tbase_type::template DoAssign<const_iterator, false>(x.begin(), x.end(), false_type());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(this_type&& x) EA_NOEXCEPT\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t// Since we are a fixed_vector, we can't swap pointers. We can possibly do something like fixed_swap or\n\t\t// we can just do an assignment from x. If we want to do the former then we need to have some complicated\n\t\t// code to deal with overflow or no overflow, and whether the memory is in the fixed-size buffer or in \n\t\t// the overflow allocator. 90% of the time the memory should be in the fixed buffer, in which case\n\t\t// a simple assignment is no worse than the fancy pathway.\n\n\t\t// Since we are a fixed_vector, we can't normally swap pointers unless both this and \n\t\t// x are using using overflow and the overflow allocators are equal. To do:\n\t\t//if(has_overflowed() && x.has_overflowed() && (get_overflow_allocator() == x.get_overflow_allocator()))\n\t\t//{\n\t\t//    We can swap contents and may need to swap the allocators as well.\n\t\t//}\n\t\tget_allocator().copy_overflow_allocator(x.get_allocator());\n\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(x.get_allocator().get_name());\n\t\t#endif\n\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tbase_type::template DoAssign<move_iterator<iterator>, true>(eastl::make_move_iterator(x.begin()), eastl::make_move_iterator(x.end()), false_type());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(this_type&& x, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\t// Since we are not swapping the allocated buffers but simply move the elements, we do not have to care about allocator compatibility.\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tbase_type::template DoAssign<move_iterator<iterator>, true>(eastl::make_move_iterator(x.begin()), eastl::make_move_iterator(x.end()), false_type());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(std::initializer_list<T> ilist, const overflow_allocator_type& overflowAllocator)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer, overflowAllocator))\n\t{\n\t\ttypedef typename std::initializer_list<value_type>::iterator InputIterator;\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tbase_type::template DoAssignFromIterator<InputIterator, false>(ilist.begin(), ilist.end(), IC());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\ttemplate <typename InputIterator>\n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_vector(InputIterator first, InputIterator last)\n\t\t: base_type(fixed_allocator_type(mBuffer.buffer))\n\t{\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tget_allocator().set_name(EASTL_FIXED_VECTOR_DEFAULT_NAME);\n\t\t#endif\n\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\tbase_type::template DoAssign<InputIterator, false>(first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type& \n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tget_allocator() = x.get_allocator(); // The primary effect of this is to copy the overflow allocator.\n\t\t\t#endif\n\n\t\t\tbase_type::template DoAssign<const_iterator, false>(x.begin(), x.end(), false_type()); // Shorter route.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type& \n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(std::initializer_list<T> ilist)\n\t{\n\t\ttypedef typename std::initializer_list<value_type>::iterator InputIterator;\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\n\t\tclear();\n\t\tbase_type::template DoAssignFromIterator<InputIterator, false>(ilist.begin(), ilist.end(), IC());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type& \n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(this_type&& x)\n\t{\n\t\t// Since we are a fixed_vector, we can't swap pointers. We can possibly do something like fixed_swap or\n\t\t// we can just do an assignment from x. If we want to do the former then we need to have some complicated\n\t\t// code to deal with overflow or no overflow, and whether the memory is in the fixed-size buffer or in \n\t\t// the overflow allocator. 90% of the time the memory should be in the fixed buffer, in which case\n\t\t// a simple assignment is no worse than the fancy pathway.\n\t\tif (this != &x)\n\t\t{\n\t\t\tclear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tget_allocator() = x.get_allocator(); // The primary effect of this is to copy the overflow allocator.\n\t\t\t#endif\n\n\t\t\tbase_type::template DoAssign<move_iterator<iterator>, true>(eastl::make_move_iterator(x.begin()), eastl::make_move_iterator(x.end()), false_type()); // Shorter route.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::swap(this_type& x)\n\t{\n\t\tif((has_overflowed() && x.has_overflowed()) && (get_overflow_allocator() == x.get_overflow_allocator())) // If both containers are using the heap instead of local memory \n\t\t{                                                                                                        // then we can do a fast pointer swap instead of content swap.\n\t\t\teastl::swap(mpBegin,    x.mpBegin);\n\t\t\teastl::swap(mpEnd,      x.mpEnd);\n\t\t\teastl::swap(internalCapacityPtr(), x.internalCapacityPtr());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\t\teastl::fixed_swap(*this, x);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::set_capacity(size_type n)\n\t{\n\t\tconst size_type nPrevSize     = (size_type)(mpEnd - mpBegin);\n\t\tconst size_type nPrevCapacity = (size_type)(internalCapacityPtr() - mpBegin);\n\n\t\tif(n == npos)       // If the user means to set the capacity so that it equals the size (i.e. free excess capacity)...\n\t\t\tn = nPrevSize;\n\n\t\tif(n != nPrevCapacity)  // If the request results in a capacity change...\n\t\t{\n\t\t\tif(can_overflow() && (((uintptr_t)mpBegin != (uintptr_t)mBuffer.buffer) || (n > kMaxSize))) // If we are or would be using dynamically allocated memory instead of our fixed-size member buffer...\n\t\t\t{\n\t\t\t\tT* const pNewData = (n <= kMaxSize) ? (T*)&mBuffer.buffer[0] : DoAllocate(n);\n\t\t\t\tT* const pCopyEnd = (n < nPrevSize) ? (mpBegin + n) : mpEnd;\n\t\t\t\teastl::uninitialized_move(mpBegin, pCopyEnd, pNewData); // Move [mpBegin, pCopyEnd) to p.\n\t\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\t\tif((uintptr_t)mpBegin != (uintptr_t)mBuffer.buffer)\n\t\t\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\t\tmpEnd      = pNewData + (pCopyEnd - mpBegin);\n\t\t\t\tmpBegin    = pNewData;\n\t\t\t\tif (n <= kMaxSize)\n\t\t\t\t\tinternalCapacityPtr() = mpBegin + nodeCount; // This is the default capacity for fixed_vector when pointing at the fixed portion\n\t\t\t\telse\n\t\t\t\t\tinternalCapacityPtr() = mpBegin + n;\n\t\t\t} // Else the new capacity would be within our fixed buffer.\n\t\t\telse if(n < nPrevSize) // If the newly requested capacity is less than our size, we do what vector::set_capacity does and resize, even though we actually aren't reducing the capacity.\n\t\t\t\tresize(n);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename Allocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, Allocator>::clear(bool freeOverflow)\n\t{\n\t\tbase_type::clear();\n\t\tif (freeOverflow && mpBegin != (value_type*)&mBuffer.buffer[0])\n\t\t{\n\t\t\tEASTLFree(get_allocator(), mpBegin, (internalCapacityPtr() - mpBegin) * sizeof(T));\n\t\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::reset_lose_memory()\n\t{\n\t\tmpBegin = mpEnd = (value_type*)&mBuffer.buffer[0];\n\t\tinternalCapacityPtr() = mpBegin + nodeCount;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::size_type\n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::max_size() const\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::full() const\n\t{\n\t\t// If size >= capacity, then we are definitely full. \n\t\t// Also, if our size is smaller but we've switched away from mBuffer due to a previous overflow, then we are considered full.\n\t\treturn ((size_t)(mpEnd - mpBegin) >= kMaxSize) || ((void*)mpBegin != (void*)mBuffer.buffer);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::has_overflowed() const\n\t{\n\t\t// This will be incorrect for the case that bOverflowEnabled is true and the container was resized\n\t\t// down to a small size where the fixed buffer could take over ownership of the data again.\n\t\t// The only simple fix for this is to take on another member variable which tracks whether this overflow\n\t\t// has occurred at some point in the past.\n\t\treturn ((void*)mpBegin != (void*)mBuffer.buffer);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void* fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::push_back_uninitialized()\n\t{\n\t\treturn DoPushBackUninitialized(typename conditional<bEnableOverflow, true_type, false_type>::type());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void* fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBackUninitialized(true_type)\n\t{\n\t\treturn base_type::push_back_uninitialized();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void* fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBackUninitialized(false_type)\n\t{\n\t\tEASTL_ASSERT(mpEnd < internalCapacityPtr());\n\n\t\treturn mpEnd++;\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::push_back(const value_type& value)\n\t{\n\t\tDoPushBack(typename conditional<bEnableOverflow, true_type, false_type>::type(), value);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBack(true_type, const value_type& value)\n\t{\n\t\tbase_type::push_back(value);\n\t}\n\n\n\t// This template specializes for overflow NOT enabled.\n\t// In this configuration, there is no need for the heavy weight push_back() which tests to see if the container should grow (it never will)\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBack(false_type, const value_type& value)\n\t{\n\t\tEASTL_ASSERT(mpEnd < internalCapacityPtr());\n\n\t\tconstruct_at(mpEnd++, value);\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::reference fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::push_back()\n\t{\n\t\treturn DoPushBack(typename conditional<bEnableOverflow, true_type, false_type>::type());\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::reference fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBack(true_type)\n\t{\n\t\treturn base_type::push_back();\n\t}\n\n\n\t// This template specializes for overflow NOT enabled.\n\t// In this configuration, there is no need for the heavy weight push_back() which tests to see if the container should grow (it never will)\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::reference fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBack(false_type)\n\t{\n\t\tEASTL_ASSERT(mpEnd < internalCapacityPtr());\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT)\n\t\tconstruct_at(mpEnd++);\n#else\n\t\t// deprecated: this is default initialization, but should be value initialization.\n\t\t::new((void*)mpEnd++) value_type;\n#endif\n\n\t\treturn *(mpEnd - 1);        // Same as return back();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::push_back(value_type&& value)\n\t{\n\t\tDoPushBackMove(typename conditional<bEnableOverflow, true_type, false_type>::type(), eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBackMove(true_type, value_type&& value)\n\t{\n\t\tbase_type::push_back(eastl::move(value)); // This will call vector::push_back(value_type &&), and possibly swap value with *mpEnd.\n\t}\n\n\n\t// This template specializes for overflow NOT enabled.\n\t// In this configuration, there is no need for the heavy weight push_back() which tests to see if the container should grow (it never will)\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::DoPushBackMove(false_type, value_type&& value)\n\t{\n\t\tEASTL_ASSERT(mpEnd < internalCapacityPtr());\n\n\t\tconstruct_at(mpEnd++, eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline const typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type& \n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn get_allocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline typename fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type& \n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT\n\t{\n\t\treturn get_allocator().get_overflow_allocator();\n\t}\n\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void \n\tfixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)\n\t{\n\t\tget_allocator().set_overflow_allocator(allocator);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\t// operator ==, !=, <, >, <=, >= come from the vector implementations.\n\n\ttemplate <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>\n\tinline void swap(fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t fixed_vector<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\t// Fixed containers use a special swap that can deal with excessively large buffers.\n\t\teastl::fixed_swap(a, b);\n\t}\n\n\n\n} // namespace eastl\n\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/functional.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FUNCTIONAL_H\n#define EASTL_FUNCTIONAL_H\n\n\n#include <EABase/eabase.h>\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/internal/functional_base.h>\n#include <EASTL/internal/mem_fn.h>\n#include <EASTL/bit.h>\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4512 4626);\n\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////\n\t// Primary C++ functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T = void>\n\tstruct plus\n\t{\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t\t{ return a + b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/plus_void\n\ttemplate <>\n\tstruct plus<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) + eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) + eastl::forward<B>(b); }\n\t};\n\n\ttemplate <typename T = void>\n\tstruct minus\n\t{\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t\t{ return a - b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/minus_void\n\ttemplate <>\n\tstruct minus<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) - eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) - eastl::forward<B>(b); }\n\t};\n\n\ttemplate <typename T = void>\n\tstruct multiplies\n\t{\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t\t{ return a * b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/multiplies_void\n\ttemplate <>\n\tstruct multiplies<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) * eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) * eastl::forward<B>(b); }\n\t};\n\n    template <typename T = void>\n    struct divides\n    {\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t\t{ return a / b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/divides_void\n\ttemplate <>\n\tstruct divides<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) / eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) / eastl::forward<B>(b); }\n\t};\n\n    template <typename T = void>\n    struct modulus\n    {\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t\t{ return a % b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/modulus_void\n\ttemplate <>\n\tstruct modulus<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) % eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) % eastl::forward<B>(b); }\n\t};\n\n    template <typename T = void>\n    struct negate\n    {\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a) const\n\t\t\t{ return -a; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/negate_void\n\ttemplate <>\n\tstruct negate<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename T>\n\t\tEA_CPP14_CONSTEXPR auto operator()(T&& t) const\n\t\t\t-> decltype(-eastl::forward<T>(t))\n\t\t\t{ return -eastl::forward<T>(t); }\n\t};\n\n\ttemplate <typename T = void>\n\tstruct equal_to\n\t{\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a == b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/equal_to_void\n\ttemplate <>\n\tstruct equal_to<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) == eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) == eastl::forward<B>(b); }\n\t};\n\n\ttemplate <typename T, typename Compare>\n\tbool validate_equal_to(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn compare(a, b) == compare(b, a);\n\t}\n\n    template <typename T = void>\n    struct not_equal_to\n    {\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a != b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/not_equal_to_void\n\ttemplate <>\n\tstruct not_equal_to<void> \n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) != eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) != eastl::forward<B>(b); }\n\t};\n\n\ttemplate <typename T, typename Compare>\n\tbool validate_not_equal_to(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn compare(a, b) == compare(b, a); // We want the not equal comparison results to be equal.\n\t}\n\n\t/// str_equal_to\n\t///\n\t/// Compares two 0-terminated string types.\n\t/// The T types are expected to be iterators or act like iterators.\n\t/// The expected behavior of str_less is the same as (strcmp(p1, p2) == 0).\n\t///\n\t/// Example usage:\n\t///     hash_set<const char*, hash<const char*>, str_equal_to<const char*> > stringHashSet;\n\t///\n\t/// Note:\n\t/// You couldn't use str_equal_to like this:\n\t///     bool result = equal(\"hi\", \"hi\" + 2, \"ho\", str_equal_to<const char*>());\n\t/// This is because equal tests an array of something, with each element by\n\t/// the comparison function. But str_equal_to tests an array of something itself.\n\t///\n\t/// To consider: Update this code to use existing word-based comparison optimizations, \n\t/// such as that used in the EAStdC Strcmp function.\n\t///\n\ttemplate <typename T>\n\tstruct str_equal_to\n\t{\n\t\tEA_CPP14_CONSTEXPR bool operator()(T a, T b) const\n\t\t{\n\t\t\twhile(*a && (*a == *b))\n\t\t\t{\n\t\t\t\t++a;\n\t\t\t\t++b;\n\t\t\t}\n\t\t\treturn (*a == *b);\n\t\t}\n\t};\n\n\ttemplate <typename T = void>\n\tstruct greater\n\t{\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a > b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/greater_void\n\ttemplate <>\n\tstruct greater<void>\n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) > eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) > eastl::forward<B>(b); }\n\t};\n\n\ttemplate <typename T, typename Compare>\n\tbool validate_greater(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn !compare(a, b) || !compare(b, a); // If (a > b), then !(b > a)\n\t}\n\n\n\ttemplate <typename T, typename Compare>\n\tbool validate_less(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn !compare(a, b) || !compare(b, a); // If (a < b), then !(b < a)\n\t}\n\n\t/// str_less\n\t///\n\t/// Compares two 0-terminated string types. \n\t/// The T types are expected to be iterators or act like iterators, \n\t/// and that includes being a pointer to a C character array.\n\t/// The expected behavior of str_less is the same as (strcmp(p1, p2) < 0).\n\t/// This function is not Unicode-correct and it's not guaranteed to work\n\t/// with all Unicode strings.\n\t///\n\t/// Example usage:\n\t///     set<const char*, str_less<const char*> > stringSet;\n\t///\n\t/// To consider: Update this code to use existing word-based comparison optimizations, \n\t/// such as that used in the EAStdC Strcmp function.\n\t///\n\ttemplate <typename T>\n\tstruct str_less\n\t{\n\t\tbool operator()(T a, T b) const\n\t\t{\n\t\t\twhile(static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*a) == \n\t\t\t\t  static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*b))\n\t\t\t{\n\t\t\t\tif(*a == 0)\n\t\t\t\t\treturn (*b != 0);\n\t\t\t\t++a;\n\t\t\t\t++b;\n\t\t\t}\n\n\t\t\tchar aValue = static_cast<typename remove_pointer<T>::type>(*a);\n\t\t\tchar bValue = static_cast<typename remove_pointer<T>::type>(*b);\n\n\t\t\ttypename make_unsigned<char>::type aValueU = static_cast<typename make_unsigned<char>::type>(aValue);\n\t\t\ttypename make_unsigned<char>::type bValueU = static_cast<typename make_unsigned<char>::type>(bValue);\n\n\t\t\treturn aValueU < bValueU;\n\n\t\t\t//return (static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*a) < \n\t\t\t//        static_cast<typename make_unsigned<typename remove_pointer<T>::type>::type>(*b));\n\t\t}\n\t};\n\n    template <typename T = void>\n    struct greater_equal\n    {\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a >= b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/greater_equal_void\n\ttemplate <>\n\tstruct greater_equal<void>\n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) >= eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) >= eastl::forward<B>(b); }\n\t};\n\n\ttemplate <typename T, typename Compare>\n\tbool validate_greater_equal(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn !compare(a, b) || !compare(b, a); // If (a >= b), then !(b >= a)\n\t}\n\n\ttemplate <typename T = void>\n\tstruct less_equal\n\t{\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a <= b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/less_equal_void\n\ttemplate <>\n\tstruct less_equal<void>\n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) <= eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) <= eastl::forward<B>(b); }\n\t};\n\n\ttemplate <typename T, typename Compare>\n\tbool validate_less_equal(const T& a, const T& b, Compare compare)\n\t{\n\t\treturn !compare(a, b) || !compare(b, a); // If (a <= b), then !(b <= a)\n\t}\n\n\t// todo: when C++20 support added, add a compare_three_way function object.\n\n\ttemplate <typename T = void>\n\tstruct logical_and\n\t{\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a && b; }\n\t};\n\t\n\t// http://en.cppreference.com/w/cpp/utility/functional/logical_and_void\n\ttemplate <>\n\tstruct logical_and<void>\n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) && eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) && eastl::forward<B>(b); }\n\t};\n\n    template <typename T = void>\n    struct logical_or\n    {\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a || b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/logical_or_void\n\ttemplate <>\n\tstruct logical_or<void>\n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) || eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) || eastl::forward<B>(b); }\n\t};\n\n    template <typename T = void>\n    struct logical_not\n    {\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a) const\n\t\t\t{ return !a; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/logical_not_void\n\ttemplate <>\n\tstruct logical_not<void>\n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename T>\n\t\tEA_CPP14_CONSTEXPR auto operator()(T&& t) const\n\t\t\t-> decltype(!eastl::forward<T>(t))\n\t\t\t{ return !eastl::forward<T>(t); }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_and\n\ttemplate <typename T = void>\n\tstruct bit_and\n\t{\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t{\n\t\t\treturn a & b;\n\t\t}\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_and_void\n\ttemplate <>\n\tstruct bit_and<void>\n\t{\n\t\ttypedef int is_transparent;\n\n\t\ttemplate<typename T, typename U>\n\t\tEA_CPP14_CONSTEXPR auto operator()(T&& a, U&& b) const\n\t\t\t-> decltype(eastl::forward<T>(a) & eastl::forward<U>(b))\n\t\t{\n\t\t\treturn eastl::forward<T>(a) & eastl::forward<U>(b);\n\t\t}\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_or\n\ttemplate <typename T = void>\n\tstruct bit_or\n\t{\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t{\n\t\t\treturn a | b;\n\t\t}\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_or_void\n\ttemplate <>\n\tstruct bit_or<void>\n\t{\n\t\ttypedef int is_transparent;\n\n\t\ttemplate<typename T, typename U>\n\t\tEA_CPP14_CONSTEXPR auto operator()(T&& a, U&& b) const\n\t\t\t-> decltype(eastl::forward<T>(a) | eastl::forward<U>(b))\n\t\t{\n\t\t\treturn eastl::forward<T>(a) | eastl::forward<U>(b);\n\t\t}\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_xor\n\ttemplate <typename T = void>\n\tstruct bit_xor\n\t{\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a, const T& b) const\n\t\t{\n\t\t\treturn a ^ b;\n\t\t}\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_xor_void\n\ttemplate <>\n\tstruct bit_xor<void>\n\t{\n\t\ttypedef int is_transparent;\n\n\t\ttemplate<typename T, typename U>\n\t\tEA_CPP14_CONSTEXPR auto operator()(T&& a, U&& b) const\n\t\t\t-> decltype(eastl::forward<T>(a) ^ eastl::forward<U>(b))\n\t\t{\n\t\t\treturn eastl::forward<T>(a) ^ eastl::forward<U>(b);\n\t\t}\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_not\n\ttemplate <typename T = void>\n\tstruct bit_not\n\t{\n\t\tEA_CPP14_CONSTEXPR T operator()(const T& a) const\n\t\t{\n\t\t\treturn ~a;\n\t\t}\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/bit_not_void\n\ttemplate <>\n\tstruct bit_not<void>\n\t{\n\t\ttypedef int is_transparent;\n\n\t\ttemplate<typename T>\n\t\tEA_CPP14_CONSTEXPR auto operator()(T&& t) const\n\t\t\t-> decltype(~eastl::forward<T>(t))\n\t\t{\n\t\t\treturn ~eastl::forward<T>(t);\n\t\t}\n\t};\n\n\t// todo: add identity function object\n\n\t// not_fn_ret\n\t// not_fn_ret is a implementation specified return type of eastl::not_fn.\n\t// The type name is not specified but it does have mandated functions that conforming implementations must support.\n\t//\n\t// http://en.cppreference.com/w/cpp/utility/functional/not_fn\n\t//\n\ttemplate <typename F>\n\tstruct not_fn_ret\n\t{\n\t\texplicit not_fn_ret(F&& f) : mDecayF(eastl::forward<F>(f)) {}\n\t\tnot_fn_ret(not_fn_ret&& f) = default;\n\t\tnot_fn_ret(const not_fn_ret& f) = default;\n\n\t\t// overloads for lvalues\n\t\ttemplate <class... Args>\n\t\tauto operator()(Args&&... args) &\n\t\t    -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F>&, Args...>>())\n\t\t{ return !eastl::invoke(mDecayF, eastl::forward<Args>(args)...); }\n\n\t\ttemplate <class... Args>\n\t\tauto operator()(Args&&... args) const &\n\t\t    -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F> const&, Args...>>())\n\t\t{ return !eastl::invoke(mDecayF, eastl::forward<Args>(args)...); }\n\n\t\t// overloads for rvalues\n\t\ttemplate <class... Args>\n\t\tauto operator()(Args&&... args) &&\n\t\t    -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F>, Args...>>())\n\t\t{ return !eastl::invoke(eastl::move(mDecayF), eastl::forward<Args>(args)...); }\n\n\t\ttemplate <class... Args>\n\t\tauto operator()(Args&&... args) const &&\n\t\t    -> decltype(!eastl::declval<eastl::invoke_result_t<eastl::decay_t<F> const, Args...>>())\n\t\t{ return !eastl::invoke(eastl::move(mDecayF), eastl::forward<Args>(args)...); }\n\n\t\teastl::decay_t<F> mDecayF;\n\t};\n\n\t/// not_fn\n\t///\n\t/// Creates an implementation specified functor that returns the complement of the callable object it was passed.\n\t/// not_fn is intended to replace the C++03-era negators eastl::not1 and eastl::not2.\n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/functional/not_fn\n\t///\n\t/// Example usage:\n\t///\n\t///\t\tauto nf = eastl::not_fn([]{ return false; });\n\t///     assert(nf());  // return true\n\t///\n\ttemplate <class F>\n\tinline not_fn_ret<F> not_fn(F&& f)\n\t{\n\t\treturn not_fn_ret<F>(eastl::forward<F>(f));\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// hash\n\t///////////////////////////////////////////////////////////////////////\n\tnamespace Internal\n\t{\n\t\t// utility to disable the generic template specialization that is\n\t\t// used for enum types only.\n\t\ttemplate <typename T, bool Enabled>\n\t\tstruct EnableHashIf {};\n\n\t\ttemplate <typename T>\n\t\tstruct EnableHashIf<T, true>\n\t\t{\n\t\t\tsize_t operator()(T p) const { return size_t(p); }\n\t\t};\n\t} // namespace Internal\n\n\n\ttemplate <typename T> struct hash;\n\n\ttemplate <typename T>\n\tstruct hash : Internal::EnableHashIf<T, is_enum_v<T>> {};\n\n\ttemplate <typename T> struct hash<T*> // Note that we use the pointer as-is and don't divide by sizeof(T*). This is because the table is of a prime size and this division doesn't benefit distribution.\n\t\t{ size_t operator()(T* p) const { return size_t(uintptr_t(p)); } };\n\n\ttemplate <> struct hash<bool>\n\t\t{ size_t operator()(bool val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<char>\n\t\t{ size_t operator()(char val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<signed char>\n\t\t{ size_t operator()(signed char val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<unsigned char>\n\t\t{ size_t operator()(unsigned char val) const { return static_cast<size_t>(val); } };\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\t\ttemplate <> struct hash<char8_t>\n\t\t\t{ size_t operator()(char8_t val) const { return static_cast<size_t>(val); } };\n\t#endif\n\n\t#if defined(EA_CHAR16_NATIVE) && EA_CHAR16_NATIVE\n\t\ttemplate <> struct hash<char16_t>\n\t\t\t{ size_t operator()(char16_t val) const { return static_cast<size_t>(val); } };\n\t#endif\n\n\t#if defined(EA_CHAR32_NATIVE) && EA_CHAR32_NATIVE\n\t\ttemplate <> struct hash<char32_t>\n\t\t\t{ size_t operator()(char32_t val) const { return static_cast<size_t>(val); } };\n\t#endif\n\n\t// If wchar_t is a native type instead of simply a define to an existing type...\n\t#if !defined(EA_WCHAR_T_NON_NATIVE)\n\t\ttemplate <> struct hash<wchar_t>\n\t\t\t{ size_t operator()(wchar_t val) const { return static_cast<size_t>(val); } };\n\t#endif\n\n\ttemplate <> struct hash<signed short>\n\t\t{ size_t operator()(signed short val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<unsigned short>\n\t\t{ size_t operator()(unsigned short val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<signed int>\n\t\t{ size_t operator()(signed int val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<unsigned int>\n\t\t{ size_t operator()(unsigned int val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<signed long>\n\t\t{ size_t operator()(signed long val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<unsigned long>\n\t\t{ size_t operator()(unsigned long val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<signed long long>\n\t\t{ size_t operator()(signed long long val) const { return static_cast<size_t>(val); } };\n\n\ttemplate <> struct hash<unsigned long long>\n\t\t{ size_t operator()(unsigned long long val) const { return static_cast<size_t>(val); } };\n\n\tnamespace internal\n\t{\n\t\tusing size_t_sized_floating_point_type = eastl::conditional_t<sizeof(size_t) == sizeof(double), double, float>;\n\n\t\ttemplate <typename T>\n\t\tsize_t floating_point_hash(T val)\n\t\t{\n\t\t\tif (val == -0.0)\n\t\t\t{\n\t\t\t\treturn eastl::bit_cast<size_t>(static_cast<internal::size_t_sized_floating_point_type>(0.0));\n\t\t\t}\n\n\t\t\treturn eastl::bit_cast<size_t>(static_cast<internal::size_t_sized_floating_point_type>(val));\n\t\t}\n\t}\n\n\ttemplate <> struct hash<float>\n\t\t{ size_t operator()(float val) const { return internal::floating_point_hash(val); } };\n\n\ttemplate <> struct hash<double>\n\t\t{ size_t operator()(double val) const { return internal::floating_point_hash(val); } };\n\n\ttemplate <> struct hash<long double>\n\t\t{ size_t operator()(long double val) const { return internal::floating_point_hash(val); } };\n\n\t#if defined(EA_HAVE_INT128) && EA_HAVE_INT128\n\ttemplate <> struct hash<uint128_t>\n\t\t{ size_t operator()(uint128_t val) const { return static_cast<size_t>(val); } };\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// string hashes\n\t//\n\t// Note that our string hashes here intentionally are slow for long strings.\n\t// The reasoning for this is so:\n\t//    - The large majority of hashed strings are only a few bytes long.\n\t//    - The hash function is significantly more efficient if it can make this assumption.\n\t//    - The user is welcome to make a custom hash for those uncommon cases where\n\t//      long strings need to be hashed. Indeed, the user can probably make a \n\t//      special hash customized for such strings that's better than what we provide.\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <> struct hash<char*>\n\t{\n\t\tsize_t operator()(const char* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // FNV1 hash. Perhaps the best string hash. Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint8_t)*p++) != 0)     // Using '!=' disables compiler warnings.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate <> struct hash<const char*>\n\t{\n\t\tsize_t operator()(const char* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint8_t)*p++) != 0)     // cast to unsigned 8 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n#if EA_CHAR8_UNIQUE\n\ttemplate <> struct hash<char8_t*>\n\t{\n\t\tsize_t operator()(const char8_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // FNV1 hash. Perhaps the best string hash. Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint8_t)*p++) != 0)     // Using '!=' disables compiler warnings.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate <> struct hash<const char8_t*>\n\t{\n\t\tsize_t operator()(const char8_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint8_t)*p++) != 0)     // cast to unsigned 8 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n#endif\n\n\n\ttemplate <> struct hash<char16_t*>\n\t{\n\t\tsize_t operator()(const char16_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint16_t)*p++) != 0)    // cast to unsigned 16 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate <> struct hash<const char16_t*>\n\t{\n\t\tsize_t operator()(const char16_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint16_t)*p++) != 0)    // cast to unsigned 16 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate <> struct hash<char32_t*>\n\t{\n\t\tsize_t operator()(const char32_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint32_t)*p++) != 0)    // cast to unsigned 32 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate <> struct hash<const char32_t*>\n\t{\n\t\tsize_t operator()(const char32_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;   // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = (uint32_t)*p++) != 0)    // cast to unsigned 32 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\ttemplate<> struct hash<wchar_t*>\n\t{\n\t\tsize_t operator()(const wchar_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;    // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile ((c = (uint32_t)*p++) != 0)    // cast to unsigned 32 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate<> struct hash<const wchar_t*>\n\t{\n\t\tsize_t operator()(const wchar_t* p) const\n\t\t{\n\t\t\tuint32_t c, result = 2166136261U;    // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile ((c = (uint32_t)*p++) != 0)    // cast to unsigned 32 bit.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n#endif\n\n\t/// string_hash\n\t///\n\t/// Defines a generic string hash for an arbitrary EASTL basic_string container.\n\t///\n\t/// Example usage:\n\t///    eastl::hash_set<MyString, eastl::string_hash<MyString> > hashSet;\n\t///\n\ttemplate <typename String>\n\tstruct string_hash\n\t{\n\t\ttypedef String                                         string_type;\n\t\ttypedef typename String::value_type                    value_type;\n\t\ttypedef typename eastl::make_unsigned<value_type>::type unsigned_value_type;\n\n\t\tsize_t operator()(const string_type& s) const\n\t\t{\n\t\t\tconst unsigned_value_type* p = (const unsigned_value_type*)s.c_str();\n\t\t\tuint32_t c, result = 2166136261U;   // Intentionally uint32_t instead of size_t, so the behavior is the same regardless of size.\n\t\t\twhile((c = *p++) != 0)\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\n} // namespace eastl\n\n#include <EASTL/internal/function.h>\n\nEA_RESTORE_VC_WARNING();\n\n#endif // Header include guard\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/hash_map.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file is based on the TR1 (technical report 1) reference implementation\n// of the unordered_set/unordered_map C++ classes as of about 4/2005. Most likely\n// many or all C++ library vendors' implementations of this classes will be \n// based off of the reference version and so will look pretty similar to this\n// file as well as other vendors' versions. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_HASH_MAP_H\n#define EASTL_HASH_MAP_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/hashtable.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_HASH_MAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_HASH_MAP_DEFAULT_NAME\n\t\t#define EASTL_HASH_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" hash_map\" // Unless the user overrides something, this is \"EASTL hash_map\".\n\t#endif\n\n\n\t/// EASTL_HASH_MULTIMAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_HASH_MULTIMAP_DEFAULT_NAME\n\t\t#define EASTL_HASH_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" hash_multimap\" // Unless the user overrides something, this is \"EASTL hash_multimap\".\n\t#endif\n\n\n\t/// EASTL_HASH_MAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_HASH_MAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_HASH_MAP_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_MAP_DEFAULT_NAME)\n\t#endif\n\n\t/// EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_MULTIMAP_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// hash_map\n\t///\n\t/// Implements a hash_map, which is a hashed associative container.\n\t/// Lookups are O(1) (that is, they are fast) but the container is \n\t/// not sorted. Note that lookups are only O(1) if the hash table\n\t/// is well-distributed (non-colliding). The lookup approaches\n\t/// O(n) behavior as the table becomes increasingly poorly distributed.\n\t///\n\t/// set_max_load_factor\n\t/// If you want to make a hashtable never increase its bucket usage,\n\t/// call set_max_load_factor with a very high value such as 100000.f.\n\t///\n\t/// bCacheHashCode\n\t/// We provide the boolean bCacheHashCode template parameter in order \n\t/// to allow the storing of the hash code of the key within the map. \n\t/// When this option is disabled, the rehashing of the table will \n\t/// call the hash function on the key. Setting bCacheHashCode to true \n\t/// is useful for cases whereby the calculation of the hash value for\n\t/// a contained object is very expensive.\n\t///\n\t/// Heterogeneous lookup, insertion and erasure\n\t/// See\n\t/// https://en.cppreference.com/w/cpp/utility/functional#Transparent_function_objects\n\t/// https://en.cppreference.com/w/cpp/utility/functional/less_void\n\t/// https://en.cppreference.com/w/cpp/container/unordered_map/find\n\t/// \n\t/// You can avoid creating key objects when calling member functions\n\t/// with a key_type parameter by declaring the container with a\n\t/// transparent hash and comparison type (eg. equal_to<void>) and\n\t/// passing objects to be passed to these function objects.\n\t/// \n\t/// This optimization is supported for member functions that take a\n\t/// key_type parameter, ie. heterogeneous lookup, insertion and erasure,\n\t/// not just find().\n\t/// \n\t/// Using transparent types is safer than using find_as because the\n\t/// latter requires the user specify hash and equality function objects\n\t/// which must have the same semantics as the container's hash and\n\t/// equality objects, otherwise the behaviour is undefined.\n\t/// \n\t/// find_as\n\t/// Note: Prefer heterogeneous lookup (see above).\n\t/// \n\t/// In order to support the ability to have a hashtable of strings but\n\t/// be able to do efficiently lookups via char pointers (i.e. so they \n\t/// aren't converted to string objects), we provide the find_as \n\t/// function. This function allows you to do a find with a key of a\n\t/// type other than the hashtable key type.\n\t///\n\t/// Example find_as usage:\n\t///     hash_map<string, int> hashMap;\n\t///     i = hashMap.find_as(\"hello\");    // Use default hash and compare.\n\t///\n\t/// Example find_as usage (namespaces omitted for brevity):\n\t///     hash_map<string, int> hashMap;\n\t///     i = hashMap.find_as(\"hello\", hash<char*>(), equal_to<>());\n\t///\n\ttemplate <typename Key, typename T, typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>, \n\t\t\t  typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>\n\tclass hash_map\n\t\t: public hashtable<Key, eastl::pair<const Key, T>, Allocator, eastl::use_first<eastl::pair<const Key, T> >, Predicate,\n\t\t\t\t\t\t\tHash, mod_range_hashing, default_ranged_hash, prime_rehash_policy, bCacheHashCode, true, true>\n\t{\n\tpublic:\n\t\ttypedef hashtable<Key, eastl::pair<const Key, T>, Allocator, \n\t\t\t\t\t\t  eastl::use_first<eastl::pair<const Key, T> >, \n\t\t\t\t\t\t  Predicate, Hash, mod_range_hashing, default_ranged_hash, \n\t\t\t\t\t\t  prime_rehash_policy, bCacheHashCode, true, true>        base_type;\n\t\ttypedef hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>      this_type;\n\t\ttypedef typename base_type::size_type                                     size_type;\n\t\ttypedef typename base_type::key_type                                      key_type;\n\t\ttypedef T                                                                 mapped_type;\n\t\ttypedef typename base_type::value_type                                    value_type;     // NOTE: 'value_type = pair<const key_type, mapped_type>'.\n\t\ttypedef typename base_type::allocator_type                                allocator_type;\n\t\ttypedef typename base_type::node_type                                     node_type;\n\t\ttypedef typename base_type::insert_return_type                            insert_return_type;\n\t\ttypedef typename base_type::iterator                                      iterator;\n\t\ttypedef typename base_type::const_iterator                                const_iterator;\n\n\t\tusing base_type::insert;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"hash_map<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"hash_map<T> value_type must be non-volatile.\");\n\n\tpublic:\n\t\t/// hash_map\n\t\t///\n\t\t/// Default constructor.\n\t\t///\n\t\thash_map()\n\t\t\t: this_type(EASTL_HASH_MAP_DEFAULT_ALLOCATOR)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\n\t\t/// hash_map\n\t\t///\n\t\t/// Constructor which creates an empty container with allocator.\n\t\t///\n\t\texplicit hash_map(const allocator_type& allocator)\n\t\t\t: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(),\n\t\t\t\t\t\tPredicate(), eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\n\t\t/// hash_map\n\t\t///\n\t\t/// Constructor which creates an empty container, but start with nBucketCount buckets.\n\t\t/// We default to a small nBucketCount value, though the user really should manually \n\t\t/// specify an appropriate value in order to prevent memory from being reallocated.\n\t\t///\n\t\t/// note: difference in explicit keyword from the standard.\n\t\texplicit hash_map(size_type nBucketCount, const Hash& hashFunction = Hash(), \n\t\t\t\t\t\t  const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MAP_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), \n\t\t\t\t\t\tpredicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_map(size_type nBucketCount, const allocator_type& allocator)\n\t\t// hash_map(size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\n\t\thash_map(const this_type& x)\n\t\t  : base_type(x)\n\t\t{\n\t\t}\n\n\t\t// hash_map(const this_type& x, const allocator_type& allocator)\n\n\n\t\thash_map(this_type&& x)\n\t\t  : base_type(eastl::move(x))\n\t\t{\n\t\t}\n\n\n\t\thash_map(this_type&& x, const allocator_type& allocator)\n\t\t  : base_type(eastl::move(x), allocator)\n\t\t{\n\t\t}\n\n\n\t\t/// hash_map\n\t\t///\n\t\t/// initializer_list-based constructor. \n\t\t/// Allows for initializing with brace values (e.g. hash_map<int, char*> hm = { {3,\"c\"}, {4,\"d\"}, {5,\"e\"} }; )\n\t\t///     \n\t\thash_map(std::initializer_list<value_type> ilist, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t   const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MAP_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(ilist.begin(), ilist.end(), nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), \n\t\t\t\t\t\tpredicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\thash_map(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t\t: base_type(ilist.begin(), ilist.end(), 0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_map(std::initializer_list<value_type> ilist, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// hash_map(std::initializer_list<value_type> ilist, size_type nBucketCount, const Hash& hashFunction,\n\t\t// \tconst allocator_type& allocator)\n\n\t\t/// hash_map\n\t\t///\n\t\t/// An input bucket count of <= 1 causes the bucket count to be equal to the number of \n\t\t/// elements in the input range.\n\t\t///\n\t\ttemplate <typename ForwardIterator>\n\t\thash_map(ForwardIterator first, ForwardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MAP_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), \n\t\t\t\t\t\tpredicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_map(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_map(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\t\tthis_type& operator=(const this_type& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(x));\n\t\t}\n\n\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(ilist));\n\t\t}\n\n\n\t\tthis_type& operator=(this_type&& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(eastl::move(x)));\n\t\t}\n\n\n\t\t/// insert\n\t\t///\n\t\t/// This is an extension to the C++ standard. We insert a default-constructed \n\t\t/// element with the given key. The reason for this is that we can avoid the \n\t\t/// potentially expensive operation of creating and/or copying a mapped_type\n\t\t/// object on the stack.\n\t\tinsert_return_type insert(const key_type& key)\n\t\t{\n\t\t\treturn base_type::DoInsertKey(true_type(), key);\n\t\t}\n\n\t\tinsert_return_type insert(key_type&& key)\n\t\t{\n\t\t\treturn base_type::DoInsertKey(true_type(), eastl::move(key));\n\t\t}\n\n\t\ttemplate <typename P, eastl::enable_if_t<eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tinsert_return_type insert(P&& otherValue)\n\t\t{\n\t\t\treturn base_type::emplace(eastl::forward<P>(otherValue));\n\t\t}\n\n\t\tT& at(const key_type& k) { return DoAt(k); }\n\n\t\tconst T& at(const key_type& k) const { return DoAt(k); }\n\n\t\ttemplate<typename KX, typename HX = Hash, typename PX = Predicate,\n\t\t\teastl::enable_if_t<eastl::detail::is_transparent_comparison_v<HX> && eastl::detail::is_transparent_comparison_v<PX>, bool> = true>\n\t\tT& at(const KX& k) { return DoAt(k); }\n\n\t\ttemplate<typename KX, typename HX = Hash, typename PX = Predicate,\n\t\t\teastl::enable_if_t<eastl::detail::is_transparent_comparison_v<HX>&& eastl::detail::is_transparent_comparison_v<PX>, bool> = true>\n\t\tconst T& at(const KX& k) const { return DoAt(k); }\n\n\n\t\tmapped_type& operator[](const key_type& key)\n\t\t{\n\t\t\treturn (*base_type::DoInsertKey(true_type(), key).first).second;\n\n\t\t\t// Slower reference version:\n\t\t\t//const typename base_type::iterator it = base_type::find(key);\n\t\t\t//if(it != base_type::end())\n\t\t\t//    return (*it).second;\n\t\t\t//return (*base_type::insert(value_type(key, mapped_type())).first).second;\n\t\t}\n\n\t\tmapped_type& operator[](key_type&& key)\n\t\t{\n\t\t\t// The Standard states that this function \"inserts the value value_type(std::move(key), mapped_type())\"\n\t\t\treturn (*base_type::DoInsertKey(true_type(), eastl::move(key)).first).second;\n\t\t}\n\n\t\ttemplate <typename KX, typename... Args, typename HX = Hash, typename PX = Predicate,\n\t\t\teastl::enable_if_t<eastl::detail::is_transparent_comparison_v<HX> && eastl::detail::is_transparent_comparison_v<PX>, bool> = true>\n\t\tmapped_type& operator[](KX&& key)\n\t\t{\n\t\t\treturn try_emplace(eastl::forward<KX>(key)).first->second;\n\t\t}\n\n\t\t// try_emplace API added in C++17\n\t\ttemplate <class... Args>\n\t\tinline insert_return_type try_emplace(const key_type& k, Args&&... args)\n\t\t{\n\t\t\treturn try_emplace_forwarding(k, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <class... Args>\n\t\tinline insert_return_type try_emplace(key_type&& k, Args&&... args) {\n\t\t\treturn try_emplace_forwarding(eastl::move(k), eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <typename KX, typename... Args, typename HX = Hash, typename PX = Predicate,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, const_iterator> && !eastl::is_convertible_v<KX&&, iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<HX> && eastl::detail::is_transparent_comparison_v<PX>, bool> = true>\n\t\tinline insert_return_type try_emplace(KX&& k, Args&&... args) {\n\t\t\treturn try_emplace_forwarding(eastl::forward<KX>(k), eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <class... Args>\n\t\tinline iterator try_emplace(const_iterator, const key_type& k, Args&&... args) {\n\t\t\t// Currently, the first parameter is ignored.\n\t\t\tinsert_return_type result = try_emplace(k, eastl::forward<Args>(args)...);\n\t\t\treturn base_type::DoGetResultIterator(true_type(), result);\n\t\t}\n\n\t\ttemplate <class... Args>\n\t\tinline iterator try_emplace(const_iterator, key_type&& k, Args&&... args) {\n\t\t\t// Currently, the first parameter is ignored.\n\t\t\tinsert_return_type result = try_emplace(eastl::move(k), eastl::forward<Args>(args)...);\n\t\t\treturn base_type::DoGetResultIterator(true_type(), result);\n\t\t}\n\n\t\ttemplate <typename KX, typename... Args, typename HX = Hash, typename PX = Predicate,\n\t\t\teastl::enable_if_t<eastl::detail::is_transparent_comparison_v<HX>&& eastl::detail::is_transparent_comparison_v<PX>, bool> = true>\n\t\tinline iterator try_emplace(const_iterator, KX&& k, Args&&... args) {\n\t\t\t// Currently, the first parameter is ignored.\n\t\t\tinsert_return_type result = try_emplace(eastl::forward<KX>(k), eastl::forward<Args>(args)...);\n\t\t\treturn base_type::DoGetResultIterator(true_type(), result);\n\t\t}\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tT& DoAt(const KX& k)\n\t\t{\n\t\t\titerator it = base_type::find(k);\n\n\t\t\tif (it == base_type::end())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t// throw exeption if exceptions enabled\n\t\t\t\tthrow std::out_of_range(\"invalid hash_map<K, T> key\");\n#else\n\t\t\t\t// assert false if asserts enabled\n\t\t\t\tEASTL_ASSERT_MSG(false, \"invalid hash_map<K, T> key\");\n#endif\n\t\t\t}\n\t\t\t// undefined behaviour if exceptions and asserts are disabled and it == end()\n\t\t\treturn it->second;\n\t\t}\n\n\t\ttemplate<typename KX>\n\t\tconst T& DoAt(const KX& k) const\n\t\t{\n\t\t\tconst_iterator it = base_type::find(k);\n\n\t\t\tif (it == base_type::end())\n\t\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t// throw exeption if exceptions enabled\n\t\t\t\tthrow std::out_of_range(\"invalid hash_map<K, T> key\");\n#else\n\t\t\t\t// assert false if asserts enabled\n\t\t\t\tEASTL_ASSERT_MSG(false, \"invalid hash_map<K, T> key\");\n#endif\n\t\t\t}\n\t\t\t// undefined behaviour if exceptions and asserts are disabled and it == end()\n\t\t\treturn it->second;\n\t\t}\n\n\t\ttemplate <class K, class... Args>\n\t\tinsert_return_type try_emplace_forwarding(K&& k, Args&&... args)\n\t\t{\n\t\t\tconst auto key_data = base_type::DoFindKeyData(k);\n\t\t\tif (key_data.node)\n\t\t\t{ // Node exists, no insertion needed.\n\t\t\t\treturn eastl::pair<iterator, bool>(\n\t\t\t\t    iterator(key_data.node, base_type::mpBucketArray + key_data.bucket_index), false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnode_type* const pNodeNew =\n\t\t\t\t    base_type::DoAllocateNode(piecewise_construct, eastl::forward_as_tuple(eastl::forward<K>(k)),\n\t\t\t\t                              forward_as_tuple(eastl::forward<Args>(args)...));\n\t\t\t\t// the key might have been moved from above, so we can't use `k` anymore.\n\t\t\t\tconst auto& key = base_type::mExtractKey(pNodeNew->mValue);\n\t\t\t\treturn base_type::template DoInsertUniqueNode<true>(key, key_data.code, key_data.bucket_index, pNodeNew);\n\t\t\t}\n\t\t}\n\t}; // hash_map\n\n\t/// hash_map erase_if\n\t///\n\t/// https://en.cppreference.com/w/cpp/container/unordered_map/erase_if\n\ttemplate <typename Key, typename T, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode, typename UserPredicate>\n\ttypename eastl::hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::size_type erase_if(eastl::hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& c, UserPredicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\t// Erases all elements that satisfy the predicate from the container.\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n\n\t/// hash_multimap\n\t///\n\t/// Implements a hash_multimap, which is the same thing as a hash_map \n\t/// except that contained elements need not be unique. See the \n\t/// documentation for hash_set for details.\n\t///\n\ttemplate <typename Key, typename T, typename Hash = eastl::hash<Key>, typename Predicate = eastl::equal_to<Key>,\n\t\t\t  typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>\n\tclass hash_multimap\n\t\t: public hashtable<Key, eastl::pair<const Key, T>, Allocator, eastl::use_first<eastl::pair<const Key, T> >, Predicate,\n\t\t\t\t\t\t   Hash, mod_range_hashing, default_ranged_hash, prime_rehash_policy, bCacheHashCode, true, false>\n\t{\n\tpublic:\n\t\ttypedef hashtable<Key, eastl::pair<const Key, T>, Allocator, \n\t\t\t\t\t\t  eastl::use_first<eastl::pair<const Key, T> >, \n\t\t\t\t\t\t  Predicate, Hash, mod_range_hashing, default_ranged_hash, \n\t\t\t\t\t\t  prime_rehash_policy, bCacheHashCode, true, false>           base_type;\n\t\ttypedef hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>     this_type;\n\t\ttypedef typename base_type::size_type                                         size_type;\n\t\ttypedef typename base_type::key_type                                          key_type;\n\t\ttypedef T                                                                     mapped_type;\n\t\ttypedef typename base_type::value_type                                        value_type;     // Note that this is pair<const key_type, mapped_type>.\n\t\ttypedef typename base_type::allocator_type                                    allocator_type;\n\t\ttypedef typename base_type::node_type                                         node_type;\n\t\ttypedef typename base_type::insert_return_type                                insert_return_type;\n\t\ttypedef typename base_type::iterator                                          iterator;\n\n\t\tusing base_type::insert;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"hash_multimap<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"hash_multimap<T> value_type must be non-volatile.\");\n\n\tprivate:\n\t\tusing base_type::insert_or_assign;\n\n\tpublic:\n\t\t/// hash_multimap\n\t\t///\n\t\t/// Default constructor.\n\t\t///\n\t\texplicit hash_multimap(const allocator_type& allocator = EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(), \n\t\t\t\t\t\tPredicate(), eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\n\t\t/// hash_multimap\n\t\t///\n\t\t/// Constructor which creates an empty container, but start with nBucketCount buckets.\n\t\t/// We default to a small nBucketCount value, though the user really should manually \n\t\t/// specify an appropriate value in order to prevent memory from being reallocated.\n\t\t///\n\t\t/// note: difference in explicit keyword from the standard.\n\t\texplicit hash_multimap(size_type nBucketCount, const Hash& hashFunction = Hash(), \n\t\t\t\t\t\t\t   const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), \n\t\t\t\t\t\tpredicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_multimap(size_type nBucketCount, const allocator_type& allocator)\n\t\t// hash_multimap(size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\n\t\thash_multimap(const this_type& x)\n\t\t  : base_type(x)\n\t\t{\n\t\t}\n\n\t\t// hash_multimap(const this_type& x, const allocator_type& allocator)\n\n\n\t\thash_multimap(this_type&& x)\n\t\t  : base_type(eastl::move(x))\n\t\t{\n\t\t}\n\n\n\t\thash_multimap(this_type&& x, const allocator_type& allocator)\n\t\t  : base_type(eastl::move(x), allocator)\n\t\t{\n\t\t}\n\n\n\t\t/// hash_multimap\n\t\t///\n\t\t/// initializer_list-based constructor. \n\t\t/// Allows for initializing with brace values (e.g. hash_multimap<int, char*> hm = { {3,\"c\"}, {3,\"C\"}, {4,\"d\"} }; )\n\t\t///     \n\t\thash_multimap(std::initializer_list<value_type> ilist, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t   const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(ilist.begin(), ilist.end(), nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), \n\t\t\t\t\t\tpredicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\thash_multimap(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t\t: base_type(ilist.begin(), ilist.end(), 0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_multimap(std::initializer_list<value_type> ilist, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// hash_multimap(std::initializer_list<value_type> ilist, size_type nBucketCount, const Hash& hashFunction,\n\t\t// \tconst allocator_type& allocator)\n\n\n\t\t/// hash_multimap\n\t\t///\n\t\t/// An input bucket count of <= 1 causes the bucket count to be equal to the number of \n\t\t/// elements in the input range.\n\t\t///\n\t\ttemplate <typename ForwardIterator>\n\t\thash_multimap(ForwardIterator first, ForwardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t\t  const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTIMAP_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), \n\t\t\t\t\t\tpredicate, eastl::use_first<eastl::pair<const Key, T> >(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_multimap(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_multimap(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\t\tthis_type& operator=(const this_type& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(x));\n\t\t}\n\n\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(ilist));\n\t\t}\n\n\n\t\tthis_type& operator=(this_type&& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(eastl::move(x)));\n\t\t}\n\n\n\t\t/// insert\n\t\t///\n\t\t/// This is an extension to the C++ standard. We insert a default-constructed \n\t\t/// element with the given key. The reason for this is that we can avoid the \n\t\t/// potentially expensive operation of creating and/or copying a mapped_type\n\t\t/// object on the stack.\n\t\tinsert_return_type insert(const key_type& key)\n\t\t{\n\t\t\treturn base_type::DoInsertKey(false_type(), key);\n\t\t}\n\n\n\t\tinsert_return_type insert(key_type&& key)\n\t\t{\n\t\t\treturn base_type::DoInsertKey(false_type(), eastl::move(key));\n\t\t}\n\n\t\ttemplate <typename P, eastl::enable_if_t<eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tinsert_return_type insert(P&& otherValue)\n\t\t{\n\t\t\treturn base_type::emplace(eastl::forward<P>(otherValue));\n\t\t}\n\n\t}; // hash_multimap\n\n\t/// hash_multimap erase_if\n\t///\n\t/// https://en.cppreference.com/w/cpp/container/unordered_multimap/erase_if\n\ttemplate <typename Key, typename T, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode, typename UserPredicate>\n\ttypename eastl::hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::size_type erase_if(eastl::hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& c, UserPredicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\t// Erases all elements that satisfy the predicate from the container.\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator==(const hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\ttypedef typename hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::const_iterator const_iterator;\n\n\t\t// We implement branching with the assumption that the return value is usually false.\n\t\tif(a.size() != b.size())\n\t\t\treturn false;\n\n\t\t// For map (with its unique keys), we need only test that each element in a can be found in b,\n\t\t// as there can be only one such pairing per element. multimap needs to do a something more elaborate.\n\t\tfor(const_iterator ai = a.begin(), aiEnd = a.end(), biEnd = b.end(); ai != aiEnd; ++ai)\n\t\t{\n\t\t\tconst_iterator bi = b.find(ai->first);\n\n\t\t\tif((bi == biEnd) || !(*ai == *bi))  // We have to compare the values, because lookups are done by keys alone but the full value_type of a map is a key/value pair. \n\t\t\t\treturn false;                   // It's possible that two elements in the two containers have identical keys but different values.\n\t\t}\n\n\t\treturn true;\n\t}\n\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename Key, typename T, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator!=(const hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n#endif\n\n\ttemplate <typename Key, typename T, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator==(const hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\ttypedef typename hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>::const_iterator const_iterator;\n\t\ttypedef typename eastl::iterator_traits<const_iterator>::difference_type difference_type;\n\n\t\t// We implement branching with the assumption that the return value is usually false.\n\t\tif(a.size() != b.size())\n\t\t\treturn false;\n\n\t\t// We can't simply search for each element of a in b, as it may be that the bucket for \n\t\t// two elements in a has those same two elements in b but in different order (which should \n\t\t// still result in equality). Also it's possible that one bucket in a has two elements which \n\t\t// both match a solitary element in the equivalent bucket in b (which shouldn't result in equality).\n\t\teastl::pair<const_iterator, const_iterator> aRange;\n\t\teastl::pair<const_iterator, const_iterator> bRange;\n\n\t\tfor(const_iterator ai = a.begin(), aiEnd = a.end(); ai != aiEnd; ai = aRange.second) // For each element in a...\n\t\t{\n\t\t\taRange = a.equal_range(ai->first); // Get the range of elements in a that are equal to ai.\n\t\t\tbRange = b.equal_range(ai->first); // Get the range of elements in b that are equal to ai.\n\n\t\t\t// We need to verify that aRange == bRange. First make sure the range sizes are equivalent...\n\t\t\tconst difference_type aDistance = eastl::distance(aRange.first, aRange.second);\n\t\t\tconst difference_type bDistance = eastl::distance(bRange.first, bRange.second);\n\n\t\t\tif(aDistance != bDistance)\n\t\t\t\treturn false;\n\n\t\t\t// At this point, aDistance > 0 and aDistance == bDistance.\n\t\t\t// Implement a fast pathway for the case that there's just a single element.\n\t\t\tif(aDistance == 1)\n\t\t\t{\n\t\t\t\tif(!(*aRange.first == *bRange.first)) // We have to compare the values, because lookups are done by keys alone but the full value_type of a map is a key/value pair. \n\t\t\t\t\treturn false;                     // It's possible that two elements in the two containers have identical keys but different values. Ditto for the permutation case below.\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Check to see if these aRange and bRange are any permutation of each other. \n\t\t\t\t// This check gets slower as there are more elements in the range.\n\t\t\t\tif(!eastl::is_permutation(aRange.first, aRange.second, bRange.first))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename Key, typename T, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator!=(const hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n#endif\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/hash_set.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file is based on the TR1 (technical report 1) reference implementation\n// of the unordered_set/unordered_map C++ classes as of about 4/2005. Most likely\n// many or all C++ library vendors' implementations of this classes will be \n// based off of the reference version and so will look pretty similar to this\n// file as well as other vendors' versions. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_HASH_SET_H\n#define EASTL_HASH_SET_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/hashtable.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_HASH_SET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_HASH_SET_DEFAULT_NAME\n\t\t#define EASTL_HASH_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" hash_set\" // Unless the user overrides something, this is \"EASTL hash_set\".\n\t#endif\n\n\n\t/// EASTL_HASH_MULTISET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_HASH_MULTISET_DEFAULT_NAME\n\t\t#define EASTL_HASH_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" hash_multiset\" // Unless the user overrides something, this is \"EASTL hash_multiset\".\n\t#endif\n\n\n\t/// EASTL_HASH_SET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_HASH_SET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_HASH_SET_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_SET_DEFAULT_NAME)\n\t#endif\n\n\t/// EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR allocator_type(EASTL_HASH_MULTISET_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// hash_set\n\t///\n\t/// Implements a hash_set, which is a hashed unique-item container.\n\t/// Lookups are O(1) (that is, they are fast) but the container is \n\t/// not sorted. Note that lookups are only O(1) if the hash table\n\t/// is well-distributed (non-colliding). The lookup approaches\n\t/// O(n) behavior as the table becomes increasingly poorly distributed.\n\t///\n\t/// set_max_load_factor\n\t/// If you want to make a hashtable never increase its bucket usage,\n\t/// call set_max_load_factor with a very high value such as 100000.f.\n\t///\n\t/// bCacheHashCode\n\t/// We provide the boolean bCacheHashCode template parameter in order \n\t/// to allow the storing of the hash code of the key within the map. \n\t/// When this option is disabled, the rehashing of the table will \n\t/// call the hash function on the key. Setting bCacheHashCode to true \n\t/// is useful for cases whereby the calculation of the hash value for\n\t/// a contained object is very expensive.\n\t///\n\t/// Heterogeneous lookup, insertion and erasure\n\t/// See\n\t/// https://en.cppreference.com/w/cpp/utility/functional#Transparent_function_objects\n\t/// https://en.cppreference.com/w/cpp/utility/functional/less_void\n\t/// https://en.cppreference.com/w/cpp/container/unordered_set/find\n\t/// \n\t/// You can avoid creating key objects when calling member functions\n\t/// with a key_type parameter by declaring the container with a\n\t/// transparent hash and comparison type (eg. equal_to<void>) and\n\t/// passing objects to be passed to these function objects.\n\t/// \n\t/// This optimization is supported for member functions that take a\n\t/// key_type parameter, ie. heterogeneous lookup, insertion and erasure,\n\t/// not just find().\n\t/// \n\t/// Using transparent types is safer than using find_as because the\n\t/// latter requires the user specify hash and equality function objects\n\t/// which must have the same semantics as the container's hash and\n\t/// equality objects, otherwise the behaviour is undefined.\n\t/// \n\t/// find_as\n\t/// Note: Prefer heterogeneous lookup (see above).\n\t/// \n\t/// In order to support the ability to have a hashtable of strings but\n\t/// be able to do efficiently lookups via char pointers (i.e. so they \n\t/// aren't converted to string objects), we provide the find_as \n\t/// function. This function allows you to do a find with a key of a\n\t/// type other than the hashtable key type.\n\t///\n\t/// Example find_as usage:\n\t///     hash_set<string> hashSet;\n\t///     i = hashSet.find_as(\"hello\");    // Use default hash and compare.\n\t///\n\t/// Example find_as usage (namespaces omitted for brevity):\n\t///     hash_set<string> hashSet;\n\t///     i = hashSet.find_as(\"hello\", hash<char*>(), equal_to<>());\n\t///\n\ttemplate <typename Value, typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>, \n\t\t\t  typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>\n\tclass hash_set\n\t\t: public hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate,\n\t\t\t\t\t\t   Hash, mod_range_hashing, default_ranged_hash, \n\t\t\t\t\t\t   prime_rehash_policy, bCacheHashCode, false, true>\n\t{\n\tpublic:\n\t\ttypedef hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate, \n\t\t\t\t\t\t  Hash, mod_range_hashing, default_ranged_hash,\n\t\t\t\t\t\t  prime_rehash_policy, bCacheHashCode, false, true>       base_type;\n\t\ttypedef hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>       this_type;\n\t\ttypedef typename base_type::size_type                                     size_type;\n\t\ttypedef typename base_type::value_type                                    value_type;\n\t\ttypedef typename base_type::allocator_type                                allocator_type;\n\t\ttypedef typename base_type::node_type                                     node_type;\n\t\ttypedef typename base_type::iterator\t\t\t\t\t\t\t\t\t  iterator;\n\t\ttypedef typename base_type::const_iterator\t\t\t\t\t\t\t\t  const_iterator;\n\t\ttypedef typename base_type::insert_return_type\t\t\t\t\t\t\t  insert_return_type;\n\n\t\tusing base_type::insert;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"hash_set<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"hash_set<T> value_type must be non-volatile.\");\n\n\tpublic:\n\t\t/// hash_set\n\t\t///\n\t\t/// Default constructor.\n\t\t///\n\t\thash_set()\n\t\t\t: this_type(EASTL_HASH_SET_DEFAULT_ALLOCATOR)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\n\t\t/// hash_set\n\t\t///\n\t\t/// Constructor which creates an empty container with allocator.\n\t\t///\n\t\texplicit hash_set(const allocator_type& allocator)\n\t\t\t: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\n\t\t/// hash_set\n\t\t///\n\t\t/// Constructor which creates an empty container, but start with nBucketCount buckets.\n\t\t/// We default to a small nBucketCount value, though the user really should manually \n\t\t/// specify an appropriate value in order to prevent memory from being reallocated.\n\t\t///\n\t\t/// note: difference in explicit keyword from the standard.\n\t\texplicit hash_set(size_type nBucketCount, const Hash& hashFunction = Hash(), const Predicate& predicate = Predicate(), \n\t\t\t\t\t\t  const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_set(size_type nBucketCount, const allocator_type& allocator)\n\t\t// hash_set(size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\n\t\thash_set(const this_type& x)\n\t\t  : base_type(x)\n\t\t{\n\t\t}\n\n\t\t// hash_set(const this_type& x, const allocator_type& allocator)\n\n\n\t\thash_set(this_type&& x)\n\t\t  : base_type(eastl::move(x))\n\t\t{\n\t\t}\n\n\n\t\thash_set(this_type&& x, const allocator_type& allocator)\n\t\t  : base_type(eastl::move(x), allocator)\n\t\t{\n\t\t}\n\n\n\t\t/// hash_set\n\t\t///\n\t\t/// initializer_list-based constructor. \n\t\t/// Allows for initializing with brace values (e.g. hash_set<int> hs = { 3, 4, 5, }; )\n\t\t///     \n\t\thash_set(std::initializer_list<value_type> ilist, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t   const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(ilist.begin(), ilist.end(), nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\thash_set(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t\t: base_type(ilist.begin(), ilist.end(), 0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_set(std::initializer_list<value_type> ilist, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// hash_set(std::initializer_list<value_type> ilist, size_type nBucketCount, const Hash& hashFunction,\n\t\t// \tconst allocator_type& allocator)\n\n\n\t\t/// hash_set\n\t\t///\n\t\t/// An input bucket count of <= 1 causes the bucket count to be equal to the number of \n\t\t/// elements in the input range.\n\t\t///\n\t\ttemplate <typename FowardIterator>\n\t\thash_set(FowardIterator first, FowardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_set(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_set(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\n\t\tthis_type& operator=(const this_type& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(x));\n\t\t}\n\n\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(ilist));\n\t\t}\n\n\n\t\tthis_type& operator=(this_type&& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(eastl::move(x)));\n\t\t}\n\n\t\ttemplate<typename KX, typename HX = Hash, typename Pred = Predicate,\n\t\t\teastl::enable_if_t<eastl::detail::is_transparent_comparison_v<HX> && eastl::detail::is_transparent_comparison_v<Pred>, bool> = true>\n\t\tinsert_return_type insert(KX&& k)\n\t\t{\n\t\t\t// There's no function in the base type that we can re-use here. insert(value_type&&) is implemented in terms of DoInsertValue(), but that\n\t\t\t// unconditionally creates a node and therefore the key_type. So we create our own appropriate implementation.\n\n\t\t\tconst typename base_type::hash_code_t c = base_type::get_hash_code(k);\n\t\t\tconst size_type n = (size_type)base_type::bucket_index(k, c, (uint32_t)base_type::mnBucketCount);\n\n\t\t\tnode_type* const pNode = base_type::DoFindNode(base_type::mpBucketArray[n], k, c);\n\n\t\t\tif (!pNode)\n\t\t\t{\n\t\t\t\tnode_type* const pNodeNew = base_type::DoAllocateNode(eastl::forward<KX>(k));\n\t\t\t\treturn base_type::template DoInsertUniqueNode<true>(pNodeNew->mValue, c, n, pNodeNew);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn pair<iterator, bool>(iterator(pNode, base_type::mpBucketArray + n), false);\n\t\t\t}\n\t\t}\n\n\t\t// this function was incorrectly defined in the hashtable base type.\n\t\t// this function implicitly converts to value_type, which it shouldn't. Additionally, it does not correctly support heterogeneous insertion (unconditionally creates a key_type).\n\t\ttemplate <typename P, typename HX = Hash, typename Pred = Predicate,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<P&&, value_type> && !(eastl::detail::is_transparent_comparison_v<HX> && eastl::detail::is_transparent_comparison_v<Pred>) && eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Replace call with insert(value_type(...)) or emplace(...) or declare container with transparent hash and comparator.\")\n\t\tinsert_return_type insert(P&& otherValue)\n\t\t{\n\t\t\treturn base_type::emplace(eastl::forward<P>(otherValue));\n\t\t}\n\n\t}; // hash_set\n\n\t/// hash_set erase_if\n\t///\n\t/// https://en.cppreference.com/w/cpp/container/unordered_set/erase_if\n\ttemplate <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode, typename UserPredicate>\n\ttypename eastl::hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>::size_type erase_if(eastl::hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>& c, UserPredicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\t// Erases all elements that satisfy the predicate pred from the container.\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n\n\t/// hash_multiset\n\t///\n\t/// Implements a hash_multiset, which is the same thing as a hash_set \n\t/// except that contained elements need not be unique. See the documentation \n\t/// for hash_set for details.\n\t///\n\ttemplate <typename Value, typename Hash = eastl::hash<Value>, typename Predicate = eastl::equal_to<Value>, \n\t\t\t  typename Allocator = EASTLAllocatorType, bool bCacheHashCode = false>\n\tclass hash_multiset\n\t\t: public hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate,\n\t\t\t\t\t\t   Hash, mod_range_hashing, default_ranged_hash,\n\t\t\t\t\t\t   prime_rehash_policy, bCacheHashCode, false, false>\n\t{\n\tpublic:\n\t\ttypedef hashtable<Value, Value, Allocator, eastl::use_self<Value>, Predicate,\n\t\t\t\t\t\t  Hash, mod_range_hashing, default_ranged_hash,\n\t\t\t\t\t\t  prime_rehash_policy, bCacheHashCode, false, false>          base_type;\n\t\ttypedef hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>      this_type;\n\t\ttypedef typename base_type::size_type                                         size_type;\n\t\ttypedef typename base_type::value_type                                        value_type;\n\t\ttypedef typename base_type::allocator_type                                    allocator_type;\n\t\ttypedef typename base_type::node_type                                         node_type;\n\t\ttypedef typename base_type::insert_return_type\t\t\t\t\t\t\t\t  insert_return_type;\n\n\t\tusing base_type::insert;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"hash_multiset<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"hash_multiset<T> value_type must be non-volatile.\");\n\n\tpublic:\n\t\t/// hash_multiset\n\t\t///\n\t\t/// Default constructor.\n\t\t/// \n\t\texplicit hash_multiset(const allocator_type& allocator = EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\n\t\t/// hash_multiset\n\t\t///\n\t\t/// Constructor which creates an empty container, but start with nBucketCount buckets.\n\t\t/// We default to a small nBucketCount value, though the user really should manually \n\t\t/// specify an appropriate value in order to prevent memory from being reallocated.\n\t\t///\n\t\t/// note: difference in explicit keyword from the standard.\n\t\texplicit hash_multiset(size_type nBucketCount, const Hash& hashFunction = Hash(), \n\t\t\t\t\t\t\t   const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_multiset(size_type nBucketCount, const allocator_type& allocator)\n\t\t// hash_multiset(size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\n\t\thash_multiset(const this_type& x)\n\t\t  : base_type(x)\n\t\t{\n\t\t}\n\n\t\t// hash_multiset(const this_type& x, const allocator_type& allocator)\n\n\n\t\thash_multiset(this_type&& x)\n\t\t  : base_type(eastl::move(x))\n\t\t{\n\t\t}\n\n\n\t\thash_multiset(this_type&& x, const allocator_type& allocator)\n\t\t  : base_type(eastl::move(x), allocator)\n\t\t{\n\t\t}\n\n\n\t\t/// hash_multiset\n\t\t///\n\t\t/// initializer_list-based constructor. \n\t\t/// Allows for initializing with brace values (e.g. hash_set<int> hs = { 3, 3, 4, }; )\n\t\t///     \n\t\thash_multiset(std::initializer_list<value_type> ilist, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t   const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(ilist.begin(), ilist.end(), nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\thash_multiset(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t\t: base_type(ilist.begin(), ilist.end(), 0, Hash(), mod_range_hashing(), default_ranged_hash(), Predicate(), eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// hash_multiset(std::initializer_list<value_type> ilist, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// hash_multiset(std::initializer_list<value_type> ilist, size_type nBucketCount, const Hash& hashFunction,\n\t\t// \tconst allocator_type& allocator)\n\n\n\t\t/// hash_multiset\n\t\t///\n\t\t/// An input bucket count of <= 1 causes the bucket count to be equal to the number of \n\t\t/// elements in the input range.\n\t\t///\n\t\ttemplate <typename FowardIterator>\n\t\thash_multiset(FowardIterator first, FowardIterator last, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t\t\t\t  const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MULTISET_DEFAULT_ALLOCATOR)\n\t\t\t: base_type(first, last, nBucketCount, hashFunction, mod_range_hashing(), default_ranged_hash(), predicate, eastl::use_self<Value>(), allocator)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_multiset(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const allocator_type& allocator)\n\n\t\t// template <typename ForwardIterator>\n\t\t// hash_multiset(ForwardIterator first, ForwardIterator last, size_type nBucketCount, const Hash& hashFunction, const allocator_type& allocator)\n\n\n\t\tthis_type& operator=(const this_type& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(x));\n\t\t}\n\n\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(ilist));\n\t\t}\n\n\n\t\tthis_type& operator=(this_type&& x)\n\t\t{\n\t\t\treturn static_cast<this_type&>(base_type::operator=(eastl::move(x)));\n\t\t}\n\n\t\t// this function was incorrectly defined in the hashtable base type.\n\t\t// this function implicitly converts to value_type, which it shouldn't.\n\t\ttemplate <typename P, eastl::enable_if_t<!eastl::is_convertible_v<P&&, value_type> && eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Replace call with insert(value_type(...)) or emplace(...).\")\n\t\tinsert_return_type insert(P&& otherValue)\n\t\t{\n\t\t\treturn base_type::emplace(eastl::forward<P>(otherValue));\n\t\t}\n\n\t}; // hash_multiset\n\n\t/// hash_multiset erase_if\n\t///\n\t/// https://en.cppreference.com/w/cpp/container/unordered_multiset/erase_if\n\ttemplate <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode, typename UserPredicate>\n\ttypename eastl::hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>::size_type erase_if(eastl::hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>& c, UserPredicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\t// Erases all elements that satisfy the predicate pred from the container.\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator==(const hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\ttypedef typename hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>::const_iterator const_iterator;\n\n\t\t// We implement branching with the assumption that the return value is usually false.\n\t\tif(a.size() != b.size())\n\t\t\treturn false;\n\n\t\t// For set (with its unique keys), we need only test that each element in a can be found in b,\n\t\t// as there can be only one such pairing per element. multiset needs to do a something more elaborate.\n\t\tfor(const_iterator ai = a.begin(), aiEnd = a.end(), biEnd = b.end(); ai != aiEnd; ++ai)\n\t\t{\n\t\t\tconst_iterator bi = b.find(*ai);\n\n\t\t\tif((bi == biEnd) || !(*ai == *bi)) // We have to compare values in addition to making sure the lookups succeeded. This is because the lookup is done via the user-supplised Predicate\n\t\t\t\treturn false;                  // which isn't strictly required to be identical to the Value operator==, though 99% of the time it will be so.  \n\t\t}\n\n\t\treturn true;\n\t}\n\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator!=(const hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n#endif\n\n\ttemplate <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator==(const hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\ttypedef typename hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>::const_iterator const_iterator;\n\t\ttypedef typename eastl::iterator_traits<const_iterator>::difference_type difference_type;\n\n\t\t// We implement branching with the assumption that the return value is usually false.\n\t\tif(a.size() != b.size())\n\t\t\treturn false;\n\n\t\t// We can't simply search for each element of a in b, as it may be that the bucket for \n\t\t// two elements in a has those same two elements in b but in different order (which should \n\t\t// still result in equality). Also it's possible that one bucket in a has two elements which \n\t\t// both match a solitary element in the equivalent bucket in b (which shouldn't result in equality).\n\t\teastl::pair<const_iterator, const_iterator> aRange;\n\t\teastl::pair<const_iterator, const_iterator> bRange;\n\n\t\tfor(const_iterator ai = a.begin(), aiEnd = a.end(); ai != aiEnd; ai = aRange.second) // For each element in a...\n\t\t{\n\t\t\taRange = a.equal_range(*ai); // Get the range of elements in a that are equal to ai.\n\t\t\tbRange = b.equal_range(*ai); // Get the range of elements in b that are equal to ai.\n\n\t\t\t// We need to verify that aRange == bRange. First make sure the range sizes are equivalent...\n\t\t\tconst difference_type aDistance = eastl::distance(aRange.first, aRange.second);\n\t\t\tconst difference_type bDistance = eastl::distance(bRange.first, bRange.second);\n\n\t\t\tif(aDistance != bDistance)\n\t\t\t\treturn false;\n\n\t\t\t// At this point, aDistance > 0 and aDistance == bDistance.\n\t\t\t// Implement a fast pathway for the case that there's just a single element.\n\t\t\tif(aDistance == 1)\n\t\t\t{\n\t\t\t\tif(!(*aRange.first == *bRange.first))   // We have to compare values in addition to making sure the distance (element count) was equal. This is because the lookup is done via the user-supplised Predicate\n\t\t\t\t\treturn false;                       // which isn't strictly required to be identical to the Value operator==, though 99% of the time it will be so. Ditto for the is_permutation usage below.\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Check to see if these aRange and bRange are any permutation of each other. \n\t\t\t\t// This check gets slower as there are more elements in the range.\n\t\t\t\tif(!eastl::is_permutation(aRange.first, aRange.second, bRange.first))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode>\n\tinline bool operator!=(const hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>& a, \n\t\t\t\t\t\t   const hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n#endif\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/heap.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements heap functionality much like the std C++ heap algorithms.\n// Such heaps are not the same thing as memory heaps or pools, but rather are\n// semi-sorted random access containers which have the primary purpose of \n// supporting the implementation of priority_queue and similar data structures.\n// \n// The primary distinctions between this heap functionality and std::heap are:\n//    - This heap exposes some extra functionality such as is_heap and change_heap.\n//    - This heap is more efficient than versions found in typical STL \n//      implementations such as STLPort, Microsoft, and Metrowerks. This comes\n//      about due to better use of array dereferencing and branch prediction.\n//      You should expect of 5-30%, depending on the usage and platform.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// The publicly usable functions we define are:\n//    push_heap     -- Adds an entry to a heap.                             Same as C++ std::push_heap.\n//    pop_heap      -- Removes the top entry from a heap.                   Same as C++ std::pop_heap.\n//    make_heap     -- Converts an array to a heap.                         Same as C++ std::make_heap.\n//    sort_heap     -- Sorts a heap in place.                               Same as C++ std::sort_heap.\n//    remove_heap   -- Removes an arbitrary entry from a heap.\n//    change_heap   -- Changes the priority of an entry in the heap.\n//    is_heap       -- Returns true if an array appears is in heap format.   Same as C++11 std::is_heap.\n//    is_heap_until -- Returns largest part of the range which is a heap.    Same as C++11 std::is_heap_until.\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef EASTL_HEAP_H\n#define EASTL_HEAP_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////\n\t// promote_heap (internal function)\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename ValueType>\n\tinline void promote_heap_impl(RandomAccessIterator first, Distance topPosition, Distance position, T value)\n\t{\n\t\tfor(Distance parentPosition = (position - 1) >> 1; // This formula assumes that (position > 0). // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.\n\t\t\t(position > topPosition) && (*(first + parentPosition) < value);\n\t\t\tparentPosition = (position - 1) >> 1)\n\t\t{\n\t\t\t*(first + position) = eastl::forward<ValueType>(*(first + parentPosition)); // Swap the node with its parent.\n\t\t\tposition = parentPosition;\n\t\t}\n\n\t\t*(first + position) = eastl::forward<ValueType>(value);\n\t}\n\n\t/// promote_heap\n\t///\n\t/// Moves a value in the heap from a given position upward until \n\t/// it is sorted correctly. It's kind of like bubble-sort, except that\n\t/// instead of moving linearly from the back of a list to the front,\n\t/// it moves from the bottom of the tree up the branches towards the\n\t/// top. But otherwise is just like bubble-sort.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T>\n\tinline void promote_heap(RandomAccessIterator first, Distance topPosition, Distance position, const T& value)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tpromote_heap_impl<RandomAccessIterator, Distance, const T&, const value_type>(first, topPosition, position, value);\n\t}\n\n\n\t/// promote_heap\n\t///\n\t/// Moves a value in the heap from a given position upward until \n\t/// it is sorted correctly. It's kind of like bubble-sort, except that\n\t/// instead of moving linearly from the back of a list to the front,\n\t/// it moves from the bottom of the tree up the branches towards the\n\t/// top. But otherwise is just like bubble-sort.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T>\n\tinline void promote_heap(RandomAccessIterator first, Distance topPosition, Distance position, T&& value)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tpromote_heap_impl<RandomAccessIterator, Distance, T&&, value_type>(first, topPosition, position, eastl::forward<T>(value));\n\t}\n\n\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename Compare, typename ValueType>\n\tinline void promote_heap_impl(RandomAccessIterator first, Distance topPosition, Distance position, T value, Compare compare)\n\t{\n\t\tfor(Distance parentPosition = (position - 1) >> 1; // This formula assumes that (position > 0). // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.\n\t\t\t(position > topPosition) && compare(*(first + parentPosition), value);\n\t\t\tparentPosition = (position - 1) >> 1)\n\t\t{\n\t\t\t*(first + position) = eastl::forward<ValueType>(*(first + parentPosition)); // Swap the node with its parent.\n\t\t\tposition = parentPosition;\n\t\t}\n\n\t\t*(first + position) = eastl::forward<ValueType>(value);\n\t}\n\n\n\t/// promote_heap\n\t///\n\t/// Takes a Compare(a, b) function (or function object) which returns true if a < b.\n\t/// For example, you could use the standard 'less' comparison object.\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename Compare>\n\tinline void promote_heap(RandomAccessIterator first, Distance topPosition, Distance position, const T& value, Compare compare)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tpromote_heap_impl<RandomAccessIterator, Distance, const T&, Compare, const value_type>(first, topPosition, position, value, compare);\n\t}\n\n\n\t/// promote_heap\n\t///\n\t/// Takes a Compare(a, b) function (or function object) which returns true if a < b.\n\t/// For example, you could use the standard 'less' comparison object.\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename Compare>\n\tinline void promote_heap(RandomAccessIterator first, Distance topPosition, Distance position, T&& value, Compare compare)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tpromote_heap_impl<RandomAccessIterator, Distance, T&&, Compare, value_type>(first, topPosition, position, eastl::forward<T>(value), compare);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// adjust_heap (internal function)\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename ValueType>\n\tvoid adjust_heap_impl(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, T value)\n\t{\n\t\t// We do the conventional approach of moving the position down to the \n\t\t// bottom then inserting the value at the back and moving it up.\n\t\tDistance childPosition = (2 * position) + 2;\n\n\t\tfor(; childPosition < heapSize; childPosition = (2 * childPosition) + 2)\n\t\t{\n\t\t\tif(*(first + childPosition) < *(first + (childPosition - 1))) // Choose the larger of the two children.\n\t\t\t\t--childPosition;\n\t\t\t*(first + position) = eastl::forward<ValueType>(*(first + childPosition)); // Swap positions with this child.\n\t\t\tposition = childPosition;\n\t\t}\n\n\t\tif(childPosition == heapSize) // If we are at the very last index of the bottom...\n\t\t{\n\t\t\t*(first + position) = eastl::forward<ValueType>(*(first + (childPosition - 1)));\n\t\t\tposition = childPosition - 1;\n\t\t}\n\n\t\teastl::promote_heap<RandomAccessIterator, Distance, T>(first, topPosition, position, eastl::forward<ValueType>(value));\n\t}\n\n\t/// adjust_heap\n\t///\n\t/// Given a position that has just been vacated, this function moves\n\t/// new values into that vacated position appropriately. The value\n\t/// argument is an entry which will be inserted into the heap after\n\t/// we move nodes into the positions that were vacated.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T>\n\tvoid adjust_heap(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, const T& value)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tadjust_heap_impl<RandomAccessIterator, Distance, const T&, const value_type>(first, topPosition, heapSize, position, eastl::forward<const T&>(value));\n\t}\n\n\n\t/// adjust_heap\n\t///\n\t/// Given a position that has just been vacated, this function moves\n\t/// new values into that vacated position appropriately. The value\n\t/// argument is an entry which will be inserted into the heap after\n\t/// we move nodes into the positions that were vacated.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T>\n\tvoid adjust_heap(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, T&& value)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tadjust_heap_impl<RandomAccessIterator, Distance, T&&, value_type>(first, topPosition, heapSize, position, eastl::forward<T>(value));\n\t}\n\n\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename Compare, typename ValueType>\n\tvoid adjust_heap_impl(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, T value, Compare compare)\n\t{\n\t\t// We do the conventional approach of moving the position down to the \n\t\t// bottom then inserting the value at the back and moving it up.\n\t\tDistance childPosition = (2 * position) + 2;\n\n\t\tfor(; childPosition < heapSize; childPosition = (2 * childPosition) + 2)\n\t\t{\n\t\t\tif(compare(*(first + childPosition), *(first + (childPosition - 1)))) // Choose the larger of the two children.\n\t\t\t\t--childPosition;\n\t\t\t*(first + position) = eastl::forward<ValueType>(*(first + childPosition)); // Swap positions with this child.\n\t\t\tposition = childPosition;\n\t\t}\n\n\t\tif(childPosition == heapSize) // If we are at the bottom...\n\t\t{\n\t\t\t*(first + position) = eastl::forward<ValueType>(*(first + (childPosition - 1)));\n\t\t\tposition = childPosition - 1;\n\t\t}\n\n\t\teastl::promote_heap<RandomAccessIterator, Distance, T, Compare>(first, topPosition, position, eastl::forward<ValueType>(value), compare);\n\t}\n\n\t/// adjust_heap\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename Compare>\n\tvoid adjust_heap(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, const T& value, Compare compare)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tadjust_heap_impl<RandomAccessIterator, Distance, const T&, Compare, const value_type>(first, topPosition, heapSize, position, eastl::forward<const T&>(value), compare);\n\t}\n\n\n\t/// adjust_heap\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\t/// This function requires that the value argument refer to a value\n\t/// that is currently not within the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename T, typename Compare>\n\tvoid adjust_heap(RandomAccessIterator first, Distance topPosition, Distance heapSize, Distance position, T&& value, Compare compare)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\t\tadjust_heap_impl<RandomAccessIterator, Distance, T&&, Compare, value_type>(first, topPosition, heapSize, position, eastl::forward<T>(value), compare);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// push_heap\n\t///////////////////////////////////////////////////////////////////////\n\n\t/// push_heap\n\t///\n\t/// Adds an item to a heap (which is an array). The item necessarily\n\t/// comes from the back of the heap (array). Thus, the insertion of a \n\t/// new item in a heap is a two step process: push_back and push_heap.\n\t///\n\t/// Example usage:\n\t///    vector<int> heap;\n\t///    \n\t///    heap.push_back(3);\n\t///    push_heap(heap.begin(), heap.end()); // Places '3' appropriately.\n\t///\n\ttemplate <typename RandomAccessIterator>\n\tinline void push_heap(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tconst value_type tempBottom(eastl::forward<value_type>(*(last - 1)));\n\n\t\teastl::promote_heap<RandomAccessIterator, difference_type, value_type>\n\t\t\t\t\t\t   (first, (difference_type)0, (difference_type)(last - first - 1), eastl::forward<const value_type>(tempBottom));\n\t}\n\n\n\t/// push_heap\n\t///\n\t/// This version is useful for cases where your object comparison is unusual \n\t/// or where you want to have the heap store pointers to objects instead of \n\t/// storing the objects themselves (often in order to improve cache coherency\n\t/// while doing sorting).\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tinline void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tconst value_type tempBottom(*(last - 1));\n\n\t\teastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>\n\t\t\t\t\t\t   (first, (difference_type)0, (difference_type)(last - first - 1), tempBottom, compare);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// pop_heap\n\t///////////////////////////////////////////////////////////////////////\n\n\t/// pop_heap\n\t///\n\t/// Removes the first item from the heap (which is an array), and adjusts\n\t/// the heap so that the highest priority item becomes the new first item.\n\t///\n\t/// Example usage:\n\t///    vector<int> heap;\n\t///    \n\t///    heap.push_back(2);\n\t///    heap.push_back(3);\n\t///    heap.push_back(1);\n\t///    <use heap[0], which is the highest priority item in the heap>\n\t///    pop_heap(heap.begin(), heap.end());  // Moves heap[0] to the back of the heap and adjusts the heap.\n\t///    heap.pop_back();                     // Remove value that was just at the top of the heap\n\t///\n\ttemplate <typename RandomAccessIterator>\n\tinline void pop_heap(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tvalue_type tempBottom(eastl::forward<value_type>(*(last - 1)));\n\t\t*(last - 1) = eastl::forward<value_type>(*first);\n\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type>\n\t\t\t\t\t\t  (first, (difference_type)0, (difference_type)(last - first - 1), 0, eastl::forward<value_type>(tempBottom));\n\t}\n\n\n\n\t/// pop_heap\n\t///\n\t/// This version is useful for cases where your object comparison is unusual \n\t/// or where you want to have the heap store pointers to objects instead of \n\t/// storing the objects themselves (often in order to improve cache coherency\n\t/// while doing sorting).\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tinline void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tvalue_type tempBottom(eastl::forward<value_type>(*(last - 1)));\n\t\t*(last - 1) = eastl::forward<value_type>(*first);\n\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>\n\t\t\t\t\t\t  (first, (difference_type)0, (difference_type)(last - first - 1), 0, eastl::forward<value_type>(tempBottom), compare);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// make_heap\n\t///////////////////////////////////////////////////////////////////////\n\n\n\t/// make_heap\n\t///\n\t/// Given an array, this function converts it into heap format.\n\t/// The complexity is O(n), where n is count of the range.\n\t/// The input range is not required to be in any order.\n\t///\n\ttemplate <typename RandomAccessIterator>\n\tvoid make_heap(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\t// We do bottom-up heap construction as per Sedgewick. Such construction is O(n).\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tconst difference_type heapSize = last - first;\n\n\t\tif(heapSize >= 2) // If there is anything to do... (we need this check because otherwise the math fails below).\n\t\t{\n\t\t\tdifference_type parentPosition = ((heapSize - 2) >> 1) + 1; // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.\n\n\t\t\tdo{\n\t\t\t\t--parentPosition;\n\t\t\t\tvalue_type temp(eastl::forward<value_type>(*(first + parentPosition)));\n\t\t\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type>\n\t\t\t\t\t\t\t\t  (first, parentPosition, heapSize, parentPosition, eastl::forward<value_type>(temp));\n\t\t\t} while(parentPosition != 0);\n\t\t}\n\t}\n\n\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tvoid make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tconst difference_type heapSize = last - first;\n\n\t\tif(heapSize >= 2) // If there is anything to do... (we need this check because otherwise the math fails below).\n\t\t{\n\t\t\tdifference_type parentPosition = ((heapSize - 2) >> 1) + 1; // We use '>> 1' instead of '/ 2' because we have seen VC++ generate better code with >>.\n\n\t\t\tdo{\n\t\t\t\t--parentPosition;\n\t\t\t\tvalue_type temp(eastl::forward<value_type>(*(first + parentPosition)));\n\t\t\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>\n\t\t\t\t\t\t\t\t  (first, parentPosition, heapSize, parentPosition, eastl::forward<value_type>(temp), compare);\n\t\t\t} while(parentPosition != 0);\n\t\t}\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// sort_heap\n\t///////////////////////////////////////////////////////////////////////\n\n\t/// sort_heap\n\t///\n\t/// After the application if this algorithm, the range it was applied to \n\t/// is no longer a heap, though it will be a reverse heap (smallest first).\n\t/// The item with the lowest priority will be first, and the highest last.\n\t/// This is not a stable sort because the relative order of equivalent \n\t/// elements is not necessarily preserved.\n\t/// The range referenced must be valid; all pointers must be dereferenceable \n\t/// and within the sequence the last position is reachable from the first \n\t/// by incrementation.\n\t/// The complexity is at most O(n * log(n)), where n is count of the range.\n\t///\n\ttemplate <typename RandomAccessIterator>\n\tinline void sort_heap(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\tfor(; (last - first) > 1; --last) // We simply use the heap to sort itself.\n\t\t\teastl::pop_heap<RandomAccessIterator>(first, last);\n\t}\n\n\n\t/// sort_heap\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tinline void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\tfor(; (last - first) > 1; --last) // We simply use the heap to sort itself.\n\t\t\teastl::pop_heap<RandomAccessIterator, Compare>(first, last, compare);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_heap\n\t///////////////////////////////////////////////////////////////////////\n\n\t/// remove_heap\n\t///\n\t/// Removes an arbitrary entry from the heap and adjusts the heap appropriately.\n\t/// This function is unlike pop_heap in that pop_heap moves the top item\n\t/// to the back of the heap, whereas remove_heap moves an arbitrary item to\n\t/// the back of the heap.\n\t///\n\t/// Note: Since this function moves the element to the back of the heap and \n\t/// doesn't actually remove it from the given container, the user must call\n\t/// the container erase function if the user wants to erase the element \n\t/// from the container.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance>\n\tinline void remove_heap(RandomAccessIterator first, Distance heapSize, Distance position)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tconst value_type tempBottom(*(first + heapSize - 1));\n\t\t*(first + heapSize - 1) = *(first + position);\n\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type>\n\t\t\t\t\t\t  (first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position, tempBottom);\n\t}\n\n\n\t/// remove_heap\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\t/// Note: Since this function moves the element to the back of the heap and \n\t/// doesn't actually remove it from the given container, the user must call\n\t/// the container erase function if the user wants to erase the element \n\t/// from the container.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename Compare>\n\tinline void remove_heap(RandomAccessIterator first, Distance heapSize, Distance position, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tconst value_type tempBottom(*(first + heapSize - 1));\n\t\t*(first + heapSize - 1) = *(first + position);\n\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>\n\t\t\t\t\t\t  (first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position, tempBottom, compare);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// change_heap\n\t///////////////////////////////////////////////////////////////////////\n\n\t/// change_heap\n\t///\n\t/// Given a value in the heap that has changed in priority, this function\n\t/// adjusts the heap appropriately. The heap size remains unchanged after\n\t/// this operation. \n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance>\n\tinline void change_heap(RandomAccessIterator first, Distance heapSize, Distance position)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\teastl::remove_heap<RandomAccessIterator, Distance>(first, heapSize, position);\n\n\t\tvalue_type tempBottom(*(first + heapSize - 1));\n\n\t\teastl::promote_heap<RandomAccessIterator, difference_type, value_type>\n\t\t\t\t\t\t   (first, (difference_type)0, (difference_type)(heapSize - 1), tempBottom);\n\t}\n\n\n\t/// change_heap\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Distance, typename Compare>\n\tinline void change_heap(RandomAccessIterator first, Distance heapSize, Distance position, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\teastl::remove_heap<RandomAccessIterator, Distance, Compare>(first, heapSize, position, compare);\n\n\t\tvalue_type tempBottom(*(first + heapSize - 1));\n\n\t\teastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>\n\t\t\t\t\t\t   (first, (difference_type)0, (difference_type)(heapSize - 1), tempBottom, compare);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_heap_until\n\t///////////////////////////////////////////////////////////////////////\n\n\t/// is_heap_until\n\t///\n\ttemplate <typename RandomAccessIterator>\n\tinline RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\tint counter = 0;\n\n\t\tfor(RandomAccessIterator child = first + 1; child < last; ++child, counter ^= 1)\n\t\t{\n\t\t\tif(*first < *child)  // We must use operator <, and are not allowed to use > or >= here.\n\t\t\t\treturn child;\n\t\t\tfirst += counter; // counter switches between 0 and 1 every time through.\n\t\t}\n\n\t\treturn last;\n\t}\n\n\n\t/// is_heap_until\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tinline RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\tint counter = 0;\n\n\t\tfor(RandomAccessIterator child = first + 1; child < last; ++child, counter ^= 1)\n\t\t{\n\t\t\tif(compare(*first, *child))\n\t\t\t\treturn child;\n\t\t\tfirst += counter; // counter switches between 0 and 1 every time through.\n\t\t}\n\n\t\treturn last;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_heap\n\t///////////////////////////////////////////////////////////////////////\n\n\t/// is_heap\n\t///\n\t/// This is a useful debugging algorithm for verifying that a random  \n\t/// access container is in heap format. \n\t///\n\ttemplate <typename RandomAccessIterator>\n\tinline bool is_heap(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\treturn (eastl::is_heap_until(first, last) == last);\n\t}\n\n\n\t/// is_heap\n\t///\n\t/// The Compare function must work equivalently to the compare function used\n\t/// to make and maintain the heap.\n\t///\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tinline bool is_heap(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\treturn (eastl::is_heap_until(first, last, compare) == last);\n\t}\n\n\n\t// To consider: The following may be a faster implementation for most cases.\n\t//\n\t// template <typename RandomAccessIterator>\n\t// inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last)\n\t// {\n\t//     if(((uintptr_t)(last - first) & 1) == 0) // If the range has an even number of elements...\n\t//         --last;\n\t// \n\t//     RandomAccessIterator parent = first, child = (first + 1);\n\t// \n\t//     for(; child < last; child += 2, ++parent)\n\t//     {\n\t//         if((*parent < *child) || (*parent < *(child + 1)))\n\t//             return false;\n\t//     }\n\t// \n\t//     if((((uintptr_t)(last - first) & 1) == 0) && (*parent < *child))\n\t//         return false;\n\t// \n\t//     return true;\n\t// }\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/initializer_list.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//\n// This file #includes <initializer_list> if it's available, else it defines \n// its own version of std::initializer_list. It does not define eastl::initializer_list\n// because that would not provide any use, due to how the C++11 Standard works.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INITIALIZER_LIST_H\n#define EASTL_INITIALIZER_LIST_H\n\n\n#include <EASTL/internal/config.h>\n#include <EABase/eahave.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n#if defined(EA_HAVE_CPP11_INITIALIZER_LIST) // If the compiler can generate calls to std::initializer_list...\n\n\t// The initializer_list type must be declared in the std namespace, as that's the \n\t// namespace the compiler uses when generating code to use it.\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <initializer_list>\n\tEA_RESTORE_ALL_VC_WARNINGS()\n\n#else\n\n\t// If you get an error here about initializer_list being already defined, then the EA_HAVE_CPP11_INITIALIZER_LIST define from <EABase/eahave.h> needs to be updated.\n\tnamespace std\n\t{\n\t\t// See the C++11 Standard, section 18.9.\n\t\ttemplate<class E> \n\t\tclass initializer_list\n\t\t{\n\t\tpublic:\n\t\t\ttypedef E         value_type;\n\t\t\ttypedef const E&  reference;\n\t\t\ttypedef const E&  const_reference;\n\t\t\ttypedef size_t    size_type;\n\t\t\ttypedef const E*  iterator;             // Must be const, as initializer_list (and its mpArray) is an immutable temp object.\n\t\t\ttypedef const E*  const_iterator;\n\n\t\tprivate:\n\t\t\titerator  mpArray;\n\t\t\tsize_type mArraySize;\n\n\t\t\t// This constructor is private, but the C++ compiler has the ability to call it, as per the C++11 Standard.\n\t\t\tinitializer_list(const_iterator pArray, size_type arraySize)\n\t\t\t  : mpArray(pArray), mArraySize(arraySize) { }\n\n\t\tpublic:\n\t\t\tinitializer_list() EA_NOEXCEPT  // EA_NOEXCEPT requires a recent version of EABase.  \n\t\t\t  : mpArray(NULL), mArraySize(0) { }\n\n#if defined(EA_COMPILER_MSVC)\n\t\t\t// MSVC generates constructor calls with two pointers instead of one pointer + size. The constructor is\n\t\t\t// public.\n\t\t\t// See: https://docs.microsoft.com/en-us/cpp/standard-library/initializer-list-class#initializer_list\n\t\t\tinitializer_list(const_iterator pFirst, const_iterator pLast) EA_NOEXCEPT\n\t\t\t  : mpArray(pFirst), mArraySize(pLast - pFirst) { }\n#endif\n\n\t\t\tsize_type      size()  const EA_NOEXCEPT { return mArraySize; }\n\t\t\tconst_iterator begin() const EA_NOEXCEPT { return mpArray; }            // Must be const_iterator, as initializer_list (and its mpArray) is an immutable temp object.\n\t\t\tconst_iterator end()   const EA_NOEXCEPT { return mpArray + mArraySize; }\n\t\t};\n\n\n\t\ttemplate<class T>\n\t\tconst T* begin(std::initializer_list<T> ilist) EA_NOEXCEPT\n\t\t{\n\t\t\treturn ilist.begin();\n\t\t}\n\n\t\ttemplate<class T>\n\t\tconst T* end(std::initializer_list<T> ilist) EA_NOEXCEPT\n\t\t{\n\t\t\treturn ilist.end();\n\t\t}\n\t}\n\n#endif\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// Include the architecture specific implementations\n//\n#if defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64)\n\n\t#include \"x86/arch_x86.h\"\n\n#elif defined(EA_PROCESSOR_ARM32) || defined(EA_PROCESSOR_ARM64)\n\n\t#include \"arm/arch_arm.h\"\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include \"arch_fetch_add.h\"\n#include \"arch_fetch_sub.h\"\n\n#include \"arch_fetch_and.h\"\n#include \"arch_fetch_xor.h\"\n#include \"arch_fetch_or.h\"\n\n#include \"arch_add_fetch.h\"\n#include \"arch_sub_fetch.h\"\n\n#include \"arch_and_fetch.h\"\n#include \"arch_xor_fetch.h\"\n#include \"arch_or_fetch.h\"\n\n#include \"arch_exchange.h\"\n\n#include \"arch_cmpxchg_weak.h\"\n#include \"arch_cmpxchg_strong.h\"\n\n#include \"arch_load.h\"\n#include \"arch_store.h\"\n\n#include \"arch_compiler_barrier.h\"\n\n#include \"arch_cpu_pause.h\"\n\n#include \"arch_memory_barrier.h\"\n\n#include \"arch_signal_fence.h\"\n\n#include \"arch_thread_fence.h\"\n\n#include \"arch_acquire_fence.h\"\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_acquire_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n#pragma once\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_ACQUIRE_FENCE()\n//\n#if defined(EASTL_ARCH_ATOMIC_ACQUIRE_FENCE)\n\t#define EASTL_ARCH_ATOMIC_ACQUIRE_FENCE_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ACQUIRE_FENCE_AVAILABLE 0\n#endif\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_add_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_ADD_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_ADD_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_ADD_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_ADD_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_and_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_AND_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_AND_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_AND_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_AND_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_cmpxchg_strong.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_CMPXCHG_STRONG_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_CMPXCHG_STRONG_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_8_AVAILABLE\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_16_AVAILABLE\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_32_AVAILABLE\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_CMPXCHG_STRONG_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_cmpxchg_weak.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_CMPXCHG_WEAK_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_CMPXCHG_WEAK_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_8_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_16_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_32_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_64_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_128_AVAILABLE\t\t\\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128_AVAILABLE\n#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_CMPXCHG_WEAK_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_compiler_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_COMPILER_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_COMPILER_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_ARCH_ATOMIC_COMPILER_BARRIER_AVAILABLE 0\n\n#define EASTL_ARCH_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY_AVAILABLE 0\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_COMPILER_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_cpu_pause.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// copyright (c) electronic arts inc. all rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_CPU_PAUSE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_CPU_PAUSE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_PAUSE()\n//\n#if defined(EASTL_ARCH_ATOMIC_CPU_PAUSE)\n\t#define EASTL_ARCH_ATOMIC_CPU_PAUSE_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CPU_PAUSE_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_CPU_PAUSE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_exchange.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_EXCHANGE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_EXCHANGE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_EXCHANGE_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_EXCHANGE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_fetch_add.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_FETCH_ADD_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_FETCH_ADD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_ADD_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_FETCH_ADD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_fetch_and.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_FETCH_AND_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_FETCH_AND_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_AND_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_FETCH_AND_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_fetch_or.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_FETCH_OR_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_FETCH_OR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_OR_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_FETCH_OR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_fetch_sub.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_FETCH_SUB_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_FETCH_SUB_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_SUB_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_FETCH_SUB_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_fetch_xor.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_FETCH_XOR_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_FETCH_XOR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_XOR_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_FETCH_XOR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_load.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_LOAD_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_LOAD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_LOAD_*_N(type, type ret, type * ptr)\n//\n#if defined(EASTL_ARCH_ATOMIC_LOAD_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_LOAD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_memory_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_MEMORY_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_MEMORY_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_MB()\n//\n#if defined(EASTL_ARCH_ATOMIC_CPU_MB)\n\t#define EASTL_ARCH_ATOMIC_CPU_MB_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CPU_MB_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_WMB()\n//\n#if defined(EASTL_ARCH_ATOMIC_CPU_WMB)\n\t#define EASTL_ARCH_ATOMIC_CPU_WMB_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CPU_WMB_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_RMB()\n//\n#if defined(EASTL_ARCH_ATOMIC_CPU_RMB)\n\t#define EASTL_ARCH_ATOMIC_CPU_RMB_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_CPU_RMB_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_MEMORY_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_or_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_OR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_OR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_OR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_OR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_signal_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_SIGNAL_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_SIGNAL_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_ARCH_ATOMIC_SIGNAL_FENCE_RELAXED_AVAILABLE 0\n#define EASTL_ARCH_ATOMIC_SIGNAL_FENCE_ACQUIRE_AVAILABLE 0\n#define EASTL_ARCH_ATOMIC_SIGNAL_FENCE_RELEASE_AVAILABLE 0\n#define EASTL_ARCH_ATOMIC_SIGNAL_FENCE_ACQ_REL_AVAILABLE 0\n#define EASTL_ARCH_ATOMIC_SIGNAL_FENCE_SEQ_CST_AVAILABLE 0\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_SIGNAL_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_store.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_STORE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_STORE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_STORE_*_N(type, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_STORE_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_STORE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_sub_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_SUB_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_SUB_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_SUB_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_SUB_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_thread_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_THREAD_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_THREAD_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_THREAD_FENCE_*()\n//\n#if defined(EASTL_ARCH_ATOMIC_THREAD_FENCE_RELAXED)\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELAXED_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELAXED_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQUIRE)\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQUIRE_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQUIRE_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_THREAD_FENCE_RELEASE)\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELEASE_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELEASE_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQ_REL)\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQ_REL_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQ_REL_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_THREAD_FENCE_SEQ_CST)\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_SEQ_CST_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_SEQ_CST_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_THREAD_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arch_xor_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_XOR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_XOR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_XOR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_8)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_8)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_8)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_8)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_8)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_16)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_16)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_16)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_16)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_16)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_32)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_32)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_32)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_32)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_32)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_64)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_64)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_64)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_64)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_64)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_128)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_128)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_128)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_128)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_128)\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_XOR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arm/arch_arm.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_ARM_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_ARM_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/**\n * NOTE: We use this mapping\n *\n * ARMv7 Mapping 'trailing sync;':\n *\n * Load Relaxed       : ldr\n * Load Acquire       : ldr; dmb ish\n * Load Seq_Cst       : ldr; dmb ish\n *\n * Store Relaxed      : str\n * Store Release      : dmb ish; str\n * Store Seq_Cst      : dmb ish; str; dmb ish\n *\n * Relaxed Fence      :\n * Acquire Fence      : dmb ish\n * Release Fence      : dmb ish\n * Acq_Rel Fence      : dmb ish\n * Seq_Cst Fence      : dmb ish\n */\n\n/**\n * ARMv7 Mapping 'leading sync;';\n *\n * Load Relaxed       : ldr\n * Load Acquire       : ldr; dmb ish\n * Load Seq_Cst       : dmb ish; ldr; dmb ish\n *\n * Store Relaxed      : str\n * Store Release      : dmb ish; str\n * Store Seq_Cst      : dmb ish: str\n *\n * Relaxed Fence      :\n * Acquire Fence      : dmb ish\n * Release Fence      : dmb ish\n * Acq_Rel Fence      : dmb ish\n * Seq_Cst Fence      : dmb ish\n */\n\n/**\n * NOTE:\n *\n * On ARM32/64, we use the 'trailing sync;' convention with the stricter load acquire that uses\n * a dmb instead of a control dependency + isb to ensure the IRIW litmus test is satisfied\n * as one reason. See EASTL/atomic.h for futher explanation and deep-dive.\n *\n * For ARMv8 we could move to use the new proper store release and load acquire, RCsc variant.\n * All ARMv7 approaches work on ARMv8 and this code path is only used on msvc which isn't used\n * heavily. Most of the ARM code will end up going thru clang or gcc since microsoft arm devices\n * aren't that abundant.\n */\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#if defined(EA_COMPILER_MSVC)\n\n\t#if EA_PLATFORM_PTR_SIZE == 8\n\t\t#define EASTL_ARCH_ATOMIC_HAS_128BIT\n\t#endif\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include \"arch_arm_load.h\"\n#include \"arch_arm_store.h\"\n\n#include \"arch_arm_memory_barrier.h\"\n\n#include \"arch_arm_thread_fence.h\"\n\n#include \"arch_arm_acquire_fence.h\"\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_ARM_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arm/arch_arm_acquire_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n#pragma once\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_ACQUIRE_FENCE()\n//\n// On ARM, we do an acquire load to synchronize over the address instead of issuing a full\n// acquire fence (i.e. dmb ishld)\n#define EASTL_ARCH_ATOMIC_ACQUIRE_FENCE()    \\\n\tthis->load(eastl::memory_order_acquire);\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arm/arch_arm_load.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_ARM_LOAD_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_ARM_LOAD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_LOAD_*_N(type, type ret, type * ptr)\n//\n#if defined(EA_COMPILER_MSVC)\n\n\n\t/**\n\t * NOTE:\n\t *\n\t * Even 8-byte aligned 64-bit memory accesses on ARM32 are not\n\t * guaranteed to be atomic on all ARM32 cpus. Only guaranteed on\n\t * cpus with the LPAE extension. We need to use a\n\t * ldrexd instruction in order to ensure no shearing is observed\n\t * for all ARM32 processors.\n\t */\n\t#if defined(EA_PROCESSOR_ARM32)\n\n\t\t#define EASTL_ARCH_ATOMIC_ARM32_LDREXD(ret, ptr)\t\\\n\t\t\tret = __ldrexd((ptr))\n\n\t#endif\n\n\n\t#define EASTL_ARCH_ATOMIC_ARM_LOAD_N(integralType, bits, type, ret, ptr) \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tretIntegral = EA_PREPROCESSOR_JOIN(__iso_volatile_load, bits)(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr))); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_ARM_LOAD_8(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_N(__int8, 8, type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_ARM_LOAD_16(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_N(__int16, 16, type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_ARM_LOAD_32(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_N(__int32, 32, type, ret, ptr)\n\n\n\t#if defined(EA_PROCESSOR_ARM32)\n\n\n\t\t#define EASTL_ARCH_ATOMIC_LOAD_64(type, ret, ptr)\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t__int64 loadRet64;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tEASTL_ARCH_ATOMIC_ARM32_LDREXD(loadRet64, EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(__int64, (ptr))); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, loadRet64);\t\t\t\t\\\n\t\t\t}\n\n\t#else\n\n\t\t#define EASTL_ARCH_ATOMIC_ARM_LOAD_64(type, ret, ptr)\t\t\\\n\t\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_N(__int64, 64, type, ret, ptr)\n\n\t#endif\n\n\n\t/**\n\t * NOTE:\n\t *\n\t * The ARM documentation states the following:\n\t * A 64-bit pair requires the address to be quadword aligned and is single-copy atomic for each doubleword at doubleword granularity\n\t *\n\t * Thus we must ensure the store succeeds inorder for the load to be observed as atomic.\n\t * Thus we must use the full cmpxchg in order to do a proper atomic load.\n\t */\n\t#define EASTL_ARCH_ATOMIC_ARM_LOAD_128(type, ret, ptr, MemoryOrder)\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tbool cmpxchgRetBool;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tret = *(ptr);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tdo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_CMPXCHG_STRONG_, MemoryOrder), _128)(type, cmpxchgRetBool, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tptr, &(ret), ret); \\\n\t\t\t} while (!cmpxchgRetBool);\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_8(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_8(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_16(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_16(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_32(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_32(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_64(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_64(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_128(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_128(type, ret, ptr, RELAXED)\n\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_8(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_8(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_16(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_16(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_32(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_32(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_64(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_64(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_128(type, ret, ptr, ACQUIRE)\n\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_8(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_8(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_16(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_16(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_32(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_32(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_64(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_64(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_LOAD_128(type, ret, ptr, SEQ_CST)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_ARM_LOAD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arm/arch_arm_memory_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_ARM_MEMORY_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_ARM_MEMORY_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#if defined(EA_COMPILER_MSVC) && !defined(EA_COMPILER_CLANG_CL)\n\n\t#if defined(EA_PROCESSOR_ARM32)\n\n\t\t#define EASTL_ARM_DMB_ISH _ARM_BARRIER_ISH\n\n\t\t#define EASTL_ARM_DMB_ISHST _ARM_BARRIER_ISHST\n\n\t\t#define EASTL_ARM_DMB_ISHLD _ARM_BARRIER_ISH\n\n\t#elif defined(EA_PROCESSOR_ARM64)\n\n\t\t#define EASTL_ARM_DMB_ISH _ARM64_BARRIER_ISH\n\n\t\t#define EASTL_ARM_DMB_ISHST _ARM64_BARRIER_ISHST\n\n\t\t#define EASTL_ARM_DMB_ISHLD _ARM64_BARRIER_ISHLD\n\n\t#endif\n\n\n\t/**\n\t * NOTE:\n\t *\n\t * While it makes no sense for a hardware memory barrier to not imply a compiler barrier.\n\t * MSVC docs do not explicitly state that, so better to be safe than sorry chasing down\n\t * hard to find bugs due to the compiler deciding to reorder things.\n\t */\n\n\t#define EASTL_ARCH_ATOMIC_ARM_EMIT_DMB(option)\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER();\t\t\t\\\n\t\t__dmb(option);\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\n#elif defined(EA_COMPILER_GNUC) || defined(__clang__)\n\n\t#define EASTL_ARM_DMB_ISH ish\n\n\t#define EASTL_ARM_DMB_ISHST ishst\n\n\t#if defined(EA_PROCESSOR_ARM32)\n\n\t\t#define EASTL_ARM_DMB_ISHLD ish\n\n\t#elif defined(EA_PROCESSOR_ARM64)\n\n\t\t#define EASTL_ARM_DMB_ISHLD ishld\n\n\t#endif\n\n\n\t#define EASTL_ARCH_ATOMIC_ARM_EMIT_DMB(option)\t\t\t\t\t\t\t\t\t\t\\\n\t\t__asm__ __volatile__ (\"dmb \" EA_STRINGIFY(option) ::: \"memory\")\n\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_MB()\n//\n#define EASTL_ARCH_ATOMIC_CPU_MB()\t\t\t\t\\\n\tEASTL_ARCH_ATOMIC_ARM_EMIT_DMB(EASTL_ARM_DMB_ISH)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_WMB()\n//\n#define EASTL_ARCH_ATOMIC_CPU_WMB()\t\t\t\t\\\n\tEASTL_ARCH_ATOMIC_ARM_EMIT_DMB(EASTL_ARM_DMB_ISHST)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_RMB()\n//\n#define EASTL_ARCH_ATOMIC_CPU_RMB()\t\t\t\t\\\n\tEASTL_ARCH_ATOMIC_ARM_EMIT_DMB(EASTL_ARM_DMB_ISHLD)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_ARM_MEMORY_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arm/arch_arm_store.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_ARM_STORE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_ARM_STORE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_STORE_*_N(type, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC)\n\n\n\t#define EASTL_ARCH_ATOMIC_ARM_STORE_N(integralType, bits, type, ptr, val) \\\n\t\tEA_PREPROCESSOR_JOIN(__iso_volatile_store, bits)(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (val)))\n\n\n\t#define EASTL_ARCH_ATOMIC_ARM_STORE_8(type, ptr, val)\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_N(__int8, 8, type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_ARM_STORE_16(type, ptr, val)\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_N(__int16, 16, type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_ARM_STORE_32(type, ptr, val)\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_N(__int32, 32, type, ptr, val)\n\n\n\t#if defined(EA_PROCESSOR_ARM64)\n\n\t\t#define EASTL_ARCH_ATOMIC_ARM_STORE_64(type, ptr, val)\t\t\t\\\n\t\t\tEASTL_ARCH_ATOMIC_ARM_STORE_N(__int64, 64, type, ptr, val)\n\n\t#endif\n\n\n\t#define EASTL_ARCH_ATOMIC_ARM_STORE_128(type, ptr, val, MemoryOrder)\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttype exchange128; EA_UNUSED(exchange128);\t\t\t\t\t\t\\\n\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_EXCHANGE_, MemoryOrder), _128)(type, exchange128, ptr, val); \\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_8(type, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_8(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_16(type, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_16(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_32(type, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_32(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_128(type, ptr, val, RELAXED)\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_8(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_8(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_16(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_16(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_32(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_32(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_128(type, ptr, val, RELEASE)\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_8(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_8(type, ptr, val) ;\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_16(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_16(type, ptr, val);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_32(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_32(type, ptr, val);\t\t\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_ARM_STORE_128(type, ptr, val, SEQ_CST)\n\n\n\t#if defined(EA_PROCESSOR_ARM32)\n\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_64(type, ptr, val)\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\ttype retExchange64; EA_UNUSED(retExchange64);\t\t\t\t\\\n\t\t\t\tEASTL_ATOMIC_EXCHANGE_RELAXED_64(type, retExchange64, ptr, val); \\\n\t\t\t}\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_64(type, ptr, val)\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\ttype retExchange64; EA_UNUSED(retExchange64);\t\t\t\t\\\n\t\t\t\tEASTL_ATOMIC_EXCHANGE_RELEASE_64(type, retExchange64, ptr, val); \\\n\t\t\t}\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_64(type, ptr, val)\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\ttype retExchange64; EA_UNUSED(retExchange64);\t\t\t\t\\\n\t\t\t\tEASTL_ATOMIC_EXCHANGE_SEQ_CST_64(type, retExchange64, ptr, val); \\\n\t\t\t}\n\n\n\t#elif defined(EA_PROCESSOR_ARM64)\n\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_64(type, ptr, val)\t\\\n\t\t\tEASTL_ARCH_ATOMIC_ARM_STORE_64(type, ptr, val)\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_64(type, ptr, val)\t\\\n\t\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ARCH_ATOMIC_ARM_STORE_64(type, ptr, val)\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_64(type, ptr, val)\t\\\n\t\t\tEASTL_ATOMIC_CPU_MB();\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ARCH_ATOMIC_ARM_STORE_64(type, ptr, val);\t\t\t\\\n\t\t\tEASTL_ATOMIC_CPU_MB()\n\n\n\t#endif\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_ARM_STORE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/arm/arch_arm_thread_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_ARM_THREAD_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_ARM_THREAD_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_THREAD_FENCE_*()\n//\n#if defined(EA_COMPILER_MSVC)\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELAXED()\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQUIRE()\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELEASE()\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQ_REL()\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_SEQ_CST()\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_ARM_THREAD_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/**\n * x86 && x64 Mappings\n *\n * Load Relaxed       : MOV\n * Load Acquire       : MOV; COMPILER_BARRIER;\n * Load Seq_Cst       : MOV; COMPILER_BARRIER;\n *\n * Store Relaxed      : MOV\n * Store Release      : COMPILER_BARRIER; MOV;\n * Store Seq_Cst      : LOCK XCHG : MOV; MFENCE;\n *\n * Relaxed Fence      :\n * Acquire Fence      : COMPILER_BARRIER\n * Release Fence      : COMPILER_BARRIER\n * Acq_Rel Fence      : COMPILER_BARRIER\n * Seq_Cst FENCE      : MFENCE\n */\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n#if (defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64)\n\t#define EASTL_ARCH_ATOMIC_HAS_128BIT\n#elif defined(EA_COMPILER_MSVC)\n\t#if EA_PLATFORM_PTR_SIZE == 8\n\t\t#define EASTL_ARCH_ATOMIC_HAS_128BIT\n\t#endif\n#endif\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/**\n * NOTE:\n *\n * On 32-bit x86 CPUs Intel Pentium and newer, AMD K5 and newer\n * and any i586 class of x86 CPUs support only 64-bit cmpxchg\n * known as cmpxchg8b.\n *\n * On these class of cpus we can guarantee that 64-bit loads/stores are\n * also atomic by using the SSE2 movq, SSE1 movlps, or x87 fild/fstp instructions.\n *\n * We support all other atomic operations\n * on compilers that only provide this 64-bit cmpxchg instruction\n * by wrapping them around the 64-bit cmpxchg8b instruction.\n */\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_NOP_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tstatic_assert(false, \"EASTL_ARCH_ATOMIC_X86_NOP_PRE_COMPUTE_DESIRED() must be implmented!\");\n\n\t#define EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET(ret, prevObserved, val)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, MemoryOrder, PRE_COMPUTE_DESIRED, POST_COMPUTE_RET) \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_DEFAULT_INIT(bool, cmpxchgRet);\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_LOAD_RELAXED_64(type, ret, ptr);\t\t\t\t\t\\\n\t\t\tdo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\ttype computedDesired;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tPRE_COMPUTE_DESIRED(computedDesired, ret, (val));\t\t\t\\\n\t\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_CMPXCHG_STRONG_, MemoryOrder), _64)(type, cmpxchgRet, ptr, &(ret), computedDesired); \\\n\t\t\t} while (!cmpxchgRet);\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tPOST_COMPUTE_RET(ret, ret, (val));\t\t\t\t\t\t\t\t\\\n\t\t}\n\n\n#endif\n\n\n/**\n * NOTE:\n *\n * 64-bit x64 CPUs support only 128-bit cmpxchg known as cmpxchg16b.\n *\n * We support all other atomic operations by wrapping them around\n * the 128-bit cmpxchg16b instruction.\n *\n * 128-bit loads are only atomic by using the cmpxchg16b instruction.\n * SSE 128-bit loads are not guaranteed to be atomic even though some CPUs\n * make them atomic such as AMD Ryzen or Intel SandyBridge.\n */\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_NOP_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tstatic_assert(false, \"EASTL_ARCH_ATOMIC_X86_NOP_PRE_COMPUTE_DESIRED() must be implmented!\");\n\n\t#define EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET(ret, prevObserved, val)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, MemoryOrder, PRE_COMPUTE_DESIRED, POST_COMPUTE_RET) \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_DEFAULT_INIT(bool, cmpxchgRet);\t\t\t\t\t\\\n\t\t\t/* This is intentionally a non-atomic 128-bit load which may observe shearing. */ \\\n\t\t\t/* Either we do not observe *(ptr) but then the cmpxchg will fail and the observed */ \\\n\t\t\t/* atomic load will be returned. Or the non-atomic load got lucky and the cmpxchg succeeds */ \\\n\t\t\t/* because the observed value equals the value in *(ptr) thus we optimistically do a non-atomic load. */ \\\n\t\t\tret = *(ptr);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tdo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\ttype computedDesired;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tPRE_COMPUTE_DESIRED(computedDesired, ret, (val));\t\t\t\\\n\t\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_CMPXCHG_STRONG_, MemoryOrder), _128)(type, cmpxchgRet, ptr, &(ret), computedDesired); \\\n\t\t\t} while (!cmpxchgRet);\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tPOST_COMPUTE_RET(ret, ret, (val));\t\t\t\t\t\t\t\t\\\n\t\t}\n\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include \"arch_x86_fetch_add.h\"\n#include \"arch_x86_fetch_sub.h\"\n\n#include \"arch_x86_fetch_and.h\"\n#include \"arch_x86_fetch_xor.h\"\n#include \"arch_x86_fetch_or.h\"\n\n#include \"arch_x86_add_fetch.h\"\n#include \"arch_x86_sub_fetch.h\"\n\n#include \"arch_x86_and_fetch.h\"\n#include \"arch_x86_xor_fetch.h\"\n#include \"arch_x86_or_fetch.h\"\n\n#include \"arch_x86_exchange.h\"\n\n#include \"arch_x86_cmpxchg_weak.h\"\n#include \"arch_x86_cmpxchg_strong.h\"\n\n#include \"arch_x86_memory_barrier.h\"\n\n#include \"arch_x86_thread_fence.h\"\n\n#include \"arch_x86_acquire_fence.h\"\n\n#include \"arch_x86_load.h\"\n#include \"arch_x86_store.h\"\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_acquire_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n#pragma once\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_ACQUIRE_FENCE()\n//\n// On x86, this can just be a compiler barrier.\n#define EASTL_ARCH_ATOMIC_ACQUIRE_FENCE()    \\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_add_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_ADD_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_ADD_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_ADD_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) + (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) + (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) + (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) + (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_ADD_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_ADD_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_ADD_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_and_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_AND_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_AND_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_AND_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) & (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) & (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) & (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) & (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_AND_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_AND_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_AND_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_cmpxchg_strong.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_CMPXCHG_STRONG_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_CMPXCHG_STRONG_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired) \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* Compare RDX:RAX with m128. If equal, set ZF and load RCX:RBX into m128. Else, clear ZF and load m128 into RDX:RAX. */ \\\n\t\t\t__asm__ __volatile__ (\"lock; cmpxchg16b %2\\n\" /* cmpxchg16b sets/clears ZF */ \\\n\t\t\t\t\t\t\t\t  \"sete %3\" /* If ZF == 1, set the return value to 1 */ \\\n\t\t\t\t\t\t\t\t  /* Output  Operands */\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t  : \"=a\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, (expected)))[0]), \"=d\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, (expected)))[1]), \\\n\t\t\t\t\t\t\t\t\t\"+m\"(*(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(__uint128_t, (ptr)))), \\\n\t\t\t\t\t\t\t\t\t\"=rm\"((ret))\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t  /* Input Operands */\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t  : \"b\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(desired)))[0]), \"c\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(desired)))[1]), \\\n\t\t\t\t\t\t\t\t\t\"a\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, (expected)))[0]), \"d\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, (expected)))[1]) \\\n\t\t\t\t\t\t\t\t  /* Clobbers */\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t  : \"memory\", \"cc\");\t\t\t\t\t\t\\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ARCH_ATOMIC_X86_CMPXCHG_STRONG_128_IMPL(type, ret, ptr, expected, desired)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_CMPXCHG_STRONG_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_cmpxchg_weak.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_CMPXCHG_WEAK_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_CMPXCHG_WEAK_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n\t#define EASTL_ARCH_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\t\tEASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_CMPXCHG_WEAK_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_exchange.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_EXCHANGE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_EXCHANGE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_EXCHANGE_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_EXCHANGE_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = (val)\n\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_EXCHANGE_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_EXCHANGE_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_EXCHANGE_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_EXCHANGE_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_EXCHANGE_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_EXCHANGE_128(type, ret, ptr, val, MemoryOrder) \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_DEFAULT_INIT(bool, cmpxchgRet);\t\t\t\t\t\\\n\t\t\t/* This is intentionally a non-atomic 128-bit load which may observe shearing. */ \\\n\t\t\t/* Either we do not observe *(ptr) but then the cmpxchg will fail and the observed */ \\\n\t\t\t/* atomic load will be returned. Or the non-atomic load got lucky and the cmpxchg succeeds */ \\\n\t\t\t/* because the observed value equals the value in *(ptr) thus we optimistically do a non-atomic load. */ \\\n\t\t\tret = *(ptr);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tdo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_CMPXCHG_STRONG_, MemoryOrder), _128)(type, cmpxchgRet, ptr, &(ret), val); \\\n\t\t\t} while (!cmpxchgRet);\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELAXED_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_EXCHANGE_128(type, ret, ptr, val, RELAXED)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQUIRE_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_EXCHANGE_128(type, ret, ptr, val, ACQUIRE)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_RELEASE_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_EXCHANGE_128(type, ret, ptr, val, RELEASE)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_ACQ_REL_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_EXCHANGE_128(type, ret, ptr, val, ACQ_REL)\n\n\t#define EASTL_ARCH_ATOMIC_EXCHANGE_SEQ_CST_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_EXCHANGE_128(type, ret, ptr, val, SEQ_CST)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_EXCHANGE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_fetch_add.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_ADD_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_ADD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_ADD_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) + (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) + (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_ADD_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_ADD_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_ADD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_fetch_and.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_AND_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_AND_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_AND_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) & (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) & (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_AND_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_AND_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_AND_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_fetch_or.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_OR_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_OR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_OR_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) | (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) | (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELAXED_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQUIRE_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_RELEASE_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_ACQ_REL_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_OR_SEQ_CST_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_OR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_OR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_fetch_sub.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_SUB_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_SUB_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_SUB_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) - (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) - (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_SUB_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_SUB_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_SUB_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_fetch_xor.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_XOR_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_XOR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_FETCH_XOR_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) ^ (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) ^ (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_FETCH_XOR_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_FETCH_XOR_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_NOP_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_FETCH_XOR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_load.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_LOAD_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_LOAD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_LOAD_*_N(type, type ret, type * ptr)\n//\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t/**\n\t * NOTE:\n\t *\n\t * Since the cmpxchg 128-bit inline assembly does a sete in the asm to set the return boolean,\n\t * it doesn't get dead-store removed even though we don't care about the success of the\n\t * cmpxchg since the compiler cannot reason about what is inside asm blocks.\n\t * Thus this variant just does the minimum required to do an atomic load.\n\t */\n#define EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, MemoryOrder)\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_FIXED_WIDTH_TYPE_128 expected = 0;\t\t\t\t\t\\\n\t\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, expected);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t/* Compare RDX:RAX with m128. If equal, set ZF and load RCX:RBX into m128. Else, clear ZF and load m128 into RDX:RAX. */ \\\n\t\t\t__asm__ __volatile__ (\"lock; cmpxchg16b %2\" /* cmpxchg16b sets/clears ZF */ \\\n\t\t\t\t\t\t\t\t  /* Output  Operands */\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t  : \"=a\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[0]), \"=d\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[1]), \\\n\t\t\t\t\t\t\t\t\t\"+m\"(*(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(__uint128_t, (ptr)))) \\\n\t\t\t\t\t\t\t\t  /* Input Operands */\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t  : \"b\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[0]), \"c\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[1]), \\\n\t\t\t\t\t\t\t\t\t\"a\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[0]), \"d\"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[1]) \\\n\t\t\t\t\t\t\t\t  /* Clobbers */\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t  : \"memory\", \"cc\");\t\t\t\t\t\t\\\n\t\t}\n\n\n#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_128(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, RELAXED)\n\n#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, ACQUIRE)\n\n#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, SEQ_CST)\n\n#elif defined(EA_COMPILER_MSVC)\n\n\n\t#if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1920) // >= VS2019\n\n\t\t#define EASTL_ARCH_ATOMIC_X86_LOAD_N(integralType, bits, type, ret, ptr) \\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tretIntegral = EA_PREPROCESSOR_JOIN(__iso_volatile_load, bits)(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr))); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t\t\t}\n\n\t#else\n\n\t\t#define EASTL_ARCH_ATOMIC_X86_LOAD_N(integralType, bits, type, ret, ptr) \\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tretIntegral = (*(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)))); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t\t\t}\n\n\t#endif\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, MemoryOrder)\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_FIXED_WIDTH_TYPE_128 expected{0, 0};\t\t\t\t\\\n\t\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, expected);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tbool cmpxchgRetBool; EA_UNUSED(cmpxchgRetBool);\t\t\t\t\t\\\n\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_CMPXCHG_STRONG_, MemoryOrder), _128)(type, cmpxchgRetBool, ptr, &(ret), ret); \\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_N(__int8, 8, type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_N(__int16, 16, type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_N(__int32, 32, type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_N(__int64, 64, type, ret, ptr)\n\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_8(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_16(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_32(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_64(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr)\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_RELAXED_128(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, RELAXED)\n\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_8(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_16(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_32(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_64(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, ACQUIRE)\n\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_8(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_16(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_32(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_64(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr);\t\t\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128(type, ret, ptr)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, SEQ_CST)\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_LOAD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_memory_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_MEMORY_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_MEMORY_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_MB()\n//\n#if defined(EA_COMPILER_MSVC)\n\n\t/**\n\t * NOTE:\n\t * While it makes no sense for a hardware memory barrier to not imply a compiler barrier.\n\t * MSVC docs do not explicitly state that, so better to be safe than sorry chasing down\n\t * hard to find bugs due to the compiler deciding to reorder things.\n\t */\n\n\t#if 1\n\n\t\t// 4459 : declaration of 'identifier' hides global declaration\n\t\t// 4456 : declaration of 'identifier' hides previous local declaration\n\t\t#define EASTL_ARCH_ATOMIC_CPU_MB()\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tEA_DISABLE_VC_WARNING(4459 4456);\t\t\\\n\t\t\t\tvolatile long _;\t\t\t\t\t\t\\\n\t\t\t\t_InterlockedExchangeAdd(&_, 0);\t\t\t\\\n\t\t\t\tEA_RESTORE_VC_WARNING();\t\t\t\t\\\n\t\t\t}\n\n\t#else\n\n\t\t#define EASTL_ARCH_ATOMIC_CPU_MB()\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_COMPILER_BARRIER();\t\t\t\\\n\t\t\t_mm_mfence();\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#endif\n\n#elif defined(__clang__) || defined(EA_COMPILER_GNUC)\n\n\t/**\n\t* NOTE:\n\t*\n\t* mfence orders all loads/stores to/from all memory types.\n\t* We only care about ordinary cacheable memory so lighter weight locked instruction\n\t* is far faster than a mfence to get a full memory barrier.\n\t* lock; addl against the top of the stack is good because:\n\t*     distinct for every thread so prevents false sharing\n\t*     that cacheline is most likely cache hot\n\t*\n\t* We intentionally do it below the stack pointer to avoid false RAW register dependencies,\n\t* in cases where the compiler reads from the stack pointer after the lock; addl instruction\n\t*\n\t* Accounting for Red Zones or Cachelines doesn't provide extra benefit.\n\t*/\n\n\t#if defined(EA_PROCESSOR_X86)\n\n\t\t#define EASTL_ARCH_ATOMIC_CPU_MB()\t\t\t\t\\\n\t\t\t__asm__ __volatile__ (\"lock; addl $0, -4(%%esp)\" ::: \"memory\", \"cc\")\n\n\t#elif defined(EA_PROCESSOR_X86_64)\n\n\t\t#define EASTL_ARCH_ATOMIC_CPU_MB()\t\t\t\t\\\n\t\t\t__asm__ __volatile__ (\"lock; addl $0, -8(%%rsp)\" ::: \"memory\", \"cc\")\n\n\t#else\n\n\t\t#define EASTL_ARCH_ATOMIC_CPU_MB()\t\t\t\t\\\n\t\t\t__asm__ __volatile__ (\"mfence\" ::: \"memory\")\n\n\t#endif\n\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_WMB()\n//\n#define EASTL_ARCH_ATOMIC_CPU_WMB()\t\t\t\t\\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_CPU_RMB()\n//\n#define EASTL_ARCH_ATOMIC_CPU_RMB()\t\t\t\t\\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_MEMORY_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_or_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_OR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_OR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_OR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) | (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) | (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) | (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) | (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELAXED_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_RELEASE_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_OR_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_OR_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_OR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_store.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_STORE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_STORE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_STORE_*_N(type, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC)\n\n\n\t#if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1920) // >= VS2019\n\n\t\t#define EASTL_ARCH_ATOMIC_X86_STORE_N(integralType, bits, type, ptr, val) \\\n\t\t\tEA_PREPROCESSOR_JOIN(__iso_volatile_store, bits)(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (val)))\n\n\t#else\n\n\t\t#define EASTL_ARCH_ATOMIC_X86_STORE_N(integralType, bits, type, ptr, val) \\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\tintegralType valIntegral = EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (val)); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t(*(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)))) = valIntegral; \\\n\t\t\t}\n\n\t#endif\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, MemoryOrder)\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttype exchange128; EA_UNUSED(exchange128);\t\t\t\t\t\t\\\n\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_EXCHANGE_, MemoryOrder), _128)(type, exchange128, ptr, val); \\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_STORE_8(type, ptr, val)\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_N(__int8, 8, type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_X86_STORE_16(type, ptr, val)\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_N(__int16, 16, type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_X86_STORE_32(type, ptr, val)\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_N(__int32, 32, type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_X86_STORE_64(type, ptr, val)\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_N(__int64, 64, type, ptr, val)\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_8(type, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_8(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_16(type, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_16(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_32(type, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_32(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_64(type, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_64(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, RELAXED)\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_8(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER();\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_8(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_16(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER();\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_16(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_32(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER();\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_32(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_64(type, ptr, val)\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER();\t\t\t\t\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_64(type, ptr, val)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, RELEASE)\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_8(type, ptr, val)\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttype exchange8; EA_UNUSED(exchange8);\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_SEQ_CST_8(type, exchange8, ptr, val);\t\\\n\t\t}\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_16(type, ptr, val)\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttype exchange16; EA_UNUSED(exchange16);\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_SEQ_CST_16(type, exchange16, ptr, val); \\\n\t\t}\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_32(type, ptr, val)\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttype exchange32; EA_UNUSED(exchange32);\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_SEQ_CST_32(type, exchange32, ptr, val); \\\n\t\t}\n\n\n\t/**\n\t * NOTE:\n\t *\n\t * Since 64-bit exchange is wrapped around a cmpxchg8b on 32-bit x86, it is\n\t * faster to just do a mov; mfence.\n\t */\n\t#if defined(EA_PROCESSOR_X86)\n\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_64(type, ptr, val)\t\t\\\n\t\t\t\t\tEASTL_ATOMIC_COMPILER_BARRIER();\t\t\t\t\t\\\n\t\t\t\t\tEASTL_ARCH_ATOMIC_X86_STORE_64(type, ptr, val);\t\t\\\n\t\t\t\t\tEASTL_ATOMIC_CPU_MB()\n\n\n\t#elif defined(EA_PROCESSOR_X86_64)\n\n\n\t\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_64(type, ptr, val)\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\ttype exchange64; EA_UNUSED(exchange64);\t\t\t\t\t\\\n\t\t\t\tEASTL_ATOMIC_EXCHANGE_SEQ_CST_64(type, exchange64, ptr, val); \\\n\t\t\t}\n\n\n\t#endif\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, SEQ_CST)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, MemoryOrder)\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttype exchange128; EA_UNUSED(exchange128);\t\t\t\t\t\t\\\n\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_EXCHANGE_, MemoryOrder), _128)(type, exchange128, ptr, val); \\\n\t\t}\n\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELAXED_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, RELAXED)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_RELEASE_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, RELEASE)\n\n\t#define EASTL_ARCH_ATOMIC_STORE_SEQ_CST_128(type, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_STORE_128(type, ptr, val, SEQ_CST)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_STORE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_sub_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_SUB_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_SUB_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_SUB_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) - (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) - (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) - (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) - (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_SUB_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_SUB_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_SUB_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_thread_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_THREAD_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_THREAD_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_THREAD_FENCE_*()\n//\n#if defined(EA_COMPILER_MSVC)\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELAXED()\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQUIRE()\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_RELEASE()\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_ACQ_REL()\t\\\n\t\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n#endif\n\n\n#if defined(EA_COMPILER_MSVC) || defined(__clang__) || defined(EA_COMPILER_GNUC)\n\n\t#define EASTL_ARCH_ATOMIC_THREAD_FENCE_SEQ_CST()\t\\\n\t\tEASTL_ATOMIC_CPU_MB()\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_THREAD_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/arch/x86/arch_x86_xor_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_XOR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_ARCH_X86_XOR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ARCH_ATOMIC_XOR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86)\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) ^ (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) ^ (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_64_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))\n\n\n\t#define EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED(ret, observed, val) \\\n\t\tret = ((observed) ^ (val))\n\n\t#define EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET(ret, prevObserved, val) \\\n\t\tret = ((prevObserved) ^ (val))\n\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELAXED_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELAXED,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQUIRE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_RELEASE_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, RELEASE,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, ACQ_REL,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\t#define EASTL_ARCH_ATOMIC_XOR_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\\\n\t\tEASTL_ARCH_ATOMIC_X86_OP_128_IMPL(type, ret, ptr, val, SEQ_CST,\t\t\\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_PRE_COMPUTE_DESIRED, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ARCH_ATOMIC_X86_XOR_FETCH_POST_COMPUTE_RET)\n\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_XOR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_H\n#define EASTL_ATOMIC_INTERNAL_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/internal/memory_base.h>\n#include <EASTL/type_traits.h>\n\n#include \"atomic_macros.h\"\n#include \"atomic_casts.h\"\n\n#include \"atomic_memory_order.h\"\n#include \"atomic_asserts.h\"\n\n#include \"atomic_size_aligned.h\"\n#include \"atomic_base_width.h\"\n\n#include \"atomic_integral.h\"\n\n#include \"atomic_pointer.h\"\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/**\n * NOTE:\n *\n * All of the actual implementation is done via the ATOMIC_MACROS in the compiler or arch sub folders.\n * The C++ code is merely boilerplate around these macros that actually implement the atomic operations.\n * The C++ boilerplate is also hidden behind macros.\n * This may seem more complicated but this is all meant to reduce copy-pasting and to ensure all operations\n * all end up going down to one macro that does the actual implementation.\n * The reduced code duplication makes it easier to verify the implementation and reason about it.\n * Ensures we do not have to re-implement the same code for compilers that do not support generic builtins such as MSVC.\n * Ensures for compilers that have separate intrinsics for different widths, that C++ boilerplate isn't copy-pasted leading to programmer errors.\n * Ensures if we ever have to implement a new platform, only the low-level leaf macros have to be implemented, everything else will be generated for you.\n */\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\n// 'class' : multiple assignment operators specified\nEA_DISABLE_VC_WARNING(4522);\n\n// misaligned atomic operation may incur significant performance penalty\n// The above warning is emitted in earlier versions of clang incorrectly.\n// All eastl::atomic<T> objects are size aligned.\n// This is static and runtime asserted.\n// Thus we disable this warning.\nEA_DISABLE_CLANG_WARNING(-Watomic-alignment);\n\n\n\ttemplate <typename T>\n\tstruct is_atomic_lockfree_size\n\t{\n\t\tstatic EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR_OR_CONST bool value = false ||\n\t\t#if defined(EASTL_ATOMIC_HAS_8BIT)\n\t\t\tsizeof(T) == 1 ||\n\t\t#endif\n\t\t#if defined(EASTL_ATOMIC_HAS_16BIT)\n\t\t\tsizeof(T) == 2 ||\n\t\t#endif\n\t\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\t\tsizeof(T) == 4 ||\n\t\t#endif\n\t\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\t\tsizeof(T) == 8 ||\n\t\t#endif\n\t\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\t\tsizeof(T) == 16 ||\n\t\t#endif\n\t\tfalse;\n\t};\n\n\n\ttemplate <typename T>\n\tstruct is_user_type_suitable_for_primary_template\n\t{\n\t\tstatic EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR_OR_CONST bool value = eastl::internal::is_atomic_lockfree_size<T>::value;\n\t};\n\n\n\ttemplate <typename T>\n\tusing select_atomic_inherit_0 = typename eastl::conditional<eastl::is_same_v<bool, T> || eastl::internal::is_user_type_suitable_for_primary_template<T>::value,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\teastl::internal::atomic_base_width<T>, /* True */\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\teastl::internal::atomic_invalid_type<T> /* False */\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>::type;\n\n\ttemplate <typename T>\n\tusing select_atomic_inherit  = select_atomic_inherit_0<T>;\n\n\n} // namespace internal\n\n\n#define EASTL_ATOMIC_CLASS_IMPL(type, base, valueType, differenceType)\t\\\n\tprivate:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_TYPE(type);\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base = base;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\ttypedef valueType value_type;\t\t\t\t\t\t\t\t\t\\\n\t\ttypedef differenceType difference_type;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tstatic EASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR_OR_CONST bool is_always_lock_free = eastl::internal::is_atomic_lockfree_size<type>::value; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* deleted ctors && assignment operators */\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic(const atomic&) EA_NOEXCEPT = delete;\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic& operator=(const atomic&)          EA_NOEXCEPT = delete; \\\n\t\tatomic& operator=(const atomic&) volatile EA_NOEXCEPT = delete; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* ctors */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic(type desired) EA_NOEXCEPT\t\t\t\t\t\\\n\t\t\t: Base{ desired }\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic() EA_NOEXCEPT_IF(eastl::is_nothrow_default_constructible_v<type>) = default; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tbool is_lock_free() const EA_NOEXCEPT\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\treturn eastl::internal::is_atomic_lockfree_size<type>::value; \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tbool is_lock_free() const volatile EA_NOEXCEPT\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(type);\t\t\t\\\n\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\n\n\n#define EASTL_ATOMIC_USING_ATOMIC_BASE(type)\t\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::operator=;\t\t\t\t\t\t\\\n\t\tusing Base::store;\t\t\t\t\t\t\t\\\n\t\tusing Base::load;\t\t\t\t\t\t\t\\\n\t\tusing Base::exchange;\t\t\t\t\t\t\\\n\t\tusing Base::compare_exchange_weak;\t\t\t\\\n\t\tusing Base::compare_exchange_strong;\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\toperator type() const volatile EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\toperator type() const EA_NOEXCEPT\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\treturn load(eastl::memory_order_seq_cst); \\\n\t\t}\n\n\n#define EASTL_ATOMIC_USING_ATOMIC_INTEGRAL()\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::fetch_add;\t\t\t\t\t\\\n\t\tusing Base::add_fetch;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::fetch_sub;\t\t\t\t\t\\\n\t\tusing Base::sub_fetch;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::fetch_and;\t\t\t\t\t\\\n\t\tusing Base::and_fetch;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::fetch_or;\t\t\t\t\t\\\n\t\tusing Base::or_fetch;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::fetch_xor;\t\t\t\t\t\\\n\t\tusing Base::xor_fetch;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::acquire_fence;   \t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::operator++;\t\t\t\t\t\\\n\t\tusing Base::operator--;\t\t\t\t\t\\\n\t\tusing Base::operator+=;\t\t\t\t\t\\\n\t\tusing Base::operator-=;\t\t\t\t\t\\\n\t\tusing Base::operator&=;\t\t\t\t\t\\\n\t\tusing Base::operator|=;\t\t\t\t\t\\\n\t\tusing Base::operator^=;\n\n\n#define EASTL_ATOMIC_USING_ATOMIC_POINTER()\t\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::fetch_add;\t\t\t\t\t\\\n\t\tusing Base::add_fetch;\t\t\t\t\t\\\n\t\tusing Base::fetch_sub;\t\t\t\t\t\\\n\t\tusing Base::sub_fetch;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::operator++;\t\t\t\t\t\\\n\t\tusing Base::operator--;\t\t\t\t\t\\\n\t\tusing Base::operator+=;\t\t\t\t\t\\\n\t\tusing Base::operator-=;\n\n\ntemplate <typename T, typename = void>\nstruct atomic : protected eastl::internal::select_atomic_inherit<T>\n{\n\tEASTL_ATOMIC_CLASS_IMPL(T, eastl::internal::select_atomic_inherit<T>, T, T)\n\n\tEASTL_ATOMIC_USING_ATOMIC_BASE(T)\n};\n\n\ntemplate <typename T>\nstruct atomic<T, eastl::enable_if_t<eastl::is_integral_v<T> && !eastl::is_same_v<bool, T>>> : protected eastl::internal::atomic_integral_width<T>\n{\n\tEASTL_ATOMIC_CLASS_IMPL(T, eastl::internal::atomic_integral_width<T>, T, T)\n\n\tEASTL_ATOMIC_USING_ATOMIC_BASE(T)\n\n\tEASTL_ATOMIC_USING_ATOMIC_INTEGRAL()\n};\n\n\ntemplate <typename T>\nstruct atomic<T*> : protected eastl::internal::atomic_pointer_width<T*>\n{\n\tEASTL_ATOMIC_CLASS_IMPL(T*, eastl::internal::atomic_pointer_width<T*>, T*, ptrdiff_t)\n\n\tEASTL_ATOMIC_USING_ATOMIC_BASE(T*)\n\n\tEASTL_ATOMIC_USING_ATOMIC_POINTER()\n};\n\n\nEA_RESTORE_VC_WARNING();\n\nEA_RESTORE_CLANG_WARNING();\n\n} // namespace eastl\n\n#endif /* EASTL_ATOMIC_INTERNAL_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_asserts.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_STATIC_ASSERTS_H\n#define EASTL_ATOMIC_INTERNAL_STATIC_ASSERTS_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(type)\t\t\t\t\\\n\tstatic_assert(!eastl::is_same<type, type>::value, \"eastl::atomic<T> : volatile eastl::atomic<T> is not what you expect! Read the docs in EASTL/atomic.h! Use the memory orders to access the atomic object!\");\n\n#define EASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(type)\t\t\t\\\n\tstatic_assert(!eastl::is_same<type, type>::value, \"eastl::atomic<T> : invalid memory order for the given operation!\");\n\n#define EASTL_ATOMIC_STATIC_ASSERT_TYPE(type)\t\t\t\t\t\t\t\\\n\t/* User Provided T must not be cv qualified */\t\t\t\t\t\t\\\n\tstatic_assert(!eastl::is_const<type>::value, \"eastl::atomic<T> : Template Typename T cannot be const!\"); \\\n\tstatic_assert(!eastl::is_volatile<type>::value, \"eastl::atomic<T> : Template Typename T cannot be volatile! Use the memory orders to access the underlying type for the guarantees you need.\"); \\\n\t/* T must satisfy StandardLayoutType */\t\t\t\t\t\t\t\t\\\n\tstatic_assert(eastl::is_standard_layout<type>::value, \"eastl::atomic<T> : Must have standard layout!\"); \\\n\t/* T must be TriviallyCopyable but it does not have to be TriviallyConstructible */ \\\n\tstatic_assert(eastl::is_trivially_copyable<type>::value, \"eastl::atomci<T> : Template Typename T must be trivially copyable!\"); \\\n\tstatic_assert(eastl::is_copy_constructible<type>::value, \"eastl::atomic<T> : Template Typename T must be copy constructible!\"); \\\n\tstatic_assert(eastl::is_move_constructible<type>::value, \"eastl::atomic<T> : Template Typename T must be move constructible!\"); \\\n\tstatic_assert(eastl::is_copy_assignable<type>::value, \"eastl::atomic<T> : Template Typename T must be copy assignable!\"); \\\n\tstatic_assert(eastl::is_move_assignable<type>::value, \"eastl::atomic<T> : Template Typename T must be move assignable!\"); \\\n\tstatic_assert(eastl::is_trivially_destructible<type>::value, \"eastl::atomic<T> : Must be trivially destructible!\"); \\\n\tstatic_assert(eastl::internal::is_atomic_lockfree_size<type>::value, \"eastl::atomic<T> : Template Typename T must be a lockfree size!\");\n\n#define EASTL_ATOMIC_STATIC_ASSERT_TYPE_IS_OBJECT(type) \\\n\tstatic_assert(eastl::is_object<type>::value, \"eastl::atomic<T> : Template Typename T must be an object type!\");\n\n#define EASTL_ATOMIC_ASSERT_ALIGNED(alignment)\t\t\t\t\t\t\t\\\n\tEASTL_ASSERT((alignment & (alignment - 1)) == 0);\t\t\t\t\t\\\n\tEASTL_ASSERT((reinterpret_cast<uintptr_t>(this) & (alignment - 1)) == 0)\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\n\ttemplate <typename T>\n\tstruct atomic_invalid_type\n\t{\n\t\t/**\n\t\t * class Test { int i; int j; int k; }; sizeof(Test) == 96 bits\n\t\t *\n\t\t * std::atomic allows non-primitive types to be used for the template type.\n\t\t * This causes the api to degrade to locking for types that cannot fit into the lockfree size\n\t\t * of the target platform such as std::atomic<Test> leading to performance traps.\n\t\t *\n\t\t * If this static_assert() fired, this means your template type T is larger than any atomic instruction\n\t\t * supported on the given platform.\n\t\t */\n\n\t\tstatic_assert(!eastl::is_same<T, T>::value, \"eastl::atomic<T> : invalid template type T!\");\n\t};\n\n\n} // namespace internal\n\n\n} // namespace eastl\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_STATIC_ASSERTS_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_base_width.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_BASE_WIDTH_H\n#define EASTL_ATOMIC_INTERNAL_BASE_WIDTH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\n// 'class' : multiple assignment operators specified\nEA_DISABLE_VC_WARNING(4522);\n\n// misaligned atomic operation may incur significant performance penalty\n// The above warning is emitted in earlier versions of clang incorrectly.\n// All eastl::atomic<T> objects are size aligned.\n// This is static and runtime asserted.\n// Thus we disable this warning.\nEA_DISABLE_CLANG_WARNING(-Watomic-alignment);\n\n\n\ttemplate <typename T, unsigned width = sizeof(T)>\n\tstruct atomic_base_width;\n\n\t/**\n\t * NOTE:\n\t *\n\t * T does not have to be trivially default constructible but it still\n\t * has to be a trivially copyable type for the primary atomic template.\n\t * Thus we must type pun into whatever storage type of the given fixed width\n\t * the platform designates. This ensures T does not have to be trivially constructible.\n\t */\n\n#define EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits)\t\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(EASTL_ATOMIC_FIXED_WIDTH_TYPE_, bits)\n\n#define EASTL_ATOMIC_STORE_FUNC_WITH_PTR_IMPL(op, bits, ptr)\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits) fixedWidthDesired = EASTL_ATOMIC_TYPE_PUN_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), desired); \\\n\tEA_PREPROCESSOR_JOIN(op, bits)(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), \\\n\t\t\t\t\t\t\t\t   EASTL_ATOMIC_TYPE_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), ptr), \\\n\t\t\t\t\t\t\t\t   fixedWidthDesired)\n\n#define EASTL_ATOMIC_STORE_FUNC_IMPL(op, bits) \\\n\tEASTL_ATOMIC_STORE_FUNC_WITH_PTR_IMPL(op, bits, this->GetAtomicAddress())\n\n#define EASTL_ATOMIC_LOAD_FUNC_WITH_PTR_IMPL(op, bits, ptr)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits) retVal;\t\t\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(op, bits)(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), \\\n\t\t\t\t\t\t\t\t   retVal,\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t   EASTL_ATOMIC_TYPE_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), ptr)); \\\n\treturn EASTL_ATOMIC_TYPE_PUN_CAST(T, retVal);\n\n#define EASTL_ATOMIC_LOAD_FUNC_IMPL(op, bits)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_LOAD_FUNC_WITH_PTR_IMPL(op, bits, this->GetAtomicAddress())\n\n#define EASTL_ATOMIC_EXCHANGE_FUNC_WITH_PTR_IMPL(op, bits, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits) retVal;\t\t\t\t\t\\\n\tEASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits) fixedWidthDesired = EASTL_ATOMIC_TYPE_PUN_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), desired); \\\n\tEA_PREPROCESSOR_JOIN(op, bits)(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), \\\n\t\t\t\t\t\t\t\t   retVal,\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t   EASTL_ATOMIC_TYPE_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), ptr), \\\n\t\t\t\t\t\t\t\t   fixedWidthDesired);\t\t\t\t\t\\\n\treturn EASTL_ATOMIC_TYPE_PUN_CAST(T, retVal);\n\n#define EASTL_ATOMIC_EXCHANGE_FUNC_IMPL(op, bits)\t\t\t\t\t\\\n\tEASTL_ATOMIC_EXCHANGE_FUNC_WITH_PTR_IMPL(op, bits, this->GetAtomicAddress())\n\n\n#define EASTL_ATOMIC_CMPXCHG_FUNC_WITH_PTR_IMPL(op, bits, ptr)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_DEFAULT_INIT(bool, retVal);\t\t\t\t\t        \\\n\tEASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits) fixedWidthDesired = EASTL_ATOMIC_TYPE_PUN_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), desired); \\\n\tEA_PREPROCESSOR_JOIN(op, bits)(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), \\\n\t\t\t\t\t\t\t\t   retVal,\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t   EASTL_ATOMIC_TYPE_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), ptr), \\\n\t\t\t\t\t\t\t\t   EASTL_ATOMIC_TYPE_CAST(EASTL_ATOMIC_BASE_FIXED_WIDTH_TYPE(bits), &expected), \\\n\t\t\t\t\t\t\t\t   fixedWidthDesired);\t\t\t\t\t\\\n\treturn retVal;\n\n#define EASTL_ATOMIC_CMPXCHG_FUNC_IMPL(op, bits) \\\n\tEASTL_ATOMIC_CMPXCHG_FUNC_WITH_PTR_IMPL(op, bits, this->GetAtomicAddress())\n\n#define EASTL_ATOMIC_BASE_OP_JOIN(op, Order)\t\t\t\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_, op), Order)\n\n\n#define EASTL_ATOMIC_BASE_CMPXCHG_FUNCS_IMPL(funcName, cmpxchgOp, bits)\t\\\n\tusing Base::funcName;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired) EA_NOEXCEPT\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _SEQ_CST_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _RELAXED_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _ACQUIRE_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_release_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _RELEASE_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acq_rel_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _ACQ_REL_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _SEQ_CST_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_relaxed_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _RELAXED_RELAXED_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acquire_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _ACQUIRE_RELAXED_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acquire_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _ACQUIRE_ACQUIRE_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_release_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _RELEASE_RELAXED_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acq_rel_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _ACQ_REL_RELAXED_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acq_rel_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _ACQ_REL_ACQUIRE_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_seq_cst_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _SEQ_CST_RELAXED_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_seq_cst_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _SEQ_CST_ACQUIRE_), bits); \\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& expected, T desired,\t\t\t\t\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_seq_cst_s,\t\t\t\t\\\n\t\t\t\t  eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_CMPXCHG_FUNC_IMPL(EASTL_ATOMIC_BASE_OP_JOIN(cmpxchgOp, _SEQ_CST_SEQ_CST_), bits); \\\n\t}\n\n#define EASTL_ATOMIC_BASE_CMPXCHG_WEAK_FUNCS_IMPL(bits)\t\t\t\t\t\\\n\tEASTL_ATOMIC_BASE_CMPXCHG_FUNCS_IMPL(compare_exchange_weak, CMPXCHG_WEAK, bits)\n\n#define EASTL_ATOMIC_BASE_CMPXCHG_STRONG_FUNCS_IMPL(bits)\t\t\t\t\\\n\tEASTL_ATOMIC_BASE_CMPXCHG_FUNCS_IMPL(compare_exchange_strong, CMPXCHG_STRONG, bits)\n\n\n#define EASTL_ATOMIC_BASE_WIDTH_SPECIALIZE(bytes, bits)\t\t\t\t\t\\\n\ttemplate <typename T>\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstruct atomic_base_width<T, bytes> : public atomic_size_aligned<T>\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tprivate:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tstatic_assert(EA_ALIGN_OF(atomic_size_aligned<T>) == bytes, \"eastl::atomic<T> must be sizeof(T) aligned!\"); \\\n\t\tstatic_assert(EA_ALIGN_OF(atomic_size_aligned<T>) == sizeof(T), \"eastl::atomic<T> must be sizeof(T) aligned!\"); \\\n\t\tusing Base = atomic_size_aligned<T>;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* ctors */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic_base_width(T desired) EA_NOEXCEPT\t\t\t\\\n\t\t\t: Base{ desired }\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic_base_width() EA_NOEXCEPT_IF(eastl::is_nothrow_default_constructible_v<T>) = default; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic_base_width(const atomic_base_width&) EA_NOEXCEPT = delete; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* store */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::store;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoid store(T desired) EA_NOEXCEPT\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_STORE_FUNC_IMPL(EASTL_ATOMIC_STORE_SEQ_CST_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoid store(T desired, eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_STORE_FUNC_IMPL(EASTL_ATOMIC_STORE_RELAXED_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoid store(T desired, eastl::internal::memory_order_release_s) EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_STORE_FUNC_IMPL(EASTL_ATOMIC_STORE_RELEASE_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tvoid store(T desired, eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_STORE_FUNC_IMPL(EASTL_ATOMIC_STORE_SEQ_CST_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* load */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::load;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT load() const EA_NOEXCEPT\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_LOAD_FUNC_IMPL(EASTL_ATOMIC_LOAD_SEQ_CST_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT load(eastl::internal::memory_order_relaxed_s) const EA_NOEXCEPT \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_LOAD_FUNC_IMPL(EASTL_ATOMIC_LOAD_RELAXED_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT load(eastl::internal::memory_order_acquire_s) const EA_NOEXCEPT \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_LOAD_FUNC_IMPL(EASTL_ATOMIC_LOAD_ACQUIRE_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT load(eastl::internal::memory_order_seq_cst_s) const EA_NOEXCEPT \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_LOAD_FUNC_IMPL(EASTL_ATOMIC_LOAD_SEQ_CST_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* exchange */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::exchange;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT exchange(T desired) EA_NOEXCEPT\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_FUNC_IMPL(EASTL_ATOMIC_EXCHANGE_SEQ_CST_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT exchange(T desired, eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_FUNC_IMPL(EASTL_ATOMIC_EXCHANGE_RELAXED_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT exchange(T desired, eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_FUNC_IMPL(EASTL_ATOMIC_EXCHANGE_ACQUIRE_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT exchange(T desired, eastl::internal::memory_order_release_s) EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_FUNC_IMPL(EASTL_ATOMIC_EXCHANGE_RELEASE_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT exchange(T desired, eastl::internal::memory_order_acq_rel_s) EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_FUNC_IMPL(EASTL_ATOMIC_EXCHANGE_ACQ_REL_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT exchange(T desired, eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_EXCHANGE_FUNC_IMPL(EASTL_ATOMIC_EXCHANGE_SEQ_CST_, bits); \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* compare_exchange_weak */\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_BASE_CMPXCHG_WEAK_FUNCS_IMPL(bits)\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* compare_exchange_strong */\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_BASE_CMPXCHG_STRONG_FUNCS_IMPL(bits)\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* assignment operator */\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::operator=;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT operator=(T desired) EA_NOEXCEPT\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tstore(desired, eastl::memory_order_seq_cst);\t\t\t\t\\\n\t\t\treturn desired;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic_base_width& operator=(const atomic_base_width&)          EA_NOEXCEPT = delete; \\\n\t\tatomic_base_width& operator=(const atomic_base_width&) volatile EA_NOEXCEPT = delete; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t};\n\n\n#if defined(EASTL_ATOMIC_HAS_8BIT)\n\tEASTL_ATOMIC_BASE_WIDTH_SPECIALIZE(1, 8)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_16BIT)\n\tEASTL_ATOMIC_BASE_WIDTH_SPECIALIZE(2, 16)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\tEASTL_ATOMIC_BASE_WIDTH_SPECIALIZE(4, 32)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\tEASTL_ATOMIC_BASE_WIDTH_SPECIALIZE(8, 64)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\tEASTL_ATOMIC_BASE_WIDTH_SPECIALIZE(16, 128)\n#endif\n\nEA_RESTORE_VC_WARNING();\n\nEA_RESTORE_CLANG_WARNING();\n\n\n} // namespace internal\n\n\n} // namespace eastl\n\n#endif /* EASTL_ATOMIC_INTERNAL_BASE_WIDTH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_casts.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_CASTS_H\n#define EASTL_ATOMIC_INTERNAL_CASTS_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#include <EASTL/internal/type_transformations.h>\n\n\n#include <string.h>\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\ntemplate <typename T>\nEASTL_FORCE_INLINE volatile T* AtomicVolatileCast(T* ptr) EA_NOEXCEPT\n{\n\tstatic_assert(!eastl::is_volatile<volatile T*>::value, \"eastl::atomic<T> : pointer must not be volatile, the pointed to type must be volatile!\");\n\tstatic_assert(eastl::is_volatile<volatile T>::value, \"eastl::atomic<T> : the pointed to type must be volatile!\");\n\n\treturn reinterpret_cast<volatile T*>(ptr);\n}\n\n\n/**\n * NOTE:\n *\n * Some compiler intrinsics do not operate on pointer types thus\n * doing atomic operations on pointers must be casted to the suitable\n * sized unsigned integral type.\n *\n * Some compiler intrinsics aren't generics and thus structs must also\n * be casted to the appropriate sized unsigned integral type.\n *\n * Atomic operations on an int* might have to be casted to a uint64_t on\n * a platform with 8-byte pointers as an example.\n *\n * Also doing an atomic operation on a struct, we must ensure that we observe\n * the whole struct as one atomic unit with no shearing between the members.\n * A load of a struct with two uint32_t members must be one uint64_t load,\n * not two separate uint32_t loads, thus casted to the suitable sized\n * unsigned integral type.\n */\ntemplate <typename Integral, typename T>\nEASTL_FORCE_INLINE volatile Integral* AtomicVolatileIntegralCast(T* ptr) EA_NOEXCEPT\n{\n\tstatic_assert(!eastl::is_volatile<volatile Integral*>::value, \"eastl::atomic<T> : pointer must not be volatile, the pointed to type must be volatile!\");\n\tstatic_assert(eastl::is_volatile<volatile Integral>::value, \"eastl::atomic<T> : the pointed to type must be volatile!\");\n\tstatic_assert(eastl::is_integral<Integral>::value, \"eastl::atomic<T> : Integral cast must cast to an Integral type!\");\n\tstatic_assert(sizeof(Integral) == sizeof(T), \"eastl::atomic<T> : Integral and T must be same size for casting!\");\n\n\treturn reinterpret_cast<volatile Integral*>(ptr);\n}\n\ntemplate <typename Integral, typename T>\nEASTL_FORCE_INLINE Integral* AtomicIntegralCast(T* ptr) EA_NOEXCEPT\n{\n\tstatic_assert(eastl::is_integral<Integral>::value, \"eastl::atomic<T> : Integral cast must cast to an Integral type!\");\n\tstatic_assert(sizeof(Integral) == sizeof(T), \"eastl::atomic<T> : Integral and T must be same size for casting!\");\n\n\treturn reinterpret_cast<Integral*>(ptr);\n}\n\n\n/**\n * NOTE:\n *\n * These casts are meant to be used with unions or structs of larger types that must be casted\n * down to the smaller integral types. Like with 128-bit atomics and msvc intrinsics.\n *\n * struct Foo128 { __int64 array[2]; }; can be casted to a __int64*\n * since a poiter to Foo128 is a pointer to the first member.\n */\ntemplate <typename ToType, typename FromType>\nEASTL_FORCE_INLINE volatile ToType* AtomicVolatileTypeCast(FromType* ptr) EA_NOEXCEPT\n{\n\tstatic_assert(!eastl::is_volatile<volatile ToType*>::value, \"eastl::atomic<T> : pointer must not be volatile, the pointed to type must be volatile!\");\n\tstatic_assert(eastl::is_volatile<volatile ToType>::value, \"eastl::atomic<T> : the pointed to type must be volatile!\");\n\n\treturn reinterpret_cast<volatile ToType*>(ptr);\n}\n\ntemplate <typename ToType, typename FromType>\nEASTL_FORCE_INLINE ToType* AtomicTypeCast(FromType* ptr) EA_NOEXCEPT\n{\n\treturn reinterpret_cast<ToType*>(ptr);\n}\n\n\n/**\n * NOTE:\n *\n * This is a compiler guaranteed safe type punning.\n * This is useful when dealing with user defined structs.\n * struct Test { uint32_t; unint32_t; };\n *\n * Example:\n * uint64_t atomicLoad = *((volatile uint64_t*)&Test);\n * Test load = AtomicTypePunCast<Test, uint64_t>(atomicLoad);\n *\n * uint64_t comparand = AtomicTypePunCast<uint64_t, Test>(Test);\n * cmpxchg(&Test, comparand, desired);\n *\n * This can be implemented in many different ways depending on the compiler such\n * as thru a union, memcpy, reinterpret_cast<Test&>(atomicLoad), etc.\n */\ntemplate <typename Pun, typename T, eastl::enable_if_t<!eastl::is_same_v<Pun, T>, int> = 0>\nEASTL_FORCE_INLINE Pun AtomicTypePunCast(const T& fromType) EA_NOEXCEPT\n{\n\tstatic_assert(sizeof(Pun) == sizeof(T), \"eastl::atomic<T> : Pun and T must be the same size for type punning!\");\n\n\t/**\n\t * aligned_storage ensures we can TypePun objects that aren't trivially default constructible\n\t * but still trivially copyable.\n\t */\n\ttypename eastl::aligned_storage<sizeof(Pun), alignof(Pun)>::type ret;\n\tmemcpy(eastl::addressof(ret), eastl::addressof(fromType), sizeof(Pun));\n\treturn reinterpret_cast<Pun&>(ret);\n}\n\ntemplate <typename Pun, typename T, eastl::enable_if_t<eastl::is_same_v<Pun, T>, int> = 0>\nEASTL_FORCE_INLINE Pun AtomicTypePunCast(const T& fromType) EA_NOEXCEPT\n{\n\treturn fromType;\n}\n\n\ntemplate <typename T>\nEASTL_FORCE_INLINE T AtomicNegateOperand(T val) EA_NOEXCEPT\n{\n\tstatic_assert(eastl::is_integral<T>::value, \"eastl::atomic<T> : Integral Negation must be an Integral type!\");\n\tstatic_assert(!eastl::is_volatile<T>::value, \"eastl::atomic<T> : T must not be volatile!\");\n\n\treturn static_cast<T>(0U - static_cast<eastl::make_unsigned_t<T>>(val));\n}\n\nEASTL_FORCE_INLINE ptrdiff_t AtomicNegateOperand(ptrdiff_t val) EA_NOEXCEPT\n{\n\treturn -val;\n}\n\n\n} // namespace internal\n\n\n} // namespace eastl\n\n\n/**\n *  NOTE:\n *\n *  These macros are meant to prevent inclusion hell.\n *  Also so that it fits with the style of the rest of the atomic macro implementation.\n */\n#define EASTL_ATOMIC_VOLATILE_CAST(ptr)\t\t\t\\\n\teastl::internal::AtomicVolatileCast((ptr))\n\n#define EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(IntegralType, ptr)\t\t\\\n\teastl::internal::AtomicVolatileIntegralCast<IntegralType>((ptr))\n\n#define EASTL_ATOMIC_INTEGRAL_CAST(IntegralType, ptr)\t\t\\\n\teastl::internal::AtomicIntegralCast<IntegralType>((ptr))\n\n#define EASTL_ATOMIC_VOLATILE_TYPE_CAST(ToType, ptr)\t\t\\\n\teastl::internal::AtomicVolatileTypeCast<ToType>((ptr))\n\n#define EASTL_ATOMIC_TYPE_CAST(ToType, ptr)\t\t\t\\\n\teastl::internal::AtomicTypeCast<ToType>((ptr))\n\n#define EASTL_ATOMIC_TYPE_PUN_CAST(PunType, fromType)\t\t\\\n\teastl::internal::AtomicTypePunCast<PunType>((fromType))\n\n#define EASTL_ATOMIC_NEGATE_OPERAND(val)\t\t\\\n\teastl::internal::AtomicNegateOperand((val))\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_CASTS_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_flag.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNA_ATOMIC_FLAG_H\n#define EASTL_ATOMIC_INTERNA_ATOMIC_FLAG_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\n// 'class' : multiple assignment operators specified\nEA_DISABLE_VC_WARNING(4522);\n\n// misaligned atomic operation may incur significant performance penalty\n// The above warning is emitted in earlier versions of clang incorrectly.\n// All eastl::atomic<T> objects are size aligned.\n// This is static and runtime asserted.\n// Thus we disable this warning.\nEA_DISABLE_CLANG_WARNING(-Watomic-alignment);\n\n\nclass atomic_flag\n{\npublic: /* ctors */\n\n\tEA_CONSTEXPR atomic_flag(bool desired) EA_NOEXCEPT\n\t\t: mFlag{ desired }\n\t{\n\t}\n\n\tEA_CONSTEXPR atomic_flag() EA_NOEXCEPT\n\t\t: mFlag{ false }\n\t{\n\t}\n\npublic: /* deleted ctors && assignment operators */\n\n\tatomic_flag(const atomic_flag&) EA_NOEXCEPT = delete;\n\n\tatomic_flag& operator=(const atomic_flag&)          EA_NOEXCEPT = delete;\n\tatomic_flag& operator=(const atomic_flag&) volatile EA_NOEXCEPT = delete;\n\npublic: /* clear */\n\n\ttemplate <typename Order>\n\tvoid clear(Order /*order*/) volatile EA_NOEXCEPT\n\t{\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(Order);\n\t}\n\n\ttemplate <typename Order>\n\tvoid clear(Order /*order*/) EA_NOEXCEPT\n\t{\n\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(Order);\n\t}\n\n\tvoid clear(eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\n\t{\n\t\tmFlag.store(false, eastl::memory_order_relaxed);\n\t}\n\n\tvoid clear(eastl::internal::memory_order_release_s) EA_NOEXCEPT\n\t{\n\t\tmFlag.store(false, eastl::memory_order_release);\n\t}\n\n\tvoid clear(eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\n\t{\n\t\tmFlag.store(false, eastl::memory_order_seq_cst);\n\t}\n\n\tvoid clear() EA_NOEXCEPT\n\t{\n\t\tmFlag.store(false, eastl::memory_order_seq_cst);\n\t}\n\npublic: /* test_and_set */\n\n\ttemplate <typename Order>\n\tbool test_and_set(Order /*order*/) volatile EA_NOEXCEPT\n\t{\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(Order);\n\t\treturn false;\n\t}\n\n\ttemplate <typename Order>\n\tbool test_and_set(Order /*order*/) EA_NOEXCEPT\n\t{\n\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(Order);\n\t\treturn false;\n\t}\n\n\tbool test_and_set(eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\n\t{\n\t\treturn mFlag.exchange(true, eastl::memory_order_relaxed);\n\t}\n\n\tbool test_and_set(eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\n\t{\n\t\treturn mFlag.exchange(true, eastl::memory_order_acquire);\n\t}\n\n\tbool test_and_set(eastl::internal::memory_order_release_s) EA_NOEXCEPT\n\t{\n\t\treturn mFlag.exchange(true, eastl::memory_order_release);\n\t}\n\n\tbool test_and_set(eastl::internal::memory_order_acq_rel_s) EA_NOEXCEPT\n\t{\n\t\treturn mFlag.exchange(true, eastl::memory_order_acq_rel);\n\t}\n\n\tbool test_and_set(eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\n\t{\n\t\treturn mFlag.exchange(true, eastl::memory_order_seq_cst);\n\t}\n\n\tbool test_and_set() EA_NOEXCEPT\n\t{\n\t\treturn mFlag.exchange(true, eastl::memory_order_seq_cst);\n\t}\n\npublic: /* test */\n\n\ttemplate <typename Order>\n\tbool test(Order /*order*/) const volatile EA_NOEXCEPT\n\t{\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(Order);\n\t\treturn false;\n\t}\n\n\ttemplate <typename Order>\n\tbool test(Order /*order*/) const EA_NOEXCEPT\n\t{\n\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(Order);\n\t\treturn false;\n\t}\n\n\tbool test(eastl::internal::memory_order_relaxed_s) const EA_NOEXCEPT\n\t{\n\t\treturn mFlag.load(eastl::memory_order_relaxed);\n\t}\n\n\tbool test(eastl::internal::memory_order_acquire_s) const EA_NOEXCEPT\n\t{\n\t\treturn mFlag.load(eastl::memory_order_acquire);\n\t}\n\n\tbool test(eastl::internal::memory_order_seq_cst_s) const EA_NOEXCEPT\n\t{\n\t\treturn mFlag.load(eastl::memory_order_seq_cst);\n\t}\n\n\tbool test() const EA_NOEXCEPT\n\t{\n\t\treturn mFlag.load(eastl::memory_order_seq_cst);\n\t}\n\nprivate:\n\n\teastl::atomic<bool> mFlag;\n};\n\nEA_RESTORE_VC_WARNING();\n\nEA_RESTORE_CLANG_WARNING();\n\n\n} // namespace eastl\n\n#endif /* EASTL_ATOMIC_INTERNA_ATOMIC_FLAG_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_flag_standalone.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_FLAG_STANDALONE_H\n#define EASTL_ATOMIC_INTERNAL_FLAG_STANDALONE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// bool atomic_flag_test_and_set(eastl::atomic<T>*)\n//\nEASTL_FORCE_INLINE bool atomic_flag_test_and_set(eastl::atomic_flag* atomicObj) EA_NOEXCEPT\n{\n\treturn atomicObj->test_and_set();\n}\n\ntemplate <typename Order>\nEASTL_FORCE_INLINE bool atomic_flag_test_and_set_explicit(eastl::atomic_flag* atomicObj, Order order)\n{\n\treturn atomicObj->test_and_set(order);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// bool atomic_flag_clear(eastl::atomic<T>*)\n//\nEASTL_FORCE_INLINE void atomic_flag_clear(eastl::atomic_flag* atomicObj)\n{\n\tatomicObj->clear();\n}\n\ntemplate <typename Order>\nEASTL_FORCE_INLINE void atomic_flag_clear_explicit(eastl::atomic_flag* atomicObj, Order order)\n{\n\tatomicObj->clear(order);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// bool atomic_flag_test(eastl::atomic<T>*)\n//\nEASTL_FORCE_INLINE bool atomic_flag_test(eastl::atomic_flag* atomicObj)\n{\n\treturn atomicObj->test();\n}\n\ntemplate <typename Order>\nEASTL_FORCE_INLINE bool atomic_flag_test_explicit(eastl::atomic_flag* atomicObj, Order order)\n{\n\treturn atomicObj->test(order);\n}\n\n\n} // namespace eastl\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_FLAG_STANDALONE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_integral.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_INTEGRAL_H\n#define EASTL_ATOMIC_INTERNAL_INTEGRAL_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\n// 'class' : multiple assignment operators specified\nEA_DISABLE_VC_WARNING(4522);\n\n// misaligned atomic operation may incur significant performance penalty\n// The above warning is emitted in earlier versions of clang incorrectly.\n// All eastl::atomic<T> objects are size aligned.\n// This is static and runtime asserted.\n// Thus we disable this warning.\nEA_DISABLE_CLANG_WARNING(-Watomic-alignment);\n\n\n#define EASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(funcName)\t\\\n\ttemplate <typename Order>\t\t\t\t\t\t\t\t\t\t\\\n\tT funcName(T /*arg*/, Order /*order*/) EA_NOEXCEPT\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(T);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\ttemplate <typename Order>\t\t\t\t\t\t\t\t\t\t\\\n\tT funcName(T /*arg*/, Order /*order*/) volatile EA_NOEXCEPT\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT funcName(T /*arg*/) volatile EA_NOEXCEPT\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\\\n\t}\n\n\n#define EASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_INC_DEC_OPERATOR_IMPL(operatorOp) \\\n\tT operator operatorOp() volatile EA_NOEXCEPT\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT operator operatorOp(int) volatile EA_NOEXCEPT\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t}\n\n\n#define EASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(operatorOp) \\\n\tT operator operatorOp(T /*arg*/) volatile EA_NOEXCEPT\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t}\n\n\n\ttemplate <typename T, unsigned width = sizeof(T)>\n\tstruct atomic_integral_base : public atomic_base_width<T, width>\n\t{\n\tprivate:\n\n\t\tusing Base = atomic_base_width<T, width>;\n\n\tpublic: /* ctors */\n\n\t\tEA_CONSTEXPR atomic_integral_base(T desired) EA_NOEXCEPT\n\t\t\t: Base{ desired }\n\t\t{\n\t\t}\n\n\t\tEA_CONSTEXPR atomic_integral_base() EA_NOEXCEPT = default;\n\n\t\tatomic_integral_base(const atomic_integral_base&) EA_NOEXCEPT = delete;\n\n\tpublic: /* assignment operator */\n\n\t\tusing Base::operator=;\n\n\t\tatomic_integral_base& operator=(const atomic_integral_base&)          EA_NOEXCEPT = delete;\n\t\tatomic_integral_base& operator=(const atomic_integral_base&) volatile EA_NOEXCEPT = delete;\n\n\tpublic: /* fetch_add */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(fetch_add)\n\n\tpublic: /* add_fetch */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(add_fetch)\n\n\tpublic: /* fetch_sub */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(fetch_sub)\n\n\tpublic: /* sub_fetch */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(sub_fetch)\n\n\tpublic: /* fetch_and */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(fetch_and)\n\n\tpublic: /* and_fetch */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(and_fetch)\n\n\tpublic: /* fetch_or */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(fetch_or)\n\n\tpublic: /* or_fetch */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(or_fetch)\n\n\tpublic: /* fetch_xor */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(fetch_xor)\n\n\tpublic: /* xor_fetch */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_FUNCS_IMPL(xor_fetch)\n\n\tpublic: /* operator++ && operator-- */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_INC_DEC_OPERATOR_IMPL(++)\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_INC_DEC_OPERATOR_IMPL(--)\n\n\tpublic: /* operator+= && operator-= */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(+=)\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(-=)\n\n\tpublic: /* operator&= */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(&=)\n\n\tpublic: /* operator|= */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(|=)\n\n\tpublic: /* operator^= */\n\n\t\tEASTL_ATOMIC_INTEGRAL_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(^=)\n\n\t};\n\n\n\ttemplate <typename T, unsigned width = sizeof(T)>\n\tstruct atomic_integral_width;\n\n#define EASTL_ATOMIC_INTEGRAL_FUNC_IMPL(op, bits, ptr, RetType)\t\\\n\tEASTL_ATOMIC_DEFAULT_INIT(RetType, retVal);\t                \\\n\tEA_PREPROCESSOR_JOIN(op, bits)(RetType, retVal, ptr, arg);  \\\n\treturn retVal;\n\n#define EASTL_ATOMIC_INTEGRAL_FETCH_IMPL(funcName, op, bits)\t\\\n\tT funcName(T arg) EA_NOEXCEPT\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FUNC_IMPL(op, bits, this->GetAtomicAddress(), T); \\\n\t}\n\n#define EASTL_ATOMIC_INTEGRAL_FETCH_ORDER_IMPL(funcName, orderType, op, bits)   \\\n\tT funcName(T arg, orderType) EA_NOEXCEPT\t\t\t\t\t\t            \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t        \\\n\t\tEASTL_ATOMIC_INTEGRAL_FUNC_IMPL(op, bits, this->GetAtomicAddress(), T); \\\n\t}\n\n#define EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(fetchOp, Order)\t\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_, fetchOp), Order)\n\n#define EASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(funcName, fetchOp, bits) \\\n\tusing Base::funcName;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_INTEGRAL_FETCH_IMPL(funcName, EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(fetchOp, _SEQ_CST_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_INTEGRAL_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_relaxed_s, \\\n\t\t\t\t\t\t\t\t\t\t   EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(fetchOp, _RELAXED_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_INTEGRAL_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_acquire_s, \\\n\t\t\t\t\t\t\t\t\t\t   EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(fetchOp, _ACQUIRE_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_INTEGRAL_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_release_s, \\\n\t\t\t\t\t\t\t\t\t\t   EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(fetchOp, _RELEASE_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_INTEGRAL_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_acq_rel_s, \\\n\t\t\t\t\t\t\t\t\t\t   EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(fetchOp, _ACQ_REL_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_INTEGRAL_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_seq_cst_s, \\\n\t\t\t\t\t\t\t\t\t\t   EASTL_ATOMIC_INTEGRAL_FETCH_OP_JOIN(fetchOp, _SEQ_CST_), bits)\n\n#define EASTL_ATOMIC_INTEGRAL_FETCH_INC_DEC_OPERATOR_IMPL(operatorOp, preFuncName, postFuncName) \\\n\tusing Base::operator operatorOp;\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT operator operatorOp() EA_NOEXCEPT\t\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn preFuncName(1, eastl::memory_order_seq_cst);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT operator operatorOp(int) EA_NOEXCEPT\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn postFuncName(1, eastl::memory_order_seq_cst);\t\t\t\\\n\t}\n\n#define EASTL_ATOMIC_INTEGRAL_FETCH_ASSIGNMENT_OPERATOR_IMPL(operatorOp, funcName) \\\n\tusing Base::operator operatorOp;\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT operator operatorOp(T arg) EA_NOEXCEPT\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn funcName(arg, eastl::memory_order_seq_cst);\t\t\t\t\\\n\t}\n\n\n#define EASTL_ATOMIC_INTEGRAL_WIDTH_SPECIALIZE(bytes, bits)\t\t\t\t\\\n\ttemplate <typename T>\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstruct atomic_integral_width<T, bytes> : public atomic_integral_base<T, bytes> \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tprivate:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base = atomic_integral_base<T, bytes>;\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* ctors */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic_integral_width(T desired) EA_NOEXCEPT\t\t\\\n\t\t\t: Base{ desired }\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic_integral_width() EA_NOEXCEPT = default;\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic_integral_width(const atomic_integral_width&) EA_NOEXCEPT = delete; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* assignment operator */\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::operator=;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic_integral_width& operator=(const atomic_integral_width&)          EA_NOEXCEPT = delete; \\\n\t\tatomic_integral_width& operator=(const atomic_integral_width&) volatile EA_NOEXCEPT = delete; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* fetch_add */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(fetch_add, FETCH_ADD, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* add_fetch */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(add_fetch, ADD_FETCH, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* fetch_sub */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(fetch_sub, FETCH_SUB, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* sub_fetch */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(sub_fetch, SUB_FETCH, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* fetch_and */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(fetch_and, FETCH_AND, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* and_fetch */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(and_fetch, AND_FETCH, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* fetch_or */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(fetch_or, FETCH_OR, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* or_fetch */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(or_fetch, OR_FETCH, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* fetch_xor */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(fetch_xor, FETCH_XOR, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* xor_fetch */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_FUNCS_IMPL(xor_fetch, XOR_FETCH, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* operator++ && operator-- */\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_INC_DEC_OPERATOR_IMPL(++, add_fetch, fetch_add) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_INC_DEC_OPERATOR_IMPL(--, sub_fetch, fetch_sub) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* operator+= && operator-= */\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_ASSIGNMENT_OPERATOR_IMPL(+=, add_fetch) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_ASSIGNMENT_OPERATOR_IMPL(-=, sub_fetch) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* operator&= */\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_ASSIGNMENT_OPERATOR_IMPL(&=, and_fetch) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* operator|= */\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_ASSIGNMENT_OPERATOR_IMPL(|=, or_fetch) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* operator^= */\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTEGRAL_FETCH_ASSIGNMENT_OPERATOR_IMPL(^=, xor_fetch) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic:                                                             \\\n\t\tvoid acquire_fence() const                                      \\\n\t\t{                                                               \\\n\t\t\tEASTL_INTERNAL_TSAN_ACQUIRE(this->GetAtomicAddress());      \\\n\t\t\tEASTL_ATOMIC_ACQUIRE_FENCE();                               \\\n\t\t}                                                               \\\n\t};\n\n\n#if defined(EASTL_ATOMIC_HAS_8BIT)\n\tEASTL_ATOMIC_INTEGRAL_WIDTH_SPECIALIZE(1, 8)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_16BIT)\n\tEASTL_ATOMIC_INTEGRAL_WIDTH_SPECIALIZE(2, 16)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\tEASTL_ATOMIC_INTEGRAL_WIDTH_SPECIALIZE(4, 32)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\tEASTL_ATOMIC_INTEGRAL_WIDTH_SPECIALIZE(8, 64)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\tEASTL_ATOMIC_INTEGRAL_WIDTH_SPECIALIZE(16, 128)\n#endif\n\nEA_RESTORE_VC_WARNING();\n\nEA_RESTORE_CLANG_WARNING();\n\n\n} // namespace internal\n\n\n} // namespace eastl\n\n#endif /* EASTL_ATOMIC_INTERNAL_INTEGRAL_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_ATOMIC_MACROS_H\n#define EASTL_ATOMIC_INTERNAL_ATOMIC_MACROS_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EABase/eabase.h>\n\n#include \"atomic_macros_base.h\"\n\n#include \"atomic_macros_fetch_add.h\"\n#include \"atomic_macros_fetch_sub.h\"\n\n#include \"atomic_macros_fetch_and.h\"\n#include \"atomic_macros_fetch_xor.h\"\n#include \"atomic_macros_fetch_or.h\"\n\n#include \"atomic_macros_add_fetch.h\"\n#include \"atomic_macros_sub_fetch.h\"\n\n#include \"atomic_macros_and_fetch.h\"\n#include \"atomic_macros_xor_fetch.h\"\n#include \"atomic_macros_or_fetch.h\"\n\n#include \"atomic_macros_exchange.h\"\n\n#include \"atomic_macros_cmpxchg_weak.h\"\n#include \"atomic_macros_cmpxchg_strong.h\"\n\n#include \"atomic_macros_load.h\"\n#include \"atomic_macros_store.h\"\n\n#include \"atomic_macros_compiler_barrier.h\"\n\n#include \"atomic_macros_cpu_pause.h\"\n\n#include \"atomic_macros_memory_barrier.h\"\n\n#include \"atomic_macros_signal_fence.h\"\n\n#include \"atomic_macros_thread_fence.h\"\n\n#include \"atomic_macros_acquire_fence.h\"\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#if defined(EASTL_COMPILER_ATOMIC_HAS_8BIT) || defined(EASTL_ARCH_ATOMIC_HAS_8BIT)\n\n\t#define EASTL_ATOMIC_HAS_8BIT\n\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_HAS_16BIT) || defined(EASTL_ARCH_ATOMIC_HAS_16BIT)\n\n\t#define EASTL_ATOMIC_HAS_16BIT\n\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_HAS_32BIT) || defined(EASTL_ARCH_ATOMIC_HAS_32BIT)\n\n\t#define EASTL_ATOMIC_HAS_32BIT\n\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_HAS_64BIT) || defined(EASTL_ARCH_ATOMIC_HAS_64BIT)\n\n\t#define EASTL_ATOMIC_HAS_64BIT\n\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_HAS_128BIT) || defined(EASTL_ARCH_ATOMIC_HAS_128BIT)\n\n\t#define EASTL_ATOMIC_HAS_128BIT\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#if defined(EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_8)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_8 EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_8\n\n#elif defined(EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_8)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_8 EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_8\n\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_16)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_16 EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_16\n\n#elif defined(EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_16)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_16 EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_16\n\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_32)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_32 EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_32\n\n#elif defined(EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_32)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_32 EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_32\n\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_64)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_64 EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_64\n\n#elif defined(EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_64)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_64 EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_64\n\n#endif\n\n\n#if defined(EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_128)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_128 EASTL_ARCH_ATOMIC_FIXED_WIDTH_TYPE_128\n\n#elif defined(EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_128)\n\n\t#define EASTL_ATOMIC_FIXED_WIDTH_TYPE_128 EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_128\n\n#endif\n\n// We write some of our variables in inline assembly, which MSAN\n// doesn't understand.  This macro forces initialization of those\n// variables when MSAN is enabled and doesn't pay the initialization\n// cost when it's not enabled.\n#if EA_MSAN_ENABLED\n\t#define EASTL_ATOMIC_DEFAULT_INIT(type, var) type var{}\n#else\n\t#define EASTL_ATOMIC_DEFAULT_INIT(type, var) type var\n#endif // EA_MSAN_ENABLED\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_ATOMIC_MACROS_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_acquire_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_ACQUIRE_FENCE()\n//\n#define EASTL_ATOMIC_ACQUIRE_FENCE()                          \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ACQUIRE_FENCE)()\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_add_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_ADD_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_ADD_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_ADD_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_ADD_FETCH_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_ADD_FETCH_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_ADD_FETCH_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_ADD_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_ADD_FETCH_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_ADD_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_ADD_FETCH_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_ADD_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_and_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_AND_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_AND_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_AND_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_AND_FETCH_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_AND_FETCH_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_AND_FETCH_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_AND_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_AND_FETCH_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_AND_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_AND_FETCH_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_AND_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_base.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_BASE_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_BASE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_ATOMIC_INTERNAL_COMPILER_AVAILABLE(op)\t\t\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_COMPILER_, op), _AVAILABLE)\n\n#define EASTL_ATOMIC_INTERNAL_ARCH_AVAILABLE(op)\t\t\t\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ARCH_, op), _AVAILABLE)\n\n\n// We can't just use static_assert(false, ...) here, since on MSVC 17.10 \n// the /Zc:static_assert flag makes non-dependent static_asserts in the body of a template \n// be evaluated at template-parse time, rather than at template instantion time.\n// So instead we just make the assert dependent on the type.\n#define EASTL_ATOMIC_INTERNAL_NOT_IMPLEMENTED_ERROR(...)\t\t\t\t\\\n\tstatic_assert(!eastl::is_same_v<T,T>, \"eastl::atomic<T> atomic macro not implemented!\")\n\n\n/* Compiler && Arch Not Implemented */\n#define EASTL_ATOMIC_INTERNAL_OP_PATTERN_00(op) \\\n\tEASTL_ATOMIC_INTERNAL_NOT_IMPLEMENTED_ERROR\n\n/* Arch Implemented */\n#define EASTL_ATOMIC_INTERNAL_OP_PATTERN_01(op) \\\n\tEA_PREPROCESSOR_JOIN(EASTL_ARCH_, op)\n\n/* Compiler Implmented */\n#define EASTL_ATOMIC_INTERNAL_OP_PATTERN_10(op) \\\n\tEA_PREPROCESSOR_JOIN(EASTL_COMPILER_, op)\n\n/* Compiler && Arch Implemented */\n#define EASTL_ATOMIC_INTERNAL_OP_PATTERN_11(op) \\\n\tEA_PREPROCESSOR_JOIN(EASTL_ARCH_, op)\n\n\n/* This macro creates the pattern macros above for the 2x2 True-False truth table */\n#define EASTL_ATOMIC_INTERNAL_OP_HELPER1(compiler, arch, op)\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(EASTL_ATOMIC_INTERNAL_OP_PATTERN_, EA_PREPROCESSOR_JOIN(compiler, arch))(op)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// EASTL_ATOMIC_CHOOSE_OP_IMPL\n//\n// This macro chooses between the compiler or architecture implementation for a\n// given atomic operation.\n//\n// USAGE:\n//\n// EASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELAXED_8)(ret, ptr, val)\n//\n#define EASTL_ATOMIC_CHOOSE_OP_IMPL(op)\t\t\t\t\t\\\n\tEASTL_ATOMIC_INTERNAL_OP_HELPER1(\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_INTERNAL_COMPILER_AVAILABLE(op),\t\\\n\t\tEASTL_ATOMIC_INTERNAL_ARCH_AVAILABLE(op),\t\t\\\n\t\top\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_BASE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_cmpxchg_strong.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_CMPXCHG_STRONG_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_CMPXCHG_STRONG_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CMPXCHG_STRONG_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128)(type, ret, ptr, expected, desired)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CMPXCHG_STRONG_*(bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_8)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_16)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_32)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_64)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_RELEASE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_RELEASE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_ACQ_REL_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_ACQ_REL_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_STRONG_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_STRONG_SEQ_CST_128)(type, ret, ptr, expected, desired)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_CMPXCHG_STRONG_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_cmpxchg_weak.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_CMPXCHG_WEAK_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_CMPXCHG_WEAK_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CMPXCHG_WEAK_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128)(type, ret, ptr, expected, desired)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CMPXCHG_WEAK_*(bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_8)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_8)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_16)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_16)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_32)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_32)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_64)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_64)(type, ret, ptr, expected, desired)\n\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELAXED_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQUIRE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_RELEASE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_RELEASE_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_ACQ_REL_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_ACQ_REL_128)(type, ret, ptr, expected, desired)\n\n#define EASTL_ATOMIC_CMPXCHG_WEAK_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CMPXCHG_WEAK_SEQ_CST_128)(type, ret, ptr, expected, desired)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_CMPXCHG_WEAK_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_compiler_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_COMPILER_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_COMPILER_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_COMPILER_BARRIER()\n//\n#define EASTL_ATOMIC_COMPILER_BARRIER()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_COMPILER_BARRIER)()\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(const T&, type)\n//\n#define EASTL_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(val, type)\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY)(val, type)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_COMPILER_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_cpu_pause.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_CPU_PAUSE_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_CPU_PAUSE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CPU_PAUSE()\n//\n#define EASTL_ATOMIC_CPU_PAUSE()\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CPU_PAUSE)()\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_CPU_PAUSE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_exchange.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_EXCHANGE_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_EXCHANGE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_EXCHANGE_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_EXCHANGE_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_EXCHANGE_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_EXCHANGE_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_EXCHANGE_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_EXCHANGE_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_EXCHANGE_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_EXCHANGE_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_EXCHANGE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_fetch_add.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_FETCH_ADD_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_FETCH_ADD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_FETCH_ADD_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_FETCH_ADD_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_ADD_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_ADD_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_ADD_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_ADD_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_ADD_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_ADD_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_FETCH_ADD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_fetch_and.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_FETCH_AND_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_FETCH_AND_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_FETCH_AND_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_FETCH_AND_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_AND_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_AND_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_AND_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_AND_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_AND_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_AND_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_FETCH_AND_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_fetch_or.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_FETCH_OR_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_FETCH_OR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_FETCH_OR_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_FETCH_OR_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_OR_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_OR_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_OR_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_OR_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_OR_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_OR_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_FETCH_OR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_fetch_sub.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_FETCH_SUB_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_FETCH_SUB_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_FETCH_SUB_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_FETCH_SUB_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_SUB_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_SUB_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_SUB_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_SUB_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_SUB_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_SUB_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_FETCH_SUB_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_fetch_xor.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_FETCH_XOR_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_FETCH_XOR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_FETCH_XOR_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_FETCH_XOR_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_XOR_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_XOR_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_XOR_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_FETCH_XOR_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_FETCH_XOR_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_FETCH_XOR_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_FETCH_XOR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_load.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_LOAD_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_LOAD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_LOAD_*_N(type, type ret, type * ptr)\n//\n#define EASTL_ATOMIC_LOAD_RELAXED_8(type, ret, ptr)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_RELAXED_8)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_ACQUIRE_8(type, ret, ptr)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_ACQUIRE_8)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_SEQ_CST_8(type, ret, ptr)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_SEQ_CST_8)(type, ret, ptr)\n\n\n#define EASTL_ATOMIC_LOAD_RELAXED_16(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_RELAXED_16)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_ACQUIRE_16(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_ACQUIRE_16)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_SEQ_CST_16(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_SEQ_CST_16)(type, ret, ptr)\n\n\n#define EASTL_ATOMIC_LOAD_RELAXED_32(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_RELAXED_32)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_ACQUIRE_32(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_ACQUIRE_32)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_SEQ_CST_32(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_SEQ_CST_32)(type, ret, ptr)\n\n\n#define EASTL_ATOMIC_LOAD_RELAXED_64(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_RELAXED_64)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_ACQUIRE_64(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_ACQUIRE_64)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_SEQ_CST_64(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_SEQ_CST_64)(type, ret, ptr)\n\n\n#define EASTL_ATOMIC_LOAD_RELAXED_128(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_RELAXED_128)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_ACQUIRE_128(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_ACQUIRE_128)(type, ret, ptr)\n\n#define EASTL_ATOMIC_LOAD_SEQ_CST_128(type, ret, ptr)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_LOAD_SEQ_CST_128)(type, ret, ptr)\n\n\n/**\n * NOTE:\n *\n * These are used for data-dependent reads through a pointer.  By default,\n * the implementation assumes the hardware doesn't reorder dependent loads\n * (unlike the DEC Alpha), which is why we just forward the implementation\n * to the relaxed version of the operations. However, this can be\n * configured to use acquire semantics instead.\n */\n#if EA_IS_ENABLED(EASTL_ATOMIC_READ_DEPENDS_IS_ACQUIRE)\n#define EASTL_ATOMIC_LOAD_READ_DEPENDS_32(type, ret, ptr) EASTL_ATOMIC_LOAD_ACQUIRE_32(type, ret, ptr)\n#define EASTL_ATOMIC_LOAD_READ_DEPENDS_64(type, ret, ptr) EASTL_ATOMIC_LOAD_ACQUIRE_64(type, ret, ptr)\n#else\n#define EASTL_ATOMIC_LOAD_READ_DEPENDS_32(type, ret, ptr) EASTL_ATOMIC_LOAD_RELAXED_32(type, ret, ptr)\n#define EASTL_ATOMIC_LOAD_READ_DEPENDS_64(type, ret, ptr) EASTL_ATOMIC_LOAD_RELAXED_64(type, ret, ptr)\n#endif\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_LOAD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_memory_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_MEMORY_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_MEMORY_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CPU_MB()\n//\n#define EASTL_ATOMIC_CPU_MB()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CPU_MB)()\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CPU_WMB()\n//\n#define EASTL_ATOMIC_CPU_WMB()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CPU_WMB)()\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_CPU_RMB()\n//\n#define EASTL_ATOMIC_CPU_RMB()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_CPU_RMB)()\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_MEMORY_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_or_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_OR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_OR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_OR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_OR_FETCH_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_OR_FETCH_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_OR_FETCH_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_OR_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_OR_FETCH_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_OR_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_OR_FETCH_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_OR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_signal_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_SIGNAL_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_SIGNAL_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_SIGNAL_FENCE_*()\n//\n#define EASTL_ATOMIC_SIGNAL_FENCE_RELAXED()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SIGNAL_FENCE_RELAXED)()\n\n#define EASTL_ATOMIC_SIGNAL_FENCE_ACQUIRE()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SIGNAL_FENCE_ACQUIRE)()\n\n#define EASTL_ATOMIC_SIGNAL_FENCE_RELEASE()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SIGNAL_FENCE_RELEASE)()\n\n#define EASTL_ATOMIC_SIGNAL_FENCE_ACQ_REL()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SIGNAL_FENCE_ACQ_REL)()\n\n#define EASTL_ATOMIC_SIGNAL_FENCE_SEQ_CST()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SIGNAL_FENCE_SEQ_CST)()\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_SIGNAL_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_store.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_STORE_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_STORE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_STORE_*_N(type, type * ptr, type val)\n//\n#define EASTL_ATOMIC_STORE_RELAXED_8(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELAXED_8)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_RELEASE_8(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELEASE_8)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_SEQ_CST_8(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_SEQ_CST_8)(type, ptr, val)\n\n\n#define EASTL_ATOMIC_STORE_RELAXED_16(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELAXED_16)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_RELEASE_16(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELEASE_16)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_SEQ_CST_16(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_SEQ_CST_16)(type, ptr, val)\n\n\n#define EASTL_ATOMIC_STORE_RELAXED_32(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELAXED_32)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_RELEASE_32(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELEASE_32)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_SEQ_CST_32(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_SEQ_CST_32)(type, ptr, val)\n\n\n#define EASTL_ATOMIC_STORE_RELAXED_64(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELAXED_64)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_RELEASE_64(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELEASE_64)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_SEQ_CST_64(type, ptr, val)\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_SEQ_CST_64)(type, ptr, val)\n\n\n#define EASTL_ATOMIC_STORE_RELAXED_128(type, ptr, val)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELAXED_128)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_RELEASE_128(type, ptr, val)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_RELEASE_128)(type, ptr, val)\n\n#define EASTL_ATOMIC_STORE_SEQ_CST_128(type, ptr, val)\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_STORE_SEQ_CST_128)(type, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_STORE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_sub_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_SUB_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_SUB_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_SUB_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_SUB_FETCH_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_SUB_FETCH_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_SUB_FETCH_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_SUB_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_SUB_FETCH_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_SUB_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_SUB_FETCH_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_SUB_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_thread_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_THREAD_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_THREAD_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_THREAD_FENCE_*()\n//\n#define EASTL_ATOMIC_THREAD_FENCE_RELAXED()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_THREAD_FENCE_RELAXED)()\n\n#define EASTL_ATOMIC_THREAD_FENCE_ACQUIRE()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_THREAD_FENCE_ACQUIRE)()\n\n#define EASTL_ATOMIC_THREAD_FENCE_RELEASE()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_THREAD_FENCE_RELEASE)()\n\n#define EASTL_ATOMIC_THREAD_FENCE_ACQ_REL()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_THREAD_FENCE_ACQ_REL)()\n\n#define EASTL_ATOMIC_THREAD_FENCE_SEQ_CST()\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_THREAD_FENCE_SEQ_CST)()\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_THREAD_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros/atomic_macros_xor_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_XOR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_XOR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_ATOMIC_XOR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_ATOMIC_XOR_FETCH_RELAXED_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELAXED_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQUIRE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_RELEASE_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELEASE_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQ_REL_8)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_SEQ_CST_8)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_XOR_FETCH_RELAXED_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELAXED_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQUIRE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_RELEASE_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELEASE_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQ_REL_16)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_SEQ_CST_16)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_XOR_FETCH_RELAXED_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELAXED_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQUIRE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_RELEASE_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELEASE_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQ_REL_32)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_SEQ_CST_32)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_XOR_FETCH_RELAXED_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELAXED_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQUIRE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_RELEASE_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELEASE_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQ_REL_64)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_SEQ_CST_64)(type, ret, ptr, val)\n\n\n#define EASTL_ATOMIC_XOR_FETCH_RELAXED_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELAXED_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQUIRE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_RELEASE_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_RELEASE_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_ACQ_REL_128)(type, ret, ptr, val)\n\n#define EASTL_ATOMIC_XOR_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\t\t\\\n\tEASTL_ATOMIC_CHOOSE_OP_IMPL(ATOMIC_XOR_FETCH_SEQ_CST_128)(type, ret, ptr, val)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_XOR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_macros.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MACROS_H\n#define EASTL_ATOMIC_INTERNAL_MACROS_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// The reason for the implementation separating out into a compiler and architecture\n// folder is as follows.\n//\n// The compiler directory is meant to implement atomics using the compiler provided\n// intrinsics. This also implies that usually the same compiler instrinsic implementation\n// can be used for any architecture the compiler supports. If a compiler provides intrinsics\n// to support barriers or atomic operations, then that implementation should be in the\n// compiler directory.\n//\n// The arch directory is meant to manually implement atomics for a specific architecture\n// such as power or x86. There may be some compiler specific code in this directory because\n// GCC inline assembly syntax may be different than another compiler as an example.\n//\n// The arch directory can also be used to implement some atomic operations ourselves\n// if we deem the compiler provided implementation to be inefficient for the given\n// architecture or we need to do some things manually for a given compiler.\n//\n// The atomic_macros directory implements the macros that the rest of the atomic\n// library uses. These macros will expand to either the compiler or arch implemented\n// macro. The arch implemented macro is given priority over the compiler implemented\n// macro if both are implemented otherwise whichever is implemented is chosen or\n// an error is emitted if none are implemented.\n//\n// The implementation being all macros has a couple nice side effects as well.\n//\n// 1. All the implementation ends up funneling into one low level macro implementation\n//    which makes it easy to verify correctness, reduce copy-paste errors and differences\n//    in various platform implementations.\n//\n// 2. Allows for the implementation to be implemented efficiently on compilers that do not\n//    directly implement the C++ memory model in their intrinsics such as msvc.\n//\n// 3. Allows for the implementation of atomics that may not be supported on the given platform,\n//    such as 128-bit atomics on 32-bit platforms since the macros will only ever be expanded\n//    on platforms that support said features. This makes implementing said features pretty easy\n//    since we do not have to worry about complicated feature detection in the low level implementations.\n//\n// The macro implementation may asume that all passed in types are trivially constructible thus it is\n// free to create local variables of the passed in types as it may please.\n// It may also assume that all passed in types are trivially copyable as well.\n// It cannot assume any passed in type is any given type thus is a specific type if needed, it must do an\n// EASTL_ATOMIC_TYPE_PUN_CAST() to the required type.\n//\n\n\n#include \"compiler/compiler.h\"\n#include \"arch/arch.h\"\n\n#include \"atomic_macros/atomic_macros.h\"\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MACROS_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_memory_order.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_MEMORY_ORDER_H\n#define EASTL_ATOMIC_INTERNAL_MEMORY_ORDER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\nstruct memory_order_relaxed_s {};\nstruct memory_order_read_depends_s {};\nstruct memory_order_acquire_s {};\nstruct memory_order_release_s {};\nstruct memory_order_acq_rel_s {};\nstruct memory_order_seq_cst_s {};\n\n\n} // namespace internal\n\n\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR auto memory_order_relaxed = internal::memory_order_relaxed_s{};\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR auto memory_order_read_depends = internal::memory_order_read_depends_s{};\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR auto memory_order_acquire = internal::memory_order_acquire_s{};\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR auto memory_order_release = internal::memory_order_release_s{};\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR auto memory_order_acq_rel = internal::memory_order_acq_rel_s{};\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR auto memory_order_seq_cst = internal::memory_order_seq_cst_s{};\n\n\n} // namespace eastl\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_MEMORY_ORDER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_pointer.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_POINTER_H\n#define EASTL_ATOMIC_INTERNAL_POINTER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#if EA_TSAN_ENABLED\n#include <sanitizer/tsan_interface_atomic.h>\n#endif\n\n// EASTL_ATOMIC_READ_DEPENDS_TSAN_INSTRUMENTATION(bits, ptr)\n//\n// We use this to communicate to TSAN that our read_depends loads are intended to\n// synchronize. Note: memory_order_consume is intended to track the dependencies on the loads\n// but in practice these operations are always upgraded to have acquire semantics, this might\n// cause TSAN to miss some potential races, specifically non-address dependent reads after a\n// read_depends load might be considered synchronized after this call but they shouldn't. We\n// provide the EASTL_ATOMIC_READ_DEPENDS_IS_ACQUIRE macro as a means to diagnose issues related\n// to misuse of the read_depends memory order.\n#if EA_TSAN_ENABLED\n\t#define EASTL_ATOMIC_READ_DEPENDS_TSAN_INSTRUMENTATION_64(ptr)\t\t\t\\\n\t\t__tsan_atomic64_load(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(int64_t, ptr), __tsan_memory_order_consume);\n\n\t// TSAN does not work on 32-bit platforms so this does nothing for now.\n\t#define EASTL_ATOMIC_READ_DEPENDS_TSAN_INSTRUMENTATION_32(ptr)\n\n\t#define EASTL_ATOMIC_READ_DEPENDS_TSAN_INSTRUMENTATION(bits, ptr)\t\t\t\\\n\t\tEA_PREPROCESSOR_JOIN(EASTL_ATOMIC_READ_DEPENDS_TSAN_INSTRUMENTATION_, bits)(ptr)\n#else\n\t#define EASTL_ATOMIC_READ_DEPENDS_TSAN_INSTRUMENTATION(bits, ptr)\n#endif\n\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\n// 'class' : multiple assignment operators specified\nEA_DISABLE_VC_WARNING(4522);\n\n// misaligned atomic operation may incur significant performance penalty\n// The above warning is emitted in earlier versions of clang incorrectly.\n// All eastl::atomic<T> objects are size aligned.\n// This is static and runtime asserted.\n// Thus we disable this warning.\nEA_DISABLE_CLANG_WARNING(-Watomic-alignment);\n\n\n\ttemplate <typename T, unsigned width = sizeof(T)>\n\tstruct atomic_pointer_base;\n\n#define EASTL_ATOMIC_POINTER_STATIC_ASSERT_FUNCS_IMPL(funcName)\t\t\\\n\ttemplate <typename Order>\t\t\t\t\t\t\t\t\t\t\\\n\tT* funcName(ptrdiff_t /*arg*/, Order /*order*/) EA_NOEXCEPT\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(T);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\ttemplate <typename Order>\t\t\t\t\t\t\t\t\t\t\\\n\tT* funcName(ptrdiff_t /*arg*/, Order /*order*/) volatile EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT* funcName(ptrdiff_t /*arg*/) volatile EA_NOEXCEPT\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\\\n\t}\n\n#define EASTL_ATOMIC_POINTER_STATIC_ASSERT_INC_DEC_OPERATOR_IMPL(operatorOp) \\\n\tT* operator operatorOp() volatile EA_NOEXCEPT\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT* operator operatorOp(int) volatile EA_NOEXCEPT\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t}\n\n#define EASTL_ATOMIC_POINTER_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(operatorOp) \\\n\tT* operator operatorOp(ptrdiff_t /*arg*/) volatile EA_NOEXCEPT\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t}\n\n\n\ttemplate <typename T, unsigned width>\n\tstruct atomic_pointer_base<T*, width> : public atomic_base_width<T*, width>\n\t{\n\tprivate:\n\n\t\tusing Base = atomic_base_width<T*, width>;\n\n\tpublic: /* ctors */\n\n\t\tEA_CONSTEXPR atomic_pointer_base(T* desired) EA_NOEXCEPT\n\t\t\t: Base{ desired }\n\t\t{\n\t\t}\n\n\t\tEA_CONSTEXPR atomic_pointer_base() EA_NOEXCEPT = default;\n\n\t\tatomic_pointer_base(const atomic_pointer_base&) EA_NOEXCEPT = delete;\n\n\tpublic: /* assignment operators */\n\n\t\tusing Base::operator=;\n\n\t\tatomic_pointer_base& operator=(const atomic_pointer_base&)          EA_NOEXCEPT = delete;\n\t\tatomic_pointer_base& operator=(const atomic_pointer_base&) volatile EA_NOEXCEPT = delete;\n\n\tpublic: /* fetch_add */\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_FUNCS_IMPL(fetch_add)\n\n\tpublic: /* add_fetch */\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_FUNCS_IMPL(add_fetch)\n\n\tpublic: /* fetch_sub */\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_FUNCS_IMPL(fetch_sub)\n\n\tpublic: /* sub_fetch */\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_FUNCS_IMPL(sub_fetch)\n\n\tpublic: /* operator++ && operator-- */\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_INC_DEC_OPERATOR_IMPL(++)\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_INC_DEC_OPERATOR_IMPL(--)\n\n\tpublic: /* operator+= && operator-= */\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(+=)\n\n\t\tEASTL_ATOMIC_POINTER_STATIC_ASSERT_ASSIGNMENT_OPERATOR_IMPL(-=)\n\n\t};\n\n\n\ttemplate <typename T, unsigned width = sizeof(T)>\n\tstruct atomic_pointer_width;\n\n#define EASTL_ATOMIC_POINTER_FUNC_IMPL(op, bits, ptr)\t\t\t\t\t\\\n\tT* retVal;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tptr_integral_type retType;\t\t\t\t\t\t\t\t\t\t\\\n\t\tptr_integral_type addend = static_cast<ptr_integral_type>(arg) * static_cast<ptr_integral_type>(sizeof(T)); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_PREPROCESSOR_JOIN(op, bits)(ptr_integral_type, retType, EASTL_ATOMIC_INTEGRAL_CAST(ptr_integral_type, ptr), addend); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tretVal = reinterpret_cast<T*>(retType);\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\treturn retVal;\n\n#define EASTL_ATOMIC_POINTER_FETCH_IMPL(funcName, op, bits)\t\t\\\n\tT* funcName(ptrdiff_t arg) EA_NOEXCEPT\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_TYPE_IS_OBJECT(T);\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FUNC_IMPL(op, bits, this->GetAtomicAddress());  \\\n\t}\n\n#define EASTL_ATOMIC_POINTER_FETCH_ORDER_IMPL(funcName, orderType, op, bits) \\\n\tT* funcName(ptrdiff_t arg, orderType) EA_NOEXCEPT\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_TYPE_IS_OBJECT(T);\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FUNC_IMPL(op, bits, this->GetAtomicAddress());\t \\\n\t}\n\n#define EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(fetchOp, Order)\t\t\t\t\\\n\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_, fetchOp), Order)\n\n#define EASTL_ATOMIC_POINTER_FETCH_FUNCS_IMPL(funcName, fetchOp, bits)\t\\\n\tusing Base::funcName;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_POINTER_FETCH_IMPL(funcName, EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(fetchOp, _SEQ_CST_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_POINTER_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_relaxed_s, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(fetchOp, _RELAXED_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_POINTER_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_acquire_s, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(fetchOp, _ACQUIRE_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_POINTER_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_release_s, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(fetchOp, _RELEASE_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_POINTER_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_acq_rel_s, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(fetchOp, _ACQ_REL_), bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tEASTL_ATOMIC_POINTER_FETCH_ORDER_IMPL(funcName, eastl::internal::memory_order_seq_cst_s, \\\n\t\t\t\t\t\t\t\t\t\t  EASTL_ATOMIC_POINTER_FETCH_OP_JOIN(fetchOp, _SEQ_CST_), bits)\n\n#define EASTL_ATOMIC_POINTER_FETCH_INC_DEC_OPERATOR_IMPL(operatorOp, preFuncName, postFuncName) \\\n\tusing Base::operator operatorOp;\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT* operator operatorOp() EA_NOEXCEPT\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn preFuncName(1, eastl::memory_order_seq_cst);\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT* operator operatorOp(int) EA_NOEXCEPT\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn postFuncName(1, eastl::memory_order_seq_cst);\t\t\t\\\n\t}\n\n#define EASTL_ATOMIC_POINTER_FETCH_ASSIGNMENT_OPERATOR_IMPL(operatorOp, funcName) \\\n\tusing Base::operator operatorOp;\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tT* operator operatorOp(ptrdiff_t arg) EA_NOEXCEPT\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn funcName(arg, eastl::memory_order_seq_cst);\t\t\t\t\\\n\t}\n\n#define EASTL_ATOMIC_POINTER_READ_DEPENDS_LOAD_IMPL(bits, ptr)                        \\\n\tT* retPointer;                                                                    \\\n\tEASTL_ATOMIC_READ_DEPENDS_TSAN_INSTRUMENTATION(bits, ptr)                         \\\n\tEA_PREPROCESSOR_JOIN(EASTL_ATOMIC_LOAD_READ_DEPENDS_, bits)(T*, retPointer, ptr); \\\n\treturn retPointer;\n\n#define EASTL_ATOMIC_POINTER_WIDTH_SPECIALIZE(bytes, bits)\t\t\t\t\\\n\ttemplate <typename T>\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstruct atomic_pointer_width<T*, bytes> : public atomic_pointer_base<T*, bytes> \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tprivate:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base = atomic_pointer_base<T*, bytes>;\t\t\t\t\t\\\n\t\tusing u_ptr_integral_type = EA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(uint, bits), _t); \\\n\t\tusing ptr_integral_type = EA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(int, bits), _t); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* ctors */\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic_pointer_width(T* desired) EA_NOEXCEPT\t\t\\\n\t\t\t: Base{ desired }\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEA_CONSTEXPR atomic_pointer_width() EA_NOEXCEPT = default;\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic_pointer_width(const atomic_pointer_width&) EA_NOEXCEPT = delete; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* assignment operators */\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::operator=;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tatomic_pointer_width& operator=(const atomic_pointer_width&)          EA_NOEXCEPT = delete; \\\n\t\tatomic_pointer_width& operator=(const atomic_pointer_width&) volatile EA_NOEXCEPT = delete; \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* fetch_add */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_FUNCS_IMPL(fetch_add, FETCH_ADD, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* add_fetch */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_FUNCS_IMPL(add_fetch, ADD_FETCH, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* fetch_sub */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_FUNCS_IMPL(fetch_sub, FETCH_SUB, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* sub_fetch */\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_FUNCS_IMPL(sub_fetch, SUB_FETCH, bits) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* operator++ && operator-- */\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_INC_DEC_OPERATOR_IMPL(++, add_fetch, fetch_add) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_INC_DEC_OPERATOR_IMPL(--, sub_fetch, fetch_sub) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic: /* operator+= && operator-= */\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_ASSIGNMENT_OPERATOR_IMPL(+=, add_fetch) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_POINTER_FETCH_ASSIGNMENT_OPERATOR_IMPL(-=, sub_fetch) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tpublic:\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tusing Base::load;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tT* load(eastl::internal::memory_order_read_depends_s) EA_NOEXCEPT \\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEASTL_ATOMIC_POINTER_READ_DEPENDS_LOAD_IMPL(bits, this->GetAtomicAddress()) \\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t};\n\n\n#if defined(EASTL_ATOMIC_HAS_32BIT) && EA_PLATFORM_PTR_SIZE == 4\n\tEASTL_ATOMIC_POINTER_WIDTH_SPECIALIZE(4, 32)\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT) && EA_PLATFORM_PTR_SIZE == 8\n\tEASTL_ATOMIC_POINTER_WIDTH_SPECIALIZE(8, 64)\n#endif\n\nEA_RESTORE_VC_WARNING();\n\nEA_RESTORE_CLANG_WARNING();\n\n\n} // namespace internal\n\n\n} // namespace eastl\n\n#endif /* EASTL_ATOMIC_INTERNAL_POINTER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_size_aligned.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_SIZE_ALIGNED_H\n#define EASTL_ATOMIC_INTERNAL_SIZE_ALIGNED_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\n// 'class' : multiple assignment operators specified\nEA_DISABLE_VC_WARNING(4522);\n\n// misaligned atomic operation may incur significant performance penalty\n// The above warning is emitted in earlier versions of clang incorrectly.\n// All eastl::atomic<T> objects are size aligned.\n// This is static and runtime asserted.\n// Thus we disable this warning.\nEA_DISABLE_CLANG_WARNING(-Watomic-alignment);\n\n\n#define EASTL_ATOMIC_SIZE_ALIGNED_STATIC_ASSERT_CMPXCHG_IMPL(funcName)\t\\\n\ttemplate <typename OrderSuccess, typename OrderFailure>\t\t\t\t\\\n\tbool funcName(T& /*expected*/, T /*desired*/,\t\t\t\t\t\t\\\n\t\t\t\t  OrderSuccess /*orderSuccess*/,\t\t\t\t\t\t\\\n\t\t\t\t  OrderFailure /*orderFailure*/) EA_NOEXCEPT\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(T);\t\t\t\t\\\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\ttemplate <typename OrderSuccess, typename OrderFailure>\t\t\t\t\\\n\tbool funcName(T& /*expected*/, T /*desired*/,\t\t\t\t\t\t\\\n\t\t\t\t  OrderSuccess /*orderSuccess*/,\t\t\t\t\t\t\\\n\t\t\t\t  OrderFailure /*orderFailure*/) volatile EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\ttemplate <typename Order>\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& /*expected*/, T /*desired*/,\t\t\t\t\t\t\\\n\t\t\t\t  Order /*order*/) EA_NOEXCEPT\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(T);\t\t\t\t\\\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\ttemplate <typename Order>\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& /*expected*/, T /*desired*/,\t\t\t\t\t\t\\\n\t\t\t\t  Order /*order*/) volatile EA_NOEXCEPT\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tbool funcName(T& /*expected*/, T /*desired*/) volatile EA_NOEXCEPT\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\t\t\t\t\t\\\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n#define EASTL_ATOMIC_SIZE_ALIGNED_STATIC_ASSERT_CMPXCHG_WEAK_IMPL()\t\t\\\n\tEASTL_ATOMIC_SIZE_ALIGNED_STATIC_ASSERT_CMPXCHG_IMPL(compare_exchange_weak)\n\n#define EASTL_ATOMIC_SIZE_ALIGNED_STATIC_ASSERT_CMPXCHG_STRONG_IMPL()\t\\\n\tEASTL_ATOMIC_SIZE_ALIGNED_STATIC_ASSERT_CMPXCHG_IMPL(compare_exchange_strong)\n\n\n\ttemplate<typename T>\n\tstruct atomic_size_aligned\n\t{\n\tpublic: /* ctors */\n\n\t\tEA_CONSTEXPR atomic_size_aligned(T desired) EA_NOEXCEPT\n\t\t\t: mAtomic{ desired }\n\t\t{\n\t\t}\n\n\t\tEA_CONSTEXPR atomic_size_aligned() EA_NOEXCEPT_IF(eastl::is_nothrow_default_constructible_v<T>)\n\t\t\t: mAtomic{} /* Value-Initialize which will Zero-Initialize Trivial Constructible types */\n\t\t{\n\t\t}\n\n\t\tatomic_size_aligned(const atomic_size_aligned&) EA_NOEXCEPT = delete;\n\n\tpublic: /* store */\n\n\t\ttemplate <typename Order>\n\t\tvoid store(T /*desired*/, Order /*order*/) EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(T);\n\t\t}\n\n\t\ttemplate <typename Order>\n\t\tvoid store(T /*desired*/, Order /*order*/) volatile EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\n\t\t}\n\n\t\tvoid store(T /*desired*/) volatile EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\n\t\t}\n\n\tpublic: /* load */\n\n\t\ttemplate <typename Order>\n\t\tT load(Order /*order*/) const EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(T);\n\t\t}\n\n\t\ttemplate <typename Order>\n\t\tT load(Order /*order*/) const volatile EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\n\t\t}\n\n\t\tT load() const volatile EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\n\t\t}\n\n\tpublic: /* exchange */\n\n\t\ttemplate <typename Order>\n\t\tT exchange(T /*desired*/, Order /*order*/) EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(T);\n\t\t}\n\n\t\ttemplate <typename Order>\n\t\tT exchange(T /*desired*/, Order /*order*/) volatile EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\n\t\t}\n\n\t\tT exchange(T /*desired*/) volatile EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\n\t\t}\n\n\tpublic: /* compare_exchange_weak */\n\n\t\tEASTL_ATOMIC_SIZE_ALIGNED_STATIC_ASSERT_CMPXCHG_WEAK_IMPL()\n\n\tpublic: /* compare_exchange_strong */\n\n\t\tEASTL_ATOMIC_SIZE_ALIGNED_STATIC_ASSERT_CMPXCHG_STRONG_IMPL()\n\n\tpublic: /* assignment operator */\n\n\t\tT operator=(T /*desired*/) volatile EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ATOMIC_STATIC_ASSERT_VOLATILE_MEM_FN(T);\n\t\t}\n\n\t\tatomic_size_aligned& operator=(const atomic_size_aligned&)          EA_NOEXCEPT = delete;\n\t\tatomic_size_aligned& operator=(const atomic_size_aligned&) volatile EA_NOEXCEPT = delete;\n\n\tprotected: /* Accessors */\n\n\t\tT* GetAtomicAddress() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn eastl::addressof(mAtomic);\n\t\t}\n\n\tprivate:\n\n\t\t/**\n\t\t * Some compilers such as MSVC will align 64-bit values on 32-bit machines on\n\t\t * 4-byte boundaries which can ruin the atomicity guarantees.\n\t\t *\n\t\t * Ensure everything is size aligned.\n\t\t *\n\t\t * mutable is needed in cases such as when loads are only guaranteed to be atomic\n\t\t * using a compare exchange, such as for 128-bit atomics, so we need to be able\n\t\t * to have write access to the variable as one example.\n\t\t */\n\t\tEA_ALIGN(sizeof(T)) mutable T mAtomic;\n\t};\n\nEA_RESTORE_VC_WARNING();\n\nEA_RESTORE_CLANG_WARNING();\n\n\n} // namespace internal\n\n\n} // namespace eastl\n\n#endif /* EASTL_ATOMIC_INTERNAL_SIZE_ALIGNED_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/atomic_standalone.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_STANDALONE_H\n#define EASTL_ATOMIC_INTERNAL_STANDALONE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// bool atomic_compare_exchange_strong(eastl::atomic<T>*, T* expected, T desired)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE bool atomic_compare_exchange_strong(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::value_type* expected,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::value_type desired) EA_NOEXCEPT\n{\n\treturn atomicObj->compare_exchange_strong(*expected, desired);\n}\n\ntemplate <typename T, typename OrderSuccess, typename OrderFailure>\nEASTL_FORCE_INLINE bool atomic_compare_exchange_strong_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttypename eastl::atomic<T>::value_type* expected,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttypename eastl::atomic<T>::value_type desired,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tOrderSuccess orderSuccess, OrderFailure orderFailure) EA_NOEXCEPT\n{\n\treturn atomicObj->compare_exchange_strong(*expected, desired, orderSuccess, orderFailure);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// bool atomic_compare_exchange_weak(eastl::atomic<T>*, T* expected, T desired)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE bool atomic_compare_exchange_weak(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t typename eastl::atomic<T>::value_type* expected,\n\t\t\t\t\t\t\t\t\t\t\t\t\t typename eastl::atomic<T>::value_type desired) EA_NOEXCEPT\n{\n\treturn atomicObj->compare_exchange_weak(*expected, desired);\n}\n\ntemplate <typename T, typename OrderSuccess, typename OrderFailure>\nEASTL_FORCE_INLINE bool atomic_compare_exchange_weak_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type* expected,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type desired,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  OrderSuccess orderSuccess, OrderFailure orderFailure) EA_NOEXCEPT\n{\n\treturn atomicObj->compare_exchange_weak(*expected, desired, orderSuccess, orderFailure);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_fetch_xor(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_xor(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_xor(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_xor_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::value_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_xor(arg, order);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_xor_fetch(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_xor_fetch(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->xor_fetch(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_xor_fetch_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::value_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->xor_fetch(arg, order);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_fetch_or(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_or(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t typename eastl::atomic<T>::value_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_or(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_or_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_or(arg, order);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_or_fetch(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_or_fetch(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t typename eastl::atomic<T>::value_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->or_fetch(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_or_fetch_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->or_fetch(arg, order);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_fetch_and(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_and(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_and(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_and_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::value_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_and(arg, order);\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_and_fetch(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_and_fetch(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->and_fetch(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_and_fetch_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::value_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->and_fetch(arg, order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_fetch_sub(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_sub(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::difference_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_sub(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_sub_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::difference_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_sub(arg, order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_sub_fetch(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_sub_fetch(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::difference_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->sub_fetch(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_sub_fetch_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::difference_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->sub_fetch(arg, order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_fetch_add(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_add(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::difference_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_add(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_fetch_add_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::difference_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->fetch_add(arg, order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_add_fetch(eastl::atomic<T>*, T arg)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_add_fetch(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::difference_type arg) EA_NOEXCEPT\n{\n\treturn atomicObj->add_fetch(arg);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_add_fetch_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   typename eastl::atomic<T>::difference_type arg,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->add_fetch(arg, order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_exchange(eastl::atomic<T>*, T desired)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_exchange(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t typename eastl::atomic<T>::value_type desired) EA_NOEXCEPT\n{\n\treturn atomicObj->exchange(desired);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_exchange_explicit(eastl::atomic<T>* atomicObj,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  typename eastl::atomic<T>::value_type desired,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->exchange(desired, order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_load(const eastl::atomic<T>*)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_load(const eastl::atomic<T>* atomicObj) EA_NOEXCEPT\n{\n\treturn atomicObj->load();\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_load_explicit(const eastl::atomic<T>* atomicObj, Order order) EA_NOEXCEPT\n{\n\treturn atomicObj->load(order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// T atomic_load_cond(const eastl::atomic<T>*)\n//\ntemplate <typename T, typename Predicate>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_load_cond(const eastl::atomic<T>* atomicObj, Predicate pred) EA_NOEXCEPT\n{\n\tfor (;;)\n\t{\n\t\ttypename eastl::atomic<T>::value_type ret = atomicObj->load();\n\n\t\tif (pred(ret))\n\t\t{\n\t\t\treturn ret;\n\t\t}\n\n\t\tEASTL_ATOMIC_CPU_PAUSE();\n\t}\n}\n\ntemplate <typename T, typename Predicate, typename Order>\nEASTL_FORCE_INLINE typename eastl::atomic<T>::value_type atomic_load_cond_explicit(const eastl::atomic<T>* atomicObj, Predicate pred, Order order) EA_NOEXCEPT\n{\n\tfor (;;)\n\t{\n\t\ttypename eastl::atomic<T>::value_type ret = atomicObj->load(order);\n\n\t\tif (pred(ret))\n\t\t{\n\t\t\treturn ret;\n\t\t}\n\n\t\tEASTL_ATOMIC_CPU_PAUSE();\n\t}\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void atomic_store(eastl::atomic<T>*, T)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE void atomic_store(eastl::atomic<T>* atomicObj, typename eastl::atomic<T>::value_type desired) EA_NOEXCEPT\n{\n\tatomicObj->store(desired);\n}\n\ntemplate <typename T, typename Order>\nEASTL_FORCE_INLINE void atomic_store_explicit(eastl::atomic<T>* atomicObj, typename eastl::atomic<T>::value_type desired, Order order) EA_NOEXCEPT\n{\n\tatomicObj->store(desired, order);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void eastl::atomic_thread_fence(Order)\n//\ntemplate <typename Order>\nEASTL_FORCE_INLINE void atomic_thread_fence(Order) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(Order);\n}\n\nEASTL_FORCE_INLINE void atomic_thread_fence(eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_THREAD_FENCE_RELAXED();\n}\n\nEASTL_FORCE_INLINE void atomic_thread_fence(eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_THREAD_FENCE_ACQUIRE();\n}\n\nEASTL_FORCE_INLINE void atomic_thread_fence(eastl::internal::memory_order_release_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_THREAD_FENCE_RELEASE();\n}\n\nEASTL_FORCE_INLINE void atomic_thread_fence(eastl::internal::memory_order_acq_rel_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_THREAD_FENCE_ACQ_REL();\n}\n\nEASTL_FORCE_INLINE void atomic_thread_fence(eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_THREAD_FENCE_SEQ_CST();\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void eastl::atomic_signal_fence(Order)\n//\ntemplate <typename Order>\nEASTL_FORCE_INLINE void atomic_signal_fence(Order) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_STATIC_ASSERT_INVALID_MEMORY_ORDER(Order);\n}\n\nEASTL_FORCE_INLINE void atomic_signal_fence(eastl::internal::memory_order_relaxed_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_SIGNAL_FENCE_RELAXED();\n}\n\nEASTL_FORCE_INLINE void atomic_signal_fence(eastl::internal::memory_order_acquire_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_SIGNAL_FENCE_ACQUIRE();\n}\n\nEASTL_FORCE_INLINE void atomic_signal_fence(eastl::internal::memory_order_release_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_SIGNAL_FENCE_RELEASE();\n}\n\nEASTL_FORCE_INLINE void atomic_signal_fence(eastl::internal::memory_order_acq_rel_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_SIGNAL_FENCE_ACQ_REL();\n}\n\nEASTL_FORCE_INLINE void atomic_signal_fence(eastl::internal::memory_order_seq_cst_s) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_SIGNAL_FENCE_SEQ_CST();\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void eastl::compiler_barrier()\n//\nEASTL_FORCE_INLINE void compiler_barrier() EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_COMPILER_BARRIER();\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void eastl::compiler_barrier_data_dependency(const T&)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE void compiler_barrier_data_dependency(const T& val) EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(val, T);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void eastl::cpu_pause()\n//\nEASTL_FORCE_INLINE void cpu_pause() EA_NOEXCEPT\n{\n\tEASTL_ATOMIC_CPU_PAUSE();\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// bool eastl::atomic_is_lock_free(eastl::atomic<T>*)\n//\ntemplate <typename T>\nEASTL_FORCE_INLINE bool atomic_is_lock_free(const eastl::atomic<T>* atomicObj) EA_NOEXCEPT\n{\n\treturn atomicObj->is_lock_free();\n}\n\n\n} // namespace eastl\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_STANDALONE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// Include the compiler specific implementations\n//\n#if defined(EA_COMPILER_GNUC) || defined(__clang__)\n\n\t#include \"gcc/compiler_gcc.h\"\n\n#elif defined(EA_COMPILER_MSVC)\n\n\t#include \"msvc/compiler_msvc.h\"\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\nnamespace eastl\n{\n\n\nnamespace internal\n{\n\n\n/**\n * NOTE:\n *\n * This can be used by specific compiler implementations to implement a data dependency compiler barrier.\n * Some compiler barriers do not take in input dependencies as is possible with the gcc asm syntax.\n * Thus we need a way to create a false dependency on the input variable so the compiler does not dead-store\n * remove it.\n * A volatile function pointer ensures the compiler must always load the function pointer and call thru it\n * since the compiler cannot reason about any side effects. Thus the compiler must always assume the\n * input variable may be accessed and thus cannot be dead-stored. This technique works even in the presence\n * of Link-Time Optimization. A compiler barrier with a data dependency is useful in these situations.\n *\n * void foo()\n * {\n *    eastl::vector<int> v;\n *    while (Benchmark.ContinueRunning())\n *    {\n *      v.push_back(0);\n *      eastl::compiler_barrier(); OR eastl::compiler_barrier_data_dependency(v);\n *    }\n * }\n *\n * We are trying to benchmark the push_back function of a vector. The vector v has only local scope.\n * The compiler is well within its writes to remove all accesses to v even with the compiler barrier\n * because there are no observable uses of the vector v.\n * The compiler barrier data dependency ensures there is an input dependency on the variable so that\n * it isn't removed. This is also useful when writing test code that the compiler may remove.\n */\n\ntypedef void (*CompilerBarrierDataDependencyFuncPtr)(void*);\n\nextern EASTL_API volatile CompilerBarrierDataDependencyFuncPtr gCompilerBarrierDataDependencyFunc;\n\n\n#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY_FUNC(ptr) \\\n\teastl::internal::gCompilerBarrierDataDependencyFunc(ptr)\n\n\n} // namespace internal\n\n\n} // namespace eastl\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include \"compiler_fetch_add.h\"\n#include \"compiler_fetch_sub.h\"\n\n#include \"compiler_fetch_and.h\"\n#include \"compiler_fetch_xor.h\"\n#include \"compiler_fetch_or.h\"\n\n#include \"compiler_add_fetch.h\"\n#include \"compiler_sub_fetch.h\"\n\n#include \"compiler_and_fetch.h\"\n#include \"compiler_xor_fetch.h\"\n#include \"compiler_or_fetch.h\"\n\n#include \"compiler_exchange.h\"\n\n#include \"compiler_cmpxchg_weak.h\"\n#include \"compiler_cmpxchg_strong.h\"\n\n#include \"compiler_load.h\"\n#include \"compiler_store.h\"\n\n#include \"compiler_barrier.h\"\n\n#include \"compiler_cpu_pause.h\"\n\n#include \"compiler_memory_barrier.h\"\n\n#include \"compiler_signal_fence.h\"\n\n#include \"compiler_thread_fence.h\"\n\n#include \"compiler_acquire_fence.h\"\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_acquire_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n#pragma once\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_ACQUIRE_FENCE()\n//\n#if defined(EASTL_COMPILER_ATOMIC_ACQUIRE_FENCE)\n\t#define EASTL_COMPILER_ATOMIC_ACQUIRE_FENCE_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ACQUIRE_FENCE_AVAILABLE 0\n#endif\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_add_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_ADD_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_ADD_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_ADD_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_ADD_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_and_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_AND_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_AND_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_AND_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_AND_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_COMPILER_BARRIER()\n//\n#if defined(EASTL_COMPILER_ATOMIC_COMPILER_BARRIER)\n\t#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(const T&, type)\n//\n#if defined(EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY)\n\t#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_cmpxchg_strong.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_CMPXCHG_STRONG_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_CMPXCHG_STRONG_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_8_AVAILABLE\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_16_AVAILABLE\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_32_AVAILABLE\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_64_AVAILABLE\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_CMPXCHG_STRONG_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_cmpxchg_weak.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_CMPXCHG_WEAK_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_CMPXCHG_WEAK_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_8_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_16_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_32_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_64_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_128_AVAILABLE\t\t\\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128_AVAILABLE\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_CMPXCHG_WEAK_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_cpu_pause.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_CPU_PAUSE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_CPU_PAUSE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CPU_PAUSE()\n//\n#if defined(EASTL_COMPILER_ATOMIC_CPU_PAUSE)\n\n\t#define EASTL_COMPILER_ATOMIC_CPU_PAUSE_AVAILABLE 1\n\n#else\n\n\t#define EASTL_COMPILER_ATOMIC_CPU_PAUSE()\t\t\\\n\t\t((void)0)\n\n\t#define EASTL_COMPILER_ATOMIC_CPU_PAUSE_AVAILABLE 1\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_CPU_PAUSE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_exchange.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_EXCHANGE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_EXCHANGE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_EXCHANGE_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_EXCHANGE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_fetch_add.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_ADD_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_ADD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_ADD_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_ADD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_fetch_and.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_AND_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_AND_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_AND_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_AND_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_fetch_or.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_OR_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_OR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_OR_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_OR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_fetch_sub.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_SUB_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_SUB_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_SUB_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_SUB_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_fetch_xor.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_XOR_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_XOR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_XOR_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_FETCH_XOR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_load.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_LOAD_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_LOAD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_LOAD_*_N(type, type ret, type * ptr)\n//\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_128_AVAILABLE 0\n#endif\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_LOAD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_memory_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MEMORY_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MEMORY_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CPU_MB()\n//\n#if defined(EASTL_COMPILER_ATOMIC_CPU_MB)\n\t#define EASTL_COMPILER_ATOMIC_CPU_MB_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CPU_MB_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CPU_WMB()\n//\n#if defined(EASTL_COMPILER_ATOMIC_CPU_WMB)\n\t#define EASTL_COMPILER_ATOMIC_CPU_WMB_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CPU_WMB_AVAILABLE 0\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CPU_RMB()\n//\n#if defined(EASTL_COMPILER_ATOMIC_CPU_RMB)\n\t#define EASTL_COMPILER_ATOMIC_CPU_RMB_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_CPU_RMB_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MEMORY_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_or_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_OR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_OR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_OR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_OR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_signal_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_SIGNAL_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_SIGNAL_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_*()\n//\n#if defined(EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELAXED)\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELAXED_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELAXED_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQUIRE)\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQUIRE_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQUIRE_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELEASE)\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELEASE_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELEASE_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQ_REL)\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQ_REL_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQ_REL_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_SEQ_CST)\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_SEQ_CST_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_SEQ_CST_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_SIGNAL_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_store.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_STORE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_STORE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_STORE_*_N(type, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_STORE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_sub_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_SUB_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_SUB_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_SUB_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_SUB_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_thread_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_THREAD_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_THREAD_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_THREAD_FENCE_*()\n//\n#if defined(EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELAXED)\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELAXED_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELAXED_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQUIRE)\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQUIRE_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQUIRE_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELEASE)\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELEASE_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELEASE_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQ_REL)\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQ_REL_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQ_REL_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_THREAD_FENCE_SEQ_CST)\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_SEQ_CST_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_SEQ_CST_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_THREAD_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/compiler_xor_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_XOR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_XOR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_XOR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_8)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_8)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_8)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_8)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_8_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_8)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_8_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_8_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_16)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_16)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_16)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_16)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_16_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_16)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_16_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_16_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_32)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_32)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_32)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_32)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_32_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_32)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_32_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_32_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_64)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_64)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_64)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_64)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_64_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_64)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_64_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_64_AVAILABLE 0\n#endif\n\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_128)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_128)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_128)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_128)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_128_AVAILABLE 0\n#endif\n\n#if defined(EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_128)\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_128_AVAILABLE 1\n#else\n\t#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_128_AVAILABLE 0\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_XOR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/**\n * NOTE:\n *\n * gcc __atomic builtins may defer to function calls in libatomic.so for architectures that do not\n * support atomic instructions of a given size. These functions will be implemented with pthread_mutex_t.\n * It also requires the explicit linking against the compiler runtime libatomic.so.\n * On architectures that do not support atomics, like armv6 the builtins may defer to kernel helpers\n * or on classic uniprocessor systems just disable interrupts.\n *\n * We do not want to have to link against libatomic.so or fall into the trap of our atomics degrading\n * into locks. We would rather have user-code explicitly use locking primitives if their code cannot\n * be satisfied with atomic instructions on the given platform.\n */\nstatic_assert(__atomic_always_lock_free(1, 0), \"eastl::atomic<T> where sizeof(T) == 1 must be lock-free!\");\nstatic_assert(__atomic_always_lock_free(2, 0), \"eastl::atomic<T> where sizeof(T) == 2 must be lock-free!\");\nstatic_assert(__atomic_always_lock_free(4, 0), \"eastl::atomic<T> where sizeof(T) == 4 must be lock-free!\");\n#if EA_PLATFORM_PTR_SIZE == 8\n\tstatic_assert(__atomic_always_lock_free(8, 0), \"eastl::atomic<T> where sizeof(T) == 8 must be lock-free!\");\n#endif\n\n/**\n * NOTE:\n *\n * The following can fail on gcc/clang on 64-bit systems.\n * Firstly, it depends on the -march setting on clang whether or not it calls out to libatomic for 128-bit operations.\n * Second, gcc always calls out to libatomic for 128-bit atomics. It is unclear if it uses locks\n * or tries to look at the cpuid and use cmpxchg16b if its available.\n * gcc mailing lists argue that since load must be implemented with cmpxchg16b, then the __atomic bultin\n * cannot be used in read-only memory which is why they always call out to libatomic.\n * There is no way to tell gcc to not do that, unfortunately.\n * We don't care about the read-only restriction because our eastl::atomic<T> object is mutable\n * and also msvc doesn't enforce this restriction thus to be fully platform agnostic we cannot either.\n *\n * Therefore, the follow static_assert is commented out for the time being, as it always fails on these compilers.\n * We still guarantee 128-bit atomics are lock-free by handrolling the inline assembly ourselves.\n *\n * static_assert(__atomic_always_lock_free(16, 0), \"eastl::atomic<T> where sizeof(T) == 16 must be lock-free!\");\n */\n\n/**\n * NOTE:\n *\n * Why do we do the cast to the unsigned fixed width types for every operation even though gcc/clang builtins are generics?\n * Well gcc/clang correctly-incorrectly call out to libatomic and do locking on user types that may be potentially misaligned.\n * struct UserType { uint8_t a,b; }; This given struct is 2 bytes in size but has only 1 byte alignment.\n * gcc/clang cannot and doesn't know that we always guarantee every type T is size aligned within eastl::atomic<T>.\n * Therefore it always emits calls into libatomic and does locking for structs like these which we do not want.\n * Therefore you'll notice we always cast each atomic ptr type to the equivalent unsigned fixed width type when doing the atomic operations.\n * This ensures all user types are size aligned and thus are lock free.\n */\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#define EASTL_COMPILER_ATOMIC_HAS_8BIT\n#define EASTL_COMPILER_ATOMIC_HAS_16BIT\n#define EASTL_COMPILER_ATOMIC_HAS_32BIT\n#define EASTL_COMPILER_ATOMIC_HAS_64BIT\n\n#if EA_PLATFORM_PTR_SIZE == 8\n\t#define EASTL_COMPILER_ATOMIC_HAS_128BIT\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_8 uint8_t\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_16 uint16_t\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_32 uint32_t\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_64 uint64_t\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_128 __uint128_t\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#define EASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, fetchIntrinsic, type, ret, ptr, val, gccMemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType valIntegral = EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (val)); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tretIntegral = fetchIntrinsic(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), valIntegral, gccMemoryOrder); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t}\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_INTRIN_N(integralType, type, ret, ptr, expected, desired, weak, successOrder, failOrder) \\\n\tret = __atomic_compare_exchange(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)),\t\t\t\t\t\t\t  \\\n\t\t\t\t\t\t\t\t\tEASTL_ATOMIC_INTEGRAL_CAST(integralType, (expected)), \t\t\t\t\t\t\t\t  \\\n\t\t\t\t\t\t\t\t\tEASTL_ATOMIC_INTEGRAL_CAST(integralType, &(desired)), \t\t\t\t\t\t\t\t  \\\n\t\t\t\t\t\t\t\t\tweak, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_EXCHANGE_INTRIN_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType valIntegral = EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (val)); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t__atomic_exchange(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), \\\n\t\t\t\t\t\t  &valIntegral, &retIntegral, gccMemoryOrder);\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include \"compiler_gcc_fetch_add.h\"\n#include \"compiler_gcc_fetch_sub.h\"\n\n#include \"compiler_gcc_fetch_and.h\"\n#include \"compiler_gcc_fetch_xor.h\"\n#include \"compiler_gcc_fetch_or.h\"\n\n#include \"compiler_gcc_add_fetch.h\"\n#include \"compiler_gcc_sub_fetch.h\"\n\n#include \"compiler_gcc_and_fetch.h\"\n#include \"compiler_gcc_xor_fetch.h\"\n#include \"compiler_gcc_or_fetch.h\"\n\n#include \"compiler_gcc_exchange.h\"\n\n#include \"compiler_gcc_cmpxchg_weak.h\"\n#include \"compiler_gcc_cmpxchg_strong.h\"\n\n#include \"compiler_gcc_load.h\"\n#include \"compiler_gcc_store.h\"\n\n#include \"compiler_gcc_barrier.h\"\n\n#include \"compiler_gcc_cpu_pause.h\"\n\n#include \"compiler_gcc_signal_fence.h\"\n\n#include \"compiler_gcc_thread_fence.h\"\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_add_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_ADD_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_ADD_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_ADD_FETCH_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_add_fetch, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_ADD_FETCH_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_ADD_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_ADD_FETCH_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_ADD_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_and_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_AND_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_AND_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_AND_FETCH_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_and_fetch, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_AND_FETCH_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_AND_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_AND_FETCH_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_AND_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_COMPILER_BARRIER()\n//\n#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER()\t\\\n\t__asm__ __volatile__ (\"\" ::: \"memory\")\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(const T&, type)\n//\n#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(val, type) \\\n\t__asm__ __volatile__ (\"\" : /* Output Operands */ : \"r\"(&(val)) : \"memory\")\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_cmpxchg_strong.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CMPXCHG_STRONG_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CMPXCHG_STRONG_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_STRONG_N(integralType, type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_INTRIN_N(integralType, type, ret, ptr, expected, desired, false, successOrder, failOrder)\n\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_N(uint8_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_N(uint16_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_N(uint32_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_N(uint64_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_N(__uint128_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CMPXCHG_STRONG_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_cmpxchg_weak.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CMPXCHG_WEAK_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CMPXCHG_WEAK_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_WEAK_N(integralType, type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_INTRIN_N(integralType, type, ret, ptr, expected, desired, true, successOrder, failOrder)\n\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_N(uint8_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_N(uint16_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_N(uint32_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_N(uint64_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n#define EASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, successOrder, failOrder) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_N(__uint128_t, type, ret, ptr, expected, desired, successOrder, failOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_RELAXED, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_RELEASE, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_8(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16(type,ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_16(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_32(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_64(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_GCC_ATOMIC_CMPXCHG_WEAK_128(type, ret, ptr, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CMPXCHG_WEAK_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_cpu_pause.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CPU_PAUSE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CPU_PAUSE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CPU_PAUSE()\n//\n#if defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_COMPILER_ATOMIC_CPU_PAUSE()\t\t\\\n\t\t__asm__ __volatile__ (\"pause\")\n\n#elif defined(EA_PROCESSOR_ARM32) || defined(EA_PROCESSOR_ARM64)\n\n\t#define EASTL_COMPILER_ATOMIC_CPU_PAUSE()\t\t\\\n\t\t__asm__ __volatile__ (\"yield\")\n\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_CPU_PAUSE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_exchange.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_EXCHANGE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_EXCHANGE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_EXCHANGE_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_EXCHANGE_INTRIN_N(integralType, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_EXCHANGE_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_EXCHANGE_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_EXCHANGE_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_EXCHANGE_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_EXCHANGE_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_EXCHANGE_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_EXCHANGE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_fetch_add.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_ADD_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_ADD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_FETCH_ADD_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_fetch_add, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_ADD_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_ADD_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_ADD_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_ADD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_fetch_and.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_AND_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_AND_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_FETCH_AND_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_fetch_and, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_AND_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_AND_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_AND_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_AND_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_fetch_or.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_OR_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_OR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_FETCH_OR_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_fetch_or, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_OR_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_OR_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_OR_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_OR_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_OR_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_OR_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_OR_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_OR_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_OR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_fetch_sub.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_SUB_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_SUB_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_FETCH_SUB_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_fetch_sub, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_SUB_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_SUB_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_SUB_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_SUB_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_fetch_xor.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_XOR_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_XOR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_FETCH_XOR_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_fetch_xor, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_FETCH_XOR_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_XOR_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_FETCH_XOR_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_FETCH_XOR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_load.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_LOAD_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_LOAD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_LOAD_N(integralType, type, ret, ptr, gccMemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\t__atomic_load(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), &retIntegral, gccMemoryOrder); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t}\n\n#define EASTL_GCC_ATOMIC_LOAD_8(type, ret, ptr, gccMemoryOrder)\t\t\t\\\n\tEASTL_GCC_ATOMIC_LOAD_N(uint8_t, type, ret, ptr, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_LOAD_16(type, ret, ptr, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_LOAD_N(uint16_t, type, ret, ptr, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_LOAD_32(type, ret, ptr, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_LOAD_N(uint32_t, type, ret, ptr, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_LOAD_64(type, ret, ptr, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_LOAD_N(uint64_t, type, ret, ptr, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_LOAD_128(type, ret, ptr, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_LOAD_N(__uint128_t, type, ret, ptr, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_LOAD_*_N(type, type ret, type * ptr)\n//\n#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_8(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_8(type, ret, ptr, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_16(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_16(type, ret, ptr, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_32(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_32(type, ret, ptr, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_64(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_64(type, ret, ptr, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_RELAXED_128(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_128(type, ret, ptr, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_8(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_8(type, ret, ptr, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_16(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_16(type, ret, ptr, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_32(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_32(type, ret, ptr, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_64(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_64(type, ret, ptr, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_ACQUIRE_128(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_128(type, ret, ptr, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_8(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_8(type, ret, ptr, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_16(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_16(type, ret, ptr, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_32(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_32(type, ret, ptr, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_64(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_64(type, ret, ptr, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_LOAD_SEQ_CST_128(type, ret, ptr)\t\\\n\tEASTL_GCC_ATOMIC_LOAD_128(type, ret, ptr, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_LOAD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_or_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_OR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_OR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_OR_FETCH_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_or_fetch, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_OR_FETCH_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_OR_FETCH_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_OR_FETCH_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_OR_FETCH_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_OR_FETCH_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_OR_FETCH_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_OR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_128(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_OR_FETCH_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_OR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_signal_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_SIGNAL_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_SIGNAL_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_SIGNAL_FENCE(gccMemoryOrder)\t\\\n\t__atomic_signal_fence(gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_*()\n//\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELAXED()\t\\\n\tEASTL_GCC_ATOMIC_SIGNAL_FENCE(__ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQUIRE()\t\\\n\tEASTL_GCC_ATOMIC_SIGNAL_FENCE(__ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELEASE()\t\\\n\tEASTL_GCC_ATOMIC_SIGNAL_FENCE(__ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQ_REL()\t\\\n\tEASTL_GCC_ATOMIC_SIGNAL_FENCE(__ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_SEQ_CST()\t\\\n\tEASTL_GCC_ATOMIC_SIGNAL_FENCE(__ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_SIGNAL_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_store.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_STORE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_STORE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_STORE_N(integralType, ptr, val, gccMemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \\\n\t\tintegralType valIntegral = EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (val)); \\\n\t\t__atomic_store(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), &valIntegral, gccMemoryOrder); \\\n\t}\n\n\n#define EASTL_GCC_ATOMIC_STORE_8(ptr, val, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_STORE_N(uint8_t, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_STORE_16(ptr, val, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_STORE_N(uint16_t, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_STORE_32(ptr, val, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_STORE_N(uint32_t, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_STORE_64(ptr, val, gccMemoryOrder)\t\t\\\n\tEASTL_GCC_ATOMIC_STORE_N(uint64_t, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_STORE_128(ptr, val, gccMemoryOrder)\t\\\n\tEASTL_GCC_ATOMIC_STORE_N(__uint128_t, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_STORE_*_N(type, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_8(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_8(ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_16(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_16(ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_32(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_32(ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_64(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_64(ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELAXED_128(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_128(ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_8(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_8(ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_16(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_16(ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_32(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_32(ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_64(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_64(ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_STORE_RELEASE_128(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_128(ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_8(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_8(ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_16(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_16(ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_32(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_32(ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_64(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_64(ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_STORE_SEQ_CST_128(type, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_STORE_128(ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_STORE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_sub_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_SUB_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_SUB_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_SUB_FETCH_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_sub_fetch, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_SUB_FETCH_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_SUB_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_SUB_FETCH_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_SUB_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_thread_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_THREAD_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_THREAD_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_THREAD_FENCE(gccMemoryOrder) \\\n\t__atomic_thread_fence(gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_THREAD_FENCE_*()\n//\n#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELAXED()\t\\\n\tEASTL_GCC_ATOMIC_THREAD_FENCE(__ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQUIRE()\t\\\n\tEASTL_GCC_ATOMIC_THREAD_FENCE(__ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_RELEASE()\t\\\n\tEASTL_GCC_ATOMIC_THREAD_FENCE(__ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_ACQ_REL()\t\\\n\tEASTL_GCC_ATOMIC_THREAD_FENCE(__ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_THREAD_FENCE_SEQ_CST()\t\\\n\tEASTL_GCC_ATOMIC_THREAD_FENCE(__ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_THREAD_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/gcc/compiler_gcc_xor_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_GCC_XOR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_GCC_XOR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_GCC_ATOMIC_XOR_FETCH_N(integralType, type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_FETCH_INTRIN_N(integralType, __atomic_xor_fetch, type, ret, ptr, val, gccMemoryOrder)\n\n\n#define EASTL_GCC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_N(uint8_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_N(uint16_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_N(uint32_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_N(uint64_t, type, ret, ptr, val, gccMemoryOrder)\n\n#define EASTL_GCC_ATOMIC_XOR_FETCH_128(type, ret, ptr, val, gccMemoryOrder) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_N(__uint128_t, type, ret, ptr, val, gccMemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_XOR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_128(type, ret, ptr, val, __ATOMIC_RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_128(type, ret, ptr, val, __ATOMIC_RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_128(type, ret, ptr, val, __ATOMIC_ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_128(type, ret, ptr, val) \\\n\tEASTL_GCC_ATOMIC_XOR_FETCH_128(type, ret, ptr, val, __ATOMIC_SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_GCC_XOR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nEA_DISABLE_ALL_VC_WARNINGS();\n#include <intrin.h>\nEA_RESTORE_ALL_VC_WARNINGS();\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#define EASTL_COMPILER_ATOMIC_HAS_8BIT\n#define EASTL_COMPILER_ATOMIC_HAS_16BIT\n#define EASTL_COMPILER_ATOMIC_HAS_32BIT\n#define EASTL_COMPILER_ATOMIC_HAS_64BIT\n\n#if EA_PLATFORM_PTR_SIZE == 8\n\t#define EASTL_COMPILER_ATOMIC_HAS_128BIT\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_8 char\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_16 short\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_32 long\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_64 __int64\n\nnamespace eastl\n{\n\nnamespace internal\n{\n\nstruct FixedWidth128\n{\n\t__int64 value[2];\n};\n\n} // namespace internal\n\n} // namespace eastl\n\n#define EASTL_COMPILER_ATOMIC_FIXED_WIDTH_TYPE_128 eastl::internal::FixedWidth128\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n/**\n * NOTE:\n *\n * Unfortunately MSVC Intrinsics depend on the architecture\n * that we are compiling for.\n * These are some indirection macros to make our lives easier and\n * ensure the least possible amount of copy-paste to reduce programmer errors.\n *\n * All compiler implementations end up deferring to the below macros.\n */\n#if defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64)\n\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_OP(ret, ptr, val, MemoryOrder, Intrinsic) \\\n\t\tret = Intrinsic(ptr, val)\n\n\t#define EASTL_MSVC_ATOMIC_EXCHANGE_OP(ret, ptr, val, MemoryOrder, Intrinsic) \\\n\t\tret = Intrinsic(ptr, val)\n\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP(ret, ptr, comparand, exchange, MemoryOrder, Intrinsic) \\\n\t\tret = Intrinsic(ptr, exchange, comparand)\n\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128_OP(ret, ptr, comparandResult, exchangeHigh, exchangeLow, MemoryOrder) \\\n\t\tret = _InterlockedCompareExchange128_np(ptr, exchangeHigh, exchangeLow, comparandResult)\n\n\n#elif defined(EA_PROCESSOR_ARM32) || defined(EA_PROCESSOR_ARM64)\n\n\n\t#define EASTL_MSVC_INTRINSIC_RELAXED(Intrinsic) \\\n\t\tEA_PREPROCESSOR_JOIN(Intrinsic, _nf)\n\n\t#define EASTL_MSVC_INTRINSIC_ACQUIRE(Intrinsic)\t\\\n\t\tEA_PREPROCESSOR_JOIN(Intrinsic, _acq)\n\n\t#define EASTL_MSVC_INTRINSIC_RELEASE(Intrinsic)\t\\\n\t\tEA_PREPROCESSOR_JOIN(Intrinsic, _rel)\n\n\t#define EASTL_MSVC_INTRINSIC_ACQ_REL(Intrinsic)\t\\\n\t\tIntrinsic\n\n\t#define EASTL_MSVC_INTRINSIC_SEQ_CST(Intrinsic)\t\\\n\t\tIntrinsic\n\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_OP(ret, ptr, val, MemoryOrder, Intrinsic) \\\n\t\tret = EA_PREPROCESSOR_JOIN(EASTL_MSVC_INTRINSIC_, MemoryOrder)(Intrinsic)(ptr, val)\n\n\t#define EASTL_MSVC_ATOMIC_EXCHANGE_OP(ret, ptr, val, MemoryOrder, Intrinsic) \\\n\t\tret = EA_PREPROCESSOR_JOIN(EASTL_MSVC_INTRINSIC_, MemoryOrder)(Intrinsic)(ptr, val)\n\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP(ret, ptr, comparand, exchange, MemoryOrder, Intrinsic) \\\n\t\tret = EA_PREPROCESSOR_JOIN(EASTL_MSVC_INTRINSIC_, MemoryOrder)(Intrinsic)(ptr, exchange, comparand)\n\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128_OP(ret, ptr, comparandResult, exchangeHigh, exchangeLow, MemoryOrder) \\\n\t\tret = EA_PREPROCESSOR_JOIN(EASTL_MSVC_INTRINSIC_, MemoryOrder)(_InterlockedCompareExchange128)(ptr, exchangeHigh, exchangeLow, comparandResult)\n\n\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#define EASTL_MSVC_NOP_POST_INTRIN_COMPUTE(ret, lhs, rhs)\n\n#define EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE(ret, val) \\\n\tret = (val)\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_INTRIN_N(integralType, fetchIntrinsic, type, ret, ptr, val, MemoryOrder, PRE_INTRIN_COMPUTE, POST_INTRIN_COMPUTE) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\ttype valCompute;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tPRE_INTRIN_COMPUTE(valCompute, (val));\t\t\t\t\t\t\t\\\n\t\tconst integralType valIntegral = EASTL_ATOMIC_TYPE_PUN_CAST(integralType, valCompute); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_MSVC_ATOMIC_FETCH_OP(retIntegral, EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), \\\n\t\t\t\t\t\t\t\t   valIntegral, MemoryOrder, fetchIntrinsic); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t\tPOST_INTRIN_COMPUTE(ret, ret, (val));\t\t\t\t\t\t\t\\\n\t}\n\n#define EASTL_MSVC_ATOMIC_EXCHANGE_INTRIN_N(integralType, exchangeIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType retIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_MSVC_ATOMIC_EXCHANGE_OP(retIntegral, EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), \\\n\t\t\t\t\t\t\t\t\t  EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (val)), MemoryOrder, \\\n\t\t\t\t\t\t\t\t\t  exchangeIntrinsic);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral);\t\t\t\\\n\t}\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_N(integralType, cmpxchgStrongIntrinsic, type, ret, ptr, expected, desired, MemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tintegralType comparandIntegral = EASTL_ATOMIC_TYPE_PUN_CAST(integralType, *(expected)); \\\n\t\tintegralType oldIntegral;\t\t\t\t\t\t\t\t\t\t\\\n\t\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP(oldIntegral, EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)), \\\n\t\t\t\t\t\t\t\t\t\t\tcomparandIntegral, EASTL_ATOMIC_TYPE_PUN_CAST(integralType, (desired)), \\\n\t\t\t\t\t\t\t\t\t\t\tMemoryOrder, cmpxchgStrongIntrinsic); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (oldIntegral == comparandIntegral)\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tret = true;\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t*(expected) = EASTL_ATOMIC_TYPE_PUN_CAST(type, oldIntegral); \\\n\t\t\tret = false;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n/**\n * In my own opinion, I found the wording on Microsoft docs a little confusing.\n * ExchangeHigh means the top 8 bytes so (ptr + 8).\n * ExchangeLow means the low 8 butes so (ptr).\n * Endianness does not matter since we are just loading data and comparing data.\n * Thought of as memcpy() and memcmp() function calls whereby the layout of the\n * data itself is irrelevant.\n * Only after we type pun back to the original type, and load from memory does\n * the layout of the data matter again.\n */\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_128(type, ret, ptr, expected, desired, MemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tunion TypePun\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\ttype templateType;\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tstruct exchange128\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t__int64 value[2];\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t};\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tstruct exchange128 exchangePun;\t\t\t\t\t\t\t\t\\\n\t\t};\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tunion TypePun typePun = { (desired) };\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tunsigned char cmpxchgRetChar;\t\t\t\t\t\t\t\t\t\\\n\t\tcmpxchgRetChar = EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128_OP(cmpxchgRetChar, EASTL_ATOMIC_VOLATILE_TYPE_CAST(__int64, (ptr)), \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t EASTL_ATOMIC_TYPE_CAST(__int64, (expected)), \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t typePun.exchangePun.value[1], typePun.exchangePun.value[0], \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t MemoryOrder); \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tret = static_cast<bool>(cmpxchgRetChar);\t\t\t\t\t\t\\\n\t}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_OP_N(integralType, fetchIntrinsic, type, ret, ptr, val, MemoryOrder, PRE_INTRIN_COMPUTE) \\\n\tEASTL_MSVC_ATOMIC_FETCH_INTRIN_N(integralType, fetchIntrinsic, type, ret, ptr, val, MemoryOrder, PRE_INTRIN_COMPUTE, EASTL_MSVC_NOP_POST_INTRIN_COMPUTE)\n\n#define EASTL_MSVC_ATOMIC_OP_FETCH_N(integralType, fetchIntrinsic, type, ret, ptr, val, MemoryOrder, PRE_INTRIN_COMPUTE, POST_INTRIN_COMPUTE) \\\n\tEASTL_MSVC_ATOMIC_FETCH_INTRIN_N(integralType, fetchIntrinsic, type, ret, ptr, val, MemoryOrder, PRE_INTRIN_COMPUTE, POST_INTRIN_COMPUTE)\n\n#define EASTL_MSVC_ATOMIC_EXCHANGE_OP_N(integralType, exchangeIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_INTRIN_N(integralType, exchangeIntrinsic, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP_N(integralType, cmpxchgStrongIntrinsic, type, ret, ptr, expected, desired, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_N(integralType, cmpxchgStrongIntrinsic, type, ret, ptr, expected, desired, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP_128(type, ret, ptr, expected, desired, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_128(type, ret, ptr, expected, desired, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include \"compiler_msvc_fetch_add.h\"\n#include \"compiler_msvc_fetch_sub.h\"\n\n#include \"compiler_msvc_fetch_and.h\"\n#include \"compiler_msvc_fetch_xor.h\"\n#include \"compiler_msvc_fetch_or.h\"\n\n#include \"compiler_msvc_add_fetch.h\"\n#include \"compiler_msvc_sub_fetch.h\"\n\n#include \"compiler_msvc_and_fetch.h\"\n#include \"compiler_msvc_xor_fetch.h\"\n#include \"compiler_msvc_or_fetch.h\"\n\n#include \"compiler_msvc_exchange.h\"\n\n#include \"compiler_msvc_cmpxchg_weak.h\"\n#include \"compiler_msvc_cmpxchg_strong.h\"\n\n#include \"compiler_msvc_barrier.h\"\n\n#include \"compiler_msvc_cpu_pause.h\"\n\n#include \"compiler_msvc_signal_fence.h\"\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_add_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_ADD_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_ADD_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_MSVC_ADD_FETCH_POST_INTRIN_COMPUTE(ret, val, addend)\t\\\n\tret = (val) + (addend)\n\n#define EASTL_MSVC_ATOMIC_ADD_FETCH_N(integralType, addIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_OP_FETCH_N(integralType, addIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE, EASTL_MSVC_ADD_FETCH_POST_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_N(char, _InterlockedExchangeAdd8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_N(short, _InterlockedExchangeAdd16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_N(long, _InterlockedExchangeAdd, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_N(__int64, _InterlockedExchangeAdd64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_ADD_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_ADD_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_ADD_FETCH_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_ADD_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_and_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_AND_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_AND_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#if defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_8 _InterlockedAnd8_np\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_16 _InterlockedAnd16_np\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_32 _InterlockedAnd_np\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_64 _InterlockedAnd64_np\n\n#else\n\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_8 _InterlockedAnd8\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_16 _InterlockedAnd16\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_32 _InterlockedAnd\n\t#define EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_64 _InterlockedAnd64\n\n#endif\n\n\n#define EASTL_MSVC_AND_FETCH_POST_INTRIN_COMPUTE(ret, val, andend)\t\\\n\tret = (val) & (andend)\n\n#define EASTL_MSVC_ATOMIC_AND_FETCH_N(integralType, andIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_OP_FETCH_N(integralType, andIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE, EASTL_MSVC_AND_FETCH_POST_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_N(char, EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_N(short, EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_N(long, EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_32, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_N(__int64, EASTL_MSVC_ATOMIC_AND_FETCH_INTRIN_64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_AND_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_AND_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_AND_FETCH_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_AND_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_barrier.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_BARRIER_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_BARRIER_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_COMPILER_BARRIER()\n//\n#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER()\t\\\n\tEA_DISABLE_CLANG_WARNING(-Wdeprecated-declarations)\t\t\\\n\t_ReadWriteBarrier()\t\t\t\t\t\t\t\t\t\t\\\n\tEA_RESTORE_CLANG_WARNING()\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(const T&, type)\n//\n#define EASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY(val, type) \\\n\tEASTL_COMPILER_ATOMIC_COMPILER_BARRIER_DATA_DEPENDENCY_FUNC(const_cast<type*>(eastl::addressof((val)))); \\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_BARRIER_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_cmpxchg_strong.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CMPXCHG_STRONG_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CMPXCHG_STRONG_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#if defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_8 _InterlockedCompareExchange8\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_16 _InterlockedCompareExchange16_np\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_32 _InterlockedCompareExchange_np\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_64 _InterlockedCompareExchange64_np\n\n#else\n\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_8 _InterlockedCompareExchange8\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_16 _InterlockedCompareExchange16\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_32 _InterlockedCompareExchange\n\t#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_64 _InterlockedCompareExchange64\n\n#endif\n\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP_N(char, EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_8, type, ret, ptr, expected, desired, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP_N(short, EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_16, type, ret, ptr, expected, desired, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP_N(long, EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_32, type, ret, ptr, expected, desired, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP_N(__int64, EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_INTRIN_64, type, ret, ptr, expected, desired, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_OP_128(type, ret, ptr, expected, desired, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, SEQ_CST)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, SEQ_CST)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_8(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_16(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_32(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_64(type, ret, ptr, expected, desired, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_MSVC_ATOMIC_CMPXCHG_STRONG_128(type, ret, ptr, expected, desired, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CMPXCHG_STRONG_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_cmpxchg_weak.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CMPXCHG_WEAK_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CMPXCHG_WEAK_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_*_*_N(type, bool ret, type * ptr, type * expected, type desired)\n//\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELAXED_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELAXED_RELAXED_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_RELAXED_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQUIRE_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_RELEASE_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_RELEASE_RELAXED_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_RELAXED_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_ACQ_REL_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_RELAXED_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_ACQUIRE_128(type, ret, ptr, expected, desired)\n\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_8(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_16(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_32(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_64(type, ret, ptr, expected, desired)\n\n#define EASTL_COMPILER_ATOMIC_CMPXCHG_WEAK_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired) \\\n\tEASTL_COMPILER_ATOMIC_CMPXCHG_STRONG_SEQ_CST_SEQ_CST_128(type, ret, ptr, expected, desired)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CMPXCHG_WEAK_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_cpu_pause.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// copyright (c) electronic arts inc. all rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CPU_PAUSE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CPU_PAUSE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#if defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64)\n\t#define EASTL_COMPILER_ATOMIC_CPU_PAUSE() _mm_pause()\n#elif defined(EA_PROCESSOR_ARM32) || defined(EA_PROCESSOR_ARM64)\n\t#define EASTL_COMPILER_ATOMIC_CPU_PAUSE() __yield()\n#else \n\t#error Unsupported CPU architecture for EASTL_COMPILER_ATOMIC_CPU_PAUSE\n#endif\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_CPU_PAUSE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_exchange.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_EXCHANGE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_EXCHANGE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_MSVC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_OP_N(char, _InterlockedExchange8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_OP_N(short, _InterlockedExchange16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_OP_N(long, _InterlockedExchange, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_OP_N(__int64, _InterlockedExchange64, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, MemoryOrder) \\\n\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tbool cmpxchgRet;\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t/* This is intentionally a non-atomic 128-bit load which may observe shearing. */ \\\n\t\t/* Either we do not observe *(ptr) but then the cmpxchg will fail and the observed */ \\\n\t\t/* atomic load will be returned. Or the non-atomic load got lucky and the cmpxchg succeeds */ \\\n\t\t/* because the observed value equals the value in *(ptr) thus we optimistically do a non-atomic load. */ \\\n\t\tret = *(ptr);\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tdo\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\tEA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_CMPXCHG_STRONG_, MemoryOrder), _128)(type, cmpxchgRet, ptr, &(ret), val); \\\n\t\t} while (!cmpxchgRet);\t\t\t\t\t\t\t\t\t\t\t\\\n\t}\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_EXCHANGE_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELAXED_128(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQUIRE_128(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_RELEASE_128(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_ACQ_REL_128(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_64(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_EXCHANGE_SEQ_CST_128(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_EXCHANGE_128(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_EXCHANGE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_fetch_add.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_ADD_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_ADD_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_ADD_N(integralType, addIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OP_N(integralType, addIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_N(char, _InterlockedExchangeAdd8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_N(short, _InterlockedExchangeAdd16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_N(long, _InterlockedExchangeAdd, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_N(__int64, _InterlockedExchangeAdd64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_ADD_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_ADD_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_ADD_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_ADD_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_fetch_and.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_AND_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_AND_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#if defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_8 _InterlockedAnd8_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_16 _InterlockedAnd16_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_32 _InterlockedAnd_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_64 _InterlockedAnd64_np\n\n#else\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_8 _InterlockedAnd8\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_16 _InterlockedAnd16\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_32 _InterlockedAnd\n\t#define EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_64 _InterlockedAnd64\n\n#endif\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_AND_N(integralType, andIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OP_N(integralType, andIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_N(char, EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_N(short, EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_N(long, EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_32, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_N(__int64, EASTL_MSVC_ATOMIC_FETCH_AND_INTRIN_64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_AND_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_AND_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_AND_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_AND_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_fetch_or.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_OR_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_OR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#if defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_8 _InterlockedOr8_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_16 _InterlockedOr16_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_32 _InterlockedOr_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_64 _InterlockedOr64_np\n\n#else\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_8 _InterlockedOr8\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_16 _InterlockedOr16\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_32 _InterlockedOr\n\t#define EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_64 _InterlockedOr64\n\n#endif\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_OR_N(integralType, orIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OP_N(integralType, orIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_N(char, EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_N(short, EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_N(long, EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_32, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_N(long long, EASTL_MSVC_ATOMIC_FETCH_OR_INTRIN_64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_OR_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_16(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_32(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELAXED_64(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_OR_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_OR_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_OR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_fetch_sub.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_SUB_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_SUB_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_MSVC_FETCH_SUB_PRE_INTRIN_COMPUTE(ret, val) \\\n\tret = EASTL_ATOMIC_NEGATE_OPERAND((val))\n\n#define EASTL_MSVC_ATOMIC_FETCH_SUB_N(integralType, subIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OP_N(integralType, subIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_FETCH_SUB_PRE_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_N(char, _InterlockedExchangeAdd8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_N(short, _InterlockedExchangeAdd16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_N(long, _InterlockedExchangeAdd, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_N(__int64, _InterlockedExchangeAdd64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_SUB_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_SUB_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_SUB_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_SUB_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_fetch_xor.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_XOR_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_XOR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#if defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_8 _InterlockedXor8_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_16 _InterlockedXor16_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_32 _InterlockedXor_np\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_64 _InterlockedXor64_np\n\n#else\n\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_8 _InterlockedXor8\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_16 _InterlockedXor16\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_32 _InterlockedXor\n\t#define EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_64 _InterlockedXor64\n\n#endif\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_XOR_N(integralType, xorIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_OP_N(integralType, xorIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_N(char, EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_N(short, EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_N(long, EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_32, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_N(__int64, EASTL_MSVC_ATOMIC_FETCH_XOR_INTRIN_64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_FETCH_XOR_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_FETCH_XOR_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_FETCH_XOR_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_FETCH_XOR_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_or_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_OR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_OR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#if defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_8 _InterlockedOr8_np\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_16 _InterlockedOr16_np\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_32 _InterlockedOr_np\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_64 _InterlockedOr64_np\n\n#else\n\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_8 _InterlockedOr8\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_16 _InterlockedOr16\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_32 _InterlockedOr\n\t#define EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_64 _InterlockedOr64\n\n#endif\n\n\n#define EASTL_MSVC_OR_FETCH_POST_INTRIN_COMPUTE(ret, val, orend)\t\\\n\tret = (val) | (orend)\n\n#define EASTL_MSVC_ATOMIC_OR_FETCH_N(integralType, orIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_OP_FETCH_N(integralType, orIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE, EASTL_MSVC_OR_FETCH_POST_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_N(char, EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_N(short, EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_N(long, EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_32, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_N(__int64, EASTL_MSVC_ATOMIC_OR_FETCH_INTRIN_64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_OR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_16(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_32(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELAXED_64(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_8(type, ret, ptr, val) \\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_OR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_OR_FETCH_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_OR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_signal_fence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_SIGNAL_FENCE_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_SIGNAL_FENCE_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_*()\n//\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELAXED()\t\\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQUIRE()\t\\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_RELEASE()\t\\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_ACQ_REL()\t\\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n#define EASTL_COMPILER_ATOMIC_SIGNAL_FENCE_SEQ_CST()\t\\\n\tEASTL_ATOMIC_COMPILER_BARRIER()\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_SIGNAL_FENCE_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_sub_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_SUB_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_SUB_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#define EASTL_MSVC_SUB_FETCH_PRE_INTRIN_COMPUTE(ret, val) \\\n\tret = EASTL_ATOMIC_NEGATE_OPERAND((val))\n\n#define EASTL_MSVC_SUB_FETCH_POST_INTRIN_COMPUTE(ret, val, subend)\t\\\n\tret = (val) - (subend)\n\n#define EASTL_MSVC_ATOMIC_SUB_FETCH_N(integralType, subIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_OP_FETCH_N(integralType, subIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_SUB_FETCH_PRE_INTRIN_COMPUTE, EASTL_MSVC_SUB_FETCH_POST_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_N(char, _InterlockedExchangeAdd8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_N(short, _InterlockedExchangeAdd16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_N(long, _InterlockedExchangeAdd, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_N(__int64, _InterlockedExchangeAdd64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_SUB_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_SUB_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_SUB_FETCH_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_SUB_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/atomic/compiler/msvc/compiler_msvc_xor_fetch.h",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_XOR_FETCH_H\n#define EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_XOR_FETCH_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#if defined(EA_PROCESSOR_X86_64)\n\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_8 _InterlockedXor8_np\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_16 _InterlockedXor16_np\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_32 _InterlockedXor_np\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_64 _InterlockedXor64_np\n\n#else\n\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_8 _InterlockedXor8\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_16 _InterlockedXor16\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_32 _InterlockedXor\n\t#define EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_64 _InterlockedXor64\n\n#endif\n\n\n#define EASTL_MSVC_XOR_FETCH_POST_INTRIN_COMPUTE(ret, val, xorend)\t\\\n\tret = (val) ^ (xorend)\n\n#define EASTL_MSVC_ATOMIC_XOR_FETCH_N(integralType, xorIntrinsic, type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_OP_FETCH_N(integralType, xorIntrinsic, type, ret, ptr, val, MemoryOrder, \\\n\t\t\t\t\t\t\t\t EASTL_MSVC_NOP_PRE_INTRIN_COMPUTE, EASTL_MSVC_XOR_FETCH_POST_INTRIN_COMPUTE)\n\n\n#define EASTL_MSVC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, MemoryOrder)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_N(char, EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_8, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_N(short, EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_16, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_N(long, EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_32, type, ret, ptr, val, MemoryOrder)\n\n#define EASTL_MSVC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, MemoryOrder) \\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_N(__int64, EASTL_MSVC_ATOMIC_XOR_FETCH_INTRIN_64, type, ret, ptr, val, MemoryOrder)\n\n\n/////////////////////////////////////////////////////////////////////////////////\n//\n// void EASTL_COMPILER_ATOMIC_XOR_FETCH_*_N(type, type ret, type * ptr, type val)\n//\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, RELAXED)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELAXED_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, RELAXED)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, ACQUIRE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQUIRE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, ACQUIRE)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, RELEASE)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_RELEASE_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, RELEASE)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, ACQ_REL)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_ACQ_REL_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, ACQ_REL)\n\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_8(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_8(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_16(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_16(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_32(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_32(type, ret, ptr, val, SEQ_CST)\n\n#define EASTL_COMPILER_ATOMIC_XOR_FETCH_SEQ_CST_64(type, ret, ptr, val)\t\\\n\tEASTL_MSVC_ATOMIC_XOR_FETCH_64(type, ret, ptr, val, SEQ_CST)\n\n\n#endif /* EASTL_ATOMIC_INTERNAL_COMPILER_MSVC_XOR_FETCH_H */\n"
  },
  {
    "path": "include/EASTL/internal/char_traits.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements similar functionality to char_traits which is part of\n// the C++ standard STL library specification. This is intended for internal\n// EASTL use only.  Functionality can be accessed through the eastl::string or\n// eastl::string_view types.  \n//\n// http://en.cppreference.com/w/cpp/string/char_traits\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_CHAR_TRAITS_H\n#define EASTL_CHAR_TRAITS_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/algorithm.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <ctype.h>              // toupper, etc.\n#include <string.h>             // memset, etc.\nEA_RESTORE_ALL_VC_WARNINGS()\n\nnamespace eastl\n{\n\tnamespace details\n\t{\n#if defined(EA_COMPILER_CPP17_ENABLED)\n\t\t// Helper to detect if wchar_t is the native type for the current platform or if -fshort-wchar was used.\n\t\t// When that flag is used all string builtins and C Standard Library functions are not usable.\n\t\tconstexpr bool UseNativeWideChar()\n\t\t{\n#if defined(EA_COMPILER_MSVC)\n\t\t\treturn true; // Irrelevant flag for windows.\n#elif defined(EA_PLATFORM_SONY) && defined(EA_PLATFORM_POSIX) && defined(EA_PLATFORM_CONSOLE)\n\t\t\treturn true; // Sony consoles use short wchar_t disregarding the flag.\n#else\n\t\t\treturn sizeof(wchar_t) == 4;\n#endif\n\t\t}\n#endif\n\t}\n\t\n\t///////////////////////////////////////////////////////////////////////////////\n\t/// DecodePart\n\t///\n\t/// These implement UTF8/UCS2/UCS4 encoding/decoding.\n\t///\n\tEASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char*&     pDest, char*     pDestEnd);\n\tEASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);\n\tEASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);\n\n\tEASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char*&     pDest, char*     pDestEnd);\n\tEASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);\n\tEASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);\n\n\tEASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char*&     pDest, char*     pDestEnd);\n\tEASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);\n\tEASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);\n\n\tEASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char*&     pDest, char*     pDestEnd);\n\tEASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);\n\tEASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);\n\n\t#if EA_CHAR8_UNIQUE\n\t\tbool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char8_t*&  pDest, char8_t*  pDestEnd);\n\n\t\tbool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char*&     pDest, char*     pDestEnd);\n\t\tbool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);\n\t\tbool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);\n\n\t\tbool DecodePart(const char*&     pSrc, const char*     pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);\n\t\tbool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);\n\t\tbool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);\n\t#endif\n\n\t#if EA_WCHAR_UNIQUE\n\t\tbool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, wchar_t*&  pDest, wchar_t*  pDestEnd);\n\n\t\tbool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char*&     pDest, char*     pDestEnd);\n\t\tbool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd);\n\t\tbool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd);\n\n\t\tbool DecodePart(const char*&     pSrc, const char*     pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);\n\t\tbool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);\n\t\tbool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);\n\t#endif\n\n\t#if EA_CHAR8_UNIQUE && EA_WCHAR_UNIQUE\n\t\tbool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd);\n\t\tbool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd);\n\t#endif\n\n\n\t#if EA_WCHAR_UNIQUE\n\t\tinline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)\n\t\t{\n\t\t\treturn DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));\n\t\t}\n\n\t\tinline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char*& pDest, char* pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t\treturn DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), pDest, pDestEnd);\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t\treturn DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), pDest, pDestEnd);\n\t\t#endif\n\t\t}\n\n\t\tinline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t\treturn DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), pDest, pDestEnd);\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t\treturn DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), pDest, pDestEnd);\n\t\t#endif\n\t\t}\n\n\t\tinline bool DecodePart(const wchar_t*& pSrc, const wchar_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t\treturn DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), pDest, pDestEnd);\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t\treturn DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), pDest, pDestEnd);\n\t\t#endif\n\t\t}\n\n\t\tinline bool DecodePart(const char*& pSrc, const char* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));\n\t\t#endif\n\t\t}\n\n\t\tinline bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));\n\t\t#endif\n\t\t}\n\n\t\tinline bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, wchar_t*& pDest, wchar_t* pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));\n\t\t#endif\n\t\t}\n\t#endif\n\n\t#if EA_CHAR8_UNIQUE\n\t    inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)\n\t    {\n\t\t    return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));\n\t    }\n\n\t    inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char*& pDest, char* pDestEnd)\n\t    {\n\t\t    return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), pDest, pDestEnd);\n\t    }\n\n\t    inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)\n\t    {\n\t\t    return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), pDest, pDestEnd);\n\t    }\n\n\t    inline bool DecodePart(const char8_t*& pSrc, const char8_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)\n\t    {\n\t\t    return DecodePart(reinterpret_cast<const char*&>(pSrc), reinterpret_cast<const char*>(pSrcEnd), pDest, pDestEnd);\n\t    }\n\n\t\tinline bool DecodePart(const char*& pSrc, const char* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)\n\t\t{\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));\n\t\t}\n\n\t\tinline bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)\n\t\t{\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));\n\t\t}\n\n\t\tinline bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char8_t*& pDest, char8_t* pDestEnd)\n\t\t{\n\t\t\treturn DecodePart(pSrc, pSrcEnd, reinterpret_cast<char*&>(pDest), reinterpret_cast<char*&>(pDestEnd));\n\t\t}\n    #endif\n\n\t#if EA_CHAR8_UNIQUE && EA_WCHAR_UNIQUE\n\t\tinline bool DecodePart(const char8_t*&  pSrc, const char8_t*  pSrcEnd, wchar_t*&  pDest, wchar_t*  pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t    return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char16_t*&>(pDest), reinterpret_cast<char16_t*>(pDestEnd));\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t    return DecodePart(pSrc, pSrcEnd, reinterpret_cast<char32_t*&>(pDest), reinterpret_cast<char32_t*>(pDestEnd));\n\t\t#endif\n\t\t}\n\n\t\tinline bool DecodePart(const wchar_t*&  pSrc, const wchar_t*  pSrcEnd, char8_t*&  pDest, char8_t*  pDestEnd)\n\t\t{\n\t\t#if (EA_WCHAR_SIZE == 2)\n\t\t\treturn DecodePart(reinterpret_cast<const char16_t*&>(pSrc), reinterpret_cast<const char16_t*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*>(pDestEnd));\n\t\t#elif (EA_WCHAR_SIZE == 4)\n\t\t\treturn DecodePart(reinterpret_cast<const char32_t*&>(pSrc), reinterpret_cast<const char32_t*>(pSrcEnd), reinterpret_cast<char*&>(pDest), reinterpret_cast<char*>(pDestEnd));\n\t\t#endif\n\t\t}\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// 'char traits' functionality\n\t//\n\tinline char CharToLower(char c)\n\t\t{ return (char)tolower((uint8_t)c); }\n\n\ttemplate<typename T>\n\tinline T CharToLower(T c)\n\t\t{ if((unsigned)c <= 0xff) return (T)tolower((uint8_t)c); return c; }\n\n\n\tinline char CharToUpper(char c)\n\t\t{ return (char)toupper((uint8_t)c); }\n\n\ttemplate<typename T>\n\tinline T CharToUpper(T c)\n\t\t{ if((unsigned)c <= 0xff) return (T)toupper((uint8_t)c); return c; }\n\n\n\ttemplate <typename T>\n\tint Compare(const T* p1, const T* p2, size_t n)\n\t{\n\t\tfor(; n > 0; ++p1, ++p2, --n)\n\t\t{\n\t\t\tif(*p1 != *p2)\n\t\t\t\treturn (static_cast<typename make_unsigned<T>::type>(*p1) < \n\t\t\t\t\t\tstatic_cast<typename make_unsigned<T>::type>(*p2)) ? -1 : 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n#if defined(EA_COMPILER_CPP17_ENABLED)\n\t// All main compilers offer a constexpr __builtin_memcmp as soon as C++17 was available.\n\tconstexpr int Compare(const char* p1, const char* p2, size_t n) { return __builtin_memcmp(p1, p2, n); }\n\n#if !defined(EA_COMPILER_GNUC)\n\t// GCC doesn't offer __builtin_wmemcmp.\n\tconstexpr int Compare(const wchar_t* p1, const wchar_t* p2, size_t n)\n\t{\n\t\tif constexpr (details::UseNativeWideChar())\n\t\t\treturn __builtin_wmemcmp(p1, p2, n);\n\t\telse\n\t\t\treturn Compare<wchar_t>(p1, p2, n);\n\t}\n#endif // !defined(EA_COMPILER_GNUC)\n#else\n\tinline int Compare(const char* p1, const char* p2, size_t n)\n\t{\n\t\tif (n > 0)\n\t\t\treturn memcmp(p1, p2, n);\n\t\telse\n\t\t\treturn 0;\n\t}\n#endif\n\n\ttemplate <typename T>\n\tinline int CompareI(const T* p1, const T* p2, size_t n)\n\t{\n\t\tfor(; n > 0; ++p1, ++p2, --n)\n\t\t{\n\t\t\tconst T c1 = CharToLower(*p1);\n\t\t\tconst T c2 = CharToLower(*p2);\n\n\t\t\tif(c1 != c2)\n\t\t\t\treturn (static_cast<typename make_unsigned<T>::type>(c1) < \n\t\t\t\t\t\tstatic_cast<typename make_unsigned<T>::type>(c2)) ? -1 : 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\n\ttemplate<typename T>\n\tinline EA_CPP14_CONSTEXPR const T* Find(const T* p, T c, size_t n)\n\t{\n\t\tfor(; n > 0; --n, ++p)\n\t\t{\n\t\t\tif(*p == c)\n\t\t\t\treturn p;\n\t\t}\n\n\t\treturn nullptr;\n\t}\n\n#if defined(EA_COMPILER_CPP17_ENABLED) && defined(EA_COMPILER_CLANG)\n\t// Only clang have __builtin_char_memchr.\n\t// __builtin_memchr doesn't work in a constexpr context since we need to cast the returned void* to a char*.\n\tinline constexpr const char* Find(const char* p, char c, size_t n)\n\t{\n\t\treturn __builtin_char_memchr(p, c, n);\n\t}\n#else\n\tinline const char* Find(const char* p, char c, size_t n)\n\t{\n\t\treturn (const char*)memchr(p, c, n);\n\t}\n#endif\n\n\ttemplate <typename T>\n\tinline EA_CPP14_CONSTEXPR size_t CharStrlen(const T* p)\n\t{\n\t\tconst auto* pCurrent = p;\n\t\twhile (*pCurrent)\n\t\t\t++pCurrent;\n\t\treturn (size_t)(pCurrent - p);\n\t}\n\n#if defined(EA_COMPILER_CPP17_ENABLED) && !defined(EA_COMPILER_GNUC)\n\t// So far, GCC seems to struggle with builtin_strlen: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816\n\t// MSVC and Clang support both builtins as soon as C++17 was available.\n\tconstexpr size_t CharStrlen(const char* p) { return __builtin_strlen(p); }\n\n\tconstexpr size_t CharStrlen(const wchar_t* p)\n\t{\n\t\tif constexpr (details::UseNativeWideChar())\n\t\t\treturn __builtin_wcslen(p);\n\t\telse\n\t\t\treturn CharStrlen<wchar_t>(p);\n\t}\n#endif\n\n\t// If either pDestination or pSource is an invalid or null pointer, the behavior is undefined, even if (pSourceEnd - pSource) is zero.\n\ttemplate <typename T>\n\tinline T* CharStringUninitializedCopy(const T* pSource, const T* pSourceEnd, T* pDestination)\n\t{\n\t\tmemmove(pDestination, pSource, (size_t)(pSourceEnd - pSource) * sizeof(T));\n\t\treturn pDestination + (pSourceEnd - pSource);\n\t}\n\n\n\t// CharTypeStringFindEnd\n\t// Specialized char version of STL find() from back function.\n\t// Not the same as RFind because search range is specified as forward iterators.\n\ttemplate <typename T>\n\tconst T* CharTypeStringFindEnd(const T* pBegin, const T* pEnd, T c)\n\t{\n\t\tconst T* pTemp = pEnd;\n\t\twhile(--pTemp >= pBegin)\n\t\t{\n\t\t\tif(*pTemp == c)\n\t\t\t\treturn pTemp;\n\t\t}\n\n\t\treturn pEnd;\n\t}\n\n\n\t// CharTypeStringSearch\n\t// Specialized value_type version of STL search() function.\n\t// Purpose: find p2 within p1. Return p1End if not found or if either string is zero length.\n\ttemplate <typename T>\n\tconst T* CharTypeStringSearch(const T* p1Begin, const T* p1End,\n\t\t\t\t\t\t\t\t  const T* p2Begin, const T* p2End)\n\t{\n\t\t// Test for zero length strings, in which case we have a match or a failure,\n\t\t// but the return value is the same either way.\n\t\tif((p1Begin == p1End) || (p2Begin == p2End))\n\t\t\treturn p1Begin;\n\n\t\t// Test for a pattern of length 1.\n\t\tif((p2Begin + 1) == p2End)\n\t\t\treturn eastl::find(p1Begin, p1End, *p2Begin);\n\n\t\t// General case.\n\t\tconst T* pTemp;\n\t\tconst T* pTemp1 = (p2Begin + 1);\n\t\tconst T* pCurrent = p1Begin;\n\n\t\twhile(p1Begin != p1End)\n\t\t{\n\t\t\tp1Begin = eastl::find(p1Begin, p1End, *p2Begin);\n\t\t\tif(p1Begin == p1End)\n\t\t\t\treturn p1End;\n\n\t\t\tpTemp = pTemp1;\n\t\t\tpCurrent = p1Begin;\n\t\t\tif(++pCurrent == p1End)\n\t\t\t\treturn p1End;\n\n\t\t\twhile(*pCurrent == *pTemp)\n\t\t\t{\n\t\t\t\tif(++pTemp == p2End)\n\t\t\t\t\treturn p1Begin;\n\t\t\t\tif(++pCurrent == p1End)\n\t\t\t\t\treturn p1End;\n\t\t\t}\n\n\t\t\t++p1Begin;\n\t\t}\n\n\t\treturn p1Begin;\n\t}\n\n\n\t// CharTypeStringRSearch\n\t// Specialized value_type version of STL find_end() function (which really is a reverse search function).\n\t// Purpose: find last instance of p2 within p1. Return p1End if not found or if either string is zero length.\n\ttemplate <typename T>\n\tconst T* CharTypeStringRSearch(const T* p1Begin, const T* p1End, \n\t\t\t\t\t\t\t\t   const T* p2Begin, const T* p2End)\n\t{\n\t\t// Test for zero length strings, in which case we have a match or a failure, \n\t\t// but the return value is the same either way.\n\t\tif((p1Begin == p1End) || (p2Begin == p2End))\n\t\t\treturn p1Begin;\n\n\t\t// Test for a pattern of length 1.\n\t\tif((p2Begin + 1) == p2End)\n\t\t\treturn CharTypeStringFindEnd(p1Begin, p1End, *p2Begin);\n\n\t\t// Test for search string length being longer than string length.\n\t\tif((p2End - p2Begin) > (p1End - p1Begin))\n\t\t\treturn p1End;\n\n\t\t// General case.\n\t\tconst T* pSearchEnd = (p1End - (p2End - p2Begin) + 1);\n\n\t\tconst T* pMatchCandidate;\n\t\twhile((pMatchCandidate = CharTypeStringFindEnd(p1Begin, pSearchEnd, *p2Begin)) != pSearchEnd)\n\t\t{\n\t\t\t// In this case, *pMatchCandidate == *p2Begin. So compare the rest.\n\t\t\tconst T* pCurrent1 = pMatchCandidate;\n\t\t\tconst T* pCurrent2 = p2Begin;\n\t\t\twhile(*pCurrent1++ == *pCurrent2++)\n\t\t\t{\n\t\t\t\tif(pCurrent2 == p2End)\n\t\t\t\t\treturn (pCurrent1 - (p2End - p2Begin));\n\t\t\t}\n\n\t\t\t// This match failed, search again with this new end.\n\t\t\tpSearchEnd = pMatchCandidate;\n\t\t}\n\n\t\treturn p1End;\n\t}\n\n\n\t// CharTypeStringFindFirstOf\n\t// Specialized value_type version of STL find_first_of() function.\n\t// This function is much like the C runtime strtok function, except the strings aren't null-terminated.\n\ttemplate <typename T>\n\tinline const T* CharTypeStringFindFirstOf(const T* p1Begin, const T* p1End, const T* p2Begin, const T* p2End)\n\t{\n\t\tfor (; p1Begin != p1End; ++p1Begin)\n\t\t{\n\t\t\tfor (const T* pTemp = p2Begin; pTemp != p2End; ++pTemp)\n\t\t\t{\n\t\t\t\tif (*p1Begin == *pTemp)\n\t\t\t\t\treturn p1Begin;\n\t\t\t}\n\t\t}\n\t\treturn p1End;\n\t}\n\n\n\t// CharTypeStringRFindFirstNotOf\n\t// Specialized value_type version of STL find_first_not_of() function in reverse.\n\ttemplate <typename T>\n\tinline const T* CharTypeStringRFindFirstNotOf(const T* p1RBegin, const T* p1REnd, const T* p2Begin, const T* p2End)\n\t{\n\t\tfor (; p1RBegin != p1REnd; --p1RBegin)\n\t\t{\n\t\t\tconst T* pTemp;\n\t\t\tfor (pTemp = p2Begin; pTemp != p2End; ++pTemp)\n\t\t\t{\n\t\t\t\tif (*(p1RBegin - 1) == *pTemp)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pTemp == p2End)\n\t\t\t\treturn p1RBegin;\n\t\t}\n\t\treturn p1REnd;\n\t}\n\n\n\t// CharTypeStringFindFirstNotOf\n\t// Specialized value_type version of STL find_first_not_of() function.\n\ttemplate <typename T>\n\tinline const T* CharTypeStringFindFirstNotOf(const T* p1Begin, const T* p1End, const T* p2Begin, const T* p2End)\n\t{\n\t\tfor (; p1Begin != p1End; ++p1Begin)\n\t\t{\n\t\t\tconst T* pTemp;\n\t\t\tfor (pTemp = p2Begin; pTemp != p2End; ++pTemp)\n\t\t\t{\n\t\t\t\tif (*p1Begin == *pTemp)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pTemp == p2End)\n\t\t\t\treturn p1Begin;\n\t\t}\n\t\treturn p1End;\n\t}\n\n\n\t// CharTypeStringRFindFirstOf\n\t// Specialized value_type version of STL find_first_of() function in reverse.\n\t// This function is much like the C runtime strtok function, except the strings aren't null-terminated.\n\ttemplate <typename T>\n\tinline const T* CharTypeStringRFindFirstOf(const T* p1RBegin, const T* p1REnd, const T* p2Begin, const T* p2End)\n\t{\n\t\tfor (; p1RBegin != p1REnd; --p1RBegin)\n\t\t{\n\t\t\tfor (const T* pTemp = p2Begin; pTemp != p2End; ++pTemp)\n\t\t\t{\n\t\t\t\tif (*(p1RBegin - 1) == *pTemp)\n\t\t\t\t\treturn p1RBegin;\n\t\t\t}\n\t\t}\n\t\treturn p1REnd;\n\t}\n\n\n\t// CharTypeStringRFind\n\t// Specialized value_type version of STL find() function in reverse.\n\ttemplate <typename T>\n\tinline const T* CharTypeStringRFind(const T* pRBegin, const T* pREnd, const T c)\n\t{\n\t\twhile (pRBegin > pREnd)\n\t\t{\n\t\t\tif (*(pRBegin - 1) == c)\n\t\t\t\treturn pRBegin;\n\t\t\t--pRBegin;\n\t\t}\n\t\treturn pREnd;\n\t}\n\n\n\tinline char* CharStringUninitializedFillN(char* pDestination, size_t n, const char c)\n\t{\n\t\tif(n) // Some compilers (e.g. GCC 4.3+) generate a warning (which can't be disabled) if you call memset with a size of 0.\n\t\t\tmemset(pDestination, (uint8_t)c, (size_t)n);\n\t\treturn pDestination + n;\n\t}\n\n\ttemplate<typename T>\n\tinline T* CharStringUninitializedFillN(T* pDestination, size_t n, const T c)\n\t{\n\t\tT * pDest           = pDestination;\n\t\tconst T* const pEnd = pDestination + n;\n\t\twhile(pDest < pEnd)\n\t\t\t*pDest++ = c;\n\t\treturn pDestination + n;\n\t}\n\n\n\tinline char* CharTypeAssignN(char* pDestination, size_t n, char c)\n\t{\n\t\tif(n) // Some compilers (e.g. GCC 4.3+) generate a warning (which can't be disabled) if you call memset with a size of 0.\n\t\t\treturn (char*)memset(pDestination, c, (size_t)n);\n\t\treturn pDestination;\n\t}\n\n\ttemplate<typename T>\n\tinline T* CharTypeAssignN(T* pDestination, size_t n, T c)\n\t{\n\t\tT* pDest            = pDestination;\n\t\tconst T* const pEnd = pDestination + n;\n\t\twhile(pDest < pEnd)\n\t\t\t*pDest++ = c;\n\t\treturn pDestination;\n\t}\n} // namespace eastl\n\n#endif // EASTL_CHAR_TRAITS_H\n"
  },
  {
    "path": "include/EASTL/internal/concepts.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_CONCEPTS_H\n#define EASTL_INTERNAL_CONCEPTS_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n#pragma once\n#endif\n\n#include <EASTL/internal/type_detected.h>\n\nnamespace eastl\n{\n\tnamespace internal\n\t{\n\t\ttemplate <typename From, typename To>\n\t\tusing detect_explicitely_convertible = decltype(static_cast<To>(declval<From>()));\n\n\t\tnamespace concepts\n\t\t{\n\t\t\ttemplate <typename T>\n\t\t\tconstexpr bool destructible = is_nothrow_destructible_v<T>;\n\n\t\t\ttemplate <typename T, typename... Args>\n\t\t\tconstexpr bool constructible_from = destructible<T> && is_constructible_v<T, Args...>;\n\n\t\t\ttemplate <typename From, typename To>\n\t\t\tconstexpr bool convertible_to =\n\t\t\t\t  is_convertible_v<From, To> && is_detected_v<detect_explicitely_convertible, From, To>;\n\n\t\t\ttemplate <typename T>\n\t\t\tconstexpr bool move_constructible = constructible_from<T, T> && convertible_to<T, T>;\n\n\t\t\ttemplate <typename T>\n\t\t\tconstexpr bool copy_constructible =\n\t\t\t\tmove_constructible<T> && constructible_from<T, T&> && convertible_to<T&, T> &&\n\t\t\t\tconstructible_from<T, const T&> && convertible_to<const T&, T> && constructible_from<T, const T> &&\n\t\t\t\tconvertible_to<const T, T>;\n\t\t} // namespace concepts\n\t} // namespace internal\n} // namespace eastl\n\n#endif"
  },
  {
    "path": "include/EASTL/internal/config.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_CONFIG_H\n#define EASTL_INTERNAL_CONFIG_H\n\n\n///////////////////////////////////////////////////////////////////////////////\n// ReadMe\n//\n// This is the EASTL configuration file. All configurable parameters of EASTL\n// are controlled through this file. However, all the settings here can be\n// manually overridden by the user. There are three ways for a user to override\n// the settings in this file:\n//\n//     - Simply edit this file.\n//     - Define EASTL_USER_CONFIG_HEADER.\n//     - Predefine individual defines (e.g. EASTL_ASSERT).\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_USER_CONFIG_HEADER\n//\n// This allows the user to define a header file to be #included before the\n// EASTL config.h contents are compiled. A primary use of this is to override\n// the contents of this config.h file. Note that all the settings below in\n// this file are user-overridable.\n//\n// Example usage:\n//     #define EASTL_USER_CONFIG_HEADER \"MyConfigOverrides.h\"\n//     #include <EASTL/vector.h>\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifdef EASTL_USER_CONFIG_HEADER\n\t#include EASTL_USER_CONFIG_HEADER\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_EABASE_DISABLED\n//\n// The user can disable EABase usage and manually supply the configuration\n// via defining EASTL_EABASE_DISABLED and defining the appropriate entities\n// globally or via the above EASTL_USER_CONFIG_HEADER.\n//\n// Example usage:\n//     #define EASTL_EABASE_DISABLED\n//     #include <EASTL/vector.h>\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_EABASE_DISABLED\n\t#include <EABase/eabase.h>\n\t#include <EABase/eadeprecated.h>\n#endif\n#include <EABase/eahave.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#if EA_TSAN_ENABLED\n#include <sanitizer/tsan_interface.h>\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_VERSION\n//\n// We more or less follow the conventional EA packaging approach to versioning\n// here. A primary distinction here is that minor versions are defined as two\n// digit entities (e.g. .03\") instead of minimal digit entities \".3\"). The logic\n// here is that the value is a counter and not a floating point fraction.\n// Note that the major version doesn't have leading zeros.\n//\n// Example version strings:\n//      \"0.91.00\"   // Major version 0, minor version 91, patch version 0.\n//      \"1.00.00\"   // Major version 1, minor and patch version 0.\n//      \"3.10.02\"   // Major version 3, minor version 10, patch version 02.\n//     \"12.03.01\"   // Major version 12, minor version 03, patch version\n//\n// Example usage:\n//     printf(\"EASTL version: %s\", EASTL_VERSION);\n//     printf(\"EASTL version: %d.%d.%d\", EASTL_VERSION_N / 10000 % 100, EASTL_VERSION_N / 100 % 100, EASTL_VERSION_N % 100);\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_VERSION\n\t#define EASTL_VERSION   \"3.27.00\"\n\t#define EASTL_VERSION_N  32700\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n//\n// Defined as 1 or undefined.\n// Implements support for the definition of EA_COMPILER_NO_STANDARD_CPP_LIBRARY for the case\n// of using EABase versions prior to the addition of its EA_COMPILER_NO_STANDARD_CPP_LIBRARY support.\n//\n#if !defined(EA_COMPILER_NO_STANDARD_CPP_LIBRARY)\n\t#if defined(EA_PLATFORM_ANDROID)\n\t\t// Disabled because EA's eaconfig/android_config/android_sdk packages currently\n\t\t// don't support linking STL libraries. Perhaps we can figure out what linker arguments\n\t\t// are needed for an app so we can manually specify them and then re-enable this code.\n\t\t//\n\t\t//#include <android/api-level.h>\n\t\t//\n\t\t//#if (__ANDROID_API__ < 9) // Earlier versions of Android provide no std C++ STL implementation.\n\t\t\t#define EA_COMPILER_NO_STANDARD_CPP_LIBRARY 1\n\t\t//#endif\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EA_NOEXCEPT\n//\n// Defined as a macro. Provided here for backward compatibility with older\n// EABase versions prior to 2.00.40 that don't yet define it themselves.\n//\n#if !defined(EA_NOEXCEPT)\n\t#define EA_NOEXCEPT\n\t#define EA_NOEXCEPT_IF(predicate)\n\t#define EA_NOEXCEPT_EXPR(expression) false\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EA_CPP14_CONSTEXPR\n//\n// Defined as constexpr when a C++14 compiler is present. Defines it as nothing\n// when using a C++11 compiler.\n// C++14 relaxes the specification for constexpr such that it allows more\n// kinds of expressions. Since a C++11 compiler doesn't allow this, we need\n// to make a unique define for C++14 constexpr. This macro should be used only\n// when you are using it with code that specfically requires C++14 constexpr\n// functionality beyond the regular C++11 constexpr functionality.\n// http://en.wikipedia.org/wiki/C%2B%2B14#Relaxed_constexpr_restrictions\n//\n#if !defined(EA_CPP14_CONSTEXPR)\n\t#if defined(EA_COMPILER_CPP14_ENABLED)\n\t\t#define EA_CPP14_CONSTEXPR constexpr\n\t#else\n\t\t#define EA_CPP14_CONSTEXPR  // not supported\n\t\t#define EA_NO_CPP14_CONSTEXPR\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL namespace\n//\n// We define this so that users that #include this config file can reference\n// these namespaces without seeing any other files that happen to use them.\n///////////////////////////////////////////////////////////////////////////////\n\n/// EA Standard Template Library\nnamespace eastl\n{\n\t// Intentionally empty.\n}\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_DEBUG\n//\n// Defined as an integer >= 0. Default is 1 for debug builds and 0 for\n// release builds. This define is also a master switch for the default value\n// of some other settings.\n//\n// Example usage:\n//    #if EASTL_DEBUG\n//       ...\n//    #endif\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_DEBUG\n\t#if defined(EA_DEBUG) || defined(_DEBUG)\n\t\t#define EASTL_DEBUG 1\n\t#else\n\t\t#define EASTL_DEBUG 0\n\t#endif\n#endif\n\n// Developer debug. Helps EASTL developers assert EASTL is coded correctly.\n// Normally disabled for users since it validates internal things and not user things.\n#ifndef EASTL_DEV_DEBUG\n\t#define EASTL_DEV_DEBUG 0\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_DEBUGPARAMS_LEVEL\n//\n// EASTL_DEBUGPARAMS_LEVEL controls what debug information is passed through to\n// the allocator by default.\n// This value may be defined by the user ... if not it will default to 1 for\n// EA_DEBUG builds, otherwise 0.\n//\n//  0 - no debug information is passed through to allocator calls.\n//  1 - 'name' is passed through to allocator calls.\n//  2 - 'name', __FILE__, and __LINE__ are passed through to allocator calls.\n//\n// This parameter mirrors the equivalent parameter in the CoreAllocator package.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_DEBUGPARAMS_LEVEL\n\t#if EASTL_DEBUG\n\t\t#define EASTL_DEBUGPARAMS_LEVEL 2\n\t#else\n\t\t#define EASTL_DEBUGPARAMS_LEVEL 0\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_DLL\n//\n// Defined as 0 or 1. The default is dependent on the definition of EA_DLL.\n// If EA_DLL is defined, then EASTL_DLL is 1, else EASTL_DLL is 0.\n// EA_DLL is a define that controls DLL builds within the EAConfig build system.\n// EASTL_DLL controls whether EASTL is built and used as a DLL.\n// Normally you wouldn't do such a thing, but there are use cases for such\n// a thing, particularly in the case of embedding C++ into C# applications.\n//\n#ifndef EASTL_DLL\n\t#if defined(EA_DLL)\n\t\t#define EASTL_DLL 1\n\t#else\n\t\t#define EASTL_DLL 0\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_IF_NOT_DLL\n//\n// Utility to include expressions only for static builds.\n//\n#ifndef EASTL_IF_NOT_DLL\n\t#if EASTL_DLL\n\t\t#define EASTL_IF_NOT_DLL(x)\n\t#else\n\t\t#define EASTL_IF_NOT_DLL(x) x\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_API\n//\n// This is used to label functions as DLL exports under Microsoft platforms.\n// If EA_DLL is defined, then the user is building EASTL as a DLL and EASTL's\n// non-templated functions will be exported. EASTL template functions are not\n// labelled as EASTL_API (and are thus not exported in a DLL build). This is\n// because it's not possible (or at least unsafe) to implement inline templated\n// functions in a DLL.\n//\n// Example usage of EASTL_API:\n//    EASTL_API int someVariable = 10;      // Export someVariable in a DLL build.\n//\n//    struct EASTL_API SomeClass{           // Export SomeClass and its member functions in a DLL build.\n//        EASTL_LOCAL void PrivateMethod(); // Not exported.\n//    };\n//\n//    EASTL_API void SomeFunction();        // Export SomeFunction in a DLL build.\n//\n//\n#if defined(EA_DLL) && !defined(EASTL_DLL)\n\t#define EASTL_DLL 1\n#endif\n\n#ifndef EASTL_API // If the build file hasn't already defined this to be dllexport...\n\t#if EASTL_DLL\n\t\t#define EASTL_API      EA_IMPORT\n\t\t#define EASTL_LOCAL    EA_LOCAL\n\t#else\n\t\t#define EASTL_API\n\t\t#define EASTL_LOCAL\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_EASTDC_API\n//\n// This is used for importing EAStdC functions into EASTL, possibly via a DLL import.\n//\n#ifndef EASTL_EASTDC_API\n\t#if EASTL_DLL\n\t\t#define EASTL_EASTDC_API\t\tEA_IMPORT\n\t\t#define EASTL_EASTDC_LOCAL\t\tEA_LOCAL\n\t#else\n\t\t#define EASTL_EASTDC_API\n\t\t#define EASTL_EASTDC_LOCAL\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_EASTDC_VSNPRINTF\n//\n// Defined as 0 or 1. By default it is 1.\n//\n// When enabled EASTL uses EAStdC's Vsnprintf function directly instead of\n// having the user provide a global Vsnprintf8/16/32 function. The benefit\n// of this is that it will allow EASTL to just link to EAStdC's Vsnprintf\n// without the user doing anything. The downside is that any users who aren't\n// already using EAStdC will either need to now depend on EAStdC or globally\n// define this property to be 0 and simply provide functions that have the same\n// names. See the usage of EASTL_EASTDC_VSNPRINTF in string.h for more info.\n//\n#if !defined(EASTL_EASTDC_VSNPRINTF)\n\t#define EASTL_EASTDC_VSNPRINTF 1\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_NAME_ENABLED / EASTL_NAME / EASTL_NAME_VAL\n//\n// Used to wrap debug string names. In a release build, the definition\n// goes away. These are present to avoid release build compiler warnings\n// and to make code simpler.\n//\n// Example usage of EASTL_NAME:\n//    // pName will defined away in a release build and thus prevent compiler warnings.\n//    void allocator::set_name(const char* EASTL_NAME(pName))\n//    {\n//        #if EASTL_NAME_ENABLED\n//            mpName = pName;\n//        #endif\n//    }\n//\n// Example usage of EASTL_NAME_VAL:\n//    // \"xxx\" is defined to NULL in a release build.\n//    vector<T, Allocator>::vector(const allocator_type& allocator = allocator_type(EASTL_NAME_VAL(\"xxx\")));\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_NAME_ENABLED\n\t#define EASTL_NAME_ENABLED EASTL_DEBUG\n#endif\n\n#ifndef EASTL_NAME\n\t#if EASTL_NAME_ENABLED\n\t\t#define EASTL_NAME(x)      x\n\t\t#define EASTL_NAME_VAL(x)  x\n\t#else\n\t\t#define EASTL_NAME(x)\n\t\t#define EASTL_NAME_VAL(x) ((const char*)NULL)\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_DEFAULT_NAME_PREFIX\n//\n// Defined as a string literal. Defaults to \"EASTL\".\n// This define is used as the default name for EASTL where such a thing is\n// referenced in EASTL. For example, if the user doesn't specify an allocator\n// name for their deque, it is named \"EASTL deque\". However, you can override\n// this to say \"SuperBaseball deque\" by changing EASTL_DEFAULT_NAME_PREFIX.\n//\n// Example usage (which is simply taken from how deque.h uses this define):\n//     #ifndef EASTL_DEQUE_DEFAULT_NAME\n//         #define EASTL_DEQUE_DEFAULT_NAME   EASTL_DEFAULT_NAME_PREFIX \" deque\"\n//     #endif\n//\n#ifndef EASTL_DEFAULT_NAME_PREFIX\n\t#define EASTL_DEFAULT_NAME_PREFIX \"EASTL\"\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ASSERT_ENABLED\n//\n// Defined as 0 or non-zero. Default is same as EASTL_DEBUG.\n// If EASTL_ASSERT_ENABLED is non-zero, then asserts will be executed via\n// the assertion mechanism.\n//\n// Example usage:\n//     #if EASTL_ASSERT_ENABLED\n//         EASTL_ASSERT(v.size() > 17);\n//     #endif\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_ASSERT_ENABLED\n\t#define EASTL_ASSERT_ENABLED EASTL_DEBUG\n#endif\n\n// Developer assert. Helps EASTL developers assert EASTL is coded correctly.\n// Normally disabled for users since it validates internal things and not user things.\n#ifndef EASTL_DEV_ASSERT_ENABLED\n\t#define EASTL_DEV_ASSERT_ENABLED EASTL_DEV_DEBUG\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n//\n// Defined as 0 or non-zero. Default is same as EASTL_ASSERT_ENABLED.\n// This is like EASTL_ASSERT_ENABLED, except it fires asserts specifically for\n// a container operation that returns a reference while the container is empty.\n// Sometimes people like to be able to take a reference to the front of the\n// container, but won't use it if the container is empty. This may or may not\n// be undefined behaviour depending on the container.\n//\n// In practice, for expressions such as &vector[0] this is not an issue -\n// at least if the subscript operator is inlined because the expression will\n// be equivalent to &*(nullptr) and optimized ti nullptr. MSVC, Clang and GCC\n// all have this behaviour and UBSan & ASan report no issues with that code.\n//\n// Code that relies on this macro being disabled should instead use the\n// container's data() member function. The range [data(), data() + size())\n// is always valid, even when the container is empty (in which case data()\n// is not dereferencable).\n//\n// Enabling this macro adds asserts if the container is empty and the function\n// invocation is well defined. If the implementation may invoke UB, or the\n// container is non-empty, then the assert fires if EASTL_ASSERT_ENABLED is\n// enabled, regardless of this macro.\n//\n// NOTE: If this is enabled, EASTL_ASSERT_ENABLED must also be enabled to\n// have any effect.\n//\n// Example usage:\n//     template <typename T, typename Allocator>\n//     inline typename vector<T, Allocator>::reference\n//     vector<T, Allocator>::front()\n//     {\n//         #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n//             EASTL_ASSERT(mpEnd > mpBegin);\n//         #endif\n//\n//         return *mpBegin;\n//     }\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t#define EASTL_EMPTY_REFERENCE_ASSERT_ENABLED EASTL_ASSERT_ENABLED\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// SetAssertionFailureFunction\n//\n// Allows the user to set a custom assertion failure mechanism.\n//\n// Example usage:\n//     void Assert(const char* pExpression, void* pContext);\n//     SetAssertionFailureFunction(Assert, this);\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_ASSERTION_FAILURE_DEFINED\n\t#define EASTL_ASSERTION_FAILURE_DEFINED\n\n\tnamespace eastl\n\t{\n\t\tusing EASTL_AssertionFailureFunction = void (*)(const char* pExpression, void* pContext);\n\t\tEASTL_API void SetAssertionFailureFunction(EASTL_AssertionFailureFunction pFunction, void* pContext);\n\t\tusing EASTL_AssertionFailureFunctionEx = void (*)(void*, const char* pExpression, void* pContext);\n\t\tEASTL_API void SetAssertionFailureFunction(EASTL_AssertionFailureFunctionEx pFunction, void* pContext);\n\n\t\t// These are the internal default functions that implement asserts.\n\t\tEASTL_API void AssertionFailure(const char* pExpression);\n\t\tEASTL_API void AssertionFailureFunctionDefault(const char* pExpression, void* pContext);\n\t\tEASTL_API void AssertionFailure(void* instructionPointer, const char* pExpression);\n\t}\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ASSERT\n//\n// Assertion macro. Can be overridden by user with a different value.\n//\n// Example usage:\n//    EASTL_ASSERT(intVector.size() < 100);\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_ASSERT\n\t#if EASTL_ASSERT_ENABLED\n\t\t#define EASTL_ASSERT(expression) \\\n\t\t\tEA_DISABLE_VC_WARNING(4127) \\\n\t\t\tdo { \\\n\t\t\t\tEA_ANALYSIS_ASSUME(expression); \\\n\t\t\t\t(void)((expression) || (eastl::AssertionFailure(EA_GET_INSTRUCTION_POINTER(), #expression), 0)); \\\n\t\t\t} while (0) \\\n\t\t\tEA_RESTORE_VC_WARNING()\n\t#else\n\t\t#define EASTL_ASSERT(expression)\n\t#endif\n#endif\n\n// Developer assert. Helps EASTL developers assert EASTL is coded correctly.\n// Normally disabled for users since it validates internal things and not user things.\n#ifndef EASTL_DEV_ASSERT\n\t#if EASTL_DEV_ASSERT_ENABLED\n\t\t#define EASTL_DEV_ASSERT(expression) \\\n\t\t\tEA_DISABLE_VC_WARNING(4127) \\\n\t\t\tdo { \\\n\t\t\t\tEA_ANALYSIS_ASSUME(expression); \\\n\t\t\t\t(void)((expression) || (eastl::AssertionFailure(EA_GET_INSTRUCTION_POINTER(), #expression), 0)); \\\n\t\t\t} while(0) \\\n\t\t\tEA_RESTORE_VC_WARNING()\n\t#else\n\t\t#define EASTL_DEV_ASSERT(expression)\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ASSERT_MSG\n//\n// Example usage:\n//    EASTL_ASSERT_MSG(false, \"detected error condition!\");\n//\n///////////////////////////////////////////////////////////////////////////////\n#ifndef EASTL_ASSERT_MSG\n\t#if EASTL_ASSERT_ENABLED\n\t\t#define EASTL_ASSERT_MSG(expression, message) \\\n\t\t\tEA_DISABLE_VC_WARNING(4127) \\\n\t\t\tdo { \\\n\t\t\t\tEA_ANALYSIS_ASSUME(expression); \\\n\t\t\t\t(void)((expression) || (eastl::AssertionFailure(EA_GET_INSTRUCTION_POINTER(), message), 0)); \\\n\t\t\t} while (0) \\\n\t\t\tEA_RESTORE_VC_WARNING()\n\t#else\n\t\t#define EASTL_ASSERT_MSG(expression, message)\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_FAIL_MSG\n//\n// Failure macro. Can be overridden by user with a different value.\n//\n// Example usage:\n//    EASTL_FAIL(\"detected error condition!\");\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FAIL_MSG\n\t#if EASTL_ASSERT_ENABLED\n#define EASTL_FAIL_MSG(message) (eastl::AssertionFailure(EA_GET_INSTRUCTION_POINTER(), message))\n\t#else\n\t\t#define EASTL_FAIL_MSG(message)\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_CT_ASSERT / EASTL_CT_ASSERT_NAMED\n//\n// EASTL_CT_ASSERT is a macro for compile time assertion checks, useful for\n// validating *constant* expressions. The advantage over using EASTL_ASSERT\n// is that errors are caught at compile time instead of runtime.\n//\n// Example usage:\n//     EASTL_CT_ASSERT(sizeof(uint32_t) == 4);\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#define EASTL_CT_ASSERT(expression) static_assert(expression, #expression)\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_CT_ASSERT_MSG\n//\n// EASTL_CT_ASSERT_MSG is a macro for compile time assertion checks, useful for\n// validating *constant* expressions. The advantage over using EASTL_ASSERT\n// is that errors are caught at compile time instead of runtime.\n// The message must be a string literal.\n//\n// Example usage:\n//     EASTL_CT_ASSERT_MSG(sizeof(uint32_t) == 4, \"The size of uint32_t must be 4.\");\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#define EASTL_CT_ASSERT_MSG(expression, message) static_assert(expression, message)\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_DEBUG_BREAK / EASTL_DEBUG_BREAK_OVERRIDE\n//\n// This function causes an app to immediately stop under the debugger.\n// It is implemented as a macro in order to allow stopping at the site\n// of the call.\n//\n// EASTL_DEBUG_BREAK_OVERRIDE allows one to define EASTL_DEBUG_BREAK directly.\n// This is useful in cases where you desire to disable EASTL_DEBUG_BREAK\n// but do not wish to (or cannot) define a custom void function() to replace\n// EASTL_DEBUG_BREAK callsites.\n//\n// Example usage:\n//     EASTL_DEBUG_BREAK();\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_DEBUG_BREAK_OVERRIDE\n    #ifndef EASTL_DEBUG_BREAK\n        #if defined(_MSC_VER) && (_MSC_VER >= 1300)\n            #define EASTL_DEBUG_BREAK() __debugbreak()    // This is a compiler intrinsic which will map to appropriate inlined asm for the platform.\n\t\t#elif defined(EA_PLATFORM_NINTENDO)\n\t\t\t#define EASTL_DEBUG_BREAK() __builtin_debugtrap()  // Consider using the CLANG define\n        #elif (defined(EA_PROCESSOR_ARM) && !defined(EA_PROCESSOR_ARM64)) && defined(__APPLE__)\n            #define EASTL_DEBUG_BREAK() asm(\"trap\")\n        #elif defined(EA_PROCESSOR_ARM64) && defined(__APPLE__)\n            #include <signal.h>\n            #include <unistd.h>\n            #define EASTL_DEBUG_BREAK() kill( getpid(), SIGINT )\n\t\t#elif defined(EA_PROCESSOR_ARM64) && defined(__GNUC__)\n\t\t\t#define EASTL_DEBUG_BREAK() asm(\"brk 10\")\n\t\t#elif defined(EA_PROCESSOR_ARM) && defined(__GNUC__)\n\t\t\t#define EASTL_DEBUG_BREAK() asm(\"BKPT 10\")     // The 10 is arbitrary. It's just a unique id.\n\t\t#elif defined(EA_PROCESSOR_ARM) && defined(__ARMCC_VERSION)\n\t\t\t#define EASTL_DEBUG_BREAK() __breakpoint(10)\n\t\t#elif defined(EA_PROCESSOR_POWERPC)               // Generic PowerPC.\n\t\t\t#define EASTL_DEBUG_BREAK() asm(\".long 0\")    // This triggers an exception by executing opcode 0x00000000.\n\t\t#elif (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64)) && defined(EA_ASM_STYLE_INTEL)\n\t\t\t#define EASTL_DEBUG_BREAK() { __asm int 3 }\n\t\t#elif (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64)) && (defined(EA_ASM_STYLE_ATT) || defined(__GNUC__))\n\t\t\t#define EASTL_DEBUG_BREAK() asm(\"int3\")\n\t\t#else\n\t\t\tvoid EASTL_DEBUG_BREAK(); // User must define this externally.\n\t\t#endif\n\t#else\n\t\tvoid EASTL_DEBUG_BREAK(); // User must define this externally.\n\t#endif\n#else\n\t#ifndef EASTL_DEBUG_BREAK\n\t\t#if EASTL_DEBUG_BREAK_OVERRIDE == 1\n\t\t\t// define an empty callable to satisfy the call site.\n\t\t\t#define EASTL_DEBUG_BREAK ([]{})\n\t\t#else\n\t\t\t#define EASTL_DEBUG_BREAK EASTL_DEBUG_BREAK_OVERRIDE\n\t\t#endif\n\t#else\n\t\t#error EASTL_DEBUG_BREAK is already defined yet you would like to override it. Please ensure no other headers are already defining EASTL_DEBUG_BREAK before this header (config.h) is included\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_CRASH\n//\n// Executes an invalid memory write, which should result in an exception\n// on most platforms.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#define EASTL_CRASH() *((volatile int*)0) = 0xDEADC0DE;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ALLOCATOR_COPY_ENABLED\n//\n// Defined as 0 or 1. Default is 0 (disabled) until some future date.\n// If enabled (1) then container operator= copies the allocator from the\n// source container. It ideally should be set to enabled but for backwards\n// compatibility with older versions of EASTL it is currently set to 0.\n// Regardless of whether this value is 0 or 1, this container copy constructs\n// or copy assigns allocators.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_ALLOCATOR_COPY_ENABLED\n\t#define EASTL_ALLOCATOR_COPY_ENABLED 0\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_FIXED_SIZE_TRACKING_ENABLED\n//\n// Defined as an integer >= 0. Default is same as EASTL_DEBUG.\n// If EASTL_FIXED_SIZE_TRACKING_ENABLED is enabled, then fixed\n// containers in debug builds track the max count of objects\n// that have been in the container. This allows for the tuning\n// of fixed container sizes to their minimum required size.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t#define EASTL_FIXED_SIZE_TRACKING_ENABLED EASTL_DEBUG\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_RTTI_ENABLED\n//\n// Defined as 0 or 1. Default is 1 if RTTI is supported by the compiler.\n// This define exists so that we can use some dynamic_cast operations in the\n// code without warning. dynamic_cast is only used if the specifically refers\n// to it; EASTL won't do dynamic_cast behind your back.\n//\n// Example usage:\n//     #if EASTL_RTTI_ENABLED\n//         pChildClass = dynamic_cast<ChildClass*>(pParentClass);\n//     #endif\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_RTTI_ENABLED\n\t// The VC++ default Standard Library (Dinkumware) disables major parts of RTTI\n\t// (e.g. type_info) if exceptions are disabled, even if RTTI itself is enabled.\n\t// _HAS_EXCEPTIONS is defined by Dinkumware to 0 or 1 (disabled or enabled).\n\t#if defined(EA_COMPILER_NO_RTTI) || (defined(_MSC_VER) && defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && !(defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS))\n\t\t#define EASTL_RTTI_ENABLED 0\n\t#else\n\t\t#define EASTL_RTTI_ENABLED 1\n\t#endif\n#endif\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_EXCEPTIONS_ENABLED\n//\n// Defined as 0 or 1. Default is to follow what the compiler settings are.\n// The user can predefine EASTL_EXCEPTIONS_ENABLED to 0 or 1; however, if the\n// compiler is set to disable exceptions then EASTL_EXCEPTIONS_ENABLED is\n// forced to a value of 0 regardless of the user predefine.\n//\n// Note that we do not enable EASTL exceptions by default if the compiler\n// has exceptions enabled. To enable EASTL_EXCEPTIONS_ENABLED you need to\n// manually set it to 1.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#if !defined(EASTL_EXCEPTIONS_ENABLED) || ((EASTL_EXCEPTIONS_ENABLED == 1) && defined(EA_COMPILER_NO_EXCEPTIONS))\n\t#define EASTL_EXCEPTIONS_ENABLED 0\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n/// EASTL_THROW_OR_ASSERT(exceptionType, message)\n//\n/// Throw an exception if exceptions enabled or assert if asserts are enabled,\n/// otherwise no-op.\n//\n///////////////////////////////////////////////////////////////////////////////\n#if EASTL_EXCEPTIONS_ENABLED\n\t#define EASTL_THROW_OR_ASSERT(exceptionType, message) throw exceptionType()\n\t#define EASTL_THROW_MSG_OR_ASSERT(exceptionType, message) throw exceptionType(message)\n#elif EASTL_ASSERT_ENABLED\n\t#define EASTL_THROW_OR_ASSERT(exceptionType, message) EASTL_FAIL_MSG(message)\n\t#define EASTL_THROW_MSG_OR_ASSERT(exceptionType, message) EASTL_FAIL_MSG(message)\n#else\n\t// empty braces to prevent the following warning in the following context:\n\t// if(expr)\n\t//     EASTL_THROW_OR_ASSERT(exceptionType, message);\n\t// warning C4390: ';': empty controlled statement found; is this the intent?\n\t#define EASTL_THROW_OR_ASSERT(exceptionType, message) {}\n\t#define EASTL_THROW_MSG_OR_ASSERT(exceptionType, message) {}\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_STRING_OPT_XXXX\n//\n// Enables some options / optimizations options that cause the string class\n// to behave slightly different from the C++ standard basic_string. These are\n// options whereby you can improve performance by avoiding operations that\n// in practice may never occur for you.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_STRING_OPT_EXPLICIT_CTORS\n\t// Defined as 0 or 1. Default is 0.\n\t// Defines if we should implement explicity in constructors where the C++\n\t// standard string does not. The advantage of enabling explicit constructors\n\t// is that you can do this: string s = \"hello\"; in addition to string s(\"hello\");\n\t// The disadvantage of enabling explicity constructors is that there can be\n\t// silent conversions done which impede performance if the user isn't paying\n\t// attention.\n\t// C++ standard string ctors are not explicit.\n\t#define EASTL_STRING_OPT_EXPLICIT_CTORS 0\n#endif\n\n#ifndef EASTL_STRING_OPT_LENGTH_ERRORS\n\t// Defined as 0 or 1. Default is equal to EASTL_EXCEPTIONS_ENABLED.\n\t// Defines if we check for string values going beyond kMaxSize\n\t// (a very large value) and throw exections if so.\n\t// C++ standard strings are expected to do such checks.\n\t#define EASTL_STRING_OPT_LENGTH_ERRORS EASTL_EXCEPTIONS_ENABLED\n#endif\n\n#ifndef EASTL_STRING_OPT_RANGE_ERRORS\n\t// Defined as 0 or 1. Default is equal to EASTL_EXCEPTIONS_ENABLED.\n\t// Defines if we check for out-of-bounds references to string\n\t// positions and throw exceptions if so. Well-behaved code shouldn't\n\t// refence out-of-bounds positions and so shouldn't need these checks.\n\t// C++ standard strings are expected to do such range checks.\n\t#define EASTL_STRING_OPT_RANGE_ERRORS EASTL_EXCEPTIONS_ENABLED\n#endif\n\n#ifndef EASTL_STRING_OPT_ARGUMENT_ERRORS\n\t// Defined as 0 or 1. Default is 0.\n\t// Defines if we check for NULL ptr arguments passed to string\n\t// functions by the user and throw exceptions if so. Well-behaved code\n\t// shouldn't pass bad arguments and so shouldn't need these checks.\n\t// Also, some users believe that strings should check for NULL pointers\n\t// in all their arguments and do no-ops if so. This is very debatable.\n\t// C++ standard strings are not required to check for such argument errors.\n\t#define EASTL_STRING_OPT_ARGUMENT_ERRORS 0\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_BITSET_SIZE_T\n//\n// Defined as 0 or 1. Default is 1.\n// Controls whether bitset uses size_t or eastl_size_t.\n//\n#ifndef EASTL_BITSET_SIZE_T\n\t#define EASTL_BITSET_SIZE_T 1\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_INT128_SUPPORTED\n//\n// Defined as 0 or 1.\n//\n#ifndef EASTL_INT128_SUPPORTED\n\t#if defined(EA_COMPILER_INTMAX_SIZE) && (EA_COMPILER_INTMAX_SIZE >= 16)\n\t\t#define EASTL_INT128_SUPPORTED 1\n\t#else\n\t\t#define EASTL_INT128_SUPPORTED 0\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_GCC_STYLE_INT128_SUPPORTED\n//\n// Defined as 0 or 1.\n// Specifies whether __int128_t/__uint128_t are defined.\n//\n#ifndef EASTL_GCC_STYLE_INT128_SUPPORTED\n#if EASTL_INT128_SUPPORTED && (defined(EA_COMPILER_GNUC) || defined(__clang__))\n#define EASTL_GCC_STYLE_INT128_SUPPORTED 1\n#else\n#define EASTL_GCC_STYLE_INT128_SUPPORTED 0\n#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_INT128_DEFINED\n//\n// Defined as 0 or 1.\n// Specifies whether eastl_int128_t/eastl_uint128_t have been typedef'd yet.\n// NB: these types are not considered fundamental, arithmetic or integral when using the EAStdC implementation.\n// this changes the compiler type traits defined in type_traits.h.\n// eg. is_signed<eastl_int128_t>::value may be false, because it is not arithmetic.\n//\n#ifndef EASTL_INT128_DEFINED\n\t#if EASTL_INT128_SUPPORTED\n\t\t#define EASTL_INT128_DEFINED 1\n\n\t\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\t\ttypedef __int128_t   eastl_int128_t;\n\t\t\ttypedef __uint128_t eastl_uint128_t;\n\t\t#else\n\t\t\ttypedef  int128_t  eastl_int128_t;  // The EAStdC package defines an EA::StdC::int128_t and uint128_t type,\n\t\t\ttypedef uint128_t eastl_uint128_t;  // though they are currently within the EA::StdC namespace.\n\t\t#endif\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_BITSET_WORD_TYPE_DEFAULT / EASTL_BITSET_WORD_SIZE_DEFAULT\n//\n// Defined as an integral power of two type, usually uint32_t or uint64_t.\n// Specifies the word type that bitset should use internally to implement\n// storage. By default this is the platform register word size, but there\n// may be reasons to use a different value.\n//\n// Defines the integral data type used by bitset by default.\n// You can override this default on a bitset-by-bitset case by supplying a\n// custom bitset WordType template parameter.\n//\n// The C++ standard specifies that the std::bitset word type be unsigned long,\n// but that isn't necessarily the most efficient data type for the given platform.\n// We can follow the standard and be potentially less efficient or we can do what\n// is more efficient but less like the C++ std::bitset.\n//\n#if !defined(EASTL_BITSET_WORD_TYPE_DEFAULT)\n\t#if defined(EASTL_BITSET_WORD_SIZE)         // EASTL_BITSET_WORD_SIZE is deprecated, but we temporarily support the ability for the user to specify it. Use EASTL_BITSET_WORD_TYPE_DEFAULT instead.\n\t\t#if (EASTL_BITSET_WORD_SIZE == 4)\n\t\t\t#define EASTL_BITSET_WORD_TYPE_DEFAULT uint32_t\n\t\t\t#define EASTL_BITSET_WORD_SIZE_DEFAULT 4\n\t\t#else\n\t\t\t#define EASTL_BITSET_WORD_TYPE_DEFAULT uint64_t\n\t\t\t#define EASTL_BITSET_WORD_SIZE_DEFAULT 8\n\t\t#endif\n\t#elif (EA_PLATFORM_WORD_SIZE == 16)                     // EA_PLATFORM_WORD_SIZE is defined in EABase.\n\t\t#define EASTL_BITSET_WORD_TYPE_DEFAULT uint128_t\n\t\t#define EASTL_BITSET_WORD_SIZE_DEFAULT 16\n\t#elif (EA_PLATFORM_WORD_SIZE == 8)\n\t\t#define EASTL_BITSET_WORD_TYPE_DEFAULT uint64_t\n\t\t#define EASTL_BITSET_WORD_SIZE_DEFAULT 8\n\t#elif (EA_PLATFORM_WORD_SIZE == 4)\n\t\t#define EASTL_BITSET_WORD_TYPE_DEFAULT uint32_t\n\t\t#define EASTL_BITSET_WORD_SIZE_DEFAULT 4\n\t#else\n\t\t#define EASTL_BITSET_WORD_TYPE_DEFAULT uint16_t\n\t\t#define EASTL_BITSET_WORD_SIZE_DEFAULT 2\n\t#endif\n#endif\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_LIST_SIZE_CACHE\n//\n// Defined as 0 or 1. Default is 1. Changed from 0 in version 1.16.01.\n// If defined as 1, the list and slist containers (and possibly any additional\n// containers as well) keep a member mSize (or similar) variable which allows\n// the size() member function to execute in constant time (a.k.a. O(1)).\n// There are debates on both sides as to whether it is better to have this\n// cached value or not, as having it entails some cost (memory and code).\n// To consider: Make list size caching an optional template parameter.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_LIST_SIZE_CACHE\n\t#define EASTL_LIST_SIZE_CACHE 1\n#endif\n\n#ifndef EASTL_SLIST_SIZE_CACHE\n\t#define EASTL_SLIST_SIZE_CACHE 1\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_MAX_STACK_USAGE\n//\n// Defined as an integer greater than zero. Default is 4000.\n// There are some places in EASTL where temporary objects are put on the\n// stack. A common example of this is in the implementation of container\n// swap functions whereby a temporary copy of the container is made.\n// There is a problem, however, if the size of the item created on the stack\n// is very large. This can happen with fixed-size containers, for example.\n// The EASTL_MAX_STACK_USAGE define specifies the maximum amount of memory\n// (in bytes) that the given platform/compiler will safely allow on the stack.\n// Platforms such as Windows will generally allow larger values than embedded\n// systems or console machines, but it is usually a good idea to stick with\n// a max usage value that is portable across all platforms, lest the user be\n// surprised when something breaks as it is ported to another platform.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_MAX_STACK_USAGE\n\t#define EASTL_MAX_STACK_USAGE 4000\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_VA_COPY_ENABLED\n//\n// Defined as 0 or 1. Default is 1 for compilers that need it, 0 for others.\n// Some compilers on some platforms implement va_list whereby its contents\n// are destroyed upon usage, even if passed by value to another function.\n// With these compilers you can use va_copy to save and restore a va_list.\n// Known compiler/platforms that destroy va_list contents upon usage include:\n//     CodeWarrior on PowerPC\n//     GCC on x86-64\n// However, va_copy is part of the C99 standard and not part of earlier C and\n// C++ standards. So not all compilers support it. VC++ doesn't support va_copy,\n// but it turns out that VC++ doesn't usually need it on the platforms it supports,\n// and va_copy can usually be implemented via memcpy(va_list, va_list) with VC++.\n//\n// Example usage:\n//     void Function(va_list arguments)\n//     {\n//         #if EASTL_VA_COPY_ENABLED\n//             va_list argumentsCopy;\n//             va_copy(argumentsCopy, arguments);\n//         #endif\n//         <use arguments or argumentsCopy>\n//         #if EASTL_VA_COPY_ENABLED\n//             va_end(argumentsCopy);\n//         #endif\n//     }\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_VA_COPY_ENABLED\n\t#if   ((defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__)) && (!defined(__i386__) || defined(__x86_64__)) && !defined(__ppc__) && !defined(__PPC__) && !defined(__PPC64__)\n\t\t#define EASTL_VA_COPY_ENABLED 1\n\t#else\n\t\t#define EASTL_VA_COPY_ENABLED 0\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_OPERATOR_EQUALS_OTHER_ENABLED\n//\n// Defined as 0 or 1. Default is 0 until such day that it's deemed safe.\n// When enabled, enables operator= for other char types, e.g. for code\n// like this:\n//     eastl::string8  s8;\n//     eastl::string16 s16;\n//     s8 = s16;\n// This option is considered experimental, and may exist as such for an\n// indefinite amount of time.\n//\n#if !defined(EASTL_OPERATOR_EQUALS_OTHER_ENABLED)\n\t#define EASTL_OPERATOR_EQUALS_OTHER_ENABLED 0\n#endif\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_STD_ITERATOR_CATEGORY_ENABLED\n//\n// Defined as 0 or 1. Default is 0.\n// If defined as non-zero, EASTL iterator categories (iterator.h's input_iterator_tag,\n// forward_iterator_tag, etc.) are defined to be those from std C++ in the std\n// namespace. The reason for wanting to enable such a feature is that it allows\n// EASTL containers and algorithms to work with std STL containes and algorithms.\n// The default value was changed from 1 to 0 in EASL 1.13.03, January 11, 2012.\n// The reason for the change was that almost nobody was taking advantage of it and\n// it was slowing down compile times for some compilers quite a bit due to them\n// having a lot of headers behind <iterator>.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_STD_ITERATOR_CATEGORY_ENABLED\n\t#define EASTL_STD_ITERATOR_CATEGORY_ENABLED 0\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ITC_NS\n//\n// Deprecated. Was intended to be used as the namespace qualifier for iterator tags.\n// Can now always use eastl as the namespace, as eastl will alias the iterator tags\n// to the standard when EASTL_STD_ITERATOR_CATEGORY_ENABLED == 1.\n#if EASTL_STD_ITERATOR_CATEGORY_ENABLED\n\t#define EASTL_ITC_NS std\n#else\n\t#define EASTL_ITC_NS eastl\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_VALIDATION_ENABLED\n//\n// Defined as an integer >= 0. Default is to be equal to EASTL_DEBUG.\n// If nonzero, then a certain amount of automatic runtime validation is done.\n// Runtime validation is not considered the same thing as asserting that user\n// input values are valid. Validation refers to internal consistency checking\n// of the validity of containers and their iterators. Validation checking is\n// something that often involves significantly more than basic assertion\n// checking, and it may sometimes be desirable to disable it.\n//\n// Validation sub-features are supported and can be enabled / disabled\n// individually.\n//\n// This macro would generally be used internally by EASTL.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_VALIDATION_ENABLED\n\t#define EASTL_VALIDATION_ENABLED EASTL_DEBUG\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_VALIDATE_COMPARE\n//\n// Defined as EASTL_ASSERT or defined away. Default is EASTL_ASSERT if EASTL_VALIDATION_ENABLED is enabled.\n// This is used to validate user-supplied comparison functions, particularly for sorting purposes.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_VALIDATE_COMPARE_ENABLED\n\t#define EASTL_VALIDATE_COMPARE_ENABLED EASTL_VALIDATION_ENABLED\n#endif\n\n#if EASTL_VALIDATE_COMPARE_ENABLED\n\t#define EASTL_VALIDATE_COMPARE(expression) EASTL_ASSERT_MSG(expression, \"Make sure the comparator satisfies the Compare named requirement (https://en.cppreference.com/w/cpp/named_req/Compare)\")\n#else\n\t#define EASTL_VALIDATE_COMPARE(expression)\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_VALIDATE_INTRUSIVE_LIST\n//\n// Defined as an integral value >= 0. Controls the amount of automatic validation\n// done by intrusive_list. A value of 0 means no automatic validation is done.\n// As of this writing, EASTL_VALIDATE_INTRUSIVE_LIST defaults to 0, as it makes\n// the intrusive_list_node become a non-POD, which may be an issue for some code.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_VALIDATE_INTRUSIVE_LIST\n\t#define EASTL_VALIDATE_INTRUSIVE_LIST 0\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_FORCE_INLINE\n//\n// Defined as a \"force inline\" expression or defined away.\n// You generally don't need to use forced inlining with the Microsoft and\n// Metrowerks compilers, but you may need it with the GCC compiler (any version).\n//\n// Example usage:\n//     template <typename T, typename Allocator>\n//     EASTL_FORCE_INLINE typename vector<T, Allocator>::size_type\n//     vector<T, Allocator>::size() const\n//        { return mpEnd - mpBegin; }\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FORCE_INLINE\n\t#define EASTL_FORCE_INLINE EA_FORCE_INLINE\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_MAY_ALIAS\n//\n// Defined as a macro that wraps the GCC may_alias attribute. This attribute\n// has no significance for VC++ because VC++ doesn't support the concept of\n// strict aliasing. Users should avoid writing code that breaks strict\n// aliasing rules; EASTL_MAY_ALIAS is for cases with no alternative.\n//\n// Example usage:\n//    uint32_t value EASTL_MAY_ALIAS;\n//\n// Example usage:\n//    typedef uint32_t EASTL_MAY_ALIAS value_type;\n//    value_type value;\n//\n#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) && !defined(EA_COMPILER_RVCT)\n\t#define EASTL_MAY_ALIAS __attribute__((__may_alias__))\n#else\n\t#define EASTL_MAY_ALIAS\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_LIKELY / EASTL_UNLIKELY\n//\n// Defined as a macro which gives a hint to the compiler for branch\n// prediction. GCC gives you the ability to manually give a hint to\n// the compiler about the result of a comparison, though it's often\n// best to compile shipping code with profiling feedback under both\n// GCC (-fprofile-arcs) and VC++ (/LTCG:PGO, etc.). However, there\n// are times when you feel very sure that a boolean expression will\n// usually evaluate to either true or false and can help the compiler\n// by using an explicity directive...\n//\n// Example usage:\n//    if(EASTL_LIKELY(a == 0)) // Tell the compiler that a will usually equal 0.\n//       { ... }\n//\n// Example usage:\n//    if(EASTL_UNLIKELY(a == 0)) // Tell the compiler that a will usually not equal 0.\n//       { ... }\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_LIKELY\n\t#if defined(__GNUC__) && (__GNUC__ >= 3)\n\t\t#define EASTL_LIKELY(x)   __builtin_expect(!!(x), true)\n\t\t#define EASTL_UNLIKELY(x) __builtin_expect(!!(x), false)\n\t#else\n\t\t#define EASTL_LIKELY(x)   (x)\n\t\t#define EASTL_UNLIKELY(x) (x)\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE\n//\n// Defined as 0 or 1; default is based on auto-detection.\n// Specifies whether the compiler provides built-in compiler type trait support\n// (e.g. __is_abstract()). Does not specify any details about which traits\n// are available or what their standards-compliance is. Nevertheless this is a\n// useful macro identifier for our type traits implementation.\n//\n#ifndef EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE\n\t#if defined(_MSC_VER) && (_MSC_VER >= 1500) && !defined(EA_COMPILER_CLANG_CL) // VS2008 or later\n\t\t#pragma warning(push, 0)\n\t\t\t#include <yvals.h>\n\t\t#pragma warning(pop)\n\t\t#if ((defined(_HAS_TR1) && _HAS_TR1) || _MSC_VER >= 1700)  // VS2012 (1700) and later has built-in type traits support.\n\t\t\t#define EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE 1\n\t\t#else\n\t\t\t#define EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE 0\n\t\t#endif\n\t#elif defined(__clang__) && defined(__APPLE__) && defined(_CXXCONFIG) // Apple clang but with GCC's libstdc++.\n\t\t#define EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE 0\n\t#elif defined(__clang__)\n\t\t#define EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE 1\n\t#elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4003) && !defined(__GCCXML__)\n\t\t#define EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE 1\n\t#elif defined(__MSL_CPP__) && (__MSL_CPP__ >= 0x8000) // CodeWarrior compiler.\n\t\t#define EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE 1\n\t#else\n\t\t#define EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE 0\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_MINMAX_ENABLED\n//\n// Defined as 0 or 1; default is 1.\n// Specifies whether the min and max algorithms are available.\n// It may be useful to disable the min and max algorithms because sometimes\n// #defines for min and max exist which would collide with EASTL min and max.\n// Note that there are already alternative versions of min and max in EASTL\n// with the min_alt and max_alt functions. You can use these without colliding\n// with min/max macros that may exist.\n//\n///////////////////////////////////////////////////////////////////////////////\n#ifndef EASTL_MINMAX_ENABLED\n\t#define EASTL_MINMAX_ENABLED 1\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_NOMINMAX\n//\n// Defined as 0 or 1; default is 1.\n// MSVC++ has #defines for min/max which collide with the min/max algorithm\n// declarations. If EASTL_NOMINMAX is defined as 1, then we undefine min and\n// max if they are #defined by an external library. This allows our min and\n// max definitions in algorithm.h to work as expected. An alternative to\n// the enabling of EASTL_NOMINMAX is to #define NOMINMAX in your project\n// settings if you are compiling for Windows.\n// Note that this does not control the availability of the EASTL min and max\n// algorithms; the EASTL_MINMAX_ENABLED configuration parameter does that.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_NOMINMAX\n\t#define EASTL_NOMINMAX 1\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_STD_CPP_ONLY\n//\n// Defined as 0 or 1; default is 0.\n// Disables the use of compiler language extensions. We use compiler language\n// extensions only in the case that they provide some benefit that can't be\n// had any other practical way. But sometimes the compiler is set to disable\n// language extensions or sometimes one compiler's preprocesor is used to generate\n// code for another compiler, and so it's necessary to disable language extension usage.\n//\n// Example usage:\n//     #if defined(_MSC_VER) && !EASTL_STD_CPP_ONLY\n//         enum : size_type { npos = container_type::npos };    // Microsoft extension which results in significantly smaller debug symbols.\n//     #else\n//         static const size_type npos = container_type::npos;\n//     #endif\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_STD_CPP_ONLY\n\t#define EASTL_STD_CPP_ONLY 0\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_NO_RVALUE_REFERENCES\n//\n// Defined as 0 or 1.\n// This is the same as EABase EA_COMPILER_NO_RVALUE_REFERENCES except that it\n// follows the convention of being always defined, as 0 or 1.\n///////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_NO_RVALUE_REFERENCES)\n\t#if defined(EA_COMPILER_NO_RVALUE_REFERENCES)\n\t\t#define EASTL_NO_RVALUE_REFERENCES 1\n\t#else\n\t\t#define EASTL_NO_RVALUE_REFERENCES 0\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_MOVE_SEMANTICS_ENABLED\n//\n// Defined as 0 or 1.\n// If enabled then C++11-like functionality with rvalue references and move\n// operations is enabled.\n///////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_MOVE_SEMANTICS_ENABLED)\n\t#if EASTL_NO_RVALUE_REFERENCES // If the compiler doesn't support rvalue references or EASTL is configured to disable them...\n\t\t#define EASTL_MOVE_SEMANTICS_ENABLED 0\n\t#else\n\t\t#define EASTL_MOVE_SEMANTICS_ENABLED 1\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_VARIADIC_TEMPLATES_ENABLED\n//\n// Defined as 0 or 1.\n// If enabled then C++11-like functionality with variadic templates is enabled.\n///////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_VARIADIC_TEMPLATES_ENABLED)\n\t#if defined(EA_COMPILER_NO_VARIADIC_TEMPLATES) // If the compiler doesn't support variadic templates\n\t\t#define EASTL_VARIADIC_TEMPLATES_ENABLED 0\n\t#else\n\t\t#define EASTL_VARIADIC_TEMPLATES_ENABLED 1\n\t#endif\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_VARIABLE_TEMPLATES_ENABLED\n//\n// Defined as 0 or 1.\n// If enabled then C++11-like functionality with variable templates is enabled.\n///////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_VARIABLE_TEMPLATES_ENABLED)\n\t#if((EABASE_VERSION_N < 20605) || defined(EA_COMPILER_NO_VARIABLE_TEMPLATES))\n\t\t#define EASTL_VARIABLE_TEMPLATES_ENABLED 0\n\t#else\n\t\t#define EASTL_VARIABLE_TEMPLATES_ENABLED 1\n\t#endif\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_INLINE_VARIABLE_ENABLED\n//\n// Defined as 0 or 1.\n// If enabled then C++17-like functionality with inline variable is enabled.\n///////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_INLINE_VARIABLE_ENABLED)\n\t#if((EABASE_VERSION_N < 20707) || defined(EA_COMPILER_NO_INLINE_VARIABLES))\n\t\t#define EASTL_INLINE_VARIABLE_ENABLED 0\n\t#else\n\t\t#define EASTL_INLINE_VARIABLE_ENABLED 1\n\t#endif\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_CPP17_INLINE_VARIABLE\n//\n// Used to prefix a variable as inline when C++17 inline variables are available\n// Usage: EASTL_CPP17_INLINE_VARIABLE constexpr bool type_trait_v = type_trait::value\n///////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_CPP17_INLINE_VARIABLE)\n\t#if EASTL_INLINE_VARIABLE_ENABLED\n\t\t#define EASTL_CPP17_INLINE_VARIABLE inline\n\t#else\n\t\t#define EASTL_CPP17_INLINE_VARIABLE\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS undef\n//\n// We need revise this macro to be undefined in some cases, in case the user\n// isn't using an updated EABase.\n///////////////////////////////////////////////////////////////////////////////\n#if defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403) // It may in fact be supported by 4.01 or 4.02 but we don't have compilers to test with.\n\t#if defined(EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS)\n\t\t#undef EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_NO_RANGE_BASED_FOR_LOOP\n//\n// Defined as 0 or 1.\n// This is the same as EABase EA_COMPILER_NO_RANGE_BASED_FOR_LOOP except that it\n// follows the convention of being always defined, as 0 or 1.\n///////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_NO_RANGE_BASED_FOR_LOOP)\n\t#if defined(EA_COMPILER_NO_RANGE_BASED_FOR_LOOP)\n\t\t#define EASTL_NO_RANGE_BASED_FOR_LOOP 1\n\t#else\n\t\t#define EASTL_NO_RANGE_BASED_FOR_LOOP 0\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ALIGN_OF\n//\n// Determines the alignment of a type.\n//\n// Example usage:\n//    size_t alignment = EASTL_ALIGN_OF(int);\n//\n///////////////////////////////////////////////////////////////////////////////\n#ifndef EASTL_ALIGN_OF\n\t#define EASTL_ALIGN_OF alignof\n#endif\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// eastl_size_t\n//\n// Defined as an unsigned integer type, usually either size_t or uint32_t.\n// Defaults to size_t to match std STL unless the user specifies to use\n// uint32_t explicitly via the EASTL_SIZE_T_32BIT define\n//\n// Example usage:\n//     eastl_size_t n = intVector.size();\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_SIZE_T_32BIT        // Defines whether EASTL_SIZE_T uses uint32_t/int32_t as opposed to size_t/ssize_t.\n\t#define EASTL_SIZE_T_32BIT 0  // This makes a difference on 64 bit platforms because they use a 64 bit size_t.\n#endif                            // By default we do the same thing as std STL and use size_t.\n\n#ifndef EASTL_SIZE_T\n\t#if (EASTL_SIZE_T_32BIT == 0) || (EA_PLATFORM_WORD_SIZE == 4)\n\t\t#include <stddef.h>\n\t\t#define EASTL_SIZE_T  size_t\n\t\t#define EASTL_SSIZE_T intptr_t\n\n\t\t// printf format specifiers for use with eastl_size_t\n\t\t#define EASTL_PRIdSIZE \"zd\"\n\t\t#define EASTL_PRIiSIZE \"zi\"\n\t\t#define EASTL_PRIoSIZE \"zo\"\n\t\t#define EASTL_PRIuSIZE \"zu\"\n\t\t#define EASTL_PRIxSIZE \"zx\"\n\t\t#define EASTL_PRIXSIZE \"zX\"\n\t#else\n\t\t#define EASTL_SIZE_T  uint32_t\n\t\t#define EASTL_SSIZE_T int32_t\n\n\t\t// printf format specifiers for use with eastl_size_t\n\t\t#define EASTL_PRIdSIZE PRId32\n\t\t#define EASTL_PRIiSIZE PRIi32\n\t\t#define EASTL_PRIoSIZE PRIo32\n\t\t#define EASTL_PRIuSIZE PRIu32\n\t\t#define EASTL_PRIxSIZE PRIx32\n\t\t#define EASTL_PRIXSIZE PRIX32\n\t#endif\n#endif\n\ntypedef EASTL_SIZE_T  eastl_size_t;  // Same concept as std::size_t.\ntypedef EASTL_SSIZE_T eastl_ssize_t; // Signed version of eastl_size_t. Concept is similar to Posix's ssize_t.\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ALLOCATOR_EXPLICIT_ENABLED\n//\n// Defined as 0 or 1. Default is 0 for now but ideally would be changed to\n// 1 some day. It's 0 because setting it to 1 breaks some existing code.\n// This option enables the allocator ctor to be explicit, which avoids\n// some undesirable silent conversions, especially with the string class.\n//\n// Example usage:\n//     class allocator\n//     {\n//     public:\n//         EASTL_ALLOCATOR_EXPLICIT allocator(const char* pName);\n//     };\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_ALLOCATOR_EXPLICIT_ENABLED\n\t#define EASTL_ALLOCATOR_EXPLICIT_ENABLED 0\n#endif\n\n#if EASTL_ALLOCATOR_EXPLICIT_ENABLED\n\t#define EASTL_ALLOCATOR_EXPLICIT explicit\n#else\n\t#define EASTL_ALLOCATOR_EXPLICIT\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_ALLOCATOR_MIN_ALIGNMENT\n//\n// Defined as an integral power-of-2 that's >= 1.\n// Identifies the minimum alignment that EASTL should assume its allocators\n// use. There is code within EASTL that decides whether to do a Malloc or\n// MallocAligned call and it's typically better if it can use the Malloc call.\n// But this requires knowing what the minimum possible alignment is.\n#if !defined(EASTL_ALLOCATOR_MIN_ALIGNMENT)\n\t#define EASTL_ALLOCATOR_MIN_ALIGNMENT EA_PLATFORM_MIN_MALLOC_ALIGNMENT\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT\n//\n// Identifies the minimum alignment that EASTL should assume system allocations\n// from malloc and new will have.\n#if !defined(EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT)\n\t#if defined(EA_PLATFORM_MICROSOFT) || defined(EA_PLATFORM_APPLE)\n\t\t#define EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT 16\n\t#else\n\t\t#define EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT (EA_PLATFORM_PTR_SIZE * 2)\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL allocator\n//\n// The EASTL allocator system allows you to redefine how memory is allocated\n// via some defines that are set up here. In the container code, memory is\n// allocated via macros which expand to whatever the user has them set to\n// expand to. Given that there are multiple allocator systems available,\n// this system allows you to configure it to use whatever system you want,\n// provided your system meets the requirements of this library.\n// The requirements are:\n//\n//     - Must be constructable via a const char* (name) parameter.\n//       Some uses of allocators won't require this, however.\n//     - Allocate a block of memory of size n and debug name string.\n//     - Allocate a block of memory of size n, debug name string,\n//       alignment a, and offset o.\n//     - Free memory allocated via either of the allocation functions above.\n//     - Provide a default allocator instance which can be used if the user\n//       doesn't provide a specific one.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n// namespace eastl\n// {\n//     class allocator\n//     {\n//         allocator(const char* pName = NULL);\n//\n//         void* allocate(size_t n, int flags = 0);\n//         void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);\n//         void  deallocate(void* p, size_t n);\n// \n//\t\t   // optional:\n//\t\t   template<typename T, typename... Args>\n//\t\t   void construct(T* p, Args&&... args);\n//\n//         const char* get_name() const;\n//         void        set_name(const char* pName);\n//     };\n//\n//     allocator* GetDefaultAllocator(); // This is used for anonymous allocations.\n// }\n\n#ifndef EASTLAlloc // To consider: Instead of calling through pAllocator, just go directly to operator new, since that's what allocator does.\n\t#define EASTLAlloc(allocator, n) (allocator).allocate(n);\n#endif\n\n#ifndef EASTLAllocFlags // To consider: Instead of calling through pAllocator, just go directly to operator new, since that's what allocator does.\n\t#define EASTLAllocFlags(allocator, n, flags) (allocator).allocate(n, flags);\n#endif\n\n#ifndef EASTLAllocAligned\n\t#define EASTLAllocAligned(allocator, n, alignment, offset) (allocator).allocate((n), (alignment), (offset))\n#endif\n\n#ifndef EASTLAllocAlignedFlags\n\t#define EASTLAllocAlignedFlags(allocator, n, alignment, offset, flags) (allocator).allocate((n), (alignment), (offset), (flags))\n#endif\n\n#ifndef EASTLFree\n\t#define EASTLFree(allocator, p, size) (allocator).deallocate((void*)(p), (size)) // Important to cast to void* as p may be non-const.\n#endif\n\n#ifndef EASTLAllocatorType\n\t#define EASTLAllocatorType eastl::allocator\n#endif\n\n#ifndef EASTLDummyAllocatorType\n\t#define EASTLDummyAllocatorType eastl::dummy_allocator\n#endif\n\n#ifndef EASTLAllocatorDefault\n\t// EASTLAllocatorDefault returns the default allocator instance. This is not a global\n\t// allocator which implements all container allocations but is the allocator that is\n\t// used when EASTL needs to allocate memory internally. There are very few cases where\n\t// EASTL allocates memory internally, and in each of these it is for a sensible reason\n\t// that is documented to behave as such.\n\t#define EASTLAllocatorDefault eastl::GetDefaultAllocator\n#endif\n\n\n/// EASTL_ALLOCATOR_DEFAULT_NAME\n///\n/// Defines a default allocator name in the absence of a user-provided name.\n///\n#ifndef EASTL_ALLOCATOR_DEFAULT_NAME\n\t#define EASTL_ALLOCATOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX // Unless the user overrides something, this is \"EASTL\".\n#endif\n\n/// EASTL_USE_FORWARD_WORKAROUND\n///\n/// This is to workaround a compiler bug that we found in VS2013. Update 1 did not fix it.\n/// This should be fixed in a future release of VS2013 http://accentuable4.rssing.com/browser.php?indx=3511740&item=15696\n///\n#ifndef EASTL_USE_FORWARD_WORKAROUND\n\t#if defined(_MSC_FULL_VER) && _MSC_FULL_VER == 180021005 || (defined(__EDG_VERSION__) && (__EDG_VERSION__ < 405))// VS2013 initial release\n\t\t#define EASTL_USE_FORWARD_WORKAROUND 1\n\t#else\n\t\t#define EASTL_USE_FORWARD_WORKAROUND 0\n\t#endif\n#endif\n\n\n/// EASTL_TUPLE_ENABLED\n/// EASTL tuple implementation depends on variadic template support\n#if EASTL_VARIADIC_TEMPLATES_ENABLED && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t#define EASTL_TUPLE_ENABLED 1\n#else\n\t#define EASTL_TUPLE_ENABLED 0\n#endif\n\n\n/// EASTL_USER_LITERALS_ENABLED\n#ifndef EASTL_USER_LITERALS_ENABLED\n\t#if defined(EA_COMPILER_CPP14_ENABLED)\n\t\t#define EASTL_USER_LITERALS_ENABLED 1\n\t#else\n\t\t#define EASTL_USER_LITERALS_ENABLED 0\n\t#endif\n#endif\n\n\n/// EASTL_INLINE_NAMESPACES_ENABLED\n#ifndef EASTL_INLINE_NAMESPACES_ENABLED\n\t#if defined(EA_COMPILER_CPP14_ENABLED)\n\t\t#define EASTL_INLINE_NAMESPACES_ENABLED 1\n\t#else\n\t\t#define EASTL_INLINE_NAMESPACES_ENABLED 0\n\t#endif\n#endif\n\n\n/// EASTL_CORE_ALLOCATOR_ENABLED\n#ifndef EASTL_CORE_ALLOCATOR_ENABLED\n\t#define EASTL_CORE_ALLOCATOR_ENABLED 0\n#endif\n\n/// EASTL_OPENSOURCE\n/// This is enabled when EASTL is building built in an \"open source\" mode.  Which is a mode that eliminates code\n/// dependencies on other technologies that have not been released publically.\n/// EASTL_OPENSOURCE = 0, is the default.\n/// EASTL_OPENSOURCE = 1, utilizes technologies that not publically available.\n///\n#ifndef EASTL_OPENSOURCE\n\t#define EASTL_OPENSOURCE 0\n#endif\n\n\n/// EASTL_OPTIONAL_ENABLED\n#if defined(EA_COMPILER_MSVC_2012)\n\t#define EASTL_OPTIONAL_ENABLED 0\n#elif defined(EA_COMPILER_MSVC_2013)\n\t#define EASTL_OPTIONAL_ENABLED 0\n#elif defined(EA_COMPILER_MSVC_2015)\n\t#define EASTL_OPTIONAL_ENABLED 1\n#elif EASTL_VARIADIC_TEMPLATES_ENABLED && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) && !defined(EA_COMPILER_NO_DEFAULTED_FUNCTIONS) && defined(EA_COMPILER_CPP11_ENABLED)\n\t#define EASTL_OPTIONAL_ENABLED 1\n#else\n\t#define EASTL_OPTIONAL_ENABLED 0\n#endif\n\n/// EASTL_HAS_INTRINSIC(x)\n///   does the compiler intrinsic (MSVC terminology) or builtin (Clang / GCC terminology) exist?\n///   where `x` does not include the leading \"__\"\n#if defined(EA_COMPILER_CLANG)\n\t// see https://clang.llvm.org/docs/LanguageExtensions.html#type-trait-primitives\n\t#if EA_COMPILER_VERSION >= 1000\n\t\t#define EASTL_HAS_INTRINSIC(x) EA_COMPILER_HAS_BUILTIN(__ ## x)\n\t#elif EA_COMPILER_VERSION >= 600\n\t\t// NB: !__is_identifier() is correct: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970#c11\n\t\t#define EASTL_HAS_INTRINSIC(x) !__is_identifier(__ ## x)\n\t#else\n\t\t// note: only works for a subset of builtins\n\t\t#define EASTL_HAS_INTRINSIC(x) EA_COMPILER_HAS_FEATURE(x)\n\t#endif\n#else\n#define EASTL_HAS_INTRINSIC(x) EA_COMPILER_HAS_BUILTIN(__ ## x)\n#endif\n\n/// EASTL_HAS_UNIQUE_OBJECT_REPRESENTATIONS_AVAILABLE\n#if EASTL_HAS_INTRINSIC(has_unique_object_representations) || (defined(_MSC_VER) && (_MSC_VER >= 1913))  // VS2017 15.6+\n\t#define EASTL_HAS_UNIQUE_OBJECT_REPRESENTATIONS_AVAILABLE 1\n#else\n\t#define EASTL_HAS_UNIQUE_OBJECT_REPRESENTATIONS_AVAILABLE 0\n#endif\n\n#if EASTL_HAS_INTRINSIC(is_final) || defined(EA_COMPILER_GNUC) || (defined(_MSC_VER) && (_MSC_VER >= 1914))\t// VS2017 15.7+\n\t#define EASTL_IS_FINAL_AVAILABLE 1\n#else\n\t#define EASTL_IS_FINAL_AVAILABLE 0\n#endif\n\n#if EASTL_HAS_INTRINSIC(is_aggregate) || defined(EA_COMPILER_GNUC) || (defined(_MSC_VER) && (_MSC_VER >= 1915))  // VS2017 15.8+\n\t#define EASTL_IS_AGGREGATE_AVAILABLE 1\n#else\n\t#define EASTL_IS_AGGREGATE_AVAILABLE 0\n#endif\n\n\n/// EASTL_ENABLE_PAIR_FIRST_ELEMENT_CONSTRUCTOR\n/// This feature define allows users to toggle the problematic eastl::pair implicit\n/// single element constructor.\n#ifndef EASTL_ENABLE_PAIR_FIRST_ELEMENT_CONSTRUCTOR\n\t#define EASTL_ENABLE_PAIR_FIRST_ELEMENT_CONSTRUCTOR 0\n#endif\n\n/// EASTL_SYSTEM_BIG_ENDIAN_STATEMENT\n/// EASTL_SYSTEM_LITTLE_ENDIAN_STATEMENT\n/// These macros allow you to write endian specific macros as statements.\n/// This allows endian specific code to be macro expanded from within other macros\n///\n#if defined(EA_SYSTEM_BIG_ENDIAN)\n\t#define EASTL_SYSTEM_BIG_ENDIAN_STATEMENT(...) __VA_ARGS__\n#else\n\t#define EASTL_SYSTEM_BIG_ENDIAN_STATEMENT(...)\n#endif\n\n#if defined(EA_SYSTEM_LITTLE_ENDIAN)\n\t#define EASTL_SYSTEM_LITTLE_ENDIAN_STATEMENT(...) __VA_ARGS__\n#else\n\t#define EASTL_SYSTEM_LITTLE_ENDIAN_STATEMENT(...)\n#endif\n\n/// EASTL_CONSTEXPR_BIT_CAST_SUPPORTED\n/// eastl::bit_cast, in order to be implemented as constexpr, requires explicit compiler support.\n/// This macro defines whether it's possible for bit_cast to be constexpr.\n///\n#if (defined(EA_COMPILER_MSVC) && defined(EA_COMPILER_MSVC_VERSION_14_26) && EA_COMPILER_VERSION >= EA_COMPILER_MSVC_VERSION_14_26) \\\n\t|| EA_COMPILER_HAS_BUILTIN(__builtin_bit_cast)\n\t#define EASTL_CONSTEXPR_BIT_CAST_SUPPORTED 1\n#else\n\t#define EASTL_CONSTEXPR_BIT_CAST_SUPPORTED 0\n#endif\n\n// EASTL_DEPRECATIONS_FOR_2024_SEPT\n// This macro is provided as a means to disable warnings temporarily (in particular if a user is compiling with warnings\n// as errors). All deprecations raised by this macro (when it is EA_ENABLED) are scheduled for removal approximately\n// September 2024.\n\n#ifndef EASTL_DEPRECATIONS_FOR_2024_SEPT\n\t#if defined(EA_DEPRECATIONS_FOR_2024_SEPT)\n\t\t#define EASTL_DEPRECATIONS_FOR_2024_SEPT EA_DEPRECATIONS_FOR_2024_SEPT\n\t#else\n\t\t#define EASTL_DEPRECATIONS_FOR_2024_SEPT EA_ENABLED\n\t#endif\n#endif\n\n#if EA_IS_ENABLED(EASTL_DEPRECATIONS_FOR_2024_SEPT)\n\t#define EASTL_REMOVE_AT_2024_SEPT EA_DEPRECATED\n#else\n\t#define EASTL_REMOVE_AT_2024_SEPT\n#endif\n\n// For internal (to EASTL) use only (ie. tests).\n#define EASTL_INTERNAL_DISABLE_DEPRECATED()\t\t\t\t\t\\\n\tEA_DISABLE_VC_WARNING(4996);\t\t\t\t\t\t\t\\\n\tEA_DISABLE_CLANG_WARNING(-Wdeprecated-declarations);\t\\\n\tEA_DISABLE_GCC_WARNING(-Wdeprecated-declarations);\n\n// For internal (to EASTL) use only (ie. tests).\n#define EASTL_INTERNAL_RESTORE_DEPRECATED()\t\\\n\tEA_RESTORE_CLANG_WARNING();\t\t\t\t\\\n\tEA_RESTORE_VC_WARNING();\t\t\t\t\\\n\tEA_RESTORE_GCC_WARNING();\n\n// EASTL_ATOMIC_READ_DEPENDS_IS_ACQUIRE, this determines if we want the semantics of EASTL's\n// read_depends memory order to be strengthened to acquire, the default is for read_depends to\n// do relaxed semantics since it's intended for performance sensitive code with very specific\n// semantics, see atomic.h for details.\n#ifndef EASTL_ATOMIC_READ_DEPENDS_IS_ACQUIRE\n\t#define EASTL_ATOMIC_READ_DEPENDS_IS_ACQUIRE EA_DISABLED\n#endif\n\n// EASTL_INTERNAL_TSAN_ACQUIRE for EASTL internal use only. Instrument an acquire operation\n// on an addres for TSAN purposes\n#if EA_TSAN_ENABLED\n\t#define EASTL_INTERNAL_TSAN_ACQUIRE(x) __tsan_acquire(x)\n#else\n\t#define EASTL_INTERNAL_TSAN_ACQUIRE(x)\n#endif\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/copy_help.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_COPY_HELP_H\n#define EASTL_INTERNAL_COPY_HELP_H\n\n#include <EASTL/internal/config.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <string.h> // memcpy, memcmp, memmove\n\n\nnamespace eastl\n{\n\t/// move / move_n / move_backward\n\t/// copy / copy_n / copy_backward\n\t///\n\t/// We want to optimize move, move_n, move_backward, copy, copy_backward, copy_n to do memmove operations\n\t/// when possible.\n\t///\n\t/// We could possibly use memcpy, though it has stricter overlap requirements than the move and copy\n\t/// algorithms and would require a runtime if/else to choose it over memmove. In particular, memcpy\n\t/// allows no range overlap at all, whereas move/copy allow output end overlap and move_backward/copy_backward\n\t/// allow output begin overlap. Despite this it might be useful to use memcpy for any platforms where\n\t/// memcpy is significantly faster than memmove, and since in most cases the copy/move operation in fact\n\t/// doesn't target overlapping memory and so memcpy would be usable.\n\t///\n\t/// We can use memmove/memcpy if the following hold true:\n\t///     InputIterator and OutputIterator have the same value type.\n\t///     InputIterator and OutputIterator are of type contiguous_iterator_tag or simply are pointers (the two are virtually synonymous).\n\t///     is_trivially_copyable<T>::value is true. i.e. from the standard (http://www.eel.is/c++draft/basic.types.general#2):\n\t///\t\t\tFor any object (other than a potentially-overlapping subobject) of trivially copyable type T, whether or not the object\n\t///\t\t\tholds a valid value of type T, the underlying bytes making up the object can be copied into an array of char, unsigned char,\n\t///\t\t\tor std::byte [footnote: By using, for example, the library functions std::memcpy or std::memmove].\n\t///\n\t/// copy normally differs from move, but there is a case where copy is the same as move: when copy is\n\t/// used with a move_iterator. We handle that case here by detecting that copy is being done with a\n\t/// move_iterator and redirect it to move (which can take advantage of memmove/memcpy).\n\n\t// Implementation moving copying both trivial and non-trivial data via a lesser iterator than random-access.\n\ttemplate <typename /*InputIteratorCategory*/, bool /*isMove*/, bool /*canMemmove*/>\n\tstruct move_and_copy_helper\n\t{\n\t\ttemplate <typename InputIterator, typename OutputIterator>\n\t\tstatic OutputIterator move_or_copy(InputIterator first, InputIterator last, OutputIterator result)\n\t\t{\n\t\t\tfor(; first != last; ++result, ++first)\n\t\t\t\t*result = *first;\n\t\t\treturn result;\n\t\t}\n\t};\n\n\t// Specialization for copying non-trivial data via a random-access iterator. It's theoretically faster because the compiler can see the count when its a compile-time const.\n\t// This specialization converts the random access InputIterator last-first to an integral type. There's simple way for us to take advantage of a random access output iterator,\n\t// as the range is specified by the input instead of the output, and distance(first, last) for a non-random-access iterator is potentially slow.\n\ttemplate <>\n\tstruct move_and_copy_helper<eastl::random_access_iterator_tag, false, false>\n\t{\n\t\ttemplate <typename InputIterator, typename OutputIterator>\n\t\tstatic OutputIterator move_or_copy(InputIterator first, InputIterator last, OutputIterator result)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<InputIterator>::difference_type difference_type;\n\n\t\t\tfor(difference_type n = (last - first); n > 0; --n, ++first, ++result)\n\t\t\t\t*result = *first;\n\n\t\t\treturn result;\n\t\t}\n\t};\n\n\t// Specialization for moving non-trivial data via a lesser iterator than random-access.\n\ttemplate <typename InputIteratorCategory>\n\tstruct move_and_copy_helper<InputIteratorCategory, true, false>\n\t{\n\t\ttemplate <typename InputIterator, typename OutputIterator>\n\t\tstatic OutputIterator move_or_copy(InputIterator first, InputIterator last, OutputIterator result)\n\t\t{\n\t\t\tfor(; first != last; ++result, ++first)\n\t\t\t\t*result = eastl::move(*first);\n\t\t\treturn result;\n\t\t}\n\t};\n\n\t// Specialization for moving non-trivial data via a random-access iterator. It's theoretically faster because the compiler can see the count when its a compile-time const.\n\ttemplate <>\n\tstruct move_and_copy_helper<eastl::random_access_iterator_tag, true, false>\n\t{\n\t\ttemplate <typename InputIterator, typename OutputIterator>\n\t\tstatic OutputIterator move_or_copy(InputIterator first, InputIterator last, OutputIterator result)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<InputIterator>::difference_type difference_type;\n\n\t\t\tfor(difference_type n = (last - first); n > 0; --n, ++first, ++result)\n\t\t\t\t*result = eastl::move(*first);\n\n\t\t\treturn result;\n\t\t}\n\t};\n\n\t// Specialization for when we can use memmove/memcpy. See the notes above for what conditions allow this.\n\ttemplate <bool isMove>\n\tstruct move_and_copy_helper<eastl::random_access_iterator_tag, isMove, true>\n\t{\n\t\ttemplate <typename T>\n\t\tstatic T* move_or_copy(const T* first, const T* last, T* result)\n\t\t{\n\t\t\tif (EASTL_UNLIKELY(first == last))\n\t\t\t\treturn result;\n\n\t\t\t// We could use memcpy here if there's no range overlap, but memcpy is rarely much faster than memmove.\n\t\t\treturn (T*)memmove(result, first, (size_t)((uintptr_t)last - (uintptr_t)first)) + (last - first);\n\t\t}\n\t};\n\n\n\tnamespace internal {\n\t\t// This exists to handle the case when EASTL_ITC_NS is `std`\n\t\t// and the C++ version is older than C++20, in this case\n\t\t// std::contiguous_iterator_tag does not exist so we can't use\n\t\t// is_same<> directly.\n\t#if !EASTL_STD_ITERATOR_CATEGORY_ENABLED || defined(EA_COMPILER_CPP20_ENABLED)\n\t\ttemplate <typename IC>\n\t\tusing is_contiguous_iterator = eastl::is_same<IC, eastl::contiguous_iterator_tag>;\n\t#else\n\t\ttemplate <typename IC>\n\t\tusing is_contiguous_iterator = eastl::false_type;\n\t#endif\n\n\t\ttemplate <typename InputIterator, typename OutputIterator>\n\t\tstruct can_be_memmoved_helper {\n\t\t\tusing IIC = typename eastl::iterator_traits<InputIterator>::iterator_category;\n\t\t\tusing OIC = typename eastl::iterator_traits<OutputIterator>::iterator_category;\n\t\t\tusing value_type_input = typename eastl::iterator_traits<InputIterator>::value_type;\n\t\t\tusing value_type_output = typename eastl::iterator_traits<OutputIterator>::value_type;\n\n\t\t\tstatic constexpr bool value = eastl::is_trivially_copyable<value_type_output>::value &&\n\t\t\t\t                          eastl::is_same<value_type_input, value_type_output>::value &&\n\t\t\t\t                         (eastl::is_pointer<InputIterator>::value  || is_contiguous_iterator<IIC>::value) &&\n\t\t\t\t                         (eastl::is_pointer<OutputIterator>::value || is_contiguous_iterator<OIC>::value);\n\n\t\t};\n\t}\n\n\ttemplate <bool isMove, typename InputIterator, typename OutputIterator>\n\tinline OutputIterator move_and_copy_chooser(InputIterator first, InputIterator last, OutputIterator result)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category  IIC;\n\n\t\tconst bool canBeMemmoved = internal::can_be_memmoved_helper<InputIterator, OutputIterator>::value;\n\n\t\t// Need to choose based on the input iterator tag and not the output iterator tag, because containers accept input ranges of iterator types different than self.\n\t\treturn eastl::move_and_copy_helper<IIC, isMove, canBeMemmoved>::move_or_copy(first, last, result);\n\t}\n\n\n\t// We have a second layer of unwrap_iterator calls because the original iterator might be something like move_iterator<reverse_iterator<int*> > (i.e. doubly-wrapped).\n\ttemplate <bool isMove, typename InputIterator, typename OutputIterator>\n\tEASTL_REMOVE_AT_2024_SEPT inline OutputIterator move_and_copy_unwrapper(InputIterator first, InputIterator last, OutputIterator result)\n\t{\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED() // 'unwrap_iterator': was declared deprecated\n\t\treturn OutputIterator(eastl::move_and_copy_chooser<isMove>(eastl::unwrap_iterator(first), eastl::unwrap_iterator(last), eastl::unwrap_iterator(result))); // Have to convert to OutputIterator because unwrap_iterator(result) could be a T*\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t}\n\n\n\t/// move\n\t///\n\t/// After this operation the elements in the moved-from range will still contain valid values of the\n\t/// appropriate type, but not necessarily the same values as before the move.\n\t/// Returns the end of the result range.\n\t/// Note: When moving between containers, the dest range must be valid; this function doesn't resize containers.\n\t/// Note: if result is within [first, last), move_backward must be used instead of move.\n\t///\n\t/// Example usage:\n\t///     eastl::move(myArray.begin(), myArray.end(), myDestArray.begin());\n\t///\n\t/// Reference implementation:\n\t///     template <typename InputIterator, typename OutputIterator>\n\t///     OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)\n\t///     {\n\t///         while(first != last)\n\t///             *result++ = eastl::move(*first++);\n\t///         return result;\n\t///     }\n\n\ttemplate <typename InputIterator, typename OutputIterator>\n\tinline OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)\n\t{\n\t\treturn eastl::move_and_copy_chooser<true>(first, last, result);\n\t}\n\n\n\t/// copy\n\t///\n\t/// Effects: Copies elements in the range [first, last) into the range [result, result + (last - first))\n\t/// starting from first and proceeding to last. For each nonnegative integer n < (last - first),\n\t/// performs *(result + n) = *(first + n).\n\t///\n\t/// Returns: result + (last - first). That is, returns the end of the result. Note that this\n\t/// is different from how memmove/memcpy work, as they return the beginning of the result.\n\t///\n\t/// Requires: result shall not be in the range [first, last). But the end of the result range\n\t/// may in fact be within the input rante.\n\t///\n\t/// Complexity: Exactly 'last - first' assignments.\n\t///\n\ttemplate <typename InputIterator, typename OutputIterator>\n\tinline OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)\n\t{\n\t\treturn eastl::move_and_copy_chooser<false>(first, last, result);\n\t}\n} // namespace eastl\n\n#endif // EASTL_INTERNAL_COPY_HELP_H\n"
  },
  {
    "path": "include/EASTL/internal/enable_shared.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_ENABLE_SHARED_H\n#define EASTL_INTERNAL_ENABLE_SHARED_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\nnamespace eastl\n{\n\n\t/// enable_shared_from_this\n\t///\n\t/// This is a helper mixin class that allows you to make any class\n\t/// export a shared_ptr instance that is associated with the class \n\t/// instance. Any class that inherits from this class gets two functions:\n\t///    shared_ptr<T> shared_from_this();\n\t///    shared_ptr<T> shared_from_this() const;\n\t/// If you call shared_from_this, you get back a shared_ptr that \n\t/// refers to the class. A second call to shared_from_this returns\n\t/// another shared_ptr that is shared with the first one. \n\t///\n\t/// The trick that happens which is not so obvious here (and which is\n\t/// not mentioned at all in the Boost documentation of their version\n\t/// of this) is that the shared_ptr constructor detects that the \n\t/// class has an enable_shared_from_this mixin and sets up this system\n\t/// automatically for the user. This is done with template tricks.\n\t///\n\t/// For some additional explanation, see the Boost documentation for \n\t/// their description of their version of enable_shared_from_this.\n\t///\n\ttemplate <typename T>\n\tclass enable_shared_from_this\n\t{\n\tpublic:\n\t\tshared_ptr<T> shared_from_this()\n\t\t\t{ return shared_ptr<T>(mWeakPtr); }\n\n\t\tshared_ptr<const T> shared_from_this() const\n\t\t\t{ return shared_ptr<const T>(mWeakPtr); }\n\n\t\tweak_ptr<T> weak_from_this()\n\t\t\t{ return mWeakPtr; }\n\n\t\tweak_ptr<const T> weak_from_this() const\n\t\t\t{ return mWeakPtr; }\n\n\tpublic: // This is public because the alternative fails on some compilers that we need to support.\n\t\tmutable weak_ptr<T> mWeakPtr;\n\n\tprotected:\n\t\ttemplate <typename U> friend class shared_ptr;\n\n\t\tEA_CONSTEXPR enable_shared_from_this() EA_NOEXCEPT\n\t\t\t{ }\n\n\t\tenable_shared_from_this(const enable_shared_from_this&) EA_NOEXCEPT\n\t\t\t{ }\n\n\t\tenable_shared_from_this& operator=(const enable_shared_from_this&) EA_NOEXCEPT\n\t\t\t{ return *this; }\n\n\t\t~enable_shared_from_this()\n\t\t\t{ }\n\n\t}; // enable_shared_from_this\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/fill_help.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_FILL_HELP_H\n#define EASTL_INTERNAL_FILL_HELP_H\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n\n#if defined(EA_COMPILER_MICROSOFT) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n#include <intrin.h>\n#endif\n\nnamespace eastl\n{\n\t// fill\n\t//\n\t// We implement some fill helper functions in order to allow us to optimize it\n\t// where possible.\n\t//\n\ttemplate <bool bIsScalar>\n\tstruct fill_imp\n\t{\n\t\ttemplate <typename ForwardIterator, typename T>\n\t\tstatic void do_fill(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t{\n\t\t\t// The C++ standard doesn't specify whether we need to create a temporary\n\t\t\t// or not, but all std STL implementations are written like what we have here.\n\t\t\tfor(; first != last; ++first)\n\t\t\t\t*first = value;\n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct fill_imp<true>\n\t{\n\t\ttemplate <typename ForwardIterator, typename T>\n\t\tstatic void do_fill(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\t// We create a temp and fill from that because value might alias to the \n\t\t\t// destination range and so the compiler would be forced into generating \n\t\t\t// less efficient code.\n\t\t\tfor(const T temp = value; first != last; ++first)\n\t\t\t{\n\t\t\t\tEA_UNUSED(temp);\n\t\t\t\t*first = static_cast<value_type>(temp);\n\t\t\t}\n\t\t}\n\t};\n\n\t/// fill\n\t///\n\t/// fill is like memset in that it assigns a single value repeatedly to a \n\t/// destination range. It allows for any type of iterator (not just an array)\n\t/// and the source value can be any type, not just a byte.\n\t/// Note that the source value (which is a reference) can come from within \n\t/// the destination range.\n\t///\n\t/// Effects: Assigns value through all the iterators in the range [first, last).\n\t///\n\t/// Complexity: Exactly 'last - first' assignments.\n\t///\n\t/// Note: The C++ standard doesn't specify anything about the value parameter\n\t/// coming from within the first-last range. All std STL implementations act\n\t/// as if the standard specifies that value must not come from within this range.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tinline void fill(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\teastl::fill_imp< is_scalar<T>::value >::do_fill(first, last, value);\n\n\t\t// Possibly better implementation, as it will deal with small PODs as well as scalars:\n\t\t// bEasyCopy is true if the type has a trivial constructor (e.g. is a POD) and if \n\t\t// it is small. Thus any built-in type or any small user-defined struct will qualify.\n\t\t//const bool bEasyCopy = eastl::type_and<eastl::has_trivial_constructor<T>::value, \n\t\t//                                       eastl::integral_constant<bool, (sizeof(T) <= 16)>::value;\n\t\t//eastl::fill_imp<bEasyCopy>::do_fill(first, last, value);\n\n\t}\n\n\t#if (defined(EA_COMPILER_GNUC) || defined(__clang__)) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\t#if defined(EA_PROCESSOR_X86_64)\n\t\t\ttemplate <typename Value>\n\t\t\tinline void fill(uint64_t* first, uint64_t* last, Value c)\n\t\t\t{\n\t\t\t\tuintptr_t count = (uintptr_t)(last - first);\n\t\t\t\tuint64_t  value = (uint64_t)(c);\n\n\t\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t\t  \"rep stosq\\n\\t\"\n\t\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\t}\n\n\n\t\t\ttemplate <typename Value>\n\t\t\tinline void fill(int64_t* first, int64_t* last, Value c)\n\t\t\t{\n\t\t\t\tuintptr_t count = (uintptr_t)(last - first);\n\t\t\t\tint64_t   value = (int64_t)(c);\n\n\t\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t\t  \"rep stosq\\n\\t\"\n\t\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\t}\n\t\t#endif\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(uint32_t* first, uint32_t* last, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(last - first);\n\t\t\tuint32_t  value = (uint32_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosl\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t}\n\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(int32_t* first, int32_t* last, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(last - first);\n\t\t\tint32_t   value = (int32_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosl\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t}\n\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(uint16_t* first, uint16_t* last, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(last - first);\n\t\t\tuint16_t  value = (uint16_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosw\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t}\n\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(int16_t* first, int16_t* last, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(last - first);\n\t\t\tint16_t   value = (int16_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosw\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t}\n\n\t#elif defined(EA_COMPILER_MICROSOFT) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\t#if defined(EA_PROCESSOR_X86_64)\n\t\t\ttemplate <typename Value>\n\t\t\tinline void fill(uint64_t* first, uint64_t* last, Value c)\n\t\t\t{\n\t\t\t\t__stosq(first, (uint64_t)c, (size_t)(last - first));\n\t\t\t}\n\n\t\t\ttemplate <typename Value>\n\t\t\tinline void fill(int64_t* first, int64_t* last, Value c)\n\t\t\t{\n\t\t\t\t__stosq((uint64_t*)first, (uint64_t)c, (size_t)(last - first));\n\t\t\t}\n\t\t#endif\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(uint32_t* first, uint32_t* last, Value c)\n\t\t{\n\t\t\t__stosd((unsigned long*)first, (unsigned long)c, (size_t)(last - first));\n\t\t}\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(int32_t* first, int32_t* last, Value c)\n\t\t{\n\t\t\t__stosd((unsigned long*)first, (unsigned long)c, (size_t)(last - first));\n\t\t}\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(uint16_t* first, uint16_t* last, Value c)\n\t\t{\n\t\t\t__stosw(first, (uint16_t)c, (size_t)(last - first));\n\t\t}\n\n\t\ttemplate <typename Value>\n\t\tinline void fill(int16_t* first, int16_t* last, Value c)\n\t\t{\n\t\t\t__stosw((uint16_t*)first, (uint16_t)c, (size_t)(last - first));\n\t\t}\n\t#endif\n\n\n\tinline void fill(char* first, char* last, const char& c) // It's debateable whether we should use 'char& c' or 'char c' here.\n\t{\n\t\tmemset(first, (unsigned char)c, (size_t)(last - first));\n\t}\n\n\tinline void fill(char* first, char* last, const int c) // This is used for cases like 'fill(first, last, 0)'.\n\t{\n\t\tmemset(first, (unsigned char)c, (size_t)(last - first));\n\t}\n\n\tinline void fill(unsigned char* first, unsigned char* last, const unsigned char& c)\n\t{\n\t\tmemset(first, (unsigned char)c, (size_t)(last - first));\n\t}\n\n\tinline void fill(unsigned char* first, unsigned char* last, const int c)\n\t{\n\t\tmemset(first, (unsigned char)c, (size_t)(last - first));\n\t}\n\n\tinline void fill(signed char* first, signed char* last, const signed char& c)\n\t{\n\t\tmemset(first, (unsigned char)c, (size_t)(last - first));\n\t}\n\n\tinline void fill(signed char* first, signed char* last, const int c)\n\t{\n\t\tmemset(first, (unsigned char)c, (size_t)(last - first));\n\t}\n\n\t#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__ICL) // ICL = Intel compiler\n\t\tinline void fill(bool* first, bool* last, const bool& b)\n\t\t{\n\t\t\tmemset(first, (char)b, (size_t)(last - first));\n\t\t}\n\t#endif\n\n\n\n\n\t// fill_n\n\t//\n\t// We implement some fill helper functions in order to allow us to optimize it\n\t// where possible.\n\t//\n\ttemplate <bool bIsScalar>\n\tstruct fill_n_imp\n\t{\n\t\ttemplate <typename OutputIterator, typename Size, typename T>\n\t\tstatic OutputIterator do_fill(OutputIterator first, Size n, const T& value)\n\t\t{\n\t\t\tfor(; n-- > 0; ++first)\n\t\t\t\t*first = value;\n\t\t\treturn first;\n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct fill_n_imp<true>\n\t{\n\t\ttemplate <typename OutputIterator, typename Size, typename T>\n\t\tstatic OutputIterator do_fill(OutputIterator first, Size n, const T& value)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<OutputIterator>::value_type value_type;\n\n\t\t\t// We create a temp and fill from that because value might alias to \n\t\t\t// the destination range and so the compiler would be forced into \n\t\t\t// generating less efficient code.\n\t\t\tfor(const T temp = value; n-- > 0; ++first)\n\t\t\t\t*first = static_cast<value_type>(temp);\n\t\t\treturn first;\n\t\t}\n\t};\n\n\t/// fill_n\n\t///\n\t/// The fill_n function is very much like memset in that a copies a source value\n\t/// n times into a destination range. The source value may come from within \n\t/// the destination range.\n\t///\n\t/// Effects: Assigns value through all the iterators in the range [first, first + n).\n\t///\n\t/// Complexity: Exactly n assignments.\n\t///\n\ttemplate <typename OutputIterator, typename Size, typename T>\n\tOutputIterator fill_n(OutputIterator first, Size n, const T& value)\n\t{\n\t\treturn eastl::fill_n_imp<is_scalar<T>::value>::do_fill(first, n, value);\n\t}\n\n\ttemplate <typename Size>\n\tinline char* fill_n(char* first, Size n, const char& c)\n\t{\n\t\treturn (char*)memset(first, (char)c, (size_t)n) + n;\n\t}\n\n\ttemplate <typename Size>\n\tinline unsigned char* fill_n(unsigned char* first, Size n, const unsigned char& c)\n\t{\n\t\treturn (unsigned char*)memset(first, (unsigned char)c, (size_t)n) + n;\n\t}\n\n\ttemplate <typename Size>\n\tinline signed char* fill_n(signed char* first, Size n, const signed char& c)\n\t{\n\t\treturn (signed char*)memset(first, (signed char)c, n) + (size_t)n;\n\t}\n\n\t#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__ICL) // ICL = Intel compiler\n\t\ttemplate <typename Size>\n\t\tinline bool* fill_n(bool* first, Size n, const bool& b)\n\t\t{\n\t\t\treturn (bool*)memset(first, (char)b, n) + (size_t)n;\n\t\t}\n\t#endif\n\n\t#if (defined(EA_COMPILER_GNUC) || defined(__clang__)) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\t#if defined(EA_PROCESSOR_X86_64)\n\t\t\ttemplate <typename Size, typename Value>\n\t\t\tinline uint64_t* fill_n(uint64_t* first, Size n, Value c)\n\t\t\t{\n\t\t\t\tuintptr_t count = (uintptr_t)(n);\n\t\t\t\tuint64_t  value = (uint64_t)(c);\n\n\t\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t\t  \"rep stosq\\n\\t\"\n\t\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\t\treturn first; // first is updated by the code above.\n\t\t\t}\n\n\n\t\t\ttemplate <typename Size, typename Value>\n\t\t\tinline int64_t* fill_n(int64_t* first, Size n, Value c)\n\t\t\t{\n\t\t\t\tuintptr_t count = (uintptr_t)(n);\n\t\t\t\tint64_t   value = (int64_t)(c);\n\n\t\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t\t  \"rep stosq\\n\\t\"\n\t\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\t\treturn first; // first is updated by the code above.\n\t\t\t}\n\t\t#endif\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline uint32_t* fill_n(uint32_t* first, Size n, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(n);\n\t\t\tuint32_t  value = (uint32_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosl\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\treturn first; // first is updated by the code above.\n\t\t}\n\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline int32_t* fill_n(int32_t* first, Size n, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(n);\n\t\t\tint32_t   value = (int32_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosl\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\treturn first; // first is updated by the code above.\n\t\t}\n\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline uint16_t* fill_n(uint16_t* first, Size n, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(n);\n\t\t\tuint16_t  value = (uint16_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosw\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\treturn first; // first is updated by the code above.\n\t\t}\n\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline int16_t* fill_n(int16_t* first, Size n, Value c)\n\t\t{\n\t\t\tuintptr_t count = (uintptr_t)(n);\n\t\t\tint16_t   value = (int16_t)(c);\n\n\t\t\t__asm__ __volatile__ (\"cld\\n\\t\"\n\t\t\t\t\t\t\t\t  \"rep stosw\\n\\t\"\n\t\t\t\t\t\t\t\t   : \"+c\" (count), \"+D\" (first), \"=m\" (first)\n\t\t\t\t\t\t\t\t   : \"a\" (value)\n\t\t\t\t\t\t\t\t   : \"cc\" );\n\t\t\treturn first; // first is updated by the code above.\n\t\t}\n\n\t#elif defined(EA_COMPILER_MICROSOFT) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\t#if defined(EA_PROCESSOR_X86_64)\n\t\t\ttemplate <typename Size, typename Value>\n\t\t\tinline uint64_t* fill_n(uint64_t* first, Size n, Value c)\n\t\t\t{\n\t\t\t\t__stosq(first, (uint64_t)c, (size_t)n);\n\t\t\t\treturn first + n;\n\t\t\t}\n\n\t\t\ttemplate <typename Size, typename Value>\n\t\t\tinline int64_t* fill_n(int64_t* first, Size n, Value c)\n\t\t\t{\n\t\t\t\t__stosq((uint64_t*)first, (uint64_t)c, (size_t)n);\n\t\t\t\treturn first + n;\n\t\t\t}\n\t\t#endif\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline uint32_t* fill_n(uint32_t* first, Size n, Value c)\n\t\t{\n\t\t\t__stosd((unsigned long*)first, (unsigned long)c, (size_t)n);\n\t\t\treturn first + n;\n\t\t}\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline int32_t* fill_n(int32_t* first, Size n, Value c)\n\t\t{\n\t\t\t__stosd((unsigned long*)first, (unsigned long)c, (size_t)n);\n\t\t\treturn first + n;\n\t\t}\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline uint16_t* fill_n(uint16_t* first, Size n, Value c)\n\t\t{\n\t\t\t__stosw(first, (uint16_t)c, (size_t)n);\n\t\t\treturn first + n;\n\t\t}\n\n\t\ttemplate <typename Size, typename Value>\n\t\tinline int16_t* fill_n(int16_t* first, Size n, Value c)\n\t\t{\n\t\t\t__stosw((uint16_t*)first, (uint16_t)c, (size_t)n);\n\t\t\treturn first + n;\n\t\t}\n\t#endif\n\n} // namespace eastl\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/fixed_pool.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the following\n//     aligned_buffer\n//     fixed_pool_base\n//     fixed_pool\n//     fixed_pool_with_overflow\n//     fixed_hashtable_allocator\n//     fixed_vector_allocator\n//     fixed_swap\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_FIXED_POOL_H\n#define EASTL_INTERNAL_FIXED_POOL_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/functional.h>\n#include <EASTL/memory.h>\n#include <EASTL/allocator.h>\n#include <EASTL/type_traits.h>\n\n\nEA_DISABLE_ALL_VC_WARNINGS();\n#include <new>\nEA_RESTORE_ALL_VC_WARNINGS();\n\n// 4275 - non dll-interface class used as base for DLL-interface classkey 'identifier'\nEA_DISABLE_VC_WARNING(4275);\n\n\nnamespace eastl\n{\n\n\t/// EASTL_FIXED_POOL_DEFAULT_NAME\n\t///\n\t/// Defines a default allocator name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_FIXED_POOL_DEFAULT_NAME\n\t\t#define EASTL_FIXED_POOL_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" fixed_pool\" // Unless the user overrides something, this is \"EASTL fixed_pool\".\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// aligned_buffer\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// aligned_buffer\n\t///\n\t/// This is useful for creating a buffer of the same size and alignment \n\t/// of a given struct or class. This is useful for creating memory pools\n\t/// that support both size and alignment requirements of stored objects\n\t/// but without wasting space in over-allocating. \n\t///\n\t/// Note that we implement this via struct specializations, as some \n\t/// compilers such as VC++ do not support specification of alignments\n\t/// in any way other than via an integral constant.\n\t///\n\t/// Example usage:\n\t///    struct Widget{ }; // This class has a given size and alignment.\n\t///\n\t///    Declare a char buffer of equal size and alignment to Widget.\n\t///    aligned_buffer<sizeof(Widget), EASTL_ALIGN_OF(Widget)> mWidgetBuffer; \n\t///\n\t///    Declare an array this time.\n\t///    aligned_buffer<sizeof(Widget), EASTL_ALIGN_OF(Widget)> mWidgetArray[15]; \n\t///\n\ttypedef char EASTL_MAY_ALIAS aligned_buffer_char; \n\n\ttemplate <size_t size, size_t alignment>\n\tstruct aligned_buffer { aligned_buffer_char buffer[size]; };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 2>    { EA_PREFIX_ALIGN(2) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(2); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 4>    { EA_PREFIX_ALIGN(4) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(4); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 8>    { EA_PREFIX_ALIGN(8) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(8); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 16>   { EA_PREFIX_ALIGN(16) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(16); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 32>   { EA_PREFIX_ALIGN(32) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(32); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 64>   { EA_PREFIX_ALIGN(64) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(64); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 128>  { EA_PREFIX_ALIGN(128) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(128); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 256>  { EA_PREFIX_ALIGN(256) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(256); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 512>  { EA_PREFIX_ALIGN(512) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(512); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 1024> { EA_PREFIX_ALIGN(1024) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(1024); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 2048> { EA_PREFIX_ALIGN(2048) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(2048); };\n\n\ttemplate<size_t size>\n\tstruct aligned_buffer<size, 4096> { EA_PREFIX_ALIGN(4096) aligned_buffer_char buffer[size] EA_POSTFIX_ALIGN(4096); };\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_pool_base\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_pool_base\n\t///\n\t/// This is a base class for the implementation of fixed-size pools.\n\t/// In particular, the fixed_pool and fixed_pool_with_overflow classes\n\t/// are based on fixed_pool_base.\n\t///\n\tstruct fixed_pool_base\n\t{\n\tpublic:\n\t\t/// fixed_pool_base\n\t\t///\n\t\tfixed_pool_base(void* pMemory = NULL)\n\t\t\t: mpHead((Link*)pMemory)\n\t\t\t, mpNext((Link*)pMemory)\n\t\t\t, mpCapacity((Link*)pMemory)\n\t\t\t, mnNodeSize(0) // This is normally set in the init function.\n\t\t{\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\tmnCurrentSize = 0;\n\t\t\t\tmnPeakSize    = 0;\n\t\t\t#endif\n\t\t}\n\n\n\t\t/// fixed_pool_base\n\t\t///\n\t\t// Disabled because the default is sufficient. While it normally makes no sense to deep copy\n\t\t// this data, our usage of this class is such that this is OK and wanted.\n\t\t//\n\t\t// fixed_pool_base(const fixed_pool_base& x)\n\t\t// {\n\t\t// }\n\n\n\t\t/// operator=\n\t\t///\n\t\tfixed_pool_base& operator=(const fixed_pool_base&)\n\t\t{\n\t\t\t// By design we do nothing. We don't attempt to deep-copy member data. \n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// init\n\t\t///\n\t\t/// Initializes a fixed_pool with a given set of parameters.\n\t\t/// You cannot call this function twice else the resulting \n\t\t/// behaviour will be undefined. You can only call this function\n\t\t/// after constructing the fixed_pool with the default constructor.\n\t\t///\n\t\tEASTL_API void init(void* pMemory, size_t memorySize, size_t nodeSize,\n\t\t\t\t\t\t\tsize_t alignment, size_t alignmentOffset = 0);\n\n\n\t\t/// peak_size\n\t\t///\n\t\t/// Returns the maximum number of outstanding allocations there have been\n\t\t/// at any one time. This represents a high water mark for the allocation count.\n\t\t///\n\t\tsize_t peak_size() const\n\t\t{\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\treturn mnPeakSize;\n\t\t\t#else\n\t\t\t\treturn 0;\n\t\t\t#endif\n\t\t}\n\n\n\t\t/// can_allocate\n\t\t///\n\t\t/// Returns true if there are any free links.\n\t\t///\n\t\tbool can_allocate() const\n\t\t{\n\t\t\treturn (mpHead != NULL) || (mpNext != mpCapacity);\n\t\t}\n\n\tpublic:\n\t\t/// Link\n\t\t/// Implements a singly-linked list.\n\t\tstruct Link\n\t\t{\n\t\t\tLink* mpNext;\n\t\t};\n\n\t\tLink*   mpHead;\n\t\tLink*   mpNext;\n\t\tLink*   mpCapacity;\n\t\tsize_t  mnNodeSize;\n\n\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\tuint32_t mnCurrentSize; /// Current number of allocated nodes.\n\t\t\tuint32_t mnPeakSize;    /// Max number of allocated nodes at any one time.\n\t\t#endif\n\n\t}; // fixed_pool_base\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_pool\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_pool\n\t///\n\t/// Implements a simple fixed pool allocator for use by fixed-size containers. \n\t/// This is not a generic eastl allocator which can be plugged into an arbitrary\n\t/// eastl container, as it simplifies some functions are arguments for the \n\t/// purpose of efficiency.\n\t/// \n\tclass EASTL_API fixed_pool : public fixed_pool_base\n\t{\n\tpublic:\n\t\t/// fixed_pool\n\t\t///\n\t\t/// Default constructor. User usually will want to call init() after  \n\t\t/// constructing via this constructor. The pMemory argument is for the \n\t\t/// purposes of temporarily storing a pointer to the buffer to be used.\n\t\t/// Even though init may have a pMemory argument, this arg is useful \n\t\t/// for temporary storage, as per copy construction.\n\t\t///\n\t\tfixed_pool(void* pMemory = NULL)\n\t\t\t: fixed_pool_base(pMemory)\n\t\t{\n\t\t}\n\n\n\t\t/// fixed_pool\n\t\t///\n\t\t/// Constructs a fixed_pool with a given set of parameters.\n\t\t///\n\t\tfixed_pool(void* pMemory, size_t memorySize, size_t nodeSize, \n\t\t\t\t\tsize_t alignment, size_t alignmentOffset = 0)\n\t\t{\n\t\t\tinit(pMemory, memorySize, nodeSize, alignment, alignmentOffset);\n\t\t}\n\n\n\t\t/// fixed_pool\n\t\t///\n\t\t// Disabled because the default is sufficient. While it normally makes no sense to deep copy\n\t\t// this data, our usage of this class is such that this is OK and wanted.\n\t\t//\n\t\t// fixed_pool(const fixed_pool& x)\n\t\t// {\n\t\t// }\n\n\n\t\t/// operator=\n\t\t///\n\t\tfixed_pool& operator=(const fixed_pool&)\n\t\t{\n\t\t\t// By design we do nothing. We don't attempt to deep-copy member data. \n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// allocate\n\t\t///\n\t\t/// Allocates a new object of the size specified upon class initialization.\n\t\t/// Returns NULL if there is no more memory. \n\t\t///\n\t\tvoid* allocate()\n\t\t{\n\t\t\tLink* pLink = mpHead;\n\n\t\t\tif(pLink) // If we have space...\n\t\t\t{\n\t\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t\tif(++mnCurrentSize > mnPeakSize)\n\t\t\t\t\t\tmnPeakSize = mnCurrentSize;\n\t\t\t\t#endif\n\n\t\t\t\tmpHead = pLink->mpNext;\n\t\t\t\treturn pLink;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If there's no free node in the free list, just\n\t\t\t\t// allocate another from the reserved memory area\n\n\t\t\t\tif(mpNext != mpCapacity)\n\t\t\t\t{\n\t\t\t\t\tpLink = mpNext;\n\t\t\t\t\t\n\t\t\t\t\tmpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + mnNodeSize);\n\n\t\t\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t\t\tif(++mnCurrentSize > mnPeakSize)\n\t\t\t\t\t\t\tmnPeakSize = mnCurrentSize;\n\t\t\t\t\t#endif\n\n\t\t\t\t\treturn pLink;\n\t\t\t\t}\n\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t}\n\n\t\tvoid* allocate(size_t /*alignment*/, size_t /*offset*/)\n\t\t{\n\t\t\treturn allocate();\n\t\t}\n\t\t\n\t\t/// deallocate\n\t\t///\n\t\t/// Frees the given object which was allocated by allocate(). \n\t\t/// If the given node was not allocated by allocate() then the behaviour \n\t\t/// is undefined.\n\t\t///\n\t\tvoid deallocate(void* p)\n\t\t{\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t--mnCurrentSize;\n\t\t\t#endif\n\n\t\t\t((Link*)p)->mpNext = mpHead;\n\t\t\tmpHead = ((Link*)p);\n\t\t}\n\n\n\t\tusing fixed_pool_base::can_allocate;\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn EASTL_FIXED_POOL_DEFAULT_NAME;\n\t\t}\n\n\n\t\tvoid set_name(const char*)\n\t\t{\n\t\t\t// Nothing to do. We don't allocate memory.\n\t\t}\n\n\t}; // fixed_pool\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_pool_with_overflow\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_pool_with_overflow\n\t///\n\ttemplate <typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_pool_with_overflow : public fixed_pool_base\n\t{\n\tpublic:\n\t\ttypedef OverflowAllocator overflow_allocator_type;\n\n\n\t\tfixed_pool_with_overflow(void* pMemory = NULL)\n\t\t\t: fixed_pool_base(pMemory),\n\t\t\t  mOverflowAllocator(EASTL_FIXED_POOL_DEFAULT_NAME)\n\t\t{\n\t\t\t// Leave mpPoolBegin, mpPoolEnd uninitialized.\n\t\t}\n\n\n\t\tfixed_pool_with_overflow(void* pMemory, const overflow_allocator_type& allocator)\n\t\t\t: fixed_pool_base(pMemory),\n\t\t\t  mOverflowAllocator(allocator)\n\t\t{\n\t\t\t// Leave mpPoolBegin, mpPoolEnd uninitialized.\n\t\t}\n\n\n\t\tfixed_pool_with_overflow(void* pMemory, size_t memorySize, size_t nodeSize, \n\t\t\t\t\t\t\t\t size_t alignment, size_t alignmentOffset = 0)\n\t\t\t: mOverflowAllocator(EASTL_FIXED_POOL_DEFAULT_NAME)\n\t\t{\n\t\t\tfixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset);\n\n\t\t\tmpPoolBegin = pMemory;\n\t\t}\n\n\n\t\tfixed_pool_with_overflow(void* pMemory, size_t memorySize, size_t nodeSize, \n\t\t\t\t\t\t\t\t size_t alignment, size_t alignmentOffset,\n\t\t\t\t\t\t\t\t const overflow_allocator_type& allocator)\n\t\t\t: mOverflowAllocator(allocator)\n\t\t{\n\t\t\tfixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset);\n\n\t\t\tmpPoolBegin = pMemory;\n\t\t}\n\n\n\t\t// Disabled because the default is sufficient. While it normally makes no sense to deep copy\n\t\t// this data, our usage of this class is such that this is OK and wanted.\n\t\t//\n\t\t//fixed_pool_with_overflow(const fixed_pool_with_overflow& x)\n\t\t//{\n\t\t//    ...\n\t\t//}\n\n\n\t\tfixed_pool_with_overflow& operator=(const fixed_pool_with_overflow& x)\n\t\t{\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tmOverflowAllocator = x.mOverflowAllocator;\n\t\t\t#else\n\t\t\t\t(void)x;\n\t\t\t#endif\n\n\t\t\treturn *this;\n\t\t}\n\n\n\t\tvoid init(void* pMemory, size_t memorySize, size_t nodeSize,\n\t\t\t\t\tsize_t alignment, size_t alignmentOffset = 0)\n\t\t{\n\t\t\tfixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset);\n\n\t\t\tmpPoolBegin = pMemory;\n\t\t}\n\n\n\t\tvoid* allocate()\n\t\t{\n\t\t\tvoid* p     = NULL;\n\t\t\tLink* pLink = mpHead;\n\n\t\t\tif(pLink)\n\t\t\t{\n\t\t\t\t// Unlink from chain\n\t\t\t\tp      = pLink;\n\t\t\t\tmpHead = pLink->mpNext;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If there's no free node in the free list, just\n\t\t\t\t// allocate another from the reserved memory area\n\n\t\t\t\tif(mpNext != mpCapacity)\n\t\t\t\t{\n\t\t\t\t\tp      = pLink = mpNext;\n\t\t\t\t\tmpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + mnNodeSize);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tp = mOverflowAllocator.allocate(mnNodeSize);\n\t\t\t}\n\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\tif(p && (++mnCurrentSize > mnPeakSize))\n\t\t\t\t\tmnPeakSize = mnCurrentSize;\n\t\t\t#endif\n\n\t\t\treturn p;\n\t\t}\n\n\n\t\tvoid* allocate(size_t alignment, size_t alignmentOffset)\n\t\t{\n\t\t\tvoid* p = NULL;\n\t\t\tLink* pLink = mpHead;\n\n\t\t\tif (pLink)\n\t\t\t{\n\t\t\t\t// Unlink from chain\n\t\t\t\tp = pLink;\n\t\t\t\tmpHead = pLink->mpNext;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If there's no free node in the free list, just\n\t\t\t\t// allocate another from the reserved memory area\n\n\t\t\t\tif (mpNext != mpCapacity)\n\t\t\t\t{\n\t\t\t\t\tp = pLink = mpNext;\n\t\t\t\t\tmpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext)+mnNodeSize);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tp = allocate_memory(mOverflowAllocator, mnNodeSize, alignment, alignmentOffset);\n\t\t\t\t\tEASTL_ASSERT_MSG(p != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\tif (p && (++mnCurrentSize > mnPeakSize))\n\t\t\t\t\tmnPeakSize = mnCurrentSize;\n\t\t\t#endif\n\n\t\t\treturn p;\n\t\t}\n\n\t\tvoid deallocate(void* p)\n\t\t{\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t--mnCurrentSize;\n\t\t\t#endif\n\n\t\t\tif((p >= mpPoolBegin) && (p < mpCapacity))\n\t\t\t{\n\t\t\t\t((Link*)p)->mpNext = mpHead;\n\t\t\t\tmpHead = ((Link*)p);\n\t\t\t}\n\t\t\telse\n\t\t\t\tmOverflowAllocator.deallocate(p, (size_t)mnNodeSize);\n\t\t}\n\n\n\t\tusing fixed_pool_base::can_allocate;\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn mOverflowAllocator.get_name();\n\t\t}\n\n\n\t\tvoid set_name(const char* pName)\n\t\t{\n\t\t\tmOverflowAllocator.set_name(pName);\n\t\t}\n\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const\n\t\t{\n\t\t\treturn mOverflowAllocator;\n\t\t}\n\n\n\t\toverflow_allocator_type& get_overflow_allocator()\n\t\t{\n\t\t\treturn mOverflowAllocator;\n\t\t}\n\t\t\n\n\t\tvoid set_overflow_allocator(const overflow_allocator_type& overflowAllocator)\n\t\t{\n\t\t\tmOverflowAllocator = overflowAllocator;\n\t\t}\n\tpublic:\n\t\tOverflowAllocator mOverflowAllocator; \n\t\tvoid*             mpPoolBegin;         // Ideally we wouldn't need this member variable. he problem is that the information about the pool buffer and object size is stored in the owning container and we can't have access to it without increasing the amount of code we need and by templating more code. It may turn out that simply storing data here is smaller in the end.\n\n\t}; // fixed_pool_with_overflow              \n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_node_allocator\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_node_allocator\n\t///\n\t/// Note: This class was previously named fixed_node_pool, but was changed because this name\n\t///       was inconsistent with the other allocators here which ended with _allocator.\n\t///\n\t/// Implements a fixed_pool with a given node count, alignment, and alignment offset.\n\t/// fixed_node_allocator is like fixed_pool except it is templated on the node type instead\n\t/// of being a generic allocator. All it does is pass allocations through to\n\t/// the fixed_pool base. This functionality is separate from fixed_pool because there\n\t/// are other uses for fixed_pool.\n\t///\n\t/// We template on kNodeSize instead of node_type because the former allows for the\n\t/// two different node_types of the same size to use the same template implementation.\n\t///\n\t/// Template parameters:\n\t///     nodeSize               The size of the object to allocate.\n\t///     nodeCount              The number of objects the pool contains.\n\t///     nodeAlignment          The alignment of the objects to allocate.\n\t///     nodeAlignmentOffset    The alignment offset of the objects to allocate.\n\t///     bEnableOverflow        Whether or not we should use the overflow heap if our object pool is exhausted.\n\t///     OverflowAllocator      Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_node_allocator\n\t{\n\tpublic:\n\t\ttypedef typename conditional<bEnableOverflow, fixed_pool_with_overflow<OverflowAllocator>, fixed_pool>::type  pool_type;\n\t\ttypedef fixed_node_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>   this_type;\n\t\ttypedef OverflowAllocator overflow_allocator_type;\n\n\t\tenum\n\t\t{\n\t\t\tkNodeSize            = nodeSize,\n\t\t\tkNodeCount           = nodeCount,\n\t\t\tkNodesSize           = nodeCount * nodeSize, // Note that the kBufferSize calculation assumes that the compiler sets sizeof(T) to be a multiple alignof(T), and so sizeof(T) is always >= alignof(T).\n\t\t\tkBufferSize          = kNodesSize + ((nodeAlignment > 1) ? nodeSize-1 : 0) + nodeAlignmentOffset,\n\t\t\tkNodeAlignment       = nodeAlignment,\n\t\t\tkNodeAlignmentOffset = nodeAlignmentOffset\n\t\t};\n\n\tpublic:\n\t\tpool_type mPool;\n\n\tpublic:\n\t\t//fixed_node_allocator(const char* pName)\n\t\t//{\n\t\t//    mPool.set_name(pName);\n\t\t//}\n\n\n\t\tfixed_node_allocator(void* pNodeBuffer)\n\t\t\t: mPool(pNodeBuffer, kNodesSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset)\n\t\t{\n\t\t}\n\n\n\t\tfixed_node_allocator(void* pNodeBuffer, const overflow_allocator_type& allocator)\n\t\t\t: mPool(pNodeBuffer, kNodesSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset, allocator)\n\t\t{\n\t\t}\n\n\n\t\t/// fixed_node_allocator\n\t\t///\n\t\t/// Note that we are copying x.mpHead to our own fixed_pool. This at first may seem \n\t\t/// broken, as fixed pools cannot take over ownership of other fixed pools' memory.\n\t\t/// However, we declare that this copy ctor can only ever be safely called when \n\t\t/// the user has intentionally pre-seeded the source with the destination pointer.\n\t\t/// This is somewhat playing with fire, but it allows us to get around chicken-and-egg\n\t\t/// problems with containers being their own allocators, without incurring any memory\n\t\t/// costs or extra code costs. There's another reason for this: we very strongly want\n\t\t/// to avoid full copying of instances of fixed_pool around, especially via the stack.\n\t\t/// Larger pools won't even be able to fit on many machine's stacks. So this solution\n\t\t/// is also a mechanism to prevent that situation from existing and being used. \n\t\t/// Perhaps some day we'll find a more elegant yet costless way around this. \n\t\t///\n\t\tfixed_node_allocator(const this_type& x)\n\t\t\t: mPool(x.mPool.mpNext, kNodesSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset, x.mPool.mOverflowAllocator)\n\t\t{\n\t\t}\n\n\n\t\tthis_type& operator=(const this_type& x)\n\t\t{\n\t\t\tmPool = x.mPool;\n\t\t\treturn *this;\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, int /*flags*/ = 0)\n\t\t{\n\t\t\t(void)n;\n\t\t\tEASTL_ASSERT(n == kNodeSize);\n\t\t\treturn mPool.allocate();\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, size_t alignment, size_t offset, int /*flags*/ = 0)\n\t\t{\n\t\t\t(void)n;\n\t\t\tEASTL_ASSERT(n == kNodeSize);\n\t\t\treturn mPool.allocate(alignment, offset);\n\t\t}\n\n\n\t\tvoid deallocate(void* p, size_t)\n\t\t{\n\t\t\tmPool.deallocate(p);\n\t\t}\n\n\n\t\t/// can_allocate\n\t\t///\n\t\t/// Returns true if there are any free links.\n\t\t///\n\t\tbool can_allocate() const\n\t\t{\n\t\t\treturn mPool.can_allocate();\n\t\t}\n\n\n\t\t/// reset\n\t\t///\n\t\t/// This function unilaterally resets the fixed pool back to a newly initialized\n\t\t/// state. This is useful for using in tandem with container reset functionality.\n\t\t///\n\t\tvoid reset(void* pNodeBuffer)\n\t\t{\n\t\t\tmPool.init(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset);\n\t\t}\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn mPool.get_name();\n\t\t}\n\n\n\t\tvoid set_name(const char* pName)\n\t\t{\n\t\t\tmPool.set_name(pName);\n\t\t}\n\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPool.mOverflowAllocator;\n\t\t}\n\n\n\t\toverflow_allocator_type& get_overflow_allocator() EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPool.mOverflowAllocator;\n\t\t}\n\n\n\t\tvoid set_overflow_allocator(const overflow_allocator_type& allocator)\n\t\t{\n\t\t\tmPool.mOverflowAllocator = allocator;\n\t\t}\n\n\n\t\tvoid copy_overflow_allocator(const this_type& x)  // This function exists so we can write generic code that works for allocators that do and don't have overflow allocators.\n\t\t{\n\t\t\tmPool.mOverflowAllocator = x.mPool.mOverflowAllocator;\n\t\t}\n\n\t}; // fixed_node_allocator\n\n\n\t// This is a near copy of the code above, with the only difference being \n\t// the 'false' bEnableOverflow template parameter, the pool_type and this_type typedefs, \n\t// and the get_overflow_allocator / set_overflow_allocator functions.\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, typename OverflowAllocator>\n\tclass fixed_node_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, false, OverflowAllocator>\n\t{\n\tpublic:\n\t\ttypedef fixed_pool pool_type;\n\t\ttypedef fixed_node_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, false, OverflowAllocator>   this_type;\n\t\ttypedef OverflowAllocator overflow_allocator_type;\n\n\t\tenum\n\t\t{\n\t\t\tkNodeSize            = nodeSize,\n\t\t\tkNodeCount           = nodeCount,\n\t\t\tkNodesSize           = nodeCount * nodeSize, // Note that the kBufferSize calculation assumes that the compiler sets sizeof(T) to be a multiple alignof(T), and so sizeof(T) is always >= alignof(T).\n\t\t\tkBufferSize          = kNodesSize + ((nodeAlignment > 1) ? nodeSize-1 : 0) + nodeAlignmentOffset,\n\t\t\tkNodeAlignment       = nodeAlignment,\n\t\t\tkNodeAlignmentOffset = nodeAlignmentOffset\n\t\t};\n\n\tpublic:\n\t\tpool_type mPool;\n\n\tpublic:\n\t\tfixed_node_allocator(void* pNodeBuffer)\n\t\t\t: mPool(pNodeBuffer, kNodesSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset)\n\t\t{\n\t\t}\n\n\n\t\tfixed_node_allocator(void* pNodeBuffer, const overflow_allocator_type& /*allocator*/) // allocator is unused because bEnableOverflow is false in this specialization.\n\t\t\t: mPool(pNodeBuffer, kNodesSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset)\n\t\t{\n\t\t}\n\n\n\t\t/// fixed_node_allocator\n\t\t///\n\t\t/// Note that we are copying x.mpHead to our own fixed_pool. This at first may seem \n\t\t/// broken, as fixed pools cannot take over ownership of other fixed pools' memory.\n\t\t/// However, we declare that this copy ctor can only ever be safely called when \n\t\t/// the user has intentionally pre-seeded the source with the destination pointer.\n\t\t/// This is somewhat playing with fire, but it allows us to get around chicken-and-egg\n\t\t/// problems with containers being their own allocators, without incurring any memory\n\t\t/// costs or extra code costs. There's another reason for this: we very strongly want\n\t\t/// to avoid full copying of instances of fixed_pool around, especially via the stack.\n\t\t/// Larger pools won't even be able to fit on many machine's stacks. So this solution\n\t\t/// is also a mechanism to prevent that situation from existing and being used. \n\t\t/// Perhaps some day we'll find a more elegant yet costless way around this. \n\t\t///\n\t\tfixed_node_allocator(const this_type& x)            // No need to copy the overflow allocator, because bEnableOverflow is false in this specialization.\n\t\t\t: mPool(x.mPool.mpNext, kNodesSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset)\n\t\t{\n\t\t}\n\n\n\t\tthis_type& operator=(const this_type& x)\n\t\t{\n\t\t\tmPool = x.mPool;\n\t\t\treturn *this;\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, int /*flags*/ = 0)\n\t\t{\n\t\t\t(void)n;\n\t\t\tEASTL_ASSERT(n == kNodeSize);\n\t\t\treturn mPool.allocate();\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, size_t alignment, size_t offset, int /*flags*/ = 0)\n\t\t{\n\t\t\t(void)n;\n\t\t\tEASTL_ASSERT(n == kNodeSize);\n\t\t\treturn mPool.allocate(alignment, offset);\n\t\t}\n\n\n\t\tvoid deallocate(void* p, size_t)\n\t\t{\n\t\t\tmPool.deallocate(p);\n\t\t}\n\n\n\t\tbool can_allocate() const\n\t\t{\n\t\t\treturn mPool.can_allocate();\n\t\t}\n\n\n\t\tvoid reset(void* pNodeBuffer)\n\t\t{\n\t\t\tmPool.init(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset);\n\t\t}\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn mPool.get_name();\n\t\t}\n\n\n\t\tvoid set_name(const char* pName)\n\t\t{\n\t\t\tmPool.set_name(pName);\n\t\t}\n\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT(false);\n\t\t\toverflow_allocator_type* pNULL = NULL;\n\t\t\treturn *pNULL; // This is not pretty, but it should never execute. This is here only to allow this to compile.\n\t\t}\n\n\n\t\toverflow_allocator_type& get_overflow_allocator() EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT(false);\n\t\t\toverflow_allocator_type* pNULL = NULL;\n\t\t\treturn *pNULL; // This is not pretty, but it should never execute. This is here only to allow this to compile.\n\t\t}\n\n\n\t\tvoid set_overflow_allocator(const overflow_allocator_type& /*allocator*/)\n\t\t{\n\t\t\t// We don't have an overflow allocator.\n\t\t\tEASTL_ASSERT(false);\n\t\t}\n\n\n\t\tvoid copy_overflow_allocator(const this_type&)  // This function exists so we can write generic code that works for allocators that do and don't have overflow allocators.\n\t\t{\n\t\t\t// We don't have an overflow allocator.\n\t\t}\n\n\t}; // fixed_node_allocator\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool operator==(const fixed_node_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t\t   const fixed_node_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\treturn (&a == &b); // They are only equal if they are the same object.\n\t}\n\n\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool operator!=(const fixed_node_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t\t   const fixed_node_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\treturn (&a != &b); // They are only equal if they are the same object.\n\t}\n\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_hashtable_allocator\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_hashtable_allocator\n\t///\n\t/// Provides a base class for fixed hashtable allocations.\n\t/// To consider: Have this inherit from fixed_node_allocator.\n\t///\n\t/// Template parameters:\n\t///     bucketCount            The fixed number of hashtable buckets to provide.\n\t///     nodeCount              The number of objects the pool contains.\n\t///     nodeAlignment          The alignment of the objects to allocate.\n\t///     nodeAlignmentOffset    The alignment offset of the objects to allocate.\n\t///     bEnableOverflow        Whether or not we should use the overflow heap if our object pool is exhausted.\n\t///     OverflowAllocator      Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <size_t bucketCount, size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_hashtable_allocator\n\t{\n\tpublic:\n\t\ttypedef typename conditional<bEnableOverflow, fixed_pool_with_overflow<OverflowAllocator>, fixed_pool>::type                                 pool_type;\n\t\ttypedef fixed_hashtable_allocator<bucketCount, nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>  this_type;\n\t\ttypedef OverflowAllocator overflow_allocator_type;\n\n\t\tenum\n\t\t{\n\t\t\tkBucketCount         = bucketCount + 1, // '+1' because the hash table needs a null terminating bucket.\n\t\t\tkBucketsSize         = bucketCount * sizeof(void*),\n\t\t\tkNodeSize            = nodeSize,\n\t\t\tkNodeCount           = nodeCount,\n\t\t\tkNodesSize           = nodeCount * nodeSize, // Note that the kBufferSize calculation assumes that the compiler sets sizeof(T) to be a multiple alignof(T), and so sizeof(T) is always >= alignof(T).\n\t\t\tkBufferSize          = kNodesSize + ((nodeAlignment > 1) ? nodeSize-1 : 0) + nodeAlignmentOffset, // Don't need to include kBucketsSize in this calculation, as fixed_hash_xxx containers have a separate buffer for buckets.\n\t\t\tkNodeAlignment       = nodeAlignment,\n\t\t\tkNodeAlignmentOffset = nodeAlignmentOffset,\n\t\t\tkAllocFlagBuckets    = 0x00400000               // Flag to allocator which indicates that we are allocating buckets and not nodes.\n\t\t};\n\n\tprotected:\n\t\tpool_type mPool;\n\t\tvoid*     mpBucketBuffer;\n\n\tpublic:\n\t\t// Disabled because it causes compile conflicts.\n\t\t//fixed_hashtable_allocator(const char* pName)\n\t\t//{\n\t\t//    mPool.set_name(pName);\n\t\t//}\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer)\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset),\n\t\t\t  mpBucketBuffer(NULL)\n\t\t{\n\t\t\t// EASTL_ASSERT(false); // As it stands now, this is not supposed to be called.\n\t\t}\n\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer, const overflow_allocator_type& allocator)\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset, allocator),\n\t\t\t  mpBucketBuffer(NULL)\n\t\t{\n\t\t\t// EASTL_ASSERT(false); // As it stands now, this is not supposed to be called.\n\t\t}\n\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer, void* pBucketBuffer)\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset),\n\t\t\t  mpBucketBuffer(pBucketBuffer)\n\t\t{\n\t\t}\n\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer, void* pBucketBuffer, const overflow_allocator_type& allocator)\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset, allocator),\n\t\t\t  mpBucketBuffer(pBucketBuffer)\n\t\t{\n\t\t}\n\n\n\t\t/// fixed_hashtable_allocator\n\t\t///\n\t\t/// Note that we are copying x.mpHead and mpBucketBuffer to our own fixed_pool. \n\t\t/// See the discussion above in fixed_node_allocator for important information about this.\n\t\t///\n\t\tfixed_hashtable_allocator(const this_type& x)\n\t\t\t: mPool(x.mPool.mpHead, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset, x.mPool.mOverflowAllocator),\n\t\t\t  mpBucketBuffer(x.mpBucketBuffer)\n\t\t{\n\t\t}\n\n\n\t\tfixed_hashtable_allocator& operator=(const fixed_hashtable_allocator& x)\n\t\t{\n\t\t\tmPool = x.mPool;\n\t\t\treturn *this;\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, int flags = 0)\n\t\t{\n\t\t\t// We expect that the caller uses kAllocFlagBuckets when it wants us to allocate buckets instead of nodes.\n\t\t\tEASTL_CT_ASSERT(kAllocFlagBuckets == 0x00400000); // Currently we expect this to be so, because the hashtable has a copy of this enum.\n\n\t\t\tif((flags & kAllocFlagBuckets) == 0) // If we are allocating nodes and (probably) not buckets...\n\t\t\t{\n\t\t\t\tEASTL_ASSERT(n == kNodeSize); EA_UNUSED(n); \n\t\t\t\treturn mPool.allocate();\n\t\t\t}\n\n\t\t\t// If bucket size no longer fits within local buffer...\n\t\t\tif ((flags & kAllocFlagBuckets) == kAllocFlagBuckets && (n > kBucketsSize))\n\t\t\t\treturn get_overflow_allocator().allocate(n);\n\n\t\t\tEASTL_ASSERT(n <= kBucketsSize);\n\t\t\treturn mpBucketBuffer;\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, size_t alignment, size_t offset, int flags = 0)\n\t\t{\n\t\t\t// We expect that the caller uses kAllocFlagBuckets when it wants us to allocate buckets instead of nodes.\n\t\t\tif ((flags & kAllocFlagBuckets) == 0) // If we are allocating nodes and (probably) not buckets...\n\t\t\t{\n\t\t\t\tEASTL_ASSERT(n == kNodeSize); EA_UNUSED(n);\n\t\t\t\treturn mPool.allocate(alignment, offset);\n\t\t\t}\n\n\t\t\t// If bucket size no longer fits within local buffer...\n\t\t\tif ((flags & kAllocFlagBuckets) == kAllocFlagBuckets && (n > kBucketsSize))\n\t\t\t\treturn get_overflow_allocator().allocate(n, alignment, offset);\n\n\t\t\tEASTL_ASSERT(n <= kBucketsSize);\n\t\t\treturn mpBucketBuffer;\n\t\t}\n\n\n\t\tvoid deallocate(void* p, size_t)\n\t\t{\n\t\t\tif(p != mpBucketBuffer) // If we are freeing a node and not buckets...\n\t\t\t\tmPool.deallocate(p);\n\t\t}\n\n\n\t\tbool can_allocate() const\n\t\t{\n\t\t\treturn mPool.can_allocate();\n\t\t}\n\n\n\t\tvoid reset(void* pNodeBuffer)\n\t\t{\n\t\t\t// No need to modify mpBucketBuffer, as that is constant.\n\t\t\tmPool.init(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset);\n\t\t}\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn mPool.get_name();\n\t\t}\n\n\n\t\tvoid set_name(const char* pName)\n\t\t{\n\t\t\tmPool.set_name(pName);\n\t\t}\n\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const\n\t\t{\n\t\t\treturn mPool.mOverflowAllocator;\n\t\t}\n\n\n\t\toverflow_allocator_type& get_overflow_allocator()\n\t\t{\n\t\t\treturn mPool.mOverflowAllocator;\n\t\t}\n\n\n\t\tvoid set_overflow_allocator(const overflow_allocator_type& allocator)\n\t\t{\n\t\t\tmPool.mOverflowAllocator = allocator;\n\t\t}\n\n\n\t\tvoid copy_overflow_allocator(const this_type& x)  // This function exists so we can write generic code that works for allocators that do and don't have overflow allocators.\n\t\t{\n\t\t\tmPool.mOverflowAllocator = x.mPool.mOverflowAllocator;\n\t\t}\n\n\t}; // fixed_hashtable_allocator\n\n\n\t// This is a near copy of the code above, with the only difference being \n\t// the 'false' bEnableOverflow template parameter, the pool_type and this_type typedefs, \n\t// and the get_overflow_allocator / set_overflow_allocator functions.\n\ttemplate <size_t bucketCount, size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, typename OverflowAllocator>\n\tclass fixed_hashtable_allocator<bucketCount, nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, false, OverflowAllocator>\n\t{\n\tpublic:\n\t\ttypedef fixed_pool pool_type;\n\t\ttypedef fixed_hashtable_allocator<bucketCount, nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, false, OverflowAllocator>  this_type;\n\t\ttypedef OverflowAllocator overflow_allocator_type;\n\n\t\tenum\n\t\t{\n\t\t\tkBucketCount         = bucketCount + 1, // '+1' because the hash table needs a null terminating bucket.\n\t\t\tkBucketsSize         = bucketCount * sizeof(void*),\n\t\t\tkNodeSize            = nodeSize,\n\t\t\tkNodeCount           = nodeCount,\n\t\t\tkNodesSize           = nodeCount * nodeSize, // Note that the kBufferSize calculation assumes that the compiler sets sizeof(T) to be a multiple alignof(T), and so sizeof(T) is always >= alignof(T).\n\t\t\tkBufferSize          = kNodesSize + ((nodeAlignment > 1) ? nodeSize-1 : 0) + nodeAlignmentOffset, // Don't need to include kBucketsSize in this calculation, as fixed_hash_xxx containers have a separate buffer for buckets.\n\t\t\tkNodeAlignment       = nodeAlignment,\n\t\t\tkNodeAlignmentOffset = nodeAlignmentOffset,\n\t\t\tkAllocFlagBuckets    = 0x00400000               // Flag to allocator which indicates that we are allocating buckets and not nodes.\n\t\t};\n\n\tprotected:\n\t\tpool_type mPool;\n\t\tvoid*     mpBucketBuffer;\n\n\tpublic:\n\t\t// Disabled because it causes compile conflicts.\n\t\t//fixed_hashtable_allocator(const char* pName)\n\t\t//{\n\t\t//    mPool.set_name(pName);\n\t\t//}\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer)\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset),\n\t\t\t  mpBucketBuffer(NULL)\n\t\t{\n\t\t\t// EASTL_ASSERT(false); // As it stands now, this is not supposed to be called.\n\t\t}\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer, const overflow_allocator_type& /*allocator*/) // allocator is unused because bEnableOverflow is false in this specialization.\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset),\n\t\t\t  mpBucketBuffer(NULL)\n\t\t{\n\t\t\t// EASTL_ASSERT(false); // As it stands now, this is not supposed to be called.\n\t\t}\n\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer, void* pBucketBuffer)\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset),\n\t\t\t  mpBucketBuffer(pBucketBuffer)\n\t\t{\n\t\t}\n\n\n\t\tfixed_hashtable_allocator(void* pNodeBuffer, void* pBucketBuffer, const overflow_allocator_type& /*allocator*/) // allocator is unused because bEnableOverflow is false in this specialization.\n\t\t\t: mPool(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset),\n\t\t\t  mpBucketBuffer(pBucketBuffer)\n\t\t{\n\t\t}\n\n\n\t\t/// fixed_hashtable_allocator\n\t\t///\n\t\t/// Note that we are copying x.mpHead and mpBucketBuffer to our own fixed_pool. \n\t\t/// See the discussion above in fixed_node_allocator for important information about this.\n\t\t///\n\t\tfixed_hashtable_allocator(const this_type& x)   // No need to copy the overflow allocator, because bEnableOverflow is false in this specialization.\n\t\t\t: mPool(x.mPool.mpHead, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset),\n\t\t\t  mpBucketBuffer(x.mpBucketBuffer)\n\t\t{\n\t\t}\n\n\n\t\tfixed_hashtable_allocator& operator=(const fixed_hashtable_allocator& x)\n\t\t{\n\t\t\tmPool = x.mPool;\n\t\t\treturn *this;\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, int flags = 0)\n\t\t{\n\t\t\t// We expect that the caller uses kAllocFlagBuckets when it wants us to allocate buckets instead of nodes.\n\t\t\tEASTL_CT_ASSERT(kAllocFlagBuckets == 0x00400000); // Currently we expect this to be so, because the hashtable has a copy of this enum.\n\t\t\tif((flags & kAllocFlagBuckets) == 0) // If we are allocating nodes and (probably) not buckets...\n\t\t\t{\n\t\t\t\tEASTL_ASSERT(n == kNodeSize);  (void)n; // Make unused var warning go away.\n\t\t\t\treturn mPool.allocate();\n\t\t\t}\n\n\t\t\t// Don't allow hashtable buckets to overflow in this case.\n\t\t\tEASTL_ASSERT(n <= kBucketsSize);\n\t\t\treturn mpBucketBuffer;\n\t\t}\n\n\n\t\tvoid* allocate(size_t n, size_t alignment, size_t offset, int flags = 0)\n\t\t{\n\t\t\t// We expect that the caller uses kAllocFlagBuckets when it wants us to allocate buckets instead of nodes.\n\t\t\tif((flags & kAllocFlagBuckets) == 0) // If we are allocating nodes and (probably) not buckets...\n\t\t\t{\n\t\t\t\tEASTL_ASSERT(n == kNodeSize); (void)n; // Make unused var warning go away.\n\t\t\t\treturn mPool.allocate(alignment, offset);\n\t\t\t}\n\n\t\t\t// Don't allow hashtable buckets to overflow in this case.\n\t\t\tEASTL_ASSERT(n <= kBucketsSize);\n\t\t\treturn mpBucketBuffer;\n\t\t}\n\n\n\t\tvoid deallocate(void* p, size_t)\n\t\t{\n\t\t\tif(p != mpBucketBuffer) // If we are freeing a node and not buckets...\n\t\t\t\tmPool.deallocate(p);\n\t\t}\n\n\n\t\tbool can_allocate() const\n\t\t{\n\t\t\treturn mPool.can_allocate();\n\t\t}\n\n\n\t\tvoid reset(void* pNodeBuffer)\n\t\t{\n\t\t\t// No need to modify mpBucketBuffer, as that is constant.\n\t\t\tmPool.init(pNodeBuffer, kBufferSize, kNodeSize, kNodeAlignment, kNodeAlignmentOffset);\n\t\t}\n\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn mPool.get_name();\n\t\t}\n\n\n\t\tvoid set_name(const char* pName)\n\t\t{\n\t\t\tmPool.set_name(pName);\n\t\t}\n\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT(false);\n\t\t\toverflow_allocator_type* pNULL = NULL;\n\t\t\treturn *pNULL; // This is not pretty, but it should never execute. This is here only to allow this to compile.\n\t\t}\n\n\n\t\toverflow_allocator_type& get_overflow_allocator() EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT(false);\n\t\t\toverflow_allocator_type* pNULL = NULL;\n\t\t\treturn *pNULL; // This is not pretty, but it should never execute. This is here only to allow this to compile.\n\t\t}\n\n\t\tvoid set_overflow_allocator(const overflow_allocator_type& /*allocator*/)\n\t\t{\n\t\t\t// We don't have an overflow allocator.\n\t\t\tEASTL_ASSERT(false);\n\t\t}\n\n\t\tvoid copy_overflow_allocator(const this_type&)  // This function exists so we can write generic code that works for allocators that do and don't have overflow allocators.\n\t\t{\n\t\t\t// We don't have an overflow allocator.\n\t\t}\n\n\t}; // fixed_hashtable_allocator\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <size_t bucketCount, size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool operator==(const fixed_hashtable_allocator<bucketCount, nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t\t   const fixed_hashtable_allocator<bucketCount, nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\treturn (&a == &b); // They are only equal if they are the same object.\n\t}\n\n\n\ttemplate <size_t bucketCount, size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool operator!=(const fixed_hashtable_allocator<bucketCount, nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t\t   const fixed_hashtable_allocator<bucketCount, nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\treturn (&a != &b); // They are only equal if they are the same object.\n\t}\n\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_vector_allocator\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_vector_allocator\n\t///\n\t/// Template parameters:\n\t///     nodeSize               The size of individual objects.\n\t///     nodeCount              The number of objects the pool contains.\n\t///     nodeAlignment          The alignment of the objects to allocate.\n\t///     nodeAlignmentOffset    The alignment offset of the objects to allocate.\n\t///     bEnableOverflow        Whether or not we should use the overflow heap if our object pool is exhausted.\n\t///     OverflowAllocator      Overflow allocator, which is only used if bEnableOverflow == true. Defaults to the global heap.\n\t///\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator = EASTLAllocatorType>\n\tclass fixed_vector_allocator\n\t{\n\tpublic:\n\t\ttypedef fixed_vector_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>  this_type;\n\t\ttypedef OverflowAllocator overflow_allocator_type;\n\n\t\tenum\n\t\t{\n\t\t\tkNodeSize            = nodeSize,\n\t\t\tkNodeCount           = nodeCount,\n\t\t\tkNodesSize           = nodeCount * nodeSize, // Note that the kBufferSize calculation assumes that the compiler sets sizeof(T) to be a multiple alignof(T), and so sizeof(T) is always >= alignof(T).\n\t\t\tkBufferSize          = kNodesSize + ((nodeAlignment > 1) ? nodeSize-1 : 0) + nodeAlignmentOffset,\n\t\t\tkNodeAlignment       = nodeAlignment,\n\t\t\tkNodeAlignmentOffset = nodeAlignmentOffset\n\t\t};\n\n\tpublic:\n\t\toverflow_allocator_type mOverflowAllocator;\n\t\tvoid*                   mpPoolBegin;         // To consider: Find some way to make this data unnecessary, without increasing template proliferation.\n\n\tpublic:\n\t\t// Disabled because it causes compile conflicts.\n\t\t//fixed_vector_allocator(const char* pName = NULL)\n\t\t//{\n\t\t//    mOverflowAllocator.set_name(pName);\n\t\t//}\n\n\t\tfixed_vector_allocator(void* pNodeBuffer = nullptr)\n\t\t\t: mpPoolBegin(pNodeBuffer)\n\t\t{\n\t\t}\n\n\t\tfixed_vector_allocator(void* pNodeBuffer, const overflow_allocator_type& allocator)\n\t\t\t: mOverflowAllocator(allocator), mpPoolBegin(pNodeBuffer)\n\t\t{\n\t\t}\n\n\t\tfixed_vector_allocator(const fixed_vector_allocator& x)\n\t\t\t: mOverflowAllocator(x.mOverflowAllocator), mpPoolBegin(x.mpPoolBegin)\n\t\t{\n\t\t}\n\n\t\tfixed_vector_allocator& operator=(const fixed_vector_allocator& x)\n\t\t{\n\t\t\t// We leave our mpPoolBegin variable alone.\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tmOverflowAllocator = x.mOverflowAllocator;\n\t\t\t#else\n\t\t\t\t(void)x;\n\t\t\t#endif\n\n\t\t\treturn *this;\n\t\t}\n\n\t\tvoid* allocate(size_t n, int flags = 0)\n\t\t{\n\t\t\treturn mOverflowAllocator.allocate(n, flags);\n\t\t}\n\n\t\tvoid* allocate(size_t n, size_t alignment, size_t offset, int flags = 0)\n\t\t{\n\t\t\treturn mOverflowAllocator.allocate(n, alignment, offset, flags);\n\t\t}\n\n\t\tvoid deallocate(void* p, size_t n)\n\t\t{\n\t\t\tif(p != mpPoolBegin)\n\t\t\t\tmOverflowAllocator.deallocate(p, n); // Can't do this to our own allocation.\n\t\t}\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn mOverflowAllocator.get_name();\n\t\t}\n\n\t\tvoid set_name(const char* pName)\n\t\t{\n\t\t\tmOverflowAllocator.set_name(pName);\n\t\t}\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mOverflowAllocator;\n\t\t}\n\n\t\toverflow_allocator_type& get_overflow_allocator() EA_NOEXCEPT\n\t\t{\n\t\t\treturn mOverflowAllocator;\n\t\t}\n\n\t\tvoid set_overflow_allocator(const overflow_allocator_type& allocator)\n\t\t{\n\t\t\tmOverflowAllocator = allocator;\n\t\t}\n\n\t\tvoid copy_overflow_allocator(const this_type& x)  // This function exists so we can write generic code that works for allocators that do and don't have overflow allocators.\n\t\t{\n\t\t\tmOverflowAllocator = x.mOverflowAllocator;\n\t\t}\n\n\t}; // fixed_vector_allocator\n\n\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, typename OverflowAllocator>\n\tclass fixed_vector_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, false, OverflowAllocator>\n\t{\n\tpublic:\n\t\ttypedef fixed_vector_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, false, OverflowAllocator>  this_type;\n\t\ttypedef OverflowAllocator overflow_allocator_type;\n\n\t\tenum\n\t\t{\n\t\t\tkNodeSize            = nodeSize,\n\t\t\tkNodeCount           = nodeCount,\n\t\t\tkNodesSize           = nodeCount * nodeSize, // Note that the kBufferSize calculation assumes that the compiler sets sizeof(T) to be a multiple alignof(T), and so sizeof(T) is always >= alignof(T).\n\t\t\tkBufferSize          = kNodesSize + ((nodeAlignment > 1) ? nodeSize-1 : 0) + nodeAlignmentOffset,\n\t\t\tkNodeAlignment       = nodeAlignment,\n\t\t\tkNodeAlignmentOffset = nodeAlignmentOffset\n\t\t};\n\n\t\t// Disabled because it causes compile conflicts.\n\t\t//fixed_vector_allocator(const char* = NULL) // This char* parameter is present so that this class can be like the other version.\n\t\t//{\n\t\t//}\n\n\t\tfixed_vector_allocator()\n\t\t{\n\t\t}\n\n\t\tfixed_vector_allocator(void* /*pNodeBuffer*/)\n\t\t{\n\t\t}\n\n\t\tfixed_vector_allocator(void* /*pNodeBuffer*/, const overflow_allocator_type& /*allocator*/)  // allocator is unused because bEnableOverflow is false in this specialization.\n\t\t{\n\t\t}\n\n\t\t/// fixed_vector_allocator\n\t\t///\n\t\t// Disabled because there is nothing to do. No member data. And the default for this is sufficient.\n\t\t// fixed_vector_allocator(const fixed_vector_allocator&)\n\t\t// {\n\t\t// }\n\n\t\t// Disabled because there is nothing to do. No member data.\n\t\t//fixed_vector_allocator& operator=(const fixed_vector_allocator& x)\n\t\t//{\n\t\t//    return *this;\n\t\t//}\n\n\t\tvoid* allocate(size_t /*n*/, int /*flags*/ = 0)\n\t\t{\n\t\t\tEASTL_ASSERT(false); // A fixed_vector should not reallocate, else the user has exhausted its space.\n\t\t\tEASTL_CRASH();\t\t // We choose to crash here since the owning vector can't handle an allocator returning null. Better to crash earlier.\n\t\t\treturn NULL;\n\t\t}\n\n\t\tvoid* allocate(size_t /*n*/, size_t /*alignment*/, size_t /*offset*/, int /*flags*/ = 0)\n\t\t{\n\t\t\tEASTL_ASSERT(false); // A fixed_vector should not reallocate, else the user has exhausted its space.\n\t\t\tEASTL_CRASH();\t\t // We choose to crash here since the owning vector can't handle an allocator returning null. Better to crash earlier.\n\t\t\treturn NULL;\n\t\t}\n\n\t\tvoid deallocate(void* /*p*/, size_t /*n*/)\n\t\t{\n\t\t}\n\n\t\tconst char* get_name() const\n\t\t{\n\t\t\treturn EASTL_FIXED_POOL_DEFAULT_NAME;\n\t\t}\n\n\t\tvoid set_name(const char* /*pName*/)\n\t\t{\n\t\t}\n\n\t\tconst overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT(false);\n\t\t\toverflow_allocator_type* pNULL = NULL;\n\t\t\treturn *pNULL; // This is not pretty, but it should never execute. This is here only to allow this to compile.\n\t\t}\n\n\t\toverflow_allocator_type& get_overflow_allocator() EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT(false);\n\t\t\toverflow_allocator_type* pNULL = NULL;\n\t\t\treturn *pNULL; // This is not pretty, but it should never execute. This is here only to allow this to compile.\n\t\t}\n\n\t\tvoid set_overflow_allocator(const overflow_allocator_type& /*allocator*/)\n\t\t{\n\t\t\t// We don't have an overflow allocator.\n\t\t\tEASTL_ASSERT(false);\n\t\t}\n\n\t\tvoid copy_overflow_allocator(const this_type&)  // This function exists so we can write generic code that works for allocators that do and don't have overflow allocators.\n\t\t{\n\t\t\t// We don't have an overflow allocator.\n\t\t}\n\n\t}; // fixed_vector_allocator\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool operator==(const fixed_vector_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t\t   const fixed_vector_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\treturn (&a == &b); // They are only equal if they are the same object.\n\t}\n\n\n\ttemplate <size_t nodeSize, size_t nodeCount, size_t nodeAlignment, size_t nodeAlignmentOffset, bool bEnableOverflow, typename OverflowAllocator>\n\tinline bool operator!=(const fixed_vector_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& a, \n\t\t\t\t\t\t   const fixed_vector_allocator<nodeSize, nodeCount, nodeAlignment, nodeAlignmentOffset, bEnableOverflow, OverflowAllocator>& b)\n\t{\n\t\treturn (&a != &b); // They are only equal if they are the same object.\n\t}\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// fixed_swap\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// fixed_swap\n\t///\n\t/// This function implements a swap suitable for fixed containers.\n\t/// This is an issue because the size of fixed containers can be very \n\t/// large, due to their having the container buffer within themselves.\n\t/// Note that we are referring to sizeof(container) and not the total\n\t/// sum of memory allocated by the container from the heap. \n\t///\n\t///\n\t/// This implementation switches at compile time whether or not the \n\t/// temporary is allocated on the stack or the heap as some compilers\n\t/// will allocate the (large) stack frame regardless of which code\n\t/// path is picked.\n\ttemplate <typename Container, bool UseHeapTemporary>\n\tclass fixed_swap_impl\n\t{\n\tpublic: \n\t\tstatic void swap(Container& a, Container& b);\n\t};\n\n\n\ttemplate <typename Container>\n\tclass fixed_swap_impl<Container, false>\n\t{\n\tpublic:\n\t\tstatic void swap(Container& a, Container& b)\n\t\t{\n\t\t\tContainer temp(EASTL_MOVE(a)); // Can't use global swap because that could\n\t\t\ta = EASTL_MOVE(b);             // itself call this swap function in return.\n\t\t\tb = EASTL_MOVE(temp);\n\t\t}\n\t};\n\n\n\ttemplate <typename Container>\n\tclass fixed_swap_impl<Container, true>\n\t{\n\tpublic:\n\t\tstatic void swap(Container& a, Container& b)\n\t\t{\n\t\t\tEASTLAllocatorType allocator(*EASTLAllocatorDefault(), EASTL_TEMP_DEFAULT_NAME);\n\t\t\tContainer* const pTemp = static_cast<Container*>(allocator.allocate(sizeof(a)));\n\n\t\t\tif(pTemp)\n\t\t\t{\n\t\t\t\tdetail::allocator_construct(allocator, pTemp, EASTL_MOVE(a));\n\t\t\t\ta = EASTL_MOVE(b);\n\t\t\t\tb = EASTL_MOVE(*pTemp);\n\n\t\t\t\tpTemp->~Container();\n\t\t\t\tallocator.deallocate(pTemp, sizeof(a));\n\t\t\t}\n\t\t}\n\t};\n\n\n\ttemplate<typename Container>\n\tvoid fixed_swap(Container& a, Container& b)\n\t{\n\t\treturn fixed_swap_impl<Container, sizeof(Container) >= EASTL_MAX_STACK_USAGE>::swap(a, b);\n\t}\n\n\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/function.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FUNCTION_H\n#define EASTL_FUNCTION_H\n\n#include <EASTL/internal/config.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/function_detail.h>\n\nnamespace eastl\n{\n\n\t/// EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE\n\t///\n\t/// Defines the size of the SSO buffer which is used to hold the specified capture state of the callable.\n\t///\n\t#ifndef EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE\n\t\t#define EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE (2 * sizeof(void*))\n\t#endif\n\n\tstatic_assert(EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE >= sizeof(void*), \"functor storage must be able to hold at least a pointer!\");\n\n\ttemplate <typename>\n\tclass function;\n\n\ttemplate <typename R, typename... Args>\n\tclass function<R(Args...)> : public internal::function_detail<EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE, R(Args...)>\n\t{\n\tprivate:\n\t\tusing Base = internal::function_detail<EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE, R(Args...)>;\n\tpublic:\n\t\tusing typename Base::result_type;\n\n\t\tfunction() EA_NOEXCEPT = default;\n\t\tfunction(std::nullptr_t p) EA_NOEXCEPT\n\t\t\t: Base(p)\n\t\t{\n\t\t}\n\n\t\tfunction(const function& other)\n\t\t\t: Base(other)\n\t\t{\n\t\t}\n\n\t\tfunction(function&& other)\n\t\t\t: Base(eastl::move(other))\n\t\t{\n\t\t}\n\n\t\ttemplate <typename Functor, typename = EASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(Functor, R, Args..., Base, function)>\n\t\tfunction(Functor&& functor)\n\t\t\t: Base(eastl::forward<Functor>(functor))\n\t\t{\n\t\t}\n\n\t\t~function() EA_NOEXCEPT = default;\n\n\t\tfunction& operator=(const function& other)\n\t\t{\n\t\t\tBase::operator=(other);\n\t\t\treturn *this;\n\t\t}\n\n\t\tfunction& operator=(function&& other)\n\t\t{\n\t\t\tBase::operator=(eastl::move(other));\n\t\t\treturn *this;\n\t\t}\n\n\t\tfunction& operator=(std::nullptr_t p) EA_NOEXCEPT\n\t\t{\n\t\t\tBase::operator=(p);\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename Functor, typename = EASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(Functor, R, Args..., Base, function)>\n\t\tfunction& operator=(Functor&& functor)\n\t\t{\n\t\t\tBase::operator=(eastl::forward<Functor>(functor));\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename Functor>\n\t\tfunction& operator=(eastl::reference_wrapper<Functor> f) EA_NOEXCEPT\n\t\t{\n\t\t\tBase::operator=(f);\n\t\t\treturn *this;\n\t\t}\n\n\t\tvoid swap(function& other) EA_NOEXCEPT\n\t\t{\n\t\t\tBase::swap(other);\n\t\t}\n\n\t\texplicit operator bool() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::operator bool();\n\t\t}\n\n\t\tR operator ()(Args... args) const\n\t\t{\n\t\t\treturn Base::operator ()(eastl::forward<Args>(args)...);\n\t\t}\n\n\t#if EASTL_RTTI_ENABLED\n\t\tconst std::type_info& target_type() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::target_type();\n\t\t}\n\n\t\ttemplate <typename Functor>\n\t\tFunctor* target() EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::template target<Functor>();\n\t\t}\n\n\t\ttemplate <typename Functor>\n\t\tconst Functor* target() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn Base::template target<Functor>();\n\t\t}\n\t#endif // EASTL_RTTI_ENABLED\n\t};\n\n\ttemplate <typename R, typename... Args>\n\tbool operator==(const function<R(Args...)>& f, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !f;\n\t}\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename R, typename... Args>\n\tbool operator==(std::nullptr_t, const function<R(Args...)>& f) EA_NOEXCEPT\n\t{\n\t\treturn !f;\n\t}\n\n\ttemplate <typename R, typename... Args>\n\tbool operator!=(const function<R(Args...)>& f, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !!f;\n\t}\n\n\ttemplate <typename R, typename... Args>\n\tbool operator!=(std::nullptr_t, const function<R(Args...)>& f) EA_NOEXCEPT\n\t{\n\t\treturn !!f;\n\t}\n#endif\n\ttemplate <typename R, typename... Args>\n\tvoid swap(function<R(Args...)>& lhs, function<R(Args...)>& rhs)\n\t{\n\t\tlhs.swap(rhs);\n\t}\n\n#ifdef __cpp_deduction_guides\n\ttemplate<typename ReturnType, typename... Args>\n\tfunction(ReturnType(*)(Args...)) -> function<ReturnType(Args...)>;\n\n\ttemplate<typename Callable>\n\tfunction(Callable) -> function<internal::extract_signature_from_callable_t<decltype(&Callable::operator())>>;\n#endif\n\n} // namespace eastl\n\n#endif // EASTL_FUNCTION_H\n"
  },
  {
    "path": "include/EASTL/internal/function_detail.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_FUNCTION_DETAIL_H\n#define EASTL_FUNCTION_DETAIL_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EABase/eabase.h>\n#include <EABase/nullptr.h>\n#include <EABase/config/eacompilertraits.h>\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/functional_base.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/internal/function_help.h>\n\n#include <EASTL/type_traits.h>\n#include <EASTL/utility.h>\n#include <EASTL/allocator.h>\n\n#if EASTL_RTTI_ENABLED\n\t#include <typeinfo>\n#endif\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <new>\n\t#include <exception>\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\n#define EASTL_EMPTY_FUNCTION_QUALIFIER\n\n// https://en.cppreference.com/w/cpp/language/noexcept_spec\n// The noexcept-specification is a part of the function type in C++17 and above, but not before.\n#if defined(EA_COMPILER_CPP17_ENABLED)\n#define EASTL_GENERATE_MEMBER_FUNCTION_NOEXCEPT_VARIANTS(PATTERN, OTHER_QUALIFIER) \\\n\tPATTERN(OTHER_QUALIFIER EASTL_EMPTY_FUNCTION_QUALIFIER) \\\n\tPATTERN(OTHER_QUALIFIER noexcept)\n#else\n#define EASTL_GENERATE_MEMBER_FUNCTION_NOEXCEPT_VARIANTS(PATTERN, OTHER_QUALIFIER) \\\n\tPATTERN(OTHER_QUALIFIER EASTL_EMPTY_FUNCTION_QUALIFIER)\n#endif\n\t\t\t\t\n#define EASTL_GENERATE_MEMBER_FUNCTION_REF_VARIANTS(PATTERN, OTHER_QUALIFIER) \\\n\tEASTL_GENERATE_MEMBER_FUNCTION_NOEXCEPT_VARIANTS(PATTERN, OTHER_QUALIFIER EASTL_EMPTY_FUNCTION_QUALIFIER) \\\n\tEASTL_GENERATE_MEMBER_FUNCTION_NOEXCEPT_VARIANTS(PATTERN, OTHER_QUALIFIER &) \\\n\tEASTL_GENERATE_MEMBER_FUNCTION_NOEXCEPT_VARIANTS(PATTERN, OTHER_QUALIFIER &&)\n\t\t\t\t\t\n#define EASTL_GENERATE_MEMBER_FUNCTION_VOLATILE_VARIANTS(PATTERN, OTHER_QUALIFIER) \\\n\tEASTL_GENERATE_MEMBER_FUNCTION_REF_VARIANTS(PATTERN, OTHER_QUALIFIER EASTL_EMPTY_FUNCTION_QUALIFIER) \\\n\tEASTL_GENERATE_MEMBER_FUNCTION_REF_VARIANTS(PATTERN, OTHER_QUALIFIER volatile)\n\t\t\t\t\n#define EASTL_GENERATE_MEMBER_FUNCTION_CONST_VARIANTS(PATTERN) \\\n\tEASTL_GENERATE_MEMBER_FUNCTION_VOLATILE_VARIANTS(PATTERN, EASTL_EMPTY_FUNCTION_QUALIFIER) \\\n\tEASTL_GENERATE_MEMBER_FUNCTION_VOLATILE_VARIANTS(PATTERN, const)\n\n// Helper to generate all combination of qualifiers you can apply to member functions.\n// PATTERN must be a macro that will receive as an argument a possible combination of qualifiers and generate a pattern from it.\n#define EASTL_GENERATE_MEMBER_FUNCTION_VARIANTS(PATTERN) EASTL_GENERATE_MEMBER_FUNCTION_CONST_VARIANTS(PATTERN)\n\nnamespace eastl\n{\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\tclass bad_function_call : public std::exception\n\t\t{\n\t\tpublic:\n\t\t\tbad_function_call() EA_NOEXCEPT = default;\n\n\t\t\tconst char* what() const EA_NOEXCEPT EA_OVERRIDE\n\t\t\t{\n\t\t\t\treturn \"bad function_detail call\";\n\t\t\t}\n\t\t};\n\t#endif\n\n\tnamespace internal\n\t{\n\t\tclass unused_class{};\n\n\t\tunion functor_storage_alignment\n\t\t{\n\t\t\tvoid (*unused_func_ptr)(void);\n\t\t\tvoid (unused_class::*unused_func_mem_ptr)(void);\n\t\t\tvoid* unused_ptr;\n\t\t\tint64_t unused_var;\n\t\t};\n\n\t\ttemplate <int SIZE_IN_BYTES>\n\t\tstruct functor_storage\n\t\t{\n\t\t\tstatic_assert(SIZE_IN_BYTES >= 0, \"local buffer storage cannot have a negative size!\");\n\t\t\t\n\t\t\tunion\n\t\t\t{\n\t\t\t\tfunctor_storage_alignment align;\n\t\t\t\tchar storage[SIZE_IN_BYTES];\n\t\t\t};\n\t\t};\n\n\t\ttemplate <>\n\t\tstruct functor_storage<0>\n\t\t{\n\t\t\tunion\n\t\t\t{\n\t\t\t\tfunctor_storage_alignment align;\n\t\t\t\tchar storage[sizeof(functor_storage_alignment)];\n\t\t\t};\n\t\t};\n\n\t\ttemplate <typename Functor, int SIZE_IN_BYTES>\n\t\tstruct is_functor_inplace_allocatable\n\t\t{\n\t\t\tstatic EA_CONSTEXPR bool value = sizeof(Functor) <= sizeof(functor_storage<SIZE_IN_BYTES>) &&\n\t\t\t                                 (alignof(functor_storage<SIZE_IN_BYTES>) % alignof(Functor)) == 0;\n\t\t};\n\n\t\tenum ManagerOperations : int\n\t\t{\n\t\t\tMGROPS_DESTRUCT_FUNCTOR = 0,\n\t\t\tMGROPS_COPY_FUNCTOR = 1,\n\t\t\tMGROPS_MOVE_FUNCTOR = 2,\n#if EASTL_RTTI_ENABLED\n\t\t\tMGROPS_GET_TYPE_INFO = 3,\n\t\t\tMGROPS_GET_FUNC_PTR = 4,\n#endif\n\t\t};\n\n\t\t/// function_base_detail\n\t\t///\n\t\ttemplate <int SIZE_IN_BYTES>\n\t\tclass function_base_detail\n\t\t{\n\t\tpublic:\n\t\t\tusing FunctorStorageType = functor_storage<SIZE_IN_BYTES>;\n\t\t\tFunctorStorageType mStorage;\n\n\t\t\t// Functor can be allocated inplace\n\t\t\ttemplate <typename Functor, typename = void>\n\t\t\tclass function_manager_base\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tstatic Functor* GetFunctorPtr(void* storage) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\t// This case we know the functor fits directly in the storage.\n\t\t\t\t\treturn static_cast<Functor*>(storage);\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T>\n\t\t\t\tstatic void CreateFunctor(void* storage, T&& functor)\n\t\t\t\t{\n\t\t\t\t\t::new (GetFunctorPtr(storage)) Functor(eastl::forward<T>(functor));\n\t\t\t\t}\n\n\t\t\t\tstatic void DestructFunctor(void* storage)\n\t\t\t\t{\n\t\t\t\t\tGetFunctorPtr(storage)->~Functor();\n\t\t\t\t}\n\n\t\t\t\tstatic void CopyFunctor(void* to, void* from)\n\t\t\t\t{\n\t\t\t\t\t::new (GetFunctorPtr(to)) Functor(*GetFunctorPtr(from));\n\t\t\t\t}\n\n\t\t\t\tstatic void MoveFunctor(void* to, void* from) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\t::new (GetFunctorPtr(to)) Functor(eastl::move(*GetFunctorPtr(from)));\n\t\t\t\t}\n\n\t\t\t\tstatic void* Manager(void* to, void* from, typename internal::ManagerOperations ops) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\tswitch (ops)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase MGROPS_DESTRUCT_FUNCTOR:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDestructFunctor(to);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MGROPS_COPY_FUNCTOR:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCopyFunctor(to, from);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MGROPS_MOVE_FUNCTOR:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMoveFunctor(to, from);\n\t\t\t\t\t\t\tDestructFunctor(from);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\treturn nullptr;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Functor is allocated on the heap\n\t\t\ttemplate <typename Functor>\n\t\t\tclass function_manager_base<Functor, typename eastl::enable_if<!is_functor_inplace_allocatable<Functor, SIZE_IN_BYTES>::value>::type>\n\t\t\t{\n\t\t\tpublic:\n\t\t\t\tstatic Functor* GetFunctorPtr(void* storage) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\t// in this case, we know the in-place storage contains a pointer\n\t\t\t\t\t// to the actual functor, so we need to read it from here.\n\t\t\t\t\treturn *static_cast<Functor**>(storage);\n\t\t\t\t}\n\n\t\t\t\tstatic Functor*& GetFunctorPtrRef(void* storage) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\t// in this case, we know the in-place storage contains a pointer\n\t\t\t\t\t// to the actual functor, so we need to read it from here.\n\t\t\t\t\treturn *static_cast<Functor**>(storage);\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T>\n\t\t\t\tstatic void CreateFunctor(void* storage, T&& functor)\n\t\t\t\t{\n\t\t\t\t\tauto& allocator = *EASTLAllocatorDefault();\n\t\t\t\t\tFunctor* func = static_cast<Functor*>(allocator.allocate(sizeof(Functor), alignof(Functor), 0));\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tif (!func)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow std::bad_alloc();\n\t\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\t\tEASTL_ASSERT_MSG(func != nullptr, \"Allocation failed!\");\n\t\t\t\t#endif\n\n\t\t\t\t\t::new (static_cast<void*>(func)) Functor(eastl::forward<T>(functor));\n\t\t\t\t\tGetFunctorPtrRef(storage) = func;\n\t\t\t\t}\n\n\t\t\t\tstatic void DestructFunctor(void* storage)\n\t\t\t\t{\n\t\t\t\t\tFunctor* func = GetFunctorPtr(storage);\n\t\t\t\t\tif (func)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto& allocator = *EASTLAllocatorDefault();\n\t\t\t\t\t\tfunc->~Functor();\n\t\t\t\t\t\tallocator.deallocate(static_cast<void*>(func), sizeof(Functor));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tstatic void CopyFunctor(void* to, void* from)\n\t\t\t\t{\n\t\t\t\t\tauto& allocator = *EASTLAllocatorDefault();\n\t\t\t\t\tFunctor* func = static_cast<Functor*>(allocator.allocate(sizeof(Functor), alignof(Functor), 0));\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tif (!func)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow std::bad_alloc();\n\t\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\t\tEASTL_ASSERT_MSG(func != nullptr, \"Allocation failed!\");\n\t\t\t\t#endif\n\t\t\t\t\t::new (static_cast<void*>(func)) Functor(*GetFunctorPtr(from));\n\t\t\t\t\tGetFunctorPtrRef(to) = func;\n\t\t\t\t}\n\n\t\t\t\tstatic void MoveFunctor(void* to, void* from) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\tFunctor* func = GetFunctorPtr(from);\n\t\t\t\t\tGetFunctorPtrRef(to) = func;\n\t\t\t\t\tGetFunctorPtrRef(from) = nullptr;\n\t\t\t\t}\n\n\t\t\t\tstatic void* Manager(void* to, void* from, typename internal::ManagerOperations ops) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\tswitch (ops)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase MGROPS_DESTRUCT_FUNCTOR:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDestructFunctor(to);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MGROPS_COPY_FUNCTOR:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCopyFunctor(to, from);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MGROPS_MOVE_FUNCTOR:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMoveFunctor(to, from);\n\t\t\t\t\t\t\t// Moved ptr, no need to destruct ourselves\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\treturn nullptr;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttemplate <typename Functor, typename R, typename... Args>\n\t\t\tclass function_manager final : public function_manager_base<Functor>\n\t\t\t{\n\t\t\tpublic:\n\t\t\t\tusing Base = function_manager_base<Functor>;\n\n\t\t\t#if EASTL_RTTI_ENABLED\n\t\t\t\tstatic void* GetTypeInfo() EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\treturn reinterpret_cast<void*>(const_cast<std::type_info*>(&typeid(Functor)));\n\t\t\t\t}\n\n\t\t\t\tstatic void* Manager(void* to, void* from, ManagerOperations ops) EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\tswitch (ops)\n\t\t\t\t\t{\n\t\t\t\t\t\tcase MGROPS_GET_TYPE_INFO:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn GetTypeInfo();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MGROPS_GET_FUNC_PTR:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn static_cast<void*>(Base::GetFunctorPtr(to));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn Base::Manager(to, from, ops);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t#endif // EASTL_RTTI_ENABLED\n\n\t\t\t\t/**\n\t\t\t\t * NOTE:\n\t\t\t\t *\n\t\t\t\t * The order of arguments here is vital to the call optimization. Let's dig into why and look at some asm.\n\t\t\t\t * We have two invoker signatures to consider:\n\t\t\t\t *   R Invoker(const FunctorStorageType& functor, Args... args)\n\t\t\t\t *   R Invoker(Args... args, const FunctorStorageType& functor)\n\t\t\t\t *\n\t\t\t\t * Assume we are using the Windows x64 Calling Convention where the first 4 arguments are passed into\n\t\t\t\t * RCX, RDX, R8, R9. This optimization works for any Calling Convention, we are just using Windows x64 for\n\t\t\t\t * this example.\n\t\t\t\t *\n\t\t\t\t * Given the following member function: void TestMemberFunc(int a, int b)\n\t\t\t\t *  RCX == this\n\t\t\t\t *  RDX == a\n\t\t\t\t *  R8  == b\n\t\t\t\t *\n\t\t\t\t * All three arguments to the function including the hidden this pointer, which in C++ is always the first argument\n\t\t\t\t * are passed into the first three registers.\n\t\t\t\t * The function call chain for eastl::function<>() is as follows:\n\t\t\t\t *  operator ()(this, Args... args) -> Invoker(Args... args, this->mStorage) -> StoredFunction(Args... arg)\n\t\t\t\t *\n\t\t\t\t * Let's look at what is happening at the asm level with the different Invoker function signatures and why.\n\t\t\t\t *\n\t\t\t\t * You will notice that operator ()() and Invoker() have the arguments reversed. operator ()() just directly calls\n\t\t\t\t * to Invoker(), it is a tail call, so we force inline the call operator to ensure we directly call to the Invoker().\n\t\t\t\t * Most compilers always inline it anyways by default; have been instances where it doesn't even though the asm ends\n\t\t\t\t * up being cheaper.\n\t\t\t\t * call -> call -> call versus call -> call\n\t\t\t\t *\n\t\t\t\t * eastl::function<int(int, int)> = FunctionPointer\n\t\t\t\t *\n\t\t\t\t * Assume we have the above eastl::function object that holds a pointer to a function as the internal callable.\n\t\t\t\t *\n\t\t\t\t * Invoker(this->mStorage, Args... args) is called with the follow arguments in registers:\n\t\t\t\t *  RCX = this  |  RDX = a  |  R8 = b\n\t\t\t\t *\n\t\t\t\t * Inside Invoker() we use RCX to deference into the eastl::function object and get the function pointer to call.\n\t\t\t\t * This function to call has signature Func(int, int) and thus requires its arguments in registers RCX and RDX.\n\t\t\t\t * The compiler must shift all the arguments towards the left. The full asm looks something as follows.\n\t\t\t\t *\n\t\t\t\t * Calling Invoker:                       Inside Invoker:\n\t\t\t\t *\n\t\t\t\t * mov rcx, this                          mov rax, [rcx]\n\t\t\t\t * mov rdx, a                             mov rcx, rdx\n\t\t\t\t * mov r8, b                              mov rdx, r8\n\t\t\t\t * call [rcx + offset to Invoker]         jmp [rax]\n\t\t\t\t *\n\t\t\t\t * Notice how the compiler shifts all the arguments before calling the callable and also we only use the this pointer\n\t\t\t\t * to access the internal storage inside the eastl::function object.\n\t\t\t\t *\n\t\t\t\t * Invoker(Args... args, this->mStorage) is called with the following arguments in registers:\n\t\t\t\t *  RCX = a  |  RDX = b  |  R8 = this\n\t\t\t\t *\n\t\t\t\t * You can see we no longer have to shift the arguments down when going to call the internal stored callable.\n\t\t\t\t *\n\t\t\t\t * Calling Invoker:                      Inside Invoker:\n\t\t\t\t *\n\t\t\t\t * mov rcx, a                            mov rax, [r8]\n\t\t\t\t * mov rdx, b                            jmp [rax]\n\t\t\t\t * mov r8, this\n\t\t\t\t * call [r8 + offset to Invoker]\n\t\t\t\t *\n\t\t\t\t * The generated asm does a straight tail jmp to the loaded function pointer. The arguments are already in the correct\n\t\t\t\t * registers.\n\t\t\t\t *\n\t\t\t\t * For Functors or Lambdas with no captures, this gives us another free register to use to pass arguments since the this\n\t\t\t\t * is at the end, it can be passed onto the stack if we run out of registers. Since the callable has no captures; inside\n\t\t\t\t * the Invoker(), we won't ever need to touch this thus we can just call the operator ()() or let the compiler inline it.\n\t\t\t\t *\n\t\t\t\t * For a callable with captures there is no perf hit since the callable in the common case is inlined and the pointer to the callable\n\t\t\t\t * buffer is passed in a register which the compiler can use to access the captures.\n\t\t\t\t *\n\t\t\t\t * For eastl::function<void(const T&, int, int)> that a holds a pointer to member function. The this pointers is implicitly\n\t\t\t\t * the first argument in the argument list, const T&, and the member function pointer will be called on that object.\n\t\t\t\t * This prevents any argument shifting since the this for the member function pointer is already in RCX.\n\t\t\t\t *\n\t\t\t\t * This is why having this at the end of the argument list is important for generating efficient Invoker() thunks.\n\t\t\t\t */\n\t\t\t\tstatic R Invoker(Args... args, void* storage)\n\t\t\t\t{\n\t\t\t\t\treturn eastl::invoke(*Base::GetFunctorPtr(storage), eastl::forward<Args>(args)...);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfunction_base_detail() EA_NOEXCEPT = default;\n\t\t\t~function_base_detail() EA_NOEXCEPT = default;\n\t\t};\n\n\t\t#define EASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(FUNCTOR, RET, ARGS, BASE, MYSELF)  \\\n\t\t\ttypename eastl::enable_if_t<eastl::is_invocable_r_v<RET, FUNCTOR, ARGS> &&         \\\n\t\t\t\t\t\t\t\t\t\t!eastl::is_base_of_v<BASE, eastl::decay_t<FUNCTOR>> && \\\n\t\t\t\t\t\t\t\t\t\t!eastl::is_same_v<eastl::decay_t<FUNCTOR>, MYSELF>>\n\n\t\t#define EASTL_INTERNAL_FUNCTION_DETAIL_VALID_FUNCTION_ARGS(FUNCTOR, RET, ARGS, MYSELF) \\\n\t\t\tEASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(FUNCTOR, RET, ARGS, MYSELF, MYSELF)\n\n\n\t\t/// function_detail\n\t\t///\n\t\ttemplate <int, typename>\n\t\tclass function_detail;\n\t\t\n\t\ttemplate <int SIZE_IN_BYTES, typename R, typename... Args>\n\t\tclass function_detail<SIZE_IN_BYTES, R(Args...)> : public function_base_detail<SIZE_IN_BYTES>\n\t\t{\n\n\t\ttemplate <int OTHER_SIZE_IN_BYTES, typename T>\n\t\tfriend class function_detail;\n\n\t\tpublic:\n\t\t\tusing result_type = R;\n\n\t\tprotected:\n\t\t\tusing Base = function_base_detail<SIZE_IN_BYTES>;\n\t\t\tusing FunctorStorageType = typename function_base_detail<SIZE_IN_BYTES>::FunctorStorageType;\n\t\t\tusing Base::mStorage;\n\n\t\tpublic:\n\t\t\tfunction_detail() EA_NOEXCEPT = default;\n\t\t\tfunction_detail(std::nullptr_t) EA_NOEXCEPT {}\n\n\t\t\tfunction_detail(const function_detail& other)\n\t\t\t{\n\t\t\t\tif (this != &other)\n\t\t\t\t{\n\t\t\t\t\tCopy(other);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction_detail(function_detail&& other)\n\t\t\t{\n\t\t\t\tif (this != &other)\n\t\t\t\t{\n\t\t\t\t\tMove(eastl::move(other));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttemplate<int OTHER_SIZE_IN_BYTES>\n\t\t\tfunction_detail(function_detail <OTHER_SIZE_IN_BYTES, R(Args...)> && other)\n\t\t\t{\n\t\t\t\tstatic_assert(OTHER_SIZE_IN_BYTES < SIZE_IN_BYTES, \"Other sized function_detail must be smaller\");\n\t\t\t\tMove(eastl::move(other));\n\t\t\t}\n\n\t\t\ttemplate <int OTHER_SIZE_IN_BYTES>\n\t\t\tfunction_detail(const function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>& other)\n\t\t\t{\n\t\t\t\tstatic_assert(OTHER_SIZE_IN_BYTES < SIZE_IN_BYTES, \"Other sized function_detail must be smaller\");\n\t\t\t\tCopy(other);\n\t\t\t}\n\n\t\t\ttemplate <typename Functor, typename = EASTL_INTERNAL_FUNCTION_DETAIL_VALID_FUNCTION_ARGS(Functor, R, Args..., function_detail)>\n\t\t\tfunction_detail(Functor&& functor)\n\t\t\t{\n\t\t\t\tCreateForwardFunctor(eastl::forward<Functor>(functor));\n\t\t\t}\n\n\t\t\t~function_detail() EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tDestroy();\n\t\t\t}\n\n\t\t\tfunction_detail& operator=(const function_detail& other)\n\t\t\t{\n\t\t\t\tif (this != &other)\n\t\t\t\t{\n\t\t\t\t\tDestroy();\n\t\t\t\t\tCopy(other);\n\t\t\t\t}\n\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\tfunction_detail& operator=(function_detail&& other)\n\t\t\t{\n\t\t\t\tif(this != &other)\n\t\t\t\t{\n\t\t\t\t\tDestroy();\n\t\t\t\t\tMove(eastl::move(other));\n\t\t\t\t}\n\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\ttemplate <int OTHER_SIZE_IN_BYTES>\n\t\t\tfunction_detail& operator=(const function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>& other)\n\t\t\t{\n\t\t\t\tstatic_assert(OTHER_SIZE_IN_BYTES < SIZE_IN_BYTES, \"Other sized function_detail must be smaller\");\n\t\t\t\tDestroy();\n\t\t\t\tCopy(other);\n\t\t\t\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\ttemplate <int OTHER_SIZE_IN_BYTES>\n\t\t\tfunction_detail& operator=(function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>&& other)\n\t\t\t{\n\t\t\t\tstatic_assert(OTHER_SIZE_IN_BYTES < SIZE_IN_BYTES, \"Other sized function_detail must be smaller\");\n\t\t\t\tDestroy();\n\t\t\t\tMove(eastl::move(other));\n\t\t\t\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\tfunction_detail& operator=(std::nullptr_t) EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tDestroy();\n\t\t\t\tmMgrFuncPtr = nullptr;\n\t\t\t\tmInvokeFuncPtr = &DefaultInvoker;\n\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename Functor, typename = EASTL_INTERNAL_FUNCTION_DETAIL_VALID_FUNCTION_ARGS(Functor, R, Args..., function_detail)>\n\t\t\tfunction_detail& operator=(Functor&& functor)\n\t\t\t{\n\t\t\t\tDestroy();\n\t\t\t\tCreateForwardFunctor(eastl::forward<Functor>(functor));\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t\t\n\t\t\ttemplate <typename Functor>\n\t\t\tfunction_detail& operator=(eastl::reference_wrapper<Functor> f) EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tDestroy();\n\t\t\t\tCreateForwardFunctor(f);\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\tvoid swap(function_detail& other) EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tif(this == &other)\n\t\t\t\t\treturn;\n\n\t\t\t\tFunctorStorageType tempStorage;\n\t\t\t\tif (other.HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*other.mMgrFuncPtr)(tempStorage.storage, other.mStorage.storage,\n\t\t\t\t\t\t\t\t\t\t\t   ManagerOperations::MGROPS_MOVE_FUNCTOR);\n\t\t\t\t}\n\n\t\t\t\tif (HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*mMgrFuncPtr)(other.mStorage.storage, mStorage.storage,\n\t\t\t\t\t\t\t\t\t\t ManagerOperations::MGROPS_MOVE_FUNCTOR);\n\t\t\t\t}\n\n\t\t\t\tif (other.HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*other.mMgrFuncPtr)(mStorage.storage, tempStorage.storage,\n\t\t\t\t\t\t\t\t\t\t\t   ManagerOperations::MGROPS_MOVE_FUNCTOR);\n\t\t\t\t}\n\n\t\t\t\teastl::swap(mMgrFuncPtr, other.mMgrFuncPtr);\n\t\t\t\teastl::swap(mInvokeFuncPtr, other.mInvokeFuncPtr);\n\t\t\t}\n\n\t\t\texplicit operator bool() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn HaveManager();\n\t\t\t}\n\n\t\t\tEASTL_FORCE_INLINE R operator ()(Args... args) const\n\t\t\t{\n\t\t\t\treturn (*mInvokeFuncPtr)(eastl::forward<Args>(args)..., const_cast<char*>(this->mStorage.storage));\n\t\t\t}\n\n\t\t\t#if EASTL_RTTI_ENABLED\n\t\t\t\tconst std::type_info& target_type() const EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\tif (HaveManager())\n\t\t\t\t\t{\n\t\t\t\t\t\tvoid* ret = (*mMgrFuncPtr)(nullptr, nullptr, ManagerOperations::MGROPS_GET_TYPE_INFO);\n\t\t\t\t\t\treturn *(static_cast<const std::type_info*>(ret));\n\t\t\t\t\t}\n\t\t\t\t\treturn typeid(void);\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename Functor>\n\t\t\t\tFunctor* target() EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\tif (HaveManager() && target_type() == typeid(Functor))\n\t\t\t\t\t{\n\t\t\t\t\t\tvoid* ret = (*mMgrFuncPtr)(mStorage.storage, nullptr, ManagerOperations::MGROPS_GET_FUNC_PTR);\n\t\t\t\t\t\treturn ret ? static_cast<Functor*>(ret) : nullptr;\n\t\t\t\t\t}\n\t\t\t\t\treturn nullptr;\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename Functor>\n\t\t\t\tconst Functor* target() const EA_NOEXCEPT\n\t\t\t\t{\n\t\t\t\t\tif (HaveManager() && target_type() == typeid(Functor))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Note: the const_cast on &mStorage is \"safe\" here because we're doing a\n\t\t\t\t\t\t// MGROPS_GET_FUNC_PTR operation. We can't change the entire signature\n\t\t\t\t\t\t// of mMgrFuncPtr because we use it to modify the storage with other\n\t\t\t\t\t\t// operations.\n\t\t\t\t\t\tconst void* ret = (*mMgrFuncPtr)(const_cast<char*>(mStorage.storage), nullptr, ManagerOperations::MGROPS_GET_FUNC_PTR);\n\t\t\t\t\t\treturn ret ? static_cast<const Functor*>(ret) : nullptr;\n\t\t\t\t\t}\n\t\t\t\t\treturn nullptr;\n\t\t\t\t}\n\t\t\t#endif // EASTL_RTTI_ENABLED\n\n\t\tprivate:\n\t\t\tbool HaveManager() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn (mMgrFuncPtr != nullptr);\n\t\t\t}\n\n\t\t\tvoid Destroy() EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tif (HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*mMgrFuncPtr)(mStorage.storage, nullptr,\n\t\t\t\t\t                     ManagerOperations::MGROPS_DESTRUCT_FUNCTOR);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvoid Copy(const function_detail& other)\n\t\t\t{\n\t\t\t\tif (other.HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*other.mMgrFuncPtr)(mStorage.storage, const_cast<char*>(other.mStorage.storage),\n\t\t\t\t\t                           ManagerOperations::MGROPS_COPY_FUNCTOR);\n\t\t\t\t}\n\n\t\t\t\tmMgrFuncPtr = other.mMgrFuncPtr;\n\t\t\t\tmInvokeFuncPtr = other.mInvokeFuncPtr;\n\t\t\t}\n\n\t\t\ttemplate <int OTHER_SIZE_IN_BYTES>\n\t\t\tvoid Copy(const function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>& other)\n\t\t\t{\n\t\t\t\tstatic_assert(OTHER_SIZE_IN_BYTES < SIZE_IN_BYTES, \"Other sized function_detail must be smaller\");\n\n\t\t\t\tif (other.HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*other.mMgrFuncPtr)(mStorage.storage, const_cast<char*>(other.mStorage.storage),\n\t\t\t\t\t                           ManagerOperations::MGROPS_COPY_FUNCTOR);\n\t\t\t\t}\n\n\t\t\t\tmMgrFuncPtr = other.mMgrFuncPtr;\n\t\t\t\tmInvokeFuncPtr = other.mInvokeFuncPtr;\n\t\t\t}\n\n\t\t\tvoid Move(function_detail&& other)\n\t\t\t{\n\t\t\t\tif (other.HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*other.mMgrFuncPtr)(mStorage.storage, other.mStorage.storage,\n\t\t\t\t\t                           ManagerOperations::MGROPS_MOVE_FUNCTOR);\n\t\t\t\t}\n\n\t\t\t\tmMgrFuncPtr = other.mMgrFuncPtr;\n\t\t\t\tmInvokeFuncPtr = other.mInvokeFuncPtr;\n\t\t\t\tother.mMgrFuncPtr = nullptr;\n\t\t\t\tother.mInvokeFuncPtr = &DefaultInvoker;\n\t\t\t}\n\n\t\t\ttemplate <int OTHER_SIZE_IN_BYTES>\n\t\t\tvoid Move(function_detail<OTHER_SIZE_IN_BYTES, R(Args...)>&& other)\n\t\t\t{\n\t\t\t\tstatic_assert(OTHER_SIZE_IN_BYTES < SIZE_IN_BYTES, \"Other sized function_detail must be smaller\");\n\n\t\t\t\tif (other.HaveManager())\n\t\t\t\t{\n\t\t\t\t\t(void)(*other.mMgrFuncPtr)(mStorage.storage, other.mStorage.storage,\n\t\t\t\t\t                           ManagerOperations::MGROPS_MOVE_FUNCTOR);\n\t\t\t\t}\n\n\t\t\t\tmMgrFuncPtr = other.mMgrFuncPtr;\n\t\t\t\tmInvokeFuncPtr = other.mInvokeFuncPtr;\n\n\t\t\t\tother.mMgrFuncPtr = nullptr;\n\t\t\t\tother.mInvokeFuncPtr =  &function_detail <OTHER_SIZE_IN_BYTES, R(Args...)>::DefaultInvoker;\n\t\t\t}\n\n\t\t\ttemplate <typename Functor>\n\t\t\tvoid CreateForwardFunctor(Functor&& functor)\n\t\t\t{\n\t\t\t\tusing DecayedFunctorType = typename eastl::decay<Functor>::type;\n\t\t\t\tusing FunctionManagerType = typename Base::template function_manager<DecayedFunctorType, R, Args...>;\n\n\t\t\t\tif (internal::is_null(functor))\n\t\t\t\t{\n\t\t\t\t\tmMgrFuncPtr = nullptr;\n\t\t\t\t\tmInvokeFuncPtr = &DefaultInvoker;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tmMgrFuncPtr = &FunctionManagerType::Manager;\n\t\t\t\t\tmInvokeFuncPtr = &FunctionManagerType::Invoker;\n\t\t\t\t\tFunctionManagerType::CreateFunctor(mStorage.storage, eastl::forward<Functor>(functor));\n\t\t\t\t}\n\t\t\t}\n\n\t\tprivate:\n\t\t\ttypedef void* (*ManagerFuncPtr)(void*, void*, typename internal::ManagerOperations);\n\t\t\ttypedef R (*InvokeFuncPtr)(Args..., void*);\n\n\t\t\tEA_DISABLE_GCC_WARNING(-Wreturn-type);\n\t\t\tEA_DISABLE_CLANG_WARNING(-Wreturn-type);\n\t\t\tEA_DISABLE_VC_WARNING(4716); // 'function' must return a value\n\t\t\tEA_DISABLE_VC_WARNING(4702); // unreachable code\n\t\t\t// We cannot assume that R is default constructible.\n\t\t\t// This function is called only when the function object CANNOT be called because it is empty,\n\t\t\t// it will always throw or assert so we never use the return value anyways and neither should the caller.\n\t\t\tstatic R DefaultInvoker(Args... /*args*/, void* /*storage*/)\n\t\t\t{\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tthrow eastl::bad_function_call();\n\t\t\t\t#else\n\t\t\t\t\tEASTL_ASSERT_MSG(false, \"function_detail call on an empty function_detail<R(Args..)>\");\n\t\t\t\t#endif\n\t\t\t\t// We want to explicitly crash here, since calling this function is equivalent\n\t\t\t\t// to dereferencing a nullptr, we don't want to silently continue execution and\n\t\t\t\t// have this function (which has no return value) potentially return arbitrary\n\t\t\t\t// garbage to the caller.\n\t\t\t\t*((volatile int*)0) = 0xDEADC0DE;\n\n\t\t\t};\n\t\t\tEA_RESTORE_VC_WARNING();\n\t\t\tEA_RESTORE_VC_WARNING();\n\t\t\tEA_RESTORE_CLANG_WARNING();\n\t\t\tEA_RESTORE_GCC_WARNING();\n\n\n\t\t\tManagerFuncPtr mMgrFuncPtr = nullptr;\n\t\t\tInvokeFuncPtr mInvokeFuncPtr = &DefaultInvoker;\n\t\t};\n\n\t\ttemplate <class Callable>\n\t\tstruct extract_signature_from_callable;\n\n\t\t#define EASTL_EXTRACT_SIGNATURE_PATTERN(QUALIFIERS) \\\n\t\t\ttemplate <typename ReturnType, typename MemberOfType, typename... Args> \\\n\t\t\tstruct extract_signature_from_callable<ReturnType (MemberOfType::*)(Args...) QUALIFIERS> \\\n\t\t\t{ \\\n\t\t\t\tusing type = ReturnType(Args...); \\\n\t\t\t};\n\n\t\tEASTL_GENERATE_MEMBER_FUNCTION_VARIANTS(EASTL_EXTRACT_SIGNATURE_PATTERN)\n\n\t\t// Helper\n\t\ttemplate <typename Callable>\n\t\tusing extract_signature_from_callable_t = typename extract_signature_from_callable<Callable>::type;\n\n\t} // namespace internal\n\t\t\n} // namespace eastl\n\n#endif // EASTL_FUNCTION_DETAIL_H\n"
  },
  {
    "path": "include/EASTL/internal/function_help.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_INTERNAL_FUNCTION_HELP_H\n#define EASTL_INTERNAL_FUNCTION_HELP_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n\nnamespace eastl\n{\n\tnamespace internal\n\t{\n\n\t\t//////////////////////////////////////////////////////////////////////\n\t\t// is_null\n\t\t//\n\t\ttemplate <typename T>\n\t\tbool is_null(const T&)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\ttemplate <typename Result, typename... Arguments>\n\t\tbool is_null(Result (*const& function_pointer)(Arguments...))\n\t\t{\n\t\t\treturn function_pointer == nullptr;\n\t\t}\n\n\t\ttemplate <typename Result, typename Class, typename... Arguments>\n\t\tbool is_null(Result (Class::*const& function_pointer)(Arguments...))\n\t\t{\n\t\t\treturn function_pointer == nullptr;\n\t\t}\n\n\t\ttemplate <typename Result, typename Class, typename... Arguments>\n\t\tbool is_null(Result (Class::*const& function_pointer)(Arguments...) const)\n\t\t{\n\t\t\treturn function_pointer == nullptr;\n\t\t}\n\n\t} // namespace internal\n} // namespace eastl\n\n#endif // Header include guard\n\n"
  },
  {
    "path": "include/EASTL/internal/functional_base.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_FUNCTIONAL_BASE_H\n#define EASTL_INTERNAL_FUNCTIONAL_BASE_H\n\n#include <EASTL/internal/config.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/memory_base.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/type_traits.h>\n\n\nnamespace eastl\n{\n\t// foward declaration for swap\n\ttemplate <typename T>\n\tinline void swap(T& a, T& b)\n\t    EA_NOEXCEPT_IF(eastl::is_nothrow_move_constructible<T>::value && eastl::is_nothrow_move_assignable<T>::value);\n\n\n\t/// invoke\n\t///\n\t/// invoke is a generalized function-call operator which works on function pointers, member function\n\t/// pointers, callable objects and member pointers.\n\t///\n\t/// For (member/non-member) function pointers and callable objects, it returns the result of calling\n\t/// the function/object with the specified arguments. For member data pointers, it simply returns\n\t/// the member.\n\t///\n\t/// Note that there are also reference_wrapper specializations of invoke, which need to be defined\n\t/// later since reference_wrapper uses invoke in its implementation. Those are defined immediately\n\t/// after the definition of reference_wrapper.\n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/functional/invoke\n\t///\n\ttemplate <typename R, typename C, typename T, typename... Args>\n\tEA_CONSTEXPR auto invoke_impl(R C::*func, T&& obj, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((eastl::forward<T>(obj).*func)(eastl::forward<Args>(args)...)))\n\t\t-> typename enable_if<is_base_of<C, decay_t<T>>::value,\n\t                       decltype((eastl::forward<T>(obj).*func)(eastl::forward<Args>(args)...))>::type\n\t{\n\t\treturn (eastl::forward<T>(obj).*func)(eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <typename F, typename... Args>\n\tEA_CONSTEXPR auto invoke_impl(F&& func, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(eastl::forward<F>(func)(eastl::forward<Args>(args)...)))\n\t\t-> decltype(eastl::forward<F>(func)(eastl::forward<Args>(args)...))\n\t{\n\t\treturn eastl::forward<F>(func)(eastl::forward<Args>(args)...);\n\t}\n\n\n\ttemplate <typename R, typename C, typename T, typename... Args>\n\tEA_CONSTEXPR auto invoke_impl(R C::*func, T&& obj, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(((*eastl::forward<T>(obj)).*func)(eastl::forward<Args>(args)...)))\n\t\t-> decltype(((*eastl::forward<T>(obj)).*func)(eastl::forward<Args>(args)...))\n\t{\n\t\treturn ((*eastl::forward<T>(obj)).*func)(eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <typename M, typename C, typename T>\n\tEA_CONSTEXPR auto invoke_impl(M C::*member, T&& obj) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(eastl::forward<T>(obj).*member))\n\t\t-> typename enable_if<\n\t\t\tis_base_of<C, decay_t<T>>::value,\n\t\t\tdecltype(eastl::forward<T>(obj).*member)\n\t>::type\n\t{\n\t\treturn eastl::forward<T>(obj).*member;\n\t}\n\n\ttemplate <typename M, typename C, typename T>\n\tEA_CONSTEXPR auto invoke_impl(M C::*member, T&& obj) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((*eastl::forward<T>(obj)).*member))\n\t\t-> decltype((*eastl::forward<T>(obj)).*member)\n\t{\n\t\treturn (*eastl::forward<T>(obj)).*member;\n\t}\n\n\ttemplate <typename F, typename... Args>\n\tEA_CONSTEXPR decltype(auto) invoke(F&& func, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(invoke_impl(eastl::forward<F>(func), eastl::forward<Args>(args)...)))\n\t{\n\t\treturn invoke_impl(eastl::forward<F>(func), eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <typename F, typename = void, typename... Args>\n\tstruct invoke_result_impl {\n\t};\n\n\ttemplate <typename F, typename... Args>\n\tstruct invoke_result_impl<F, void_t<decltype(invoke_impl(eastl::declval<F>(), eastl::declval<Args>()...))>, Args...>\n\t{\n\t\ttypedef decltype(invoke_impl(eastl::declval<F>(), eastl::declval<Args>()...)) type;\n\t};\n\n\ttemplate <typename F, typename... Args>\n\tstruct invoke_result : public invoke_result_impl<F, void, Args...> {};\n\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename F, typename... Args>\n\t\tusing invoke_result_t = typename invoke_result<F, Args...>::type;\n\t#endif\n\n\ttemplate <typename F, typename = void, typename... Args>\n\tstruct is_invocable_impl : public eastl::false_type {};\n\n\ttemplate <typename F, typename... Args>\n\tstruct is_invocable_impl<F, void_t<typename eastl::invoke_result<F, Args...>::type>, Args...> : public eastl::true_type {};\n\n\ttemplate <typename F, typename... Args>\n\tstruct is_invocable : public is_invocable_impl<F, void, Args...> {};\n\n\ttemplate <typename R, typename F, typename = void, typename... Args>\n\tstruct is_invocable_r_impl : public eastl::false_type {};\n\n\ttemplate <typename R, typename F, typename... Args>\n\tstruct is_invocable_r_impl<R, F, void_t<typename invoke_result<F, Args...>::type>, Args...>\n\t\t: public disjunction<is_convertible<typename invoke_result<F, Args...>::type, R>,\n\t\t\t\t\t\t\t is_same<typename remove_cv<R>::type, void>> {};\n\n\ttemplate <typename R, typename F, typename... Args>\n\tstruct is_invocable_r : public is_invocable_r_impl<R, F, void, Args...> {};\n\n\ttemplate <typename F, typename... Args>\n\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_invocable_v = is_invocable<F, Args...>::value;\n\n\ttemplate <typename R, typename F, typename... Args>\n\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_invocable_r_v = is_invocable_r<R, F, Args...>::value;\n\n\ttemplate <typename F, typename = void, typename... Args>\n\tstruct is_nothrow_invocable_impl : public eastl::false_type\t{};\n\n\ttemplate <typename F, typename... Args>\n\tstruct is_nothrow_invocable_impl<F, void_t<typename eastl::invoke_result<F, Args...>::type>, Args...>\n\t    : public eastl::bool_constant<EA_NOEXCEPT_EXPR(eastl::invoke(eastl::declval<F>(), eastl::declval<Args>()...))>\t{};\n\n\ttemplate <typename F, typename... Args>\n\tstruct is_nothrow_invocable : public is_nothrow_invocable_impl<F, void, Args...> {};\n\n\ttemplate <typename R, typename F, typename = void, typename... Args>\n\tstruct is_nothrow_invocable_r_impl : public eastl::false_type {};\n\n\ttemplate <typename R, typename F, typename... Args>\n\tstruct is_nothrow_invocable_r_impl<R, F, void_t<typename eastl::invoke_result<F, Args...>::type>, Args...>\n\t{\n\t\tstatic EA_CONSTEXPR_OR_CONST bool value = eastl::is_convertible<typename eastl::invoke_result<F, Args...>::type, R>::value\n\t\t\t\t\t\t\t\t\t\t&& eastl::is_nothrow_invocable<F, Args...>::value;\n\t};\n\n\ttemplate <typename R, typename F, typename... Args>\n\tstruct is_nothrow_invocable_r : public is_nothrow_invocable_r_impl<R, F, void, Args...> {};\n\n\ttemplate <typename F, typename... Args>\n\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_no_throw_invocable_v = is_nothrow_invocable<F, Args...>::value;\n\n\ttemplate <typename R, typename F, typename... Args>\n\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, F, Args...>::value;\n\n\t/// allocator_arg_t\n\t///\n\t/// allocator_arg_t is an empty class type used to disambiguate the overloads of\n\t/// constructors and member functions of allocator-aware objects, including tuple,\n\t/// function, promise, and packaged_task.\n\t/// http://en.cppreference.com/w/cpp/memory/allocator_arg_t\n\t///\n\tstruct allocator_arg_t\n\t{};\n\n\n\t/// allocator_arg\n\t///\n\t/// allocator_arg is a constant of type allocator_arg_t used to disambiguate, at call site,\n\t/// the overloads of the constructors and member functions of allocator-aware objects,\n\t/// such as tuple, function, promise, and packaged_task.\n\t/// http://en.cppreference.com/w/cpp/memory/allocator_arg\n\t///\n\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR allocator_arg_t allocator_arg = allocator_arg_t();\n\n\n\t/// less<T>\n\ttemplate <typename T = void>\n\tstruct less\n\t{\n\t\tEA_CPP14_CONSTEXPR bool operator()(const T& a, const T& b) const\n\t\t\t{ return a < b; }\n\t};\n\n\t// http://en.cppreference.com/w/cpp/utility/functional/less_void\n\ttemplate <>\n\tstruct less<void>\n\t{\n\t\ttypedef int is_transparent;\n\t\ttemplate<typename A, typename B>\n\t\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t\t\t-> decltype(eastl::forward<A>(a) < eastl::forward<B>(b))\n\t\t\t{ return eastl::forward<A>(a) < eastl::forward<B>(b); }\n\t};\n\n\n\t/// reference_wrapper\n\ttemplate <typename T>\n\tclass reference_wrapper\n\t{\n\tpublic:\n\t\ttypedef T type;\n\n\t\treference_wrapper(T&) EA_NOEXCEPT;\n\t\treference_wrapper(T&&) = delete;\n\t\treference_wrapper(const reference_wrapper<T>& x) EA_NOEXCEPT;\n\n\t\treference_wrapper& operator=(const reference_wrapper<T>& x) EA_NOEXCEPT;\n\n\t\toperator T& () const EA_NOEXCEPT;\n\t\tT& get() const EA_NOEXCEPT;\n\n\t\ttemplate <typename... ArgTypes>\n\t\ttypename eastl::invoke_result<T&, ArgTypes...>::type operator() (ArgTypes&&...) const;\n\n\tprivate:\n\t\tT* val;\n\t};\n\n\ttemplate <typename T>\n\treference_wrapper<T>::reference_wrapper(T &v) EA_NOEXCEPT\n\t\t: val(eastl::addressof(v))\n\t{}\n\n\ttemplate <typename T>\n\treference_wrapper<T>::reference_wrapper(const reference_wrapper<T>& other) EA_NOEXCEPT\n\t\t: val(other.val)\n\t{}\n\n\ttemplate <typename T>\n\treference_wrapper<T>& reference_wrapper<T>::operator=(const reference_wrapper<T>& other) EA_NOEXCEPT\n\t{\n\t\tval = other.val;\n\t\treturn *this;\n\t}\n\n\ttemplate <typename T>\n\treference_wrapper<T>::operator T&() const EA_NOEXCEPT\n\t{\n\t\treturn *val;\n\t}\n\n\ttemplate <typename T>\n\tT& reference_wrapper<T>::get() const EA_NOEXCEPT\n\t{\n\t\treturn *val;\n\t}\n\n\ttemplate <typename T>\n\ttemplate <typename... ArgTypes>\n\ttypename eastl::invoke_result<T&, ArgTypes...>::type reference_wrapper<T>::operator() (ArgTypes&&... args) const\n\t{\n\t\treturn eastl::invoke(*val, eastl::forward<ArgTypes>(args)...);\n\t}\n\n\t// reference_wrapper-specific utilties\n\ttemplate <typename T>\n\treference_wrapper<T> ref(T& t) EA_NOEXCEPT\n\t{\n\t\treturn eastl::reference_wrapper<T>(t);\n\t}\n\n\ttemplate <typename T>\n\tvoid ref(const T&&) = delete;\n\n\ttemplate <typename T>\n\treference_wrapper<T> ref(reference_wrapper<T>t) EA_NOEXCEPT\n\t{\n\t\treturn eastl::ref(t.get());\n\t}\n\n\ttemplate <typename T>\n\treference_wrapper<const T> cref(const T& t) EA_NOEXCEPT\n\t{\n\t\treturn eastl::reference_wrapper<const T>(t);\n\t}\n\n\ttemplate <typename T>\n\tvoid cref(const T&&) = delete;\n\n\ttemplate <typename T>\n\treference_wrapper<const T> cref(reference_wrapper<T> t) EA_NOEXCEPT\n\t{\n\t\treturn eastl::cref(t.get());\n\t}\n\n\n\t// reference_wrapper-specific type traits\n\ttemplate <typename T>\n\tstruct is_reference_wrapper_helper\n\t\t: public eastl::false_type {};\n\n\ttemplate <typename T>\n\tstruct is_reference_wrapper_helper<eastl::reference_wrapper<T> >\n\t\t: public eastl::true_type {};\n\n\ttemplate <typename T>\n\tstruct is_reference_wrapper\n\t\t: public eastl::is_reference_wrapper_helper<typename eastl::remove_cv<T>::type> {};\n\n\n\t// Helper which adds a reference to a type when given a reference_wrapper of that type.\n\ttemplate <typename T>\n\tstruct remove_reference_wrapper\n\t\t{ typedef T type; };\n\n\ttemplate <typename T>\n\tstruct remove_reference_wrapper< eastl::reference_wrapper<T> >\n\t\t{ typedef T& type; };\n\n\ttemplate <typename T>\n\tstruct remove_reference_wrapper< const eastl::reference_wrapper<T> >\n\t\t{ typedef T& type; };\n\n\t// reference_wrapper specializations of invoke\n\t// These have to come after reference_wrapper is defined, but reference_wrapper needs to have a\n\t// definition of invoke, so these specializations need to come after everything else has been defined.\n\ttemplate <typename R, typename C, typename T, typename... Args>\n\tEA_CONSTEXPR auto invoke_impl(R C::*func, T&& obj, Args&&... args) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR((obj.get().*func)(eastl::forward<Args>(args)...)))\n\t   -> typename enable_if<is_reference_wrapper<eastl::decay_t<T>>::value,\n\t\t\t\t\t\t   decltype((obj.get().*func)(eastl::forward<Args>(args)...))>::type\n\t{\n\t\treturn (obj.get().*func)(eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <typename M, typename C, typename T>\n\tEA_CONSTEXPR auto invoke_impl(M C::*member, T&& obj) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(obj.get().*member))\n\t   ->  typename enable_if<is_reference_wrapper<eastl::decay_t<T>>::value,\n\t                       decltype(obj.get().*member)>::type\n\t{\n\t\treturn obj.get().*member;\n\t}\n\n} // namespace eastl\n\n#endif // EASTL_INTERNAL_FUNCTIONAL_BASE_H\n"
  },
  {
    "path": "include/EASTL/internal/generic_iterator.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Implements a generic iterator from a given iteratable type, such as a pointer.\n// We cannot put this file into our own iterator.h file because we need to \n// still be able to use this file when we have our iterator.h disabled.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_GENERIC_ITERATOR_H\n#define EASTL_INTERNAL_GENERIC_ITERATOR_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <EASTL/type_traits.h>\n\n// There is no warning number 'number'.\n// Member template functions cannot be used for copy-assignment or copy-construction.\nEA_DISABLE_VC_WARNING(4619 4217);\n\n\nnamespace eastl\n{\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // 'generic_iterator': was declared deprecated\n\n\t/// generic_iterator\n\t///\n\t/// Converts something which can be iterated into a formal iterator.\n\t/// While this class' primary purpose is to allow the conversion of \n\t/// a pointer to an iterator, you can convert anything else to an \n\t/// iterator by defining an iterator_traits<> specialization for that\n\t/// object type. See EASTL iterator.h for this.\n\t///\n\t/// Example usage:\n\t///     typedef generic_iterator<int*>       IntArrayIterator;\n\t///     typedef generic_iterator<int*, char> IntArrayIteratorOther;\n\t///\n\ttemplate <typename Iterator, typename Container = void>\n\tclass EASTL_REMOVE_AT_2024_SEPT generic_iterator\n\t{\n\tprotected:\n\t\tIterator mIterator;\n\n\tpublic:\n\t\ttypedef typename eastl::iterator_traits<Iterator>::iterator_category iterator_category;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::value_type        value_type;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::difference_type   difference_type;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::reference         reference;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::pointer           pointer;\n\t\ttypedef Iterator                                                     iterator_type;\n\t\ttypedef Container                                                    container_type;\n\t\ttypedef generic_iterator<Iterator, Container>                        this_type;\n\n\t\tgeneric_iterator()\n\t\t\t: mIterator(iterator_type()) { }\n\n\t\texplicit generic_iterator(const iterator_type& x)\n\t\t\t: mIterator(x) { }\n\n\t\tthis_type& operator=(const iterator_type& x)\n\t\t\t{ mIterator = x; return *this; }\n\n\t\ttemplate <typename Iterator2>\n\t\tgeneric_iterator(const generic_iterator<Iterator2, Container>& x)\n\t\t\t: mIterator(x.base()) { }\n\n\t\treference operator*() const\n\t\t\t{ return *mIterator; }\n\n\t\tpointer operator->() const\n\t\t\t{ return mIterator; }\n\n\t\tthis_type& operator++()\n\t\t\t{ ++mIterator; return *this; }\n\n\t\tthis_type operator++(int)\n\t\t\t{ return this_type(mIterator++); }\n\n\t\tthis_type& operator--()\n\t\t\t{ --mIterator; return *this; }\n\n\t\tthis_type operator--(int)\n\t\t\t{ return this_type(mIterator--); }\n\n\t\treference operator[](const difference_type& n) const\n\t\t\t{ return mIterator[n]; }\n\n\t\tthis_type& operator+=(const difference_type& n)\n\t\t\t{ mIterator += n; return *this; }\n\n\t\tthis_type operator+(const difference_type& n) const\n\t\t\t{ return this_type(mIterator + n); }\n\n\t\tthis_type& operator-=(const difference_type& n)\n\t\t\t{ mIterator -= n; return *this; }\n\n\t\tthis_type operator-(const difference_type& n) const\n\t\t\t{ return this_type(mIterator - n); }\n\n\t\tconst iterator_type& base() const\n\t\t\t{ return mIterator; }\n\n\tprivate:\n\t\t// Unwrapping interface, not part of the public API.\n\t\tconst iterator_type& unwrap() const\n\t\t\t{ return mIterator; }\n\n\t\t// The unwrapper helpers need access to unwrap().\n\t\tfriend is_iterator_wrapper_helper<this_type, true>;\n\t\tfriend is_iterator_wrapper<this_type>;\n\n\t}; // class generic_iterator\n\n\n\ttemplate <typename IteratorL, typename IteratorR, typename Container>\n\tinline bool operator==(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)\n\t\t{ return lhs.base() == rhs.base(); }\n\n\ttemplate <typename Iterator, typename Container>\n\tinline bool operator==(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)\n\t\t{ return lhs.base() == rhs.base(); }\n\n\ttemplate <typename IteratorL, typename IteratorR, typename Container>\n\tinline bool operator!=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)\n\t\t{ return lhs.base() != rhs.base(); }\n\n\ttemplate <typename Iterator, typename Container>\n\tinline bool operator!=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)\n\t\t{ return lhs.base() != rhs.base(); }\n\n\ttemplate <typename IteratorL, typename IteratorR, typename Container>\n\tinline bool operator<(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)\n\t\t{ return lhs.base() < rhs.base(); }\n\n\ttemplate <typename Iterator, typename Container>\n\tinline bool operator<(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)\n\t\t{ return lhs.base() < rhs.base(); }\n\n\ttemplate <typename IteratorL, typename IteratorR, typename Container>\n\tinline bool operator>(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)\n\t\t{ return lhs.base() > rhs.base(); }\n\n\ttemplate <typename Iterator, typename Container>\n\tinline bool operator>(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)\n\t\t{ return lhs.base() > rhs.base(); }\n\n\ttemplate <typename IteratorL, typename IteratorR, typename Container>\n\tinline bool operator<=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)\n\t\t{ return lhs.base() <= rhs.base(); }\n\n\ttemplate <typename Iterator, typename Container>\n\tinline bool operator<=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)\n\t\t{ return lhs.base() <= rhs.base(); }\n\n\ttemplate <typename IteratorL, typename IteratorR, typename Container>\n\tinline bool operator>=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)\n\t\t{ return lhs.base() >= rhs.base(); }\n\n\ttemplate <typename Iterator, typename Container>\n\tinline bool operator>=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)\n\t\t{ return lhs.base() >= rhs.base(); }\n\n\ttemplate <typename IteratorL, typename IteratorR, typename Container>\n\tinline typename generic_iterator<IteratorL, Container>::difference_type\n\toperator-(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)\n\t\t{ return lhs.base() - rhs.base(); }\n\n\ttemplate <typename Iterator, typename Container>\n\tinline generic_iterator<Iterator, Container>\n\toperator+(typename generic_iterator<Iterator, Container>::difference_type n, const generic_iterator<Iterator, Container>& x)\n\t\t{ return generic_iterator<Iterator, Container>(x.base() + n); }\n\n\n\n\t/// is_generic_iterator\n\t///\n\t/// Tells if an iterator is one of these generic_iterators. This is useful if you want to \n\t/// write code that uses miscellaneous iterators but wants to tell if they are generic_iterators.\n\t/// A primary reason to do so is that you can get at the pointer within the generic_iterator.\n\t///\n\ttemplate <typename Iterator>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_generic_iterator : public false_type { };\n\n\ttemplate <typename Iterator, typename Container>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_generic_iterator<generic_iterator<Iterator, Container> > : public true_type { };\n\n\n\t/// unwrap_generic_iterator\n\t///\n\t/// Returns `it.base()` if it's a generic_iterator, else returns `it` as-is.\n\t///\n\t/// Example usage:\n\t///      vector<int> intVector;\n\t///      eastl::generic_iterator<vector<int>::iterator> genericIterator(intVector.begin());\n\t///      vector<int>::iterator it = unwrap_generic_iterator(genericIterator);\n\t///\n\ttemplate <typename Iterator>\n\tEASTL_REMOVE_AT_2024_SEPT inline typename eastl::is_iterator_wrapper_helper<Iterator, eastl::is_generic_iterator<Iterator>::value>::iterator_type unwrap_generic_iterator(Iterator it)\n\t{\n\t\t// get_unwrapped(it) -> it.unwrap() which is equivalent to `it.base()` for generic_iterator and to `it` otherwise.\n\t\treturn eastl::is_iterator_wrapper_helper<Iterator, eastl::is_generic_iterator<Iterator>::value>::get_unwrapped(it);\n\t}\n\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/hashtable.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a hashtable, much like the C++11 unordered_set/unordered_map.\n// proposed classes.\n// The primary distinctions between this hashtable and C++11 unordered containers are:\n//    - hashtable is savvy to an environment that doesn't have exception handling,\n//      as is sometimes the case with console or embedded environments.\n//    - hashtable is slightly more space-efficient than a conventional std hashtable \n//      implementation on platforms with 64 bit size_t.  This is \n//      because std STL uses size_t (64 bits) in data structures whereby 32 bits \n//      of data would be fine.\n//    - hashtable can contain objects with alignment requirements. TR1 hash tables \n//      cannot do so without a bit of tedious non-portable effort.\n//    - hashtable supports debug memory naming natively.\n//    - hashtable provides a find function that lets you specify a type that is \n//      different from the hash table key type. This is particularly useful for \n//      the storing of string objects but finding them by char pointers.\n//    - hashtable provides a lower level insert function which lets the caller \n//      specify the hash code and optionally the node instance.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_HASHTABLE_H\n#define EASTL_INTERNAL_HASHTABLE_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/allocator.h>\n#include <EASTL/iterator.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/tuple.h>\n#include <EASTL/memory.h>\n#include <string.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\nEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <new>\n\t#include <stddef.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n// 4512/4626 - 'class' : assignment operator could not be generated.\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\nEA_DISABLE_VC_WARNING(4512 4626 4530 4571);\n\n\nnamespace eastl\n{\n\n\t/// EASTL_HASHTABLE_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_HASHTABLE_DEFAULT_NAME\n\t\t#define EASTL_HASHTABLE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" hashtable\" // Unless the user overrides something, this is \"EASTL hashtable\".\n\t#endif\n\n\n\t/// EASTL_HASHTABLE_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_HASHTABLE_DEFAULT_ALLOCATOR\n\t\t#define EASTL_HASHTABLE_DEFAULT_ALLOCATOR allocator_type(EASTL_HASHTABLE_DEFAULT_NAME)\n\t#endif\n\n\t\n\t/// kHashtableAllocFlagBuckets\n\t/// Flag to allocator which indicates that we are allocating buckets and not nodes.\n\tenum { kHashtableAllocFlagBuckets = 0x00400000 };\n\n\n\t/// gpEmptyBucketArray\n\t///\n\t/// A shared representation of an empty hash table. This is present so that\n\t/// a new empty hashtable allocates no memory. It has two entries, one for \n\t/// the first lone empty (NULL) bucket, and one for the non-NULL trailing sentinel.\n\t/// \n\textern EASTL_API void* gpEmptyBucketArray[2];\n\n\n\t/// EASTL_MACRO_SWAP\n\t///\n\t/// Use EASTL_MACRO_SWAP because GCC (at least v4.6-4.8) has a bug where it fails to compile eastl::swap(mpBucketArray, x.mpBucketArray).\n\t///\n\t#define EASTL_MACRO_SWAP(Type, a, b) \\\n\t\t{ Type temp = a; a = b; b = temp; }\n\n\n\t/// hash_node\n\t///\n\t/// A hash_node stores an element in a hash table, much like a \n\t/// linked list node stores an element in a linked list. \n\t/// A hash_node additionally can, via template parameter,\n\t/// store a hash code in the node to speed up hash calculations \n\t/// and comparisons in some cases.\n\t/// \n\ttemplate <typename Value, bool bCacheHashCode>\n\tstruct hash_node;\n\n\tEA_DISABLE_VC_WARNING(4625 4626) // \"copy constructor / assignment operator could not be generated because a base class copy constructor is inaccessible or deleted\"\n\t#ifdef EA_COMPILER_MSVC_2015\n\t\tEA_DISABLE_VC_WARNING(5026) // disable warning: \"move constructor was implicitly defined as deleted\"\n\t#endif\n\t\ttemplate <typename Value>\n\t\tstruct hash_node<Value, true>\n\t\t{\n\t\t\thash_node() = default;\n\t\t\thash_node(const hash_node&) = default;\n\t\t\thash_node(hash_node&&) = default;\n\n\t\t\tValue        mValue;\n\t\t\thash_node*   mpNext;\n\t\t\teastl_size_t mnHashCode;      // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\t} EASTL_MAY_ALIAS;\n\n\t\ttemplate <typename Value>\n\t\tstruct hash_node<Value, false>\n\t\t{\n\t\t\thash_node() = default;\n\t\t\thash_node(const hash_node&) = default;\n\t\t\thash_node(hash_node&&) = default;\n\n\t\t    Value      mValue;\n\t\t\thash_node* mpNext;\n\t\t} EASTL_MAY_ALIAS;\n\n\t#ifdef EA_COMPILER_MSVC_2015\n\t\tEA_RESTORE_VC_WARNING()\n\t#endif\n\tEA_RESTORE_VC_WARNING()\n\n\n\t// has_hashcode_member\n\t//\n\t// Custom type-trait that checks for the existence of a class data member 'mnHashCode'.  \n\t//\n\t// In order to explicitly instantiate the hashtable without error we need to SFINAE away the functions that will\n\t// fail to compile based on if the 'hash_node' contains a 'mnHashCode' member dictated by the hashtable template\n\t// parameters. The hashtable support this level of configuration to allow users to choose which between the space vs.\n\t// time optimization.\n\t//\n\tnamespace Internal\n\t{\n\t\ttemplate <class T>\n\t\tstruct has_hashcode_member \n\t\t{\n\t\tprivate:\n\t\t\ttemplate <class U> static eastl::no_type test(...);\n\t\t\ttemplate <class U> static eastl::yes_type test(decltype(U::mnHashCode)* = 0);\n\t\tpublic:\n\t\t\tstatic const bool value = sizeof(test<T>(0)) == sizeof(eastl::yes_type);\n\t\t};\n\t}\n\t\n\tstatic_assert(Internal::has_hashcode_member<hash_node<int, true>>::value, \"contains a mnHashCode member\");\n\tstatic_assert(!Internal::has_hashcode_member<hash_node<int, false>>::value, \"doesn't contain a mnHashCode member\");\n\n\t// convenience macros to increase the readability of the code paths that must SFINAE on if the 'hash_node'\n\t// contains the cached hashed value or not. \n\t#define ENABLE_IF_HAS_HASHCODE(T, RT) typename eastl::enable_if<Internal::has_hashcode_member<T>::value, RT>::type*\n\t#define ENABLE_IF_HASHCODE_EASTLSIZET(T, RT) typename eastl::enable_if<eastl::is_convertible<T, eastl_size_t>::value, RT>::type\n\t#define ENABLE_IF_TRUETYPE(T) typename eastl::enable_if<T::value>::type*\n\t#define DISABLE_IF_TRUETYPE(T) typename eastl::enable_if<!T::value>::type*\n\n\n\t/// node_iterator_base\n\t///\n\t/// Node iterators iterate nodes within a given bucket.\n\t///\n\t/// We define a base class here because it is shared by both const and\n\t/// non-const iterators.\n\t///\n\ttemplate <typename Value, bool bCacheHashCode>\n\tstruct node_iterator_base\n\t{\n\t\ttypedef hash_node<Value, bCacheHashCode> node_type;\n\n\t\tnode_type* mpNode;\n\n\t\tnode_iterator_base(node_type* pNode)\n\t\t\t: mpNode(pNode) { }\n\n\t\tvoid increment()\n\t\t\t{ mpNode = mpNode->mpNext; }\n\t};\n\n\n\n\t/// node_iterator\n\t///\n\t/// Node iterators iterate nodes within a given bucket.\n\t///\n\t/// The bConst parameter defines if the iterator is a const_iterator\n\t/// or an iterator.\n\t///\n\ttemplate <typename Value, bool bConst, bool bCacheHashCode>\n\tstruct node_iterator : public node_iterator_base<Value, bCacheHashCode>\n\t{\n\tpublic:\n\t\ttypedef node_iterator_base<Value, bCacheHashCode>                base_type;\n\t\ttypedef node_iterator<Value, bConst, bCacheHashCode>             this_type;\n\t\ttypedef typename base_type::node_type                            node_type;\n\t\ttypedef Value                                                    value_type;\n\t\ttypedef typename conditional<bConst, const Value*, Value*>::type pointer;\n\t\ttypedef typename conditional<bConst, const Value&, Value&>::type reference;\n\t\ttypedef ptrdiff_t                                                difference_type;\n\t\ttypedef eastl::forward_iterator_tag                       iterator_category;\n\n\tpublic:\n\t\texplicit node_iterator(node_type* pNode = NULL)\n\t\t\t: base_type(pNode) { }\n\n\t\tnode_iterator(const node_iterator<Value, true, bCacheHashCode>& x)\n\t\t\t: base_type(x.mpNode) { }\n\n\t\treference operator*() const\n\t\t\t{ return base_type::mpNode->mValue; }\n\n\t\tpointer operator->() const\n\t\t\t{ return &(base_type::mpNode->mValue); }\n\n\t\tnode_iterator& operator++()\n\t\t\t{ base_type::increment(); return *this; }\n\n\t\tnode_iterator operator++(int)\n\t\t\t{ node_iterator temp(*this); base_type::increment(); return temp; }\n\n\t}; // node_iterator\n\n\n\n\t/// hashtable_iterator_base\n\t///\n\t/// A hashtable_iterator iterates the entire hash table and not just\n\t/// nodes within a single bucket. Users in general will use a hash\n\t/// table iterator much more often, as it is much like other container\n\t/// iterators (e.g. vector::iterator).\n\t///\n\t/// We define a base class here because it is shared by both const and\n\t/// non-const iterators.\n\t///\n\ttemplate <typename Value, bool bCacheHashCode>\n\tstruct hashtable_iterator_base\n\t{\n\tpublic:\n\t\ttypedef hashtable_iterator_base<Value, bCacheHashCode> this_type;\n\t\ttypedef hash_node<Value, bCacheHashCode>               node_type;\n\n\tprotected:\n\t\ttemplate <typename, typename, typename, typename, typename, typename, typename, typename, typename, bool, bool, bool>\n\t\tfriend class hashtable;\n\n\t\ttemplate <typename, bool, bool>\n\t\tfriend struct hashtable_iterator;\n\n\t\ttemplate <typename V, bool b>\n\t\tfriend bool operator==(const hashtable_iterator_base<V, b>&, const hashtable_iterator_base<V, b>&);\n\n\t\ttemplate <typename V, bool b>\n\t\tfriend bool operator!=(const hashtable_iterator_base<V, b>&, const hashtable_iterator_base<V, b>&);\n\n\t\tnode_type*  mpNode;      // Current node within current bucket.\n\t\tnode_type** mpBucket;    // Current bucket.\n\n\tpublic:\n\t\thashtable_iterator_base(node_type* pNode, node_type** pBucket)\n\t\t\t: mpNode(pNode), mpBucket(pBucket) { }\n\n\t\tvoid increment_bucket()\n\t\t{\n\t\t\t++mpBucket;\n\t\t\twhile(*mpBucket == NULL) // We store an extra bucket with some non-NULL value at the end \n\t\t\t\t++mpBucket;          // of the bucket array so that finding the end of the bucket\n\t\t\tmpNode = *mpBucket;      // array is quick and simple.\n\t\t}\n\n\t\tvoid increment()\n\t\t{\n\t\t\tmpNode = mpNode->mpNext;\n\n\t\t\twhile(mpNode == NULL)\n\t\t\t\tmpNode = *++mpBucket;\n\t\t}\n\n\t}; // hashtable_iterator_base\n\n\n\n\n\t/// hashtable_iterator\n\t///\n\t/// A hashtable_iterator iterates the entire hash table and not just\n\t/// nodes within a single bucket. Users in general will use a hash\n\t/// table iterator much more often, as it is much like other container\n\t/// iterators (e.g. vector::iterator).\n\t///\n\t/// The bConst parameter defines if the iterator is a const_iterator\n\t/// or an iterator.\n\t///\n\ttemplate <typename Value, bool bConst, bool bCacheHashCode>\n\tstruct hashtable_iterator : public hashtable_iterator_base<Value, bCacheHashCode>\n\t{\n\tpublic:\n\t\ttypedef hashtable_iterator_base<Value, bCacheHashCode>           base_type;\n\t\ttypedef hashtable_iterator<Value, bConst, bCacheHashCode>        this_type;\n\t\ttypedef hashtable_iterator<Value, false, bCacheHashCode>         this_type_non_const;\n\t\ttypedef typename base_type::node_type                            node_type;\n\t\ttypedef Value                                                    value_type;\n\t\ttypedef typename conditional<bConst, const Value*, Value*>::type pointer;\n\t\ttypedef typename conditional<bConst, const Value&, Value&>::type reference;\n\t\ttypedef ptrdiff_t                                                difference_type;\n\t\ttypedef eastl::forward_iterator_tag                       iterator_category;\n\n\tpublic:\n\t\thashtable_iterator(node_type* pNode = NULL, node_type** pBucket = NULL)\n\t\t\t: base_type(pNode, pBucket) { }\n\n\t\thashtable_iterator(node_type** pBucket)\n\t\t\t: base_type(*pBucket, pBucket) { }\n\n\t\ttemplate <bool IsConst = bConst, typename enable_if<IsConst, int>::type = 0>\n\t\thashtable_iterator(const this_type_non_const& x)\n\t\t\t: base_type(x.mpNode, x.mpBucket) { }\n\n\t\thashtable_iterator(const hashtable_iterator&) = default;\n\t\thashtable_iterator(hashtable_iterator&&) = default;\n\t\thashtable_iterator& operator=(const hashtable_iterator&) = default;\n\t\thashtable_iterator& operator=(hashtable_iterator&&) = default;\n\n\t\treference operator*() const\n\t\t\t{ return base_type::mpNode->mValue; }\n\n\t\tpointer operator->() const\n\t\t\t{ return &(base_type::mpNode->mValue); }\n\n\t\thashtable_iterator& operator++()\n\t\t\t{ base_type::increment(); return *this; }\n\n\t\thashtable_iterator operator++(int)\n\t\t\t{ hashtable_iterator temp(*this); base_type::increment(); return temp; }\n\n\t\tconst node_type* get_node() const\n\t\t\t{ return base_type::mpNode; }\n\n\t}; // hashtable_iterator\n\n\n\n\n\t/// ht_distance\n\t///\n\t/// This function returns the same thing as distance() for \n\t/// forward iterators but returns zero for input iterators.\n\t/// The reason why is that input iterators can only be read\n\t/// once, and calling distance() on an input iterator destroys\n\t/// the ability to read it. This ht_distance is used only for\n\t/// optimization and so the code will merely work better with\n\t/// forward iterators that input iterators.\n\t///\n\ttemplate <typename Iterator>\n\tinline typename eastl::iterator_traits<Iterator>::difference_type\n\tdistance_fw_impl(Iterator /*first*/, Iterator /*last*/, eastl::input_iterator_tag)\n\t{\n\t\treturn 0;\n\t}\n\n\ttemplate <typename Iterator>\n\tinline typename eastl::iterator_traits<Iterator>::difference_type\n\tdistance_fw_impl(Iterator first, Iterator last, eastl::forward_iterator_tag)\n\t\t{ return eastl::distance(first, last); }\n\n\ttemplate <typename Iterator>\n\tinline typename eastl::iterator_traits<Iterator>::difference_type\n\tht_distance(Iterator first, Iterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<Iterator>::iterator_category IC;\n\t\treturn distance_fw_impl(first, last, IC());\n\t}\n\n\n\n\n\t/// mod_range_hashing\n\t///\n\t/// Implements the algorithm for conversion of a number in the range of\n\t/// [0, SIZE_T_MAX] to the range of [0, BucketCount).\n\t///\n\tstruct mod_range_hashing\n\t{\n\t\tuint32_t operator()(size_t r, uint32_t n) const\n\t\t\t{ return r % n; }\n\t};\n\n\n\t/// default_ranged_hash\n\t///\n\t/// Default ranged hash function H. In principle it should be a\n\t/// function object composed from objects of type H1 and H2 such that\n\t/// h(k, n) = h2(h1(k), n), but that would mean making extra copies of\n\t/// h1 and h2. So instead we'll just use a tag to tell class template\n\t/// hashtable to do that composition.\n\t///\n\t/// Note: For all containers where hashtable is a base type this is the\n\t/// only possible H (users can't specify H).\n\tstruct default_ranged_hash{ };\n\n\n\t/// prime_rehash_policy\n\t///\n\t/// Default value for rehash policy. Bucket size is (usually) the\n\t/// smallest prime that keeps the load factor small enough.\n\t///\n\tstruct EASTL_API prime_rehash_policy\n\t{\n\tpublic:\n\t\tfloat            mfMaxLoadFactor;\n\t\tfloat            mfGrowthFactor;\n\t\tmutable uint32_t mnNextResize;\n\n\tpublic:\n\t\tprime_rehash_policy(float fMaxLoadFactor = 1.f)\n\t\t\t: mfMaxLoadFactor(fMaxLoadFactor), mfGrowthFactor(2.f), mnNextResize(0) { }\n\n\t\tfloat GetMaxLoadFactor() const\n\t\t\t{ return mfMaxLoadFactor; }\n\n\t\t/// Return a bucket count no greater than nBucketCountHint, \n\t\t/// Don't update member variables while at it.\n\t\tstatic uint32_t GetPrevBucketCountOnly(uint32_t nBucketCountHint);\n\n\t\t/// Return a bucket count no greater than nBucketCountHint.\n\t\t/// This function has a side effect of updating mnNextResize.\n\t\tuint32_t GetPrevBucketCount(uint32_t nBucketCountHint) const;\n\n\t\t/// Return a bucket count no smaller than nBucketCountHint.\n\t\t/// This function has a side effect of updating mnNextResize.\n\t\tuint32_t GetNextBucketCount(uint32_t nBucketCountHint) const;\n\n\t\t/// Return a bucket count appropriate for nElementCount elements.\n\t\t/// This function has a side effect of updating mnNextResize.\n\t\tuint32_t GetBucketCount(uint32_t nElementCount) const;\n\n\t\t/// nBucketCount is current bucket count, nElementCount is current element count,\n\t\t/// and nElementAdd is number of elements to be inserted. Do we need \n\t\t/// to increase bucket count? If so, return pair(true, n), where \n\t\t/// n is the new bucket count. If not, return pair(false, 0).\n\t\teastl::pair<bool, uint32_t>\n\t\tGetRehashRequired(uint32_t nBucketCount, uint32_t nElementCount, uint32_t nElementAdd) const;\n\t};\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// Base classes for hashtable. We define these base classes because \n\t// in some cases we want to do different things depending on the \n\t// value of a policy class. In some cases the policy class affects\n\t// which member functions and nested typedefs are defined; we handle that\n\t// by specializing base class templates. Several of the base class templates\n\t// need to access other members of class template hashtable, so we use\n\t// the \"curiously recurring template pattern\" (parent class is templated \n\t// on type of child class) for them.\n\t///////////////////////////////////////////////////////////////////////\n\n\n\t/// rehash_base\n\t///\n\t/// Give hashtable the get_max_load_factor functions if the rehash \n\t/// policy is prime_rehash_policy.\n\t///\n\ttemplate <typename RehashPolicy, typename Hashtable>\n\tstruct rehash_base { };\n\n\ttemplate <typename Hashtable>\n\tstruct rehash_base<prime_rehash_policy, Hashtable>\n\t{\n\t\t// Returns the max load factor, which is the load factor beyond\n\t\t// which we rebuild the container with a new bucket count.\n\t\tfloat get_max_load_factor() const\n\t\t{\n\t\t\tconst Hashtable* const pThis = static_cast<const Hashtable*>(this);\n\t\t\treturn pThis->rehash_policy().GetMaxLoadFactor();\n\t\t}\n\n\t\t// If you want to make the hashtable never rehash (resize), \n\t\t// set the max load factor to be a very high number (e.g. 100000.f).\n\t\tvoid set_max_load_factor(float fMaxLoadFactor)\n\t\t{\n\t\t\tHashtable* const pThis = static_cast<Hashtable*>(this);\n\t\t\tpThis->rehash_policy(prime_rehash_policy(fMaxLoadFactor));    \n\t\t}\n\t};\n\n\n\n\n\t/// hash_code_base\n\t///\n\t/// Encapsulates two policy issues that aren't quite orthogonal.\n\t///   (1) The difference between using a ranged hash function and using\n\t///       the combination of a hash function and a range-hashing function.\n\t///       In the former case we don't have such things as hash codes, so\n\t///       we have a dummy type as placeholder.\n\t///   (2) Whether or not we cache hash codes. Caching hash codes is\n\t///       meaningless if we have a ranged hash function. This is because\n\t///       a ranged hash function converts an object directly to its\n\t///       bucket index without ostensibly using a hash code.\n\t/// We also put the key extraction and equality comparison function \n\t/// objects here, for convenience.\n\t/// \n\t/// Key is unused because we now support heterogenous lookup, so we can't\n\t/// assume the key type is the same as the hashtable's Key type parameter.\n\t///\n\ttemplate <typename /* unused */ Key, typename Value, typename ExtractKey, typename Equal,\n\t\t\t  typename H1, typename H2, typename H, bool bCacheHashCode>\n\tstruct hash_code_base;\n\n\n\t/// hash_code_base\n\t///\n\t/// Specialization: ranged hash function, no caching hash codes. \n\t/// H1 and H2 are provided but ignored. We define a dummy hash code type.\n\t///\n\t/// Note: Never instantiated because for all containers where hashtable\n\t/// is a base type this is the only possible H (users can't specify H).\n\ttemplate <typename /* unused */ Key, typename Value, typename ExtractKey, typename Equal, typename H1, typename H2, typename H>\n\tstruct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, false>\n\t{\n\tprotected:\n\t\tExtractKey  mExtractKey;    // To do: Make this member go away entirely, as it never has any data.\n\t\tEqual       mEqual;         // To do: Make this instance use zero space when it is zero size.\n\t\tH           mRangedHash;    // To do: Make this instance use zero space when it is zero size\n\n\tpublic:\n\t\tH1 hash_function() const\n\t\t\t{ return H1(); }\n\n\t\tconst Equal& key_eq() const\n\t\t\t{ return mEqual; }\n\n\t\tEqual& key_eq()\n\t\t\t{ return mEqual; }\n\n\tprotected:\n\t\ttypedef void*    hash_code_t;\n\t\ttypedef uint32_t bucket_index_t;\n\n\t\thash_code_base(const ExtractKey& extractKey, const Equal& eq, const H1&, const H2&, const H& h)\n\t\t\t: mExtractKey(extractKey), mEqual(eq), mRangedHash(h) { }\n\n\t\ttemplate<typename KeyX>\n\t\thash_code_t get_hash_code(const KeyX&) const\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\tbucket_index_t bucket_index(hash_code_t, uint32_t) const\n\t\t\t{ return (bucket_index_t)0; }\n\n\t\ttemplate<typename KeyX>\n\t\tbucket_index_t bucket_index(const KeyX& key, hash_code_t, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)mRangedHash(key, nBucketCount); }\n\n\t\tbucket_index_t bucket_index(const hash_node<Value, false>* pNode, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)mRangedHash(mExtractKey(pNode->mValue), nBucketCount); }\n\n\t\ttemplate<typename KeyX>\n\t\tbool compare(const KeyX& key, hash_code_t, hash_node<Value, false>* pNode) const\n\t\t\t{ return mEqual(key, mExtractKey(pNode->mValue)); }\n\n\t\tvoid copy_code(hash_node<Value, false>*, const hash_node<Value, false>*) const\n\t\t\t{ } // Nothing to do.\n\n\t\tvoid set_code(hash_node<Value, false>* pDest, hash_code_t c) const\n\t\t{\n\t\t\tEA_UNUSED(pDest);\n\t\t\tEA_UNUSED(c);\n\t\t}\n\n\t\tvoid base_swap(hash_code_base& x)\n\t\t{\n\t\t\teastl::swap(mExtractKey, x.mExtractKey);\n\t\t\teastl::swap(mEqual,      x.mEqual);\n\t\t\teastl::swap(mRangedHash, x.mRangedHash);\n\t\t}\n\n\t}; // hash_code_base\n\n\n\n\t// No specialization for ranged hash function while caching hash codes.\n\t// That combination is meaningless, and trying to do it is an error.\n\n\n\t/// hash_code_base\n\t///\n\t/// Specialization: ranged hash function, cache hash codes. \n\t/// This combination is meaningless, so we provide only a declaration\n\t/// and no definition.\n\t///\n\t/// Note: Never instantiated because for all containers where hashtable\n\t/// is a base type this is the only possible H (users can't specify H).\n\ttemplate <typename Key, typename Value, typename ExtractKey, typename Equal, typename H1, typename H2, typename H>\n\tstruct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, true>;\n\n\n\n\t/// hash_code_base\n\t///\n\t/// Specialization: hash function and range-hashing function, \n\t/// no caching of hash codes. H is provided but ignored. \n\t/// Provides typedef and accessor required by TR1.\n\t///\n\ttemplate <typename /* unused */ Key, typename Value, typename ExtractKey, typename Equal, typename H1, typename H2>\n\tstruct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, default_ranged_hash, false>\n\t{\n\tprotected:\n\t\tExtractKey  mExtractKey;\n\t\tEqual       mEqual;\n\t\tH1          m_h1;\n\t\tH2          m_h2;\n\n\tpublic:\n\t\ttypedef H1 hasher;\n\n\t\tH1 hash_function() const\n\t\t\t{ return m_h1; }\n\n\t\tconst Equal& key_eq() const\n\t\t\t{ return mEqual; }\n\n\t\tEqual& key_eq()\n\t\t\t{ return mEqual; }\n\n\tprotected:\n\t\ttypedef size_t hash_code_t;\n\t\ttypedef uint32_t bucket_index_t;\n\t\ttypedef hash_node<Value, false> node_type;\n\n\t\thash_code_base(const ExtractKey& ex, const Equal& eq, const H1& h1, const H2& h2, const default_ranged_hash&)\n\t\t\t: mExtractKey(ex), mEqual(eq), m_h1(h1), m_h2(h2) { }\n\n\t\ttemplate<typename KeyX>\n\t\thash_code_t get_hash_code(const KeyX& key) const\n\t\t\t{ return (hash_code_t)m_h1(key); }\n\n\t\tbucket_index_t bucket_index(hash_code_t c, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)m_h2(c, nBucketCount); }\n\n\t\ttemplate<typename KeyX>\n\t\tbucket_index_t bucket_index(const KeyX&, hash_code_t c, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)m_h2(c, nBucketCount); }\n\n\t\tbucket_index_t bucket_index(const node_type* pNode, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)m_h2((hash_code_t)m_h1(mExtractKey(pNode->mValue)), nBucketCount); }\n\n\t\ttemplate<typename KeyX>\n\t\tbool compare(const KeyX& key, hash_code_t, node_type* pNode) const\n\t\t\t{ return mEqual(key, mExtractKey(pNode->mValue)); }\n\n\t\tvoid copy_code(node_type*, const node_type*) const\n\t\t\t{ } // Nothing to do.\n\n\t\tvoid set_code(node_type*, hash_code_t) const\n\t\t\t{ } // Nothing to do.\n\n\t\tvoid base_swap(hash_code_base& x)\n\t\t{\n\t\t\teastl::swap(mExtractKey, x.mExtractKey);\n\t\t\teastl::swap(mEqual,      x.mEqual);\n\t\t\teastl::swap(m_h1,        x.m_h1);\n\t\t\teastl::swap(m_h2,        x.m_h2);\n\t\t}\n\n\t}; // hash_code_base\n\n\n\n\t/// hash_code_base\n\t///\n\t/// Specialization: hash function and range-hashing function, \n\t/// caching hash codes. H is provided but ignored. \n\t/// Provides typedef and accessor required by TR1.\n\t///\n\ttemplate <typename /* unused */ Key, typename Value, typename ExtractKey, typename Equal, typename H1, typename H2>\n\tstruct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, default_ranged_hash, true>\n\t{\n\tprotected:\n\t\tExtractKey  mExtractKey;\n\t\tEqual       mEqual;\n\t\tH1          m_h1;\n\t\tH2          m_h2;\n\n\tpublic:\n\t\ttypedef H1 hasher;\n\n\t\tH1 hash_function() const\n\t\t\t{ return m_h1; }\n\n\t\tconst Equal& key_eq() const\n\t\t\t{ return mEqual; }\n\n\t\tEqual& key_eq()\n\t\t\t{ return mEqual; }\n\n\tprotected:\n\t\ttypedef uint32_t hash_code_t;\n\t\ttypedef uint32_t bucket_index_t;\n\t\ttypedef hash_node<Value, true> node_type;\n\n\t\thash_code_base(const ExtractKey& ex, const Equal& eq, const H1& h1, const H2& h2, const default_ranged_hash&)\n\t\t\t: mExtractKey(ex), mEqual(eq), m_h1(h1), m_h2(h2) { }\n\n\t\ttemplate<typename KeyX>\n\t\thash_code_t get_hash_code(const KeyX& key) const\n\t\t\t{ return (hash_code_t)m_h1(key); }\n\n\t\tbucket_index_t bucket_index(hash_code_t c, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)m_h2(c, nBucketCount); }\n\n\t\ttemplate<typename KeyX>\n\t\tbucket_index_t bucket_index(const KeyX&, hash_code_t c, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)m_h2(c, nBucketCount); }\n\n\t\tbucket_index_t bucket_index(const node_type* pNode, uint32_t nBucketCount) const\n\t\t\t{ return (bucket_index_t)m_h2((uint32_t)pNode->mnHashCode, nBucketCount); }\n\n\t\ttemplate<typename KeyX>\n\t\tbool compare(const KeyX& key, hash_code_t c, node_type* pNode) const\n\t\t\t{ return (pNode->mnHashCode == c) && mEqual(key, mExtractKey(pNode->mValue)); }\n\n\t\tvoid copy_code(node_type* pDest, const node_type* pSource) const\n\t\t\t{ pDest->mnHashCode = pSource->mnHashCode; }\n\n\t\tvoid set_code(node_type* pDest, hash_code_t c) const\n\t\t\t{ pDest->mnHashCode = c; }\n\n\t\tvoid base_swap(hash_code_base& x)\n\t\t{\n\t\t\teastl::swap(mExtractKey, x.mExtractKey);\n\t\t\teastl::swap(mEqual,      x.mEqual);\n\t\t\teastl::swap(m_h1,        x.m_h1);\n\t\t\teastl::swap(m_h2,        x.m_h2);\n\t\t}\n\n\t}; // hash_code_base\n\n\n\n\tnamespace internal {\n\n\t// Equality and the hash comparison must both be transparent.\n\t// The hash function we use is dependent on whether we use the default_ranged_hash or not.\n\t//\n\t// Note: For all containers where hashtable is a base type this default_ranged_hash the\n\t// only possible H (users can't specify H).\n\ttemplate<typename EqX, typename H1X, typename HX>\n\tstruct is_transparent_key_available : eastl::bool_constant<eastl::detail::is_transparent_comparison_v<EqX>\n\t\t&& ((eastl::is_same_v<HX, default_ranged_hash> && eastl::detail::is_transparent_comparison_v<H1X>)\n\t\t\t|| (!eastl::is_same_v<HX, default_ranged_hash> && eastl::detail::is_transparent_comparison_v<HX>))> {};\n\n\ttemplate<typename EqX, typename H1X, typename HX>\n\tEA_CONSTEXPR bool is_transparent_key_available_v = is_transparent_key_available<EqX, H1X, HX>::value;\n\n\t} // namespace internal\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t/// hashtable\n\t///\n\t/// Key and Value: arbitrary CopyConstructible types.\n\t///\n\t/// ExtractKey: function object that takes a object of type Value\n\t/// and returns a value of type Key.\n\t///\n\t/// Equal: function object that takes two objects of type k and returns\n\t/// a bool-like value that is true if the two objects are considered equal.\n\t///\n\t/// H1: a hash function. A unary function object with argument type\n\t/// Key and result type size_t. Return values should be distributed\n\t/// over the entire range [0, numeric_limits<uint32_t>::max()].\n\t///\n\t/// H2: a range-hashing function (in the terminology of Tavori and\n\t/// Dreizin). This is a function which takes the output of H1 and \n\t/// converts it to the range of [0, n]. Usually it merely takes the\n\t/// output of H1 and mods it to n.\n\t///\n\t/// H: a ranged hash function (Tavori and Dreizin). This is merely\n\t/// a class that combines the functionality of H1 and H2 together, \n\t/// possibly in some way that is somehow improved over H1 and H2\n\t/// It is a binary function whose argument types are Key and size_t \n\t/// and whose result type is uint32_t. Given arguments k and n, the \n\t/// return value is in the range [0, n). Default: h(k, n) = h2(h1(k), n). \n\t/// If H is anything other than the default, H1 and H2 are ignored, \n\t/// as H is thus overriding H1 and H2.\n\t///\n\t/// RehashPolicy: Policy class with three members, all of which govern\n\t/// the bucket count. nBucket(n) returns a bucket count no smaller\n\t/// than n. GetBucketCount(n) returns a bucket count appropriate\n\t/// for an element count of n. GetRehashRequired(nBucketCount, nElementCount, nElementAdd)\n\t/// determines whether, if the current bucket count is nBucket and the\n\t/// current element count is nElementCount, we need to increase the bucket\n\t/// count. If so, returns pair(true, n), where n is the new\n\t/// bucket count. If not, returns pair(false, <anything>).\n\t///\n\t/// Currently it is hard-wired that the number of buckets never\n\t/// shrinks. Should we allow RehashPolicy to change that?\n\t///\n\t/// bCacheHashCode: true if we store the value of the hash\n\t/// function along with the value. This is a time-space tradeoff.\n\t/// Storing it may improve lookup speed by reducing the number of \n\t/// times we need to call the Equal function.\n\t///\n\t/// bMutableIterators: true if hashtable::iterator is a mutable\n\t/// iterator, false if iterator and const_iterator are both const \n\t/// iterators. This is true for hash_map and hash_multimap,\n\t/// false for hash_set and hash_multiset.\n\t///\n\t/// bUniqueKeys: true if the return value of hashtable::count(k)\n\t/// is always at most one, false if it may be an arbitrary number. \n\t/// This is true for hash_set and hash_map and is false for \n\t/// hash_multiset and hash_multimap.\n\t///\n\t///////////////////////////////////////////////////////////////////////\n\t/// Note:\n\t/// If you want to make a hashtable never increase its bucket usage,\n\t/// call set_max_load_factor with a very high value such as 100000.f.\n\t///\n\t/// Heterogeneous lookup, insertion and erasure\n\t/// See\n\t/// https://en.cppreference.com/w/cpp/utility/functional#Transparent_function_objects\n\t/// https://en.cppreference.com/w/cpp/utility/functional/less_void\n\t/// https://en.cppreference.com/w/cpp/container/map/find\n\t/// \n\t/// You can avoid creating key objects when calling member functions\n\t/// with a key_type parameter by declaring the container with\n\t/// transparent comparison types and passing objects to be passed to\n\t/// these function objects.\n\t/// \n\t/// This optimization is supported for member functions that take a\n\t/// key_type parameter, ie. heterogeneous lookup, insertion and erasure,\n\t/// not just find().\n\t/// \n\t/// Using transparent types is safer than using find_as because the\n\t/// latter requires the user specify function objects which must have\n\t/// the same semantics as the container's function objects, otherwise\n\t/// the behaviour is undefined.\n\t/// \n\t/// find_as\n\t/// Note: Prefer heterogeneous lookup (see above).\n\t/// \n\t/// In order to support the ability to have a hashtable of strings but\n\t/// be able to do efficiently lookups via char pointers (i.e. so they \n\t/// aren't converted to string objects), we provide the find_as \n\t/// function. This function allows you to do a find with a key of a\n\t/// type other than the hashtable key type. See the find_as function\n\t/// for more documentation on this.\n\t///\n\t/// find_by_hash\n\t/// In the interest of supporting fast operations wherever possible,\n\t/// we provide a find_by_hash function which finds a node using its\n\t/// hash code.  This is useful for cases where the node's hash is\n\t/// already known, allowing us to avoid a redundant hash operation\n\t/// in the normal find path.\n\t/// \n\ttemplate <typename Key, typename Value, typename Allocator, typename ExtractKey, \n\t\t\t  typename Equal, typename H1, typename H2, typename H, \n\t\t\t  typename RehashPolicy, bool bCacheHashCode, bool bMutableIterators, bool bUniqueKeys>\n\tclass hashtable\n\t\t:   public rehash_base<RehashPolicy, hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, bCacheHashCode, bMutableIterators, bUniqueKeys> >,\n\t\t\tpublic hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, bCacheHashCode>\n\t{\n\tpublic:\n\t\ttypedef Key                                                                                 key_type;\n\t\ttypedef Value                                                                               value_type;\n\t\ttypedef typename ExtractKey::result_type                                                    mapped_type;\n\t\ttypedef hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, bCacheHashCode>            hash_code_base_type;\n\t\ttypedef typename hash_code_base_type::hash_code_t                                           hash_code_t;\n\t\ttypedef Allocator                                                                           allocator_type;\n\t\ttypedef Equal                                                                               key_equal;\n\t\ttypedef ptrdiff_t                                                                           difference_type;\n\t\ttypedef eastl_size_t                                                                        size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef value_type&                                                                         reference;\n\t\ttypedef const value_type&                                                                   const_reference;\n\t\ttypedef node_iterator<value_type, !bMutableIterators, bCacheHashCode>                       local_iterator;\n\t\ttypedef node_iterator<value_type, true,               bCacheHashCode>                       const_local_iterator;\n\t\ttypedef hashtable_iterator<value_type, !bMutableIterators, bCacheHashCode>                  iterator;\n\t\ttypedef hashtable_iterator<value_type, true,               bCacheHashCode>                  const_iterator;\n\t\ttypedef hash_node<value_type, bCacheHashCode>                                               node_type;\n\t\ttypedef typename conditional<bUniqueKeys, eastl::pair<iterator, bool>, iterator>::type      insert_return_type;\n\t\ttypedef hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, \n\t\t\t\t\t\t\tRehashPolicy, bCacheHashCode, bMutableIterators, bUniqueKeys>           this_type;\n\t\ttypedef RehashPolicy                                                                        rehash_policy_type;\n\t\ttypedef ExtractKey                                                                          extract_key_type;\n\t\ttypedef H1                                                                                  h1_type;\n\t\ttypedef H2                                                                                  h2_type;\n\t\ttypedef H                                                                                   h_type;\n\t\ttypedef integral_constant<bool, bUniqueKeys>                                                has_unique_keys_type;\n\n\t\tusing hash_code_base_type::key_eq;\n\t\tusing hash_code_base_type::hash_function;\n\t\tusing hash_code_base_type::mExtractKey;\n\t\tusing hash_code_base_type::get_hash_code;\n\t\tusing hash_code_base_type::bucket_index;\n\t\tusing hash_code_base_type::compare;\n\t\tusing hash_code_base_type::set_code;\n\t\tusing hash_code_base_type::copy_code;\n\n\t\tstatic const bool kCacheHashCode = bCacheHashCode;\n\n\tprotected:\n\t\tnode_type**     mpBucketArray;\n\t\tsize_type       mnBucketCount;\n\t\tsize_type       mnElementCount;\n\t\tRehashPolicy    mRehashPolicy;  // To do: Use base class optimization to make this go away.\n\t\tallocator_type  mAllocator;     // To do: Use base class optimization to make this go away.\n\n\t\tstruct NodeFindKeyData {\n\t\t\tnode_type* node;\n\t\t\thash_code_t code;\n\t\t\tsize_type bucket_index;\n\t\t};\n\n\tpublic:\n\t\thashtable(size_type nBucketCount, const H1&, const H2&, const H&, const Equal&, const ExtractKey&, \n\t\t\t\t  const allocator_type& allocator = EASTL_HASHTABLE_DEFAULT_ALLOCATOR);\n\t\t\n\t\t// note: standard only requires InputIterator.\n\t\ttemplate <typename FowardIterator>\n\t\thashtable(FowardIterator first, FowardIterator last, size_type nBucketCount, \n\t\t\t\t  const H1&, const H2&, const H&, const Equal&, const ExtractKey&, \n\t\t\t\t  const allocator_type& allocator = EASTL_HASHTABLE_DEFAULT_ALLOCATOR); \n\t\t\n\t\thashtable(const hashtable& x);\n\n\t\t// initializer_list ctor support is implemented in subclasses (e.g. hash_set).\n\t\t// hashtable(initializer_list<value_type>, size_type nBucketCount, const H1&, const H2&, const H&, \n\t\t//           const Equal&, const ExtractKey&, const allocator_type& allocator = EASTL_HASHTABLE_DEFAULT_ALLOCATOR);\n\n\t\thashtable(this_type&& x);\n\t\thashtable(this_type&& x, const allocator_type& allocator);\n\t   ~hashtable();\n\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT;\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT;\n\t\tvoid                  set_allocator(const allocator_type& allocator);\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\titerator begin() EA_NOEXCEPT\n\t\t{\n\t\t\t// Early out if the table is empty, increment_bucket() below will loop over the\n\t\t\t// entire bucket array, which is undesirable if we know there aren't any elements.\n\t\t\tif (mnElementCount == 0)\n\t\t\t{\n\t\t\t\treturn end();\n\t\t\t}\n\t\t\titerator i(mpBucketArray);\n\t\t\tif (!i.mpNode)\n\t\t\t{\n\t\t\t\ti.increment_bucket();\n\t\t\t}\n\t\t\treturn i;\n\t\t}\n\n\t\tconst_iterator begin() const EA_NOEXCEPT\n\t\t{\n\t\t\t// Early out if the table is empty, increment_bucket() below will loop over the\n\t\t\t// entire bucket array, which is undesirable if we know there aren't any elements.\n\t\t\tif (mnElementCount == 0)\n\t\t\t{\n\t\t\t\treturn end();\n\t\t\t}\n\t\t\tconst_iterator i(mpBucketArray);\n\t\t\tif (!i.mpNode)\n\t\t\t{\n\t\t\t\ti.increment_bucket();\n\t\t\t}\n\t\t\treturn i;\n\t\t}\n\n\t\tconst_iterator cbegin() const EA_NOEXCEPT\n\t\t\t{ return begin(); }\n\n\t\titerator end() EA_NOEXCEPT\n\t\t\t{ return iterator(mpBucketArray + mnBucketCount); }\n\n\t\tconst_iterator end() const EA_NOEXCEPT\n\t\t\t{ return const_iterator(mpBucketArray + mnBucketCount); }\n\n\t\tconst_iterator cend() const EA_NOEXCEPT\n\t\t\t{ return const_iterator(mpBucketArray + mnBucketCount); }\n\n\t\t// Returns an iterator to the first item in bucket n.\n\t\tlocal_iterator begin(size_type n) EA_NOEXCEPT\n\t\t\t{ return local_iterator(mpBucketArray[n]); }\n\n\t\tconst_local_iterator begin(size_type n) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(mpBucketArray[n]); }\n\n\t\tconst_local_iterator cbegin(size_type n) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(mpBucketArray[n]); }\n\n\t\t// Returns an iterator to the last item in a bucket returned by begin(n).\n\t\tlocal_iterator end(size_type) EA_NOEXCEPT\n\t\t\t{ return local_iterator(NULL); }\n\n\t\tconst_local_iterator end(size_type) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(NULL); }\n\n\t\tconst_local_iterator cend(size_type) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(NULL); }\n\n\t\tbool empty() const EA_NOEXCEPT\n\t\t\t{ return mnElementCount == 0; }\n\n\t\tsize_type size() const EA_NOEXCEPT\n\t\t\t{ return mnElementCount; }\n\n\t\t// size_type max_size() const EA_NOEXCEPT;\n\n\t\tsize_type bucket_count() const EA_NOEXCEPT\n\t\t\t{ return mnBucketCount; }\n\n\t\t// size_type max_bucket_count() const;\n\n\t\tsize_type bucket_size(size_type n) const EA_NOEXCEPT\n\t\t\t{ return (size_type)eastl::distance(begin(n), end(n)); }\n\n\t\t//size_type bucket(const key_type& k) const\n\t\t//    { return bucket_index(k, (hash code here), (uint32_t)mnBucketCount); }\n\n\t\t// template<typename KX> size_type bucket(const KX& x) const;\n\n\t\t// Returns the ratio of element count to bucket count. A return value of 1 means \n\t\t// there's an optimal 1 bucket for each element.\n\t\tfloat load_factor() const EA_NOEXCEPT\n\t\t\t{ return (float)mnElementCount / (float)mnBucketCount; }\n\n\t\t// float max_load_factor() const;\n\t\t// void max_load_factor( float ml );\n\n\t\t// Inherited from the base class.\n\t\t// Returns the max load factor, which is the load factor beyond\n\t\t// which we rebuild the container with a new bucket count.\n\t\t// get_max_load_factor comes from rehash_base.\n\t\t//    float get_max_load_factor() const;\n\n\t\t// Inherited from the base class.\n\t\t// If you want to make the hashtable never rehash (resize), \n\t\t// set the max load factor to be a very high number (e.g. 100000.f).\n\t\t// set_max_load_factor comes from rehash_base.\n\t\t//    void set_max_load_factor(float fMaxLoadFactor);\n\n\t\t/// Generalization of get_max_load_factor. This is an extension that's\n\t\t/// not present in C++ hash tables (unordered containers).\n\t\tconst rehash_policy_type& rehash_policy() const EA_NOEXCEPT\n\t\t\t{ return mRehashPolicy; }\n\n\t\t/// Generalization of set_max_load_factor. This is an extension that's\n\t\t/// not present in C++ hash tables (unordered containers).\n\t\tvoid rehash_policy(const rehash_policy_type& rehashPolicy);\n\n\t\ttemplate <class... Args>\n\t\tinsert_return_type emplace(Args&&... args);\n\n\t\ttemplate <class... Args>\n\t\titerator emplace_hint(const_iterator position, Args&&... args);\n\n\t\tinsert_return_type                     insert(const value_type& value);\n\t\tinsert_return_type                     insert(value_type&& otherValue);\n\t\titerator                               insert(const_iterator hint, const value_type& value);\n\t\titerator                               insert(const_iterator hint, value_type&& value);\n\t\tvoid                                   insert(std::initializer_list<value_type> ilist);\n\t\ttemplate <typename InputIterator> void insert(InputIterator first, InputIterator last);\n\t  //insert_return_type                     insert(node_type&& nh);\n\t  //iterator                               insert(const_iterator hint, node_type&& nh);\n\n\n\t\t// Non-standard extension\n\t\ttemplate <class P> // See comments below for the const value_type& equivalent to this function.\n\t\tinsert_return_type insert(hash_code_t c, node_type* pNodeNew, P&& otherValue);\n\n\t\t// We provide a version of insert which lets the caller directly specify the hash value and \n\t\t// a potential node to insert if needed. This allows for less thread contention in the case\n\t\t// of a thread-shared hash table that's accessed during a mutex lock, because the hash calculation\n\t\t// and node creation is done outside of the lock. If pNodeNew is supplied by the user (i.e. non-NULL) \n\t\t// then it must be freeable via the hash table's allocator. If the return value is true then this function \n\t\t// took over ownership of pNodeNew, else pNodeNew is still owned by the caller to free or to pass \n\t\t// to another call to insert. pNodeNew need not be assigned the value by the caller, as the insert\n\t\t// function will assign value to pNodeNew upon insertion into the hash table. pNodeNew may be \n\t\t// created by the user with the allocate_uninitialized_node function, and freed by the free_uninitialized_node function.\n\t\tinsert_return_type insert(hash_code_t c, node_type* pNodeNew, const value_type& value);\n\n\t\ttemplate <class M> eastl::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) { return DoInsertOrAssign(k, eastl::forward<M>(obj)); }\n\t\ttemplate <class M> eastl::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) { return DoInsertOrAssign(eastl::move(k), eastl::forward<M>(obj)); }\n\t\ttemplate<typename KX, typename M, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\teastl::pair<iterator, bool>\t\t\t\t\t\tinsert_or_assign(KX&& k, M&& obj) { return DoInsertOrAssign(eastl::forward<KX>(k), eastl::forward<M>(obj)); }\n\t\ttemplate <class M> iterator\t\t\t\t\t\tinsert_or_assign(const_iterator hint, const key_type& k, M&& obj) { return DoInsertOrAssign(hint, k, eastl::forward<M>(obj)); }\n\t\ttemplate <class M> iterator\t\t\t\t\t\tinsert_or_assign(const_iterator hint, key_type&& k, M&& obj) { return DoInsertOrAssign(hint, eastl::move(k), eastl::forward<M>(obj)); }\n\t\ttemplate<typename KX, typename M, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\titerator\t\t\t\t\t\t\t\t\t\tinsert_or_assign(const_iterator hint, KX&& k, M&& obj) { return DoInsertOrAssign(hint, eastl::forward<KX>(k), eastl::forward<M>(obj)); }\n\n\t\t// Used to allocate and free memory used by insert(const value_type& value, hash_code_t c, node_type* pNodeNew).\n\t\tnode_type* allocate_uninitialized_node();\n\t\tvoid       free_uninitialized_node(node_type* pNode);\n\n\t\ttemplate <typename Iter = iterator, typename eastl::enable_if<!eastl::is_same_v<Iter, const_iterator>, int>::type = 0>\n\t\titerator         erase(iterator position) { return erase(const_iterator(position)); }\n\t\titerator         erase(const_iterator position);\n\t\titerator         erase(const_iterator first, const_iterator last);\n\t\tsize_type        erase(const key_type& k) { return DoErase(k); }\n\t\ttemplate<typename KX, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, iterator> && !eastl::is_convertible_v<KX&&, const_iterator>\n\t\t\t&& internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\tsize_type        erase(KX&& k) { return DoErase(eastl::forward<KX>(k)); }\n\n\t\tvoid clear();\n\t\tvoid clear(bool clearBuckets);                  // If clearBuckets is true, we free the bucket memory and set the bucket count back to the newly constructed count.\n\t\tvoid reset_lose_memory() EA_NOEXCEPT;           // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\t\tvoid rehash(size_type nBucketCount);\n\t\tvoid reserve(size_type nElementCount);\n\n\t\titerator       find(const key_type& key) { return DoFind(key); }\n\t\tconst_iterator find(const key_type& key) const { return DoFind(key); }\n\n\t\ttemplate<typename KX, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\titerator       find(const KX& key) { return DoFind(key); }\n\t\ttemplate<typename KX, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\tconst_iterator find(const KX& key) const { return DoFind(key); }\n\n\t\tbool contains(const key_type& key) const { return DoFind(key) != end(); }\n\n\t\ttemplate<typename KX, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\tbool contains(const KX& key) const { return DoFind(key) != end(); }\n\n\t\t/// Implements a find whereby the user supplies a comparison of a different type\n\t\t/// than the hashtable value_type. A useful case of this is one whereby you have\n\t\t/// a container of string objects but want to do searches via passing in char pointers.\n\t\t/// The problem is that without this kind of find, you need to do the expensive operation\n\t\t/// of converting the char pointer to a string so it can be used as the argument to the \n\t\t/// find function.\n\t\t///\n\t\t/// Example usage (namespaces omitted for brevity):\n\t\t///     hash_set<string> hashSet;\n\t\t///     hashSet.find_as(\"hello\");    // Use default hash and compare.\n\t\t///\n\t\t/// Example usage (note that the predicate uses string as first type and char* as second):\n\t\t///     hash_set<string> hashSet;\n\t\t///     hashSet.find_as(\"hello\", hash<char*>(), equal_to<>());\n\t\t///\n\t\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\t\titerator       find_as(const U& u, UHash uhash, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\t\tconst_iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate) const;\n\n\t\t// Using default hash and equality objects may result in incorrect semantics (undefined behaviour).\n\t\t// Use find() with heterogenous lookup (ie. function objects with a is_transparent type member) or explicitly specify hash and equality objects.\n\t\t// See doc\\BestPractices.md#search-hash_mapstring-using-heterogeneous-lookup\n\t\ttemplate <typename U>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\t\titerator       find_as(const U& u);\n\n\t\t// Using default hash and equality objects may result in incorrect semantics (undefined behaviour).\n\t\t// Use find() with heterogenous lookup (ie. function objects with a is_transparent type member) or explicitly specify hash and equality objects.\n\t\t// See doc\\BestPractices.md#search-hash_mapstring-using-heterogeneous-lookup\n\t\ttemplate <typename U>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\t\tconst_iterator find_as(const U& u) const;\n\n\t\t// Note: find_by_hash and find_range_by_hash both perform a search based on a hash value.\n\t\t// It is important to note that multiple hash values may map to the same hash bucket, so\n\t\t// it would be incorrect to assume all items returned match the hash value that\n\t\t// was searched for.\n\n\t\t/// Implements a find whereby the user supplies the node's hash code.\n\t\t/// It returns an iterator to the first element that matches the given hash. However, there may be multiple elements that match the given hash.\n\n\t\ttemplate<typename HashCodeT>\n\t\tENABLE_IF_HASHCODE_EASTLSIZET(HashCodeT, iterator) find_by_hash(HashCodeT c)\n\t\t{\n\t\t\tEASTL_CT_ASSERT_MSG(bCacheHashCode,\n\t\t\t\t\"find_by_hash(hash_code_t c) is designed to avoid recomputing hashes, \"\n\t\t\t\t\"so it requires cached hash codes.  Consider setting template parameter \"\n\t\t\t\t\"bCacheHashCode to true or using find_by_hash(const key_type& k, hash_code_t c) instead.\");\n\n\t\t\tconst size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);\n\n\t\t\tnode_type* const pNode = DoFindNode(mpBucketArray[n], c);\n\n\t\t\treturn pNode ? iterator(pNode, mpBucketArray + n) :\n\t\t\t\t\t\t   iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t\t}\n\n\t\ttemplate<typename HashCodeT>\n\t\tENABLE_IF_HASHCODE_EASTLSIZET(HashCodeT, const_iterator) find_by_hash(HashCodeT c) const\n\t\t{\n\t\t\tEASTL_CT_ASSERT_MSG(bCacheHashCode,\n\t\t\t\t\t\t\t\t\"find_by_hash(hash_code_t c) is designed to avoid recomputing hashes, \"\n\t\t\t\t\t\t\t\t\"so it requires cached hash codes.  Consider setting template parameter \"\n\t\t\t\t\t\t\t\t\"bCacheHashCode to true or using find_by_hash(const key_type& k, hash_code_t c) instead.\");\n\n\t\t\tconst size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);\n\n\t\t\tnode_type* const pNode = DoFindNode(mpBucketArray[n], c);\n\n\t\t\treturn pNode ?\n\t\t\t\t\t   const_iterator(pNode, mpBucketArray + n) :\n\t\t\t\t\t   const_iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t\t}\n\n\t\titerator find_by_hash(const key_type& k, hash_code_t c)\n\t\t{\n\t\t\tconst size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);\n\n\t\t\tnode_type* const pNode = DoFindNode(mpBucketArray[n], k, c);\n\t\t\treturn pNode ? iterator(pNode, mpBucketArray + n) : iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t\t}\n\n\t\tconst_iterator find_by_hash(const key_type& k, hash_code_t c) const\n\t\t{\n\t\t\tconst size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);\n\n\t\t\tnode_type* const pNode = DoFindNode(mpBucketArray[n], k, c);\n\t\t\treturn pNode ? const_iterator(pNode, mpBucketArray + n) : const_iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t\t}\n\n\t\t// todo: heterogeneous find_by_hash\n\n\t\t// Returns a pair that allows iterating over all nodes in a hash bucket\n\t\t//   first in the pair returned holds the iterator for the beginning of the bucket,\n\t\t//   second in the pair returned holds the iterator for the end of the bucket,\n\t\t// If no bucket is found, both values in the pair are set to end().\n\t\t//\n\t\t// See also the note above.\n\t\teastl::pair<iterator, iterator> find_range_by_hash(hash_code_t c);\n\t\teastl::pair<const_iterator, const_iterator> find_range_by_hash(hash_code_t c) const;\n\n\t\tsize_type count(const key_type& k) const EA_NOEXCEPT { return DoCount(k); }\n\n\t\ttemplate<typename KX, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\tsize_type count(const KX& key) const EA_NOEXCEPT { return DoCount(key); }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const key_type& k) { return DoEqualRange(k); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const { return DoEqualRange(k); }\n\n\t\ttemplate<typename KX, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& k) { return DoEqualRange(k); }\n\t\ttemplate<typename KX, typename EqX = Equal, typename H1X = H1, typename HX = H,\n\t\t\teastl::enable_if_t<internal::is_transparent_key_available_v<EqX, H1X, HX>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& k) const { return DoEqualRange(k); }\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\tprotected:\n\t\t// We must remove one of the 'DoGetResultIterator' overloads from the overload-set (via SFINAE) because both can\n\t\t// not compile successfully at the same time. The 'bUniqueKeys' template parameter chooses at compile-time the\n\t\t// type of 'insert_return_type' between a pair<iterator,bool> and a raw iterator. We must pick between the two\n\t\t// overloads that unpacks the iterator from the pair or simply passes the provided iterator to the caller based\n\t\t// on the class template parameter.\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoGetResultIterator(BoolConstantT,\n\t\t                             const insert_return_type& irt,\n\t\t                             ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn irt.first;\n\t\t}\n\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoGetResultIterator(BoolConstantT,\n\t\t                             const insert_return_type& irt,\n\t\t                             DISABLE_IF_TRUETYPE(BoolConstantT) = nullptr) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn irt;\n\t\t}\n\n\t\t// Note: only usable in hash_map / hash_multimap because this function calls: value_type(pair_first_construct, key)\n\t\tnode_type*  DoAllocateNodeFromKey(const key_type& key);\n\t\t// Note: only usable in hash_map / hash_multimap because this function calls: value_type(pair_first_construct, eastl::move(key))\n\t\tnode_type*  DoAllocateNodeFromKey(key_type&& key);\n\t\tvoid        DoFreeNode(node_type* pNode);\n\t\tvoid        DoFreeNodes(node_type** pBucketArray, size_type);\n\n\t\tnode_type** DoAllocateBuckets(size_type n);\n\t\tvoid        DoFreeBuckets(node_type** pBucketArray, size_type n);\n\n\t\ttemplate <bool bDeleteOnException, typename Enabled = bool_constant<bUniqueKeys>, ENABLE_IF_TRUETYPE(Enabled) = nullptr> // only enabled when keys are unique\n\t\teastl::pair<iterator, bool> DoInsertUniqueNode(const key_type& k, hash_code_t c, size_type n, node_type* pNodeNew);\n\n\t\t// this overload will always allocate a node.\n\t\ttemplate <typename BoolConstantT, class... Args, ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr>\n\t\teastl::pair<iterator, bool> DoInsertValue(BoolConstantT, Args&&... args);\n\n\t\t// this overload will always allocate a node.\n\t\ttemplate <typename BoolConstantT, class... Args, DISABLE_IF_TRUETYPE(BoolConstantT) = nullptr>\n\t\titerator DoInsertValue(BoolConstantT, Args&&... args);\n\n\n\t\ttemplate <typename BoolConstantT>\n\t\teastl::pair<iterator, bool> DoInsertValueExtra(BoolConstantT,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   const key_type& k,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   hash_code_t c,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   node_type* pNodeNew,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   value_type&& value,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\teastl::pair<iterator, bool> DoInsertValue(BoolConstantT,\n\t\t\t\t\t\t\t\t\t\t\t\t  value_type&& value,\n\t\t\t\t\t\t\t\t\t\t\t\t  ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\teastl::pair<iterator, bool> DoInsertValue(BoolConstantT,\n\t\t\t\t\t\t\t\t\t\t\t\t  const value_type&& value,\n\t\t\t\t\t\t\t\t\t\t\t\t  ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoInsertValueExtra(BoolConstantT,\n\t\t\t\t\t\t\t\t\tconst key_type& k,\n\t\t\t\t\t\t\t\t\thash_code_t c,\n\t\t\t\t\t\t\t\t\tnode_type* pNodeNew,\n\t\t\t\t\t\t\t\t\tvalue_type&& value,\n\t\t\t\t\t\t\t\t\tDISABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoInsertValue(BoolConstantT, value_type&& value, DISABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoInsertValue(BoolConstantT, const value_type&& value, DISABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\n\t\ttemplate <typename BoolConstantT>\n\t\teastl::pair<iterator, bool> DoInsertValueExtra(BoolConstantT,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   const key_type& k,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   hash_code_t c,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   node_type* pNodeNew,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   const value_type& value,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\teastl::pair<iterator, bool> DoInsertValue(BoolConstantT,\n\t\t                                          const value_type& value,\n\t\t                                          ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\teastl::pair<iterator, bool> DoInsertValue(BoolConstantT,\n\t\t                                          value_type& value,\n\t\t                                          ENABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoInsertValueExtra(BoolConstantT,\n\t\t                            const key_type& k,\n\t\t                            hash_code_t c,\n\t\t                            node_type* pNodeNew,\n\t\t                            const value_type& value,\n\t\t                            DISABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoInsertValue(BoolConstantT, const value_type& value, DISABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\t// this overload won't allocate a node if an element with the same key exists.\n\t\ttemplate <typename BoolConstantT>\n\t\titerator DoInsertValue(BoolConstantT, value_type& value, DISABLE_IF_TRUETYPE(BoolConstantT) = nullptr);\n\n\t\ttemplate <class... Args>\n\t\tnode_type* DoAllocateNode(Args&&... args);\n\t\tnode_type* DoAllocateNode(value_type&& value);\n\t\tnode_type* DoAllocateNode(const value_type& value);\n\n\t\t// DoInsertKey is supposed to get hash_code_t c  = get_hash_code(key).\n\t\t// it is done in case application has it's own hashset/hashmap-like containter, where hash code is for some reason known prior the insert\n\t\t// this allows to save some performance, especially with heavy hash functions\n\t\t// \n\t\t// Note: only usable in hash_map / hash_multimap because this function (transitively) calls: value_type(pair_first_construct, key)\n\t\teastl::pair<iterator, bool> DoInsertKey(true_type, const key_type& key, hash_code_t c);\n\t\titerator                    DoInsertKey(false_type, const key_type& key, hash_code_t c);\n\n\t\t// We keep DoInsertKey overload without third parameter, for compatibility with older revisions of EASTL (3.12.07 and earlier)\n\t\t// It used to call get_hash_code as a first call inside the DoInsertKey.\n\t\t// \n\t\t// Note: only usable in hash_map / hash_multimap because this function (transitively) calls: value_type(pair_first_construct, key)\n\t\teastl::pair<iterator, bool> DoInsertKey(true_type, const key_type& key)  { return DoInsertKey(true_type(),  key, get_hash_code(key)); }\n\t\titerator                    DoInsertKey(false_type, const key_type& key) { return DoInsertKey(false_type(), key, get_hash_code(key)); }\n\n\t\tvoid       DoRehash(size_type nBucketCount);\n\t\ttemplate <typename KX>\n\t\tnode_type* DoFindNode(node_type* pNode, const KX& k, hash_code_t c) const;\n\t\ttemplate <typename KX>\n\t\tNodeFindKeyData DoFindKeyData(const KX& k) const;\n\n\t\ttemplate <typename T>\n\t\tENABLE_IF_HAS_HASHCODE(T, node_type) DoFindNode(T* pNode, hash_code_t c) const\n\t\t{\n\t\t\tfor (; pNode; pNode = pNode->mpNext)\n\t\t\t{\n\t\t\t\tif (pNode->mnHashCode == c)\n\t\t\t\t\treturn pNode;\n\t\t\t}\n\t\t\treturn NULL;\n\t\t}\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\tnode_type* DoFindNodeT(node_type* pNode, const U& u, BinaryPredicate predicate) const;\n\n\tprivate:\n\t\ttemplate <typename V, typename Enabled = bool_constant<bUniqueKeys>, ENABLE_IF_TRUETYPE(Enabled) = nullptr>\n\t\teastl::pair<iterator, bool> DoInsertValueExtraForwarding(const key_type& k,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thash_code_t c,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnode_type* pNodeNew,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tV&& value);\n\n\t\ttemplate<typename KX, typename M>\n\t\teastl::pair<iterator, bool> DoInsertOrAssign(KX&& k, M&& obj);\n\t\ttemplate<typename KX, typename M>\n\t\titerator\t\t\t\t\tDoInsertOrAssign(const_iterator hint, KX&& k, M&& obj);\n\n\t\ttemplate<typename KX>\n\t\tsize_type        DoErase(KX&& k);\n\n\t\ttemplate<typename KX>\n\t\titerator DoFind(const KX& key);\n\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoFind(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\tsize_type DoCount(const KX& key) const EA_NOEXCEPT;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& k);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& k) const;\n\n\t}; // class hashtable\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// node_iterator_base\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, bool bCacheHashCode>\n\tinline bool operator==(const node_iterator_base<Value, bCacheHashCode>& a, const node_iterator_base<Value, bCacheHashCode>& b)\n\t\t{ return a.mpNode == b.mpNode; }\n\n\ttemplate <typename Value, bool bCacheHashCode>\n\tinline bool operator!=(const node_iterator_base<Value, bCacheHashCode>& a, const node_iterator_base<Value, bCacheHashCode>& b)\n\t\t{ return a.mpNode != b.mpNode; }\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// hashtable_iterator_base\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, bool bCacheHashCode>\n\tinline bool operator==(const hashtable_iterator_base<Value, bCacheHashCode>& a, const hashtable_iterator_base<Value, bCacheHashCode>& b)\n\t\t{ return a.mpNode == b.mpNode; }\n\n\ttemplate <typename Value, bool bCacheHashCode>\n\tinline bool operator!=(const hashtable_iterator_base<Value, bCacheHashCode>& a, const hashtable_iterator_base<Value, bCacheHashCode>& b)\n\t\t{ return a.mpNode != b.mpNode; }\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// hashtable\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>\n\t::hashtable(size_type nBucketCount, const H1& h1, const H2& h2, const H& h,\n\t\t\t\tconst Eq& eq, const EK& ek, const allocator_type& allocator)\n\t\t:   rehash_base<RP, hashtable>(),\n\t\t\thash_code_base<K, V, EK, Eq, H1, H2, H, bC>(ek, eq, h1, h2, h),\n\t\t\tmnBucketCount(0),\n\t\t\tmnElementCount(0),\n\t\t\tmRehashPolicy(),\n\t\t\tmAllocator(allocator)\n\t{\n\t\tif(nBucketCount < 2)  // If we are starting in an initially empty state, with no memory allocation done.\n\t\t\treset_lose_memory();\n\t\telse // Else we are creating a potentially non-empty hashtable...\n\t\t{\n\t\t\tEASTL_ASSERT(nBucketCount < 10000000);\n\t\t\tmnBucketCount = (size_type)mRehashPolicy.GetNextBucketCount((uint32_t)nBucketCount);\n\t\t\tmpBucketArray = DoAllocateBuckets(mnBucketCount); // mnBucketCount will always be at least 2.\n\t\t}\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename FowardIterator>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(FowardIterator first, FowardIterator last, size_type nBucketCount, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t const H1& h1, const H2& h2, const H& h, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t const Eq& eq, const EK& ek, const allocator_type& allocator)\n\t\t:   rehash_base<rehash_policy_type, hashtable>(),\n\t\t\thash_code_base<key_type, value_type, extract_key_type, key_equal, h1_type, h2_type, h_type, kCacheHashCode>(ek, eq, h1, h2, h),\n\t\t  //mnBucketCount(0), // This gets re-assigned below.\n\t\t\tmnElementCount(0),\n\t\t\tmRehashPolicy(),\n\t\t\tmAllocator(allocator)\n\t{\n\t\tif(nBucketCount < 2)\n\t\t{\n\t\t\tconst size_type nElementCount = (size_type)eastl::ht_distance(first, last);\n\t\t\tmnBucketCount = (size_type)mRehashPolicy.GetBucketCount((uint32_t)nElementCount);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tEASTL_ASSERT(nBucketCount < 10000000);\n\t\t\tmnBucketCount = nBucketCount;\n\t\t}\n\n\t\tmpBucketArray = DoAllocateBuckets(mnBucketCount); // mnBucketCount will always be at least 2.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tfor(; first != last; ++first)\n\t\t\t\t\tinsert(*first);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tclear();\n\t\t\t\tDoFreeBuckets(mpBucketArray, mnBucketCount);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(const this_type& x)\n\t\t:   rehash_base<RP, hashtable>(x),\n\t\t\thash_code_base<K, V, EK, Eq, H1, H2, H, bC>(x),\n\t\t\tmnBucketCount(x.mnBucketCount),\n\t\t\tmnElementCount(x.mnElementCount),\n\t\t\tmRehashPolicy(x.mRehashPolicy),\n\t\t\tmAllocator(x.mAllocator)\n\t{\n\t\tif(mnElementCount) // If there is anything to copy...\n\t\t{\n\t\t\tmpBucketArray = DoAllocateBuckets(mnBucketCount); // mnBucketCount will be at least 2.\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\tfor(size_type i = 0; i < x.mnBucketCount; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tnode_type*  pNodeSource = x.mpBucketArray[i];\n\t\t\t\t\t\tnode_type** ppNodeDest  = mpBucketArray + i;\n\n\t\t\t\t\t\twhile(pNodeSource)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t*ppNodeDest = DoAllocateNode(pNodeSource->mValue);\n\t\t\t\t\t\t\tcopy_code(*ppNodeDest, pNodeSource);\n\t\t\t\t\t\t\tppNodeDest = &(*ppNodeDest)->mpNext;\n\t\t\t\t\t\t\tpNodeSource = pNodeSource->mpNext;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tclear();\n\t\t\t\t\tDoFreeBuckets(mpBucketArray, mnBucketCount);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// In this case, instead of allocate memory and copy nothing from x, \n\t\t\t// we reset ourselves to a zero allocation state.\n\t\t\treset_lose_memory();\n\t\t}\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(this_type&& x)\n\t\t:   rehash_base<RP, hashtable>(x),\n\t\t\thash_code_base<K, V, EK, Eq, H1, H2, H, bC>(x),\n\t\t\tmnBucketCount(0),\n\t\t\tmnElementCount(0),\n\t\t\tmRehashPolicy(x.mRehashPolicy),\n\t\t\tmAllocator(x.mAllocator)\n\t{\n\t\treset_lose_memory(); // We do this here the same as we do it in the default ctor because it puts the container in a proper initial empty state. This code would be cleaner if we could rely on being able to use C++11 delegating constructors and just call the default ctor here.\n\t\tswap(x);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(this_type&& x, const allocator_type& allocator)\n\t\t:   rehash_base<RP, hashtable>(x),\n\t\t\thash_code_base<K, V, EK, Eq, H1, H2, H, bC>(x),\n\t\t\tmnBucketCount(0),\n\t\t\tmnElementCount(0),\n\t\t\tmRehashPolicy(x.mRehashPolicy),\n\t\t\tmAllocator(allocator)\n\t{\n\t\treset_lose_memory(); // We do this here the same as we do it in the default ctor because it puts the container in a proper initial empty state. This code would be cleaner if we could rely on being able to use C++11 delegating constructors and just call the default ctor here.\n\t\tswap(x); // swap will directly or indirectly handle the possibility that mAllocator != x.mAllocator.\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline const typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::allocator_type&\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::get_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::allocator_type&\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::get_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::set_allocator(const allocator_type& allocator)\n\t{\n\t\tif(mnBucketCount > 1 && mAllocator != allocator)\n\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"hashtable::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\t\n\t\tmAllocator = allocator;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::this_type&\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tmAllocator = x.mAllocator;\n\t\t\t#endif\n\n\t\t\tinsert(x.begin(), x.end());\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::this_type&\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::operator=(this_type&& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();        // To consider: Are we really required to clear here? x is going away soon and will clear itself in its dtor.\n\t\t\tswap(x);        // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::this_type&\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\t// The simplest means of doing this is to clear and insert. There probably isn't a generic\n\t\t// solution that's any more efficient without having prior knowledge of the ilist contents.\n\t\tclear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::~hashtable()\n\t{\n\t\tclear();\n\t\tDoFreeBuckets(mpBucketArray, mnBucketCount);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNodeFromKey(const key_type& key)\n\t{\n\t\tnode_type* const pNode = (node_type*)allocate_memory(mAllocator, sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT_MSG(pNode != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), piecewise_construct, eastl::make_tuple(key), eastl::tuple<>{});\n\t\t\t\tpNode->mpNext = NULL;\n\t\t\t\treturn pNode;\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNodeFromKey(key_type&& key)\n\t{\n\t\tnode_type* const pNode = (node_type*)allocate_memory(mAllocator, sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT_MSG(pNode != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), piecewise_construct, eastl::forward_as_tuple(eastl::move(key)), eastl::tuple<>{});\n\t\t\t\tpNode->mpNext = NULL;\n\t\t\t\treturn pNode;\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFreeNode(node_type* pNode)\n\t{\n\t\tpNode->~node_type();\n\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tvoid hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFreeNodes(node_type** pNodeArray, size_type n)\n\t{\n\t\t// If n <= 1, then pNodeArray is the shared gpEmptyBucketArray. We don't test for\n\t\t// pBucketArray == &gpEmptyBucketArray because one library have a different\n\t\t// gpEmptyBucketArray than another but pass a hashtable to another. So we go by the\n\t\t// size. We want to early out here because the code below writes to the bucket array,\n\t\t// and we don't want to concurrently write to a global, it is not thread safe and TSAN\n\t\t// will complain.\n\t\tif (n < 2)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tfor(size_type i = 0; i < n; ++i)\n\t\t{\n\t\t\tnode_type* pNode = pNodeArray[i];\n\t\t\twhile(pNode)\n\t\t\t{\n\t\t\t\tnode_type* const pTempNode = pNode;\n\t\t\t\tpNode = pNode->mpNext;\n\t\t\t\tDoFreeNode(pTempNode);\n\t\t\t}\n\t\t\tpNodeArray[i] = nullptr;\n\t\t}\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type**\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateBuckets(size_type n)\n\t{\n\t\t// We allocate one extra bucket to hold a sentinel, an arbitrary\n\t\t// non-null pointer. Iterator increment relies on this.\n\t\tEASTL_ASSERT(n > 1); // We reserve an mnBucketCount of 1 for the shared gpEmptyBucketArray.\n\t\tEASTL_CT_ASSERT(kHashtableAllocFlagBuckets == 0x00400000); // Currently we expect this to be so, because the allocator has a copy of this enum.\n\t\tnode_type** const pBucketArray = (node_type**)EASTLAllocAlignedFlags(mAllocator, (n + 1) * sizeof(node_type*), EASTL_ALIGN_OF(node_type*), 0, kHashtableAllocFlagBuckets);\n\t\t//eastl::fill(pBucketArray, pBucketArray + n, (node_type*)NULL);\n\t\tmemset(pBucketArray, 0, n * sizeof(node_type*));\n\t\tpBucketArray[n] = reinterpret_cast<node_type*>((uintptr_t)~0);\n\t\treturn pBucketArray;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFreeBuckets(node_type** pBucketArray, size_type n)\n\t{\n\t\t// If n <= 1, then pBucketArray is from the shared gpEmptyBucketArray. We don't test \n\t\t// for pBucketArray == &gpEmptyBucketArray because one library have a different gpEmptyBucketArray\n\t\t// than another but pass a hashtable to another. So we go by the size.\n\t\tif(n > 1)\n\t\t\tEASTLFree(mAllocator, pBucketArray, (n + 1) * sizeof(node_type*)); // '+1' because DoAllocateBuckets allocates nBucketCount + 1 buckets in order to have a NULL sentinel at the end.\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tvoid hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::swap(this_type& x)\n\t{\n\t\thash_code_base<K, V, EK, Eq, H1, H2, H, bC>::base_swap(x); // hash_code_base has multiple implementations, so we let them handle the swap.\n\t\teastl::swap(mRehashPolicy, x.mRehashPolicy);\n\t\tEASTL_MACRO_SWAP(node_type**, mpBucketArray, x.mpBucketArray);\n\t\teastl::swap(mnBucketCount, x.mnBucketCount);\n\t\teastl::swap(mnElementCount, x.mnElementCount);\n\n\t\tif (mAllocator != x.mAllocator) // If allocators are not equivalent...\n\t\t{\n\t\t\teastl::swap(mAllocator, x.mAllocator);\n\t\t}\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::rehash_policy(const rehash_policy_type& rehashPolicy)\n\t{\n\t\tmRehashPolicy = rehashPolicy;\n\n\t\tconst size_type nBuckets = rehashPolicy.GetBucketCount((uint32_t)mnElementCount);\n\n\t\tif(nBuckets > mnBucketCount)\n\t\t\tDoRehash(nBuckets);\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFind(const KX& k)\n\t{\n\t\tconst hash_code_t c = get_hash_code(k);\n\t\tconst size_type   n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\n\t\tnode_type* const pNode = DoFindNode(mpBucketArray[n], k, c);\n\t\treturn pNode ? iterator(pNode, mpBucketArray + n) : iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFind(const KX& k) const\n\t{\n\t\tconst hash_code_t c = get_hash_code(k);\n\t\tconst size_type   n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\n\t\tnode_type* const pNode = DoFindNode(mpBucketArray[n], k, c);\n\t\treturn pNode ? const_iterator(pNode, mpBucketArray + n) : const_iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(const U& other, UHash uhash, BinaryPredicate predicate)\n\t{\n\t\tconst hash_code_t c = (hash_code_t)uhash(other);\n\t\tconst size_type   n = (size_type)(c % mnBucketCount); // This assumes we are using the mod range policy.\n\n\t\tnode_type* const pNode = DoFindNodeT(mpBucketArray[n], other, predicate);\n\t\treturn pNode ? iterator(pNode, mpBucketArray + n) : iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(const U& other, UHash uhash, BinaryPredicate predicate) const\n\t{\n\t\tconst hash_code_t c = (hash_code_t)uhash(other);\n\t\tconst size_type   n = (size_type)(c % mnBucketCount); // This assumes we are using the mod range policy.\n\n\t\tnode_type* const pNode = DoFindNodeT(mpBucketArray[n], other, predicate);\n\t\treturn pNode ? const_iterator(pNode, mpBucketArray + n) : const_iterator(mpBucketArray + mnBucketCount); // iterator(mpBucketArray + mnBucketCount) == end()\n\t}\n\n\n\t/// hashtable_find\n\t///\n\t/// Deprecated: Using default hash and equality objects may result in\n\t/// incorrect semantics (undefined behaviour).\n\t/// Use find() with heterogenous lookup (ie. function objects with a\n\t/// is_transparent type member) or explicitly specify hash and equality\n\t/// objects.\n\t///\n\t/// Helper function that defaults to using hash<U> and equal_to<>.\n\t/// This makes it so that by default you don't need to provide these.\n\t/// Note that the default hash functions may not be what you want, though.\n\t///\n\t/// Example usage. Instead of this:\n\t///     hash_set<string> hashSet;\n\t///     hashSet.find(\"hello\", hash<char*>(), equal_to<>());\n\t///\n\t/// You can use this:\n\t///     hash_set<string> hashSet;\n\t///     hashtable_find(hashSet, \"hello\");\n\ttemplate <typename H, typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename H::iterator hashtable_find(H& hashTable, U u)\n\t\t{ return hashTable.find_as(u, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\ttemplate <typename H, typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename H::const_iterator hashtable_find(const H& hashTable, U u)\n\t\t{ return hashTable.find_as(u, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(const U& other)\n\t{\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\treturn eastl::hashtable_find(*this, other);\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t}\n\t\t// VC++ doesn't appear to like the following, though it seems correct to me.\n\t\t// So we implement the workaround above until we can straighten this out.\n\t\t//{ return find_as(other, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(const U& other) const\n\t{\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\treturn eastl::hashtable_find(*this, other);\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t}\n\t\t// VC++ doesn't appear to like the following, though it seems correct to me.\n\t\t// So we implement the workaround above until we can straighten this out.\n\t\t//{ return find_as(other, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq, \n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator,\n\t\t\t\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_range_by_hash(hash_code_t c) const\n\t{\n\t\tconst size_type start = (size_type)bucket_index(c, (uint32_t)mnBucketCount);\n\t\tnode_type* const pNodeStart = mpBucketArray[start];\n\n\t\tif (pNodeStart)\n\t\t{\n\t\t\teastl::pair<const_iterator, const_iterator> pair(const_iterator(pNodeStart, mpBucketArray + start), \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t const_iterator(pNodeStart, mpBucketArray + start));\n\t\t\tpair.second.increment_bucket();\n\t\t\treturn pair;\n\t\t}\n\n\t\treturn eastl::pair<const_iterator, const_iterator>(const_iterator(mpBucketArray + mnBucketCount),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   const_iterator(mpBucketArray + mnBucketCount));\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq, \n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,\n\t\t\t\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_range_by_hash(hash_code_t c)\n\t{\n\t\tconst size_type start = (size_type)bucket_index(c, (uint32_t)mnBucketCount);\n\t\tnode_type* const pNodeStart = mpBucketArray[start];\n\n\t\tif (pNodeStart)\n\t\t{\n\t\t\teastl::pair<iterator, iterator> pair(iterator(pNodeStart, mpBucketArray + start), \n\t\t\t\t\t\t\t\t\t\t\t\t iterator(pNodeStart, mpBucketArray + start));\n\t\t\tpair.second.increment_bucket();\n\t\t\treturn pair;\n\n\t\t}\n\n\t\treturn eastl::pair<iterator, iterator>(iterator(mpBucketArray + mnBucketCount),\n\t\t\t\t\t\t\t\t\t\t\t   iterator(mpBucketArray + mnBucketCount));\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::size_type\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoCount(const KX& k) const EA_NOEXCEPT\n\t{\n\t\tconst hash_code_t c      = get_hash_code(k);\n\t\tconst size_type   n      = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\t\tsize_type         result = 0;\n\n\t\t// To do: Make a specialization for bU (unique keys) == true and take \n\t\t// advantage of the fact that the count will always be zero or one in that case. \n\t\tfor(node_type* pNode = mpBucketArray[n]; pNode; pNode = pNode->mpNext)\n\t\t{\n\t\t\tif(compare(k, c, pNode))\n\t\t\t\t++result;\n\t\t}\n\t\treturn result;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,\n\t\t\t\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoEqualRange(const KX& k)\n\t{\n\t\tconst hash_code_t c     = get_hash_code(k);\n\t\tconst size_type   n     = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\t\tnode_type**       head  = mpBucketArray + n;\n\t\tnode_type*        pNode = DoFindNode(*head, k, c);\n\n\t\tif(pNode)\n\t\t{\n\t\t\tnode_type* p1 = pNode->mpNext;\n\n\t\t\tfor(; p1; p1 = p1->mpNext)\n\t\t\t{\n\t\t\t\tif(!compare(k, c, p1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\titerator first(pNode, head);\n\t\t\titerator last(p1, head);\n\n\t\t\tif(!p1)\n\t\t\t\tlast.increment_bucket();\n\n\t\t\treturn eastl::pair<iterator, iterator>(first, last);\n\t\t}\n\n\t\treturn eastl::pair<iterator, iterator>(iterator(mpBucketArray + mnBucketCount),  // iterator(mpBucketArray + mnBucketCount) == end()\n\t\t\t\t\t\t\t\t\t\t\t   iterator(mpBucketArray + mnBucketCount));\n\t}\n\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator,\n\t\t\t\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoEqualRange(const KX& k) const\n\t{\n\t\tconst hash_code_t c     = get_hash_code(k);\n\t\tconst size_type   n     = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\t\tnode_type**       head  = mpBucketArray + n;\n\t\tnode_type*        pNode = DoFindNode(*head, k, c);\n\n\t\tif(pNode)\n\t\t{\n\t\t\tnode_type* p1 = pNode->mpNext;\n\n\t\t\tfor(; p1; p1 = p1->mpNext)\n\t\t\t{\n\t\t\t\tif(!compare(k, c, p1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst_iterator first(pNode, head);\n\t\t\tconst_iterator last(p1, head);\n\n\t\t\tif(!p1)\n\t\t\t\tlast.increment_bucket();\n\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(first, last);\n\t\t}\n\n\t\treturn eastl::pair<const_iterator, const_iterator>(const_iterator(mpBucketArray + mnBucketCount),  // iterator(mpBucketArray + mnBucketCount) == end()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   const_iterator(mpBucketArray + mnBucketCount));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::NodeFindKeyData\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFindKeyData(const KX& k) const {\n\t\tNodeFindKeyData d;\n\t\td.code\t\t   = get_hash_code(k);\n\t\td.bucket_index = (size_type)bucket_index(k, d.code, (uint32_t)mnBucketCount);\n\t\td.node\t\t   = DoFindNode(mpBucketArray[d.bucket_index], k, d.code);\n\t\treturn d;\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type* \n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFindNode(node_type* pNode, const KX& k, hash_code_t c) const\n\t{\n\t\tfor(; pNode; pNode = pNode->mpNext)\n\t\t{\n\t\t\tif(compare(k, c, pNode))\n\t\t\t\treturn pNode;\n\t\t}\n\t\treturn NULL;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type* \n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFindNodeT(node_type* pNode, const U& other, BinaryPredicate predicate) const\n\t{\n\t\tfor(; pNode; pNode = pNode->mpNext)\n\t\t{\n\t\t\tif(predicate(mExtractKey(pNode->mValue), other)) // Intentionally compare with key as first arg and other as second arg.\n\t\t\t\treturn pNode;\n\t\t}\n\t\treturn NULL;\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <bool bDeleteOnException, typename Enabled, ENABLE_IF_TRUETYPE(Enabled)> // only enabled when keys are unique\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertUniqueNode(const key_type& k, hash_code_t c, size_type n, node_type* pNodeNew)\n\t{\n\t\tconst eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);\n\n\t\tset_code(pNodeNew, c); // This is a no-op for most hashtables.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tif(bRehash.first)\n\t\t\t\t{\n\t\t\t\t\tn = (size_type)bucket_index(k, c, (uint32_t)bRehash.second);\n\t\t\t\t\tDoRehash(bRehash.second);\n\t\t\t\t}\n\n\t\t\t\tEASTL_ASSERT((uintptr_t)mpBucketArray != (uintptr_t)&gpEmptyBucketArray[0]);\n\t\t\t\tpNodeNew->mpNext = mpBucketArray[n];\n\t\t\t\tmpBucketArray[n] = pNodeNew;\n\t\t\t\t++mnElementCount;\n\n\t\t\t\treturn eastl::pair<iterator, bool>(iterator(pNodeNew, mpBucketArray + n), true);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t    EA_CONSTEXPR_IF(bDeleteOnException) { DoFreeNode(pNodeNew); }\n\t\t\t    throw;\n\t\t    }\n\t\t#endif\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT, class... Args, ENABLE_IF_TRUETYPE(BoolConstantT)>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, Args&&... args) // true_type means bUniqueKeys is true.\n\t{\n\t\t// Adds the value to the hash table if not already present. \n\t\t// If already present then the existing value is returned via an iterator/bool pair.\n\n\t\t// We have a chicken-and-egg problem here. In order to know if and where to insert the value, we need to get the \n\t\t// hashtable key for the value. But we don't explicitly have a value argument, we have a templated Args&&... argument.\n\t\t// We need the value_type in order to proceed, but that entails getting an instance of a value_type from the args.\n\t\t// And it may turn out that the value is already present in the hashtable and we need to cancel the insertion, \n\t\t// despite having obtained a value_type to put into the hashtable. We have mitigated this problem somewhat by providing\n\t\t// specializations of the insert function for const value_type& and value_type&&, and so the only time this function\n\t\t// should get called is when args refers to arguments to construct a value_type.\n\n\t\tnode_type* const  pNodeNew = DoAllocateNode(eastl::forward<Args>(args)...);\n\t\tconst key_type&   k        = mExtractKey(pNodeNew->mValue);\n\t\tconst hash_code_t c        = get_hash_code(k);\n\t\tsize_type         n        = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\t\tnode_type* const  pNode    = DoFindNode(mpBucketArray[n], k, c);\n\n\t\tif(pNode == NULL) // If value is not present... add it.\n\t\t{\n\t\t\treturn DoInsertUniqueNode<true>(k, c, n, pNodeNew);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// To do: We have an inefficiency to deal with here. We allocated a node above but we are freeing it here because\n\t\t\t// it turned out it wasn't needed. But we needed to create the node in order to get the hashtable key for\n\t\t\t// the node. One possible resolution is to create specializations: DoInsertValue(true_type, value_type&&) and \n\t\t\t// DoInsertValue(true_type, const value_type&) which don't need to create a node up front in order to get the \n\t\t\t// hashtable key. Probably most users would end up using these pathways instead of this Args... pathway.\n\t\t\t// While we should considering handling this to-do item, a lot of the performance limitations of maps and sets \n\t\t\t// in practice is with finding elements rather than adding (potentially redundant) new elements.\n\t\t\tDoFreeNode(pNodeNew);\n\t\t}\n\n\t\treturn eastl::pair<iterator, bool>(iterator(pNode, mpBucketArray + n), false);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT, class... Args, DISABLE_IF_TRUETYPE(BoolConstantT)>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, Args&&... args) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);\n\n\t\tif(bRehash.first)\n\t\t\tDoRehash(bRehash.second);\n\n\t\tnode_type*        pNodeNew = DoAllocateNode(eastl::forward<Args>(args)...);\n\t\tconst key_type&   k        = mExtractKey(pNodeNew->mValue);\n\t\tconst hash_code_t c        = get_hash_code(k);\n\t\tconst size_type   n        = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\n\t\tset_code(pNodeNew, c); // This is a no-op for most hashtables.\n\n\t\t// To consider: Possibly make this insertion not make equal elements contiguous.\n\t\t// As it stands now, we insert equal values contiguously in the hashtable.\n\t\t// The benefit is that equal_range can work in a sensible manner and that\n\t\t// erase(value) can more quickly find equal values. The downside is that\n\t\t// this insertion operation taking some extra time. How important is it to\n\t\t// us that equal_range span all equal items? \n\t\tnode_type* const pNodePrev = DoFindNode(mpBucketArray[n], k, c);\n\n\t\tif(pNodePrev == NULL)\n\t\t{\n\t\t\tEASTL_ASSERT((void**)mpBucketArray != &gpEmptyBucketArray[0]);\n\t\t\tpNodeNew->mpNext = mpBucketArray[n];\n\t\t\tmpBucketArray[n] = pNodeNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpNodeNew->mpNext  = pNodePrev->mpNext;\n\t\t\tpNodePrev->mpNext = pNodeNew;\n\t\t}\n\n\t\t++mnElementCount;\n\n\t\treturn iterator(pNodeNew, mpBucketArray + n);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <class... Args>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNode(Args&&... args)\n\t{\n\t\tnode_type* const pNode = (node_type*)allocate_memory(mAllocator, sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT_MSG(pNode != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), eastl::forward<Args>(args)...);\n\t\t\t\tpNode->mpNext = NULL;\n\t\t\t\treturn pNode;\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\t////////////////////////////////////////////////////////////////////////////////////////////////////\n\t// Note: The following insertion-related functions are nearly copies of the above three functions,\n\t// but are for value_type&& and const value_type& arguments. It's useful for us to have the functions\n\t// below, even when using a fully compliant C++11 compiler that supports the above functions. \n\t// The reason is because the specializations below are slightly more efficient because they can delay\n\t// the creation of a node until it's known that it will be needed.\n\t////////////////////////////////////////////////////////////////////////////////////////////////////\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT>\n\tinline eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT, const key_type& k,\n\t\thash_code_t c, node_type* pNodeNew, value_type&& value, ENABLE_IF_TRUETYPE(BoolConstantT)) // true_type means bUniqueKeys is true.\n\t{\n\t\treturn DoInsertValueExtraForwarding(k, c, pNodeNew, eastl::move(value));\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT>\n\tinline eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT, const key_type& k,\n\t\thash_code_t c, node_type* pNodeNew, const value_type& value, ENABLE_IF_TRUETYPE(BoolConstantT)) // true_type means bUniqueKeys is true.\n\t{\n\t\treturn DoInsertValueExtraForwarding(k, c, pNodeNew, value);\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename VFwd, typename Enabled, ENABLE_IF_TRUETYPE(Enabled)> // true_type means bUniqueKeys is true.\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtraForwarding(const key_type& k,\n\t\thash_code_t c, node_type* pNodeNew, VFwd&& value)\n\t{\n\t\t// Adds the value to the hash table if not already present. \n\t\t// If already present then the existing value is returned via an iterator/bool pair.\n\t\tsize_type         n     = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\t\tnode_type* const  pNode = DoFindNode(mpBucketArray[n], k, c);\n\n\t\tif(pNode == NULL) // If value is not present... add it.\n\t\t{\n\t\t\t// Allocate the new node before doing the rehash so that we don't\n\t\t\t// do a rehash if the allocation throws.\n\t\t\tif(pNodeNew)\n\t\t\t{\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNodeNew->mValue), eastl::forward<VFwd>(value)); // It's expected that pNodeNew was allocated with allocate_uninitialized_node.\n\t\t\t\treturn DoInsertUniqueNode<false>(k, c, n, pNodeNew);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpNodeNew = DoAllocateNode(eastl::move(value));\n\t\t\t\treturn DoInsertUniqueNode<true>(k, c, n, pNodeNew);\n\t\t\t}\n\t\t}\n\t\t// Else the value is already present, so don't add a new node. And don't free pNodeNew.\n\n\t\treturn eastl::pair<iterator, bool>(iterator(pNode, mpBucketArray + n), false);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, value_type&& value, ENABLE_IF_TRUETYPE(BoolConstantT)) // true_type means bUniqueKeys is true.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(true_type(), k, c, NULL, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, const value_type&& value, ENABLE_IF_TRUETYPE(BoolConstantT)) // true_type means bUniqueKeys is true.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(true_type(), k, c, NULL, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT, const key_type& k, hash_code_t c, node_type* pNodeNew, value_type&& value, \n\t\t\tDISABLE_IF_TRUETYPE(BoolConstantT)) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);\n\n\t\tif(bRehash.first)\n\t\t\tDoRehash(bRehash.second); // Note: We don't need to wrap this call with try/catch because there's nothing we would need to do in the catch.\n\n\t\tconst size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\n\t\tif(pNodeNew)\n\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNodeNew->mValue), eastl::move(value)); // It's expected that pNodeNew was allocated with allocate_uninitialized_node.\n\t\telse\n\t\t\tpNodeNew = DoAllocateNode(eastl::move(value));\n\n\t\tset_code(pNodeNew, c); // This is a no-op for most hashtables.\n\n\t\t// To consider: Possibly make this insertion not make equal elements contiguous.\n\t\t// As it stands now, we insert equal values contiguously in the hashtable.\n\t\t// The benefit is that equal_range can work in a sensible manner and that\n\t\t// erase(value) can more quickly find equal values. The downside is that\n\t\t// this insertion operation taking some extra time. How important is it to\n\t\t// us that equal_range span all equal items? \n\t\tnode_type* const pNodePrev = DoFindNode(mpBucketArray[n], k, c);\n\n\t\tif(pNodePrev == NULL)\n\t\t{\n\t\t\tEASTL_ASSERT((void**)mpBucketArray != &gpEmptyBucketArray[0]);\n\t\t\tpNodeNew->mpNext = mpBucketArray[n];\n\t\t\tmpBucketArray[n] = pNodeNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpNodeNew->mpNext  = pNodePrev->mpNext;\n\t\t\tpNodePrev->mpNext = pNodeNew;\n\t\t}\n\n\t\t++mnElementCount;\n\n\t\treturn iterator(pNodeNew, mpBucketArray + n);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate<typename BoolConstantT>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, value_type&& value, DISABLE_IF_TRUETYPE(BoolConstantT)) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(false_type(), k, c, NULL, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate<typename BoolConstantT>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, const value_type&& value, DISABLE_IF_TRUETYPE(BoolConstantT)) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(false_type(), k, c, NULL, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNode(value_type&& value)\n\t{\n\t\tnode_type* const pNode = (node_type*)allocate_memory(mAllocator, sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT_MSG(pNode != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), eastl::move(value));\n\t\t\t\tpNode->mpNext = NULL;\n\t\t\t\treturn pNode;\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate<typename BoolConstantT>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, const value_type& value, ENABLE_IF_TRUETYPE(BoolConstantT)) // true_type means bUniqueKeys is true.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(true_type(), k, c, NULL, value);\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate<typename BoolConstantT>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, value_type& value, ENABLE_IF_TRUETYPE(BoolConstantT)) // true_type means bUniqueKeys is true.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(true_type(), k, c, NULL, value);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename BoolConstantT>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT, const key_type& k, hash_code_t c, node_type* pNodeNew, const value_type& value,\n\t\t\tDISABLE_IF_TRUETYPE(BoolConstantT)) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);\n\n\t\tif(bRehash.first)\n\t\t\tDoRehash(bRehash.second); // Note: We don't need to wrap this call with try/catch because there's nothing we would need to do in the catch.\n\n\t\tconst size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\n\t\tif(pNodeNew)\n\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNodeNew->mValue), value); // It's expected that pNodeNew was allocated with allocate_uninitialized_node.\n\t\telse\n\t\t\tpNodeNew = DoAllocateNode(value);\n\n\t\tset_code(pNodeNew, c); // This is a no-op for most hashtables.\n\n\t\t// To consider: Possibly make this insertion not make equal elements contiguous.\n\t\t// As it stands now, we insert equal values contiguously in the hashtable.\n\t\t// The benefit is that equal_range can work in a sensible manner and that\n\t\t// erase(value) can more quickly find equal values. The downside is that\n\t\t// this insertion operation taking some extra time. How important is it to\n\t\t// us that equal_range span all equal items? \n\t\tnode_type* const pNodePrev = DoFindNode(mpBucketArray[n], k, c);\n\n\t\tif(pNodePrev == NULL)\n\t\t{\n\t\t\tEASTL_ASSERT((void**)mpBucketArray != &gpEmptyBucketArray[0]);\n\t\t\tpNodeNew->mpNext = mpBucketArray[n];\n\t\t\tmpBucketArray[n] = pNodeNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpNodeNew->mpNext  = pNodePrev->mpNext;\n\t\t\tpNodePrev->mpNext = pNodeNew;\n\t\t}\n\n\t\t++mnElementCount;\n\n\t\treturn iterator(pNodeNew, mpBucketArray + n);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate<typename BoolConstantT>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, const value_type& value, DISABLE_IF_TRUETYPE(BoolConstantT)) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(false_type(), k, c, NULL, value);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate<typename BoolConstantT>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, value_type& value, DISABLE_IF_TRUETYPE(BoolConstantT)) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst key_type&   k = mExtractKey(value);\n\t\tconst hash_code_t c = get_hash_code(k);\n\n\t\treturn DoInsertValueExtra(false_type(), k, c, NULL, value);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNode(const value_type& value)\n\t{\n\t\tnode_type* const pNode = (node_type*)allocate_memory(mAllocator, sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT_MSG(pNode != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), value);\n\t\t\t\tpNode->mpNext = NULL;\n\t\t\t\treturn pNode;\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::allocate_uninitialized_node()\n\t{\n\t\t// We don't wrap this in try/catch because users of this function are expected to do that themselves as needed.\n\t\tnode_type* const pNode = (node_type*)allocate_memory(mAllocator, sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT_MSG(pNode != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\t\t// Leave pNode->mValue uninitialized.\n\t\tpNode->mpNext = NULL;\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tvoid hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::free_uninitialized_node(node_type* pNode)\n\t{\n\t\t// pNode->mValue is expected to be uninitialized.\n\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertKey(true_type, const key_type& key, const hash_code_t c) // true_type means bUniqueKeys is true.\n\t{\n\t\tsize_type         n     = (size_type)bucket_index(key, c, (uint32_t)mnBucketCount);\n\t\tnode_type* const  pNode = DoFindNode(mpBucketArray[n], key, c);\n\n\t\tif(pNode == NULL)\n\t\t{\n\t\t\tconst eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);\n\n\t\t\t// Allocate the new node before doing the rehash so that we don't\n\t\t\t// do a rehash if the allocation throws.\n\t\t\tnode_type* const pNodeNew = DoAllocateNodeFromKey(key);\n\t\t\tset_code(pNodeNew, c); // This is a no-op for most hashtables.\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\tif(bRehash.first)\n\t\t\t\t\t{\n\t\t\t\t\t\tn = (size_type)bucket_index(key, c, (uint32_t)bRehash.second);\n\t\t\t\t\t\tDoRehash(bRehash.second);\n\t\t\t\t\t}\n\n\t\t\t\t\tEASTL_ASSERT((void**)mpBucketArray != &gpEmptyBucketArray[0]);\n\t\t\t\t\tpNodeNew->mpNext = mpBucketArray[n];\n\t\t\t\t\tmpBucketArray[n] = pNodeNew;\n\t\t\t\t\t++mnElementCount;\n\n\t\t\t\t\treturn eastl::pair<iterator, bool>(iterator(pNodeNew, mpBucketArray + n), true);\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tDoFreeNode(pNodeNew);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\n\t\treturn eastl::pair<iterator, bool>(iterator(pNode, mpBucketArray + n), false);\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertKey(false_type, const key_type& key, const hash_code_t c) // false_type means bUniqueKeys is false.\n\t{\n\t\tconst eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);\n\n\t\tif(bRehash.first)\n\t\t\tDoRehash(bRehash.second);\n\n\t\tconst size_type   n = (size_type)bucket_index(key, c, (uint32_t)mnBucketCount);\n\n\t\tnode_type* const pNodeNew = DoAllocateNodeFromKey(key);\n\t\tset_code(pNodeNew, c); // This is a no-op for most hashtables.\n\n\t\t// To consider: Possibly make this insertion not make equal elements contiguous.\n\t\t// As it stands now, we insert equal values contiguously in the hashtable.\n\t\t// The benefit is that equal_range can work in a sensible manner and that\n\t\t// erase(value) can more quickly find equal values. The downside is that\n\t\t// this insertion operation taking some extra time. How important is it to\n\t\t// us that equal_range span all equal items? \n\t\tnode_type* const pNodePrev = DoFindNode(mpBucketArray[n], key, c);\n\n\t\tif(pNodePrev == NULL)\n\t\t{\n\t\t\tEASTL_ASSERT((void**)mpBucketArray != &gpEmptyBucketArray[0]);\n\t\t\tpNodeNew->mpNext = mpBucketArray[n];\n\t\t\tmpBucketArray[n] = pNodeNew;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpNodeNew->mpNext  = pNodePrev->mpNext;\n\t\t\tpNodePrev->mpNext = pNodeNew;\n\t\t}\n\n\t\t++mnElementCount;\n\n\t\treturn iterator(pNodeNew, mpBucketArray + n);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <class... Args>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::emplace(Args&&... args)\n\t{\n\t\t// note: DoInsertValue has overloads for const/non-const lvalue/rvalue value_type which won't allocate a node if an element with the same key exists.\n\t\t// these four overloads are necessary so that we don't call DoInsertValue(BoolConstantT, Args&&...) instead, which always allocates a node.\n\t\treturn DoInsertValue(has_unique_keys_type(), eastl::forward<Args>(args)...); // Need to use forward instead of move because Args&& is a \"universal reference\" instead of an rvalue reference.\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t\ttypename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <class... Args>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::emplace_hint(const_iterator, Args&&... args)\n\t{\n\t\t// We currently ignore the iterator argument as a hint.\n\t\tinsert_return_type result = DoInsertValue(has_unique_keys_type(), eastl::forward<Args>(args)...);\n\t\treturn DoGetResultIterator(has_unique_keys_type(), result);\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(value_type&& otherValue)\n\t{\n\t\treturn DoInsertValue(has_unique_keys_type(), eastl::move(otherValue));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <class P>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(hash_code_t c, node_type* pNodeNew, P&& otherValue)\n\t{\n\t\t// pNodeNew->mValue is expected to be uninitialized.\n\t\tvalue_type value(eastl::forward<P>(otherValue)); // Need to use forward instead of move because P&& is a \"universal reference\" instead of an rvalue reference.\n\t\tconst key_type& k = mExtractKey(value);\n\t\treturn DoInsertValueExtra(has_unique_keys_type(), k, c, pNodeNew, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(const_iterator, value_type&& value)\n\t{\n\t\t// We currently ignore the iterator argument as a hint.\n\t\tinsert_return_type result = DoInsertValue(has_unique_keys_type(), value_type(eastl::move(value)));\n\t\treturn DoGetResultIterator(has_unique_keys_type(), result);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(const value_type& value) \n\t{\n\t\treturn DoInsertValue(has_unique_keys_type(), value);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(hash_code_t c, node_type* pNodeNew, const value_type& value) \n\t{\n\t\t// pNodeNew->mValue is expected to be uninitialized.\n\t\tconst key_type& k = mExtractKey(value);\n\t\treturn DoInsertValueExtra(has_unique_keys_type(), k, c, pNodeNew, value);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(const_iterator, const value_type& value)\n\t{\n\t\t// We ignore the first argument (hint iterator). It's not likely to be useful for hashtable containers.\n\t\tinsert_return_type result = DoInsertValue(has_unique_keys_type(), value);\n\t\treturn DoGetResultIterator(has_unique_keys_type(), result);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tvoid hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(std::initializer_list<value_type> ilist)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename InputIterator>\n\tvoid\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(InputIterator first, InputIterator last)\n\t{\n\t\tconst uint32_t nElementAdd = (uint32_t)eastl::ht_distance(first, last);\n\t\tconst eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, nElementAdd);\n\n\t\tif(bRehash.first)\n\t\t\tDoRehash(bRehash.second);\n\n\t\tfor(; first != last; ++first)\n\t\t\tDoInsertValue(has_unique_keys_type(), *first);\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <class KX, class M>\n\teastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator, bool>\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertOrAssign(KX&& k, M&& obj)\n\t{\n\t\tauto iter = find(k);\n\t\tif(iter == end())\n\t\t{\n\t\t\treturn insert(value_type(eastl::forward<KX>(k), eastl::forward<M>(obj)));\n\t\t}\n\t\telse\n\t\t{\n\t\t\titer->second = eastl::forward<M>(obj);\n\t\t\treturn {iter, false};\n\t\t}\n\t}\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <class KX, class M>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator \n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertOrAssign(const_iterator, KX&& k, M&& obj)\n\t{\n\t\treturn DoInsertOrAssign(eastl::forward<KX>(k), eastl::forward<M>(obj)).first; // we ignore the iterator hint\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::erase(const_iterator i)\n\t{\n\t\titerator iNext(i.mpNode, i.mpBucket); // Convert from const_iterator to iterator while constructing.\n\t\t++iNext;\n\n\t\tnode_type* pNode        =  i.mpNode;\n\t\tnode_type* pNodeCurrent = *i.mpBucket;\n\n\t\tif(pNodeCurrent == pNode)\n\t\t\t*i.mpBucket = pNodeCurrent->mpNext;\n\t\telse\n\t\t{\n\t\t\t// We have a singly-linked list, so we have no choice but to\n\t\t\t// walk down it till we find the node before the node at 'i'.\n\t\t\tnode_type* pNodeNext = pNodeCurrent->mpNext;\n\n\t\t\twhile(pNodeNext != pNode)\n\t\t\t{\n\t\t\t\tpNodeCurrent = pNodeNext;\n\t\t\t\tpNodeNext    = pNodeCurrent->mpNext;\n\t\t\t}\n\n\t\t\tpNodeCurrent->mpNext = pNodeNext->mpNext;\n\t\t}\n\n\t\tDoFreeNode(pNode);\n\t\t--mnElementCount;\n\n\t\treturn iNext;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator\n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::erase(const_iterator first, const_iterator last)\n\t{\n\t\twhile(first != last)\n\t\t\tfirst = erase(first);\n\t\treturn iterator(first.mpNode, first.mpBucket);\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\ttemplate <typename KX>\n\ttypename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::size_type \n\thashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoErase(KX&& k)\n\t{\n\t\t// To do: Reimplement this function to do a single loop and not try to be \n\t\t// smart about element contiguity. The mechanism here is only a benefit if the \n\t\t// buckets are heavily overloaded; otherwise this mechanism may be slightly slower.\n\n\t\tconst hash_code_t c = get_hash_code(k);\n\t\tconst size_type   n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);\n\t\tconst size_type   nElementCountSaved = mnElementCount;\n\n\t\tnode_type** pBucketArray = mpBucketArray + n;\n\n\t\twhile(*pBucketArray && !compare(k, c, *pBucketArray))\n\t\t\tpBucketArray = &(*pBucketArray)->mpNext;\n\n\t\tnode_type* pDeleteList = nullptr;\n\t\twhile(*pBucketArray && compare(k, c, *pBucketArray))\n\t\t{\n\t\t\tnode_type* const pNode = *pBucketArray;\n\t\t\t*pBucketArray = pNode->mpNext;\n\t\t\t// Don't free the node here, k might be a reference to the key inside this node,\n\t\t\t// and we're re-using it when we compare to the following nodes.\n\t\t\t// Instead, add it to the list of things to be deleted.\n\t\t\tpNode->mpNext = pDeleteList;\n\t\t\tpDeleteList = pNode;\n\t\t\t--mnElementCount;\n\t\t}\n\n\t\twhile (pDeleteList) {\n\t\t\tnode_type* const pToDelete = pDeleteList;\n\t\t\tpDeleteList = pDeleteList->mpNext;\n\t\t\tDoFreeNode(pToDelete);\n\t\t}\n\n\t\treturn nElementCountSaved - mnElementCount;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::clear()\n\t{\n\t\tDoFreeNodes(mpBucketArray, mnBucketCount);\n\t\tmnElementCount = 0;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::clear(bool clearBuckets)\n\t{\n\t\tDoFreeNodes(mpBucketArray, mnBucketCount);\n\t\tif(clearBuckets)\n\t\t{\n\t\t\tDoFreeBuckets(mpBucketArray, mnBucketCount);\n\t\t\treset_lose_memory();\n\t\t}\n\t\tmnElementCount = 0;\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::reset_lose_memory() EA_NOEXCEPT\n\t{\n\t\t// The reset function is a special extension function which unilaterally \n\t\t// resets the container to an empty state without freeing the memory of \n\t\t// the contained objects. This is useful for very quickly tearing down a \n\t\t// container built into scratch memory.\n\t\tmnBucketCount  = 1;\n\n\t\t#ifdef _MSC_VER\n\t\t\tmpBucketArray = (node_type**)&gpEmptyBucketArray[0];\n\t\t#else\n\t\t\tvoid* p = &gpEmptyBucketArray[0];\n\t\t\tmemcpy(&mpBucketArray, &p, sizeof(mpBucketArray)); // Other compilers implement strict aliasing and casting is thus unsafe.\n\t\t#endif\n\n\t\tmnElementCount = 0;\n\t\tmRehashPolicy.mnNextResize = 0;\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::reserve(size_type nElementCount)\n\t{\n\t\trehash(mRehashPolicy.GetBucketCount(uint32_t(nElementCount)));\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::rehash(size_type nBucketCount)\n\t{\n\t\t// Note that we unilaterally use the passed in bucket count; we do not attempt migrate it\n\t\t// up to the next prime number. We leave it at the user's discretion to do such a thing.\n\t\tDoRehash(nBucketCount);\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tvoid hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoRehash(size_type nNewBucketCount)\n\t{\n\t\tnode_type** const pBucketArray = DoAllocateBuckets(nNewBucketCount); // nNewBucketCount should always be >= 2.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tnode_type* pNode;\n\n\t\t\t\tfor(size_type i = 0; i < mnBucketCount; ++i)\n\t\t\t\t{\n\t\t\t\t\twhile((pNode = mpBucketArray[i]) != NULL) // Using '!=' disables compiler warnings.\n\t\t\t\t\t{\n\t\t\t\t\t\tconst size_type nNewBucketIndex = (size_type)bucket_index(pNode, (uint32_t)nNewBucketCount);\n\n\t\t\t\t\t\tmpBucketArray[i] = pNode->mpNext;\n\t\t\t\t\t\tpNode->mpNext    = pBucketArray[nNewBucketIndex];\n\t\t\t\t\t\tpBucketArray[nNewBucketIndex] = pNode;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tDoFreeBuckets(mpBucketArray, mnBucketCount);\n\t\t\t\tmnBucketCount = nNewBucketCount;\n\t\t\t\tmpBucketArray = pBucketArray;\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\t// A failure here means that a hash function threw an exception.\n\t\t\t\t// We can't restore the previous state without calling the hash\n\t\t\t\t// function again, so the only sensible recovery is to delete everything.\n\t\t\t\tDoFreeNodes(pBucketArray, nNewBucketCount);\n\t\t\t\tDoFreeBuckets(pBucketArray, nNewBucketCount);\n\t\t\t\tDoFreeNodes(mpBucketArray, mnBucketCount);\n\t\t\t\tmnElementCount = 0;\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline bool hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::validate() const\n\t{\n\t\t// Verify our empty bucket array is unmodified.\n\t\tif(gpEmptyBucketArray[0] != NULL)\n\t\t\treturn false;\n\n\t\tif(gpEmptyBucketArray[1] != (void*)uintptr_t(~0))\n\t\t\treturn false;\n\n\t\t// Verify that we have at least one bucket. Calculations can  \n\t\t// trigger division by zero exceptions otherwise.\n\t\tif(mnBucketCount == 0)\n\t\t\treturn false;\n\n\t\t// Verify that gpEmptyBucketArray is used correctly.\n\t\t// gpEmptyBucketArray is only used when initially empty.\n\t\tif((void**)mpBucketArray == &gpEmptyBucketArray[0])\n\t\t{\n\t\t\tif(mnElementCount) // gpEmptyBucketArray is used only for empty hash tables.\n\t\t\t\treturn false;\n\n\t\t\tif(mnBucketCount != 1) // gpEmptyBucketArray is used exactly an only for mnBucketCount == 1.\n\t\t\t\treturn false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif(mnBucketCount < 2) // Small bucket counts *must* use gpEmptyBucketArray.\n\t\t\t\treturn false;\n\t\t}\n\n\t\t// Verify that the element count matches mnElementCount. \n\t\tsize_type nElementCount = 0;\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t\t++nElementCount;\n\n\t\tif(nElementCount != mnElementCount)\n\t\t\treturn false;\n\n\t\t// To do: Verify that individual elements are in the expected buckets.\n\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tint hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Come up with a more efficient mechanism of doing this.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\t// operator==, != have been moved to the specific container subclasses (e.g. hash_map).\n\n\ttemplate <typename K, typename V, typename A, typename EK, typename Eq,\n\t\t\t  typename H1, typename H2, typename H, typename RP, bool bC, bool bM, bool bU>\n\tinline void swap(const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& a, \n\t\t\t\t\t const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/in_place_t.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_IN_PLACE_T_H\n#define EASTL_INTERNAL_IN_PLACE_T_H\n\n#include <cstddef> // for std::size_t\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////////\n\t/// in_place, in_place_type<T>, in_place_index<size_t>\n\t/// in_place_t, in_place_type_t<T>, in_place_index_t<size_t>\n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/in_place\n\t///\n\tstruct in_place_t\n\t{\n\t\texplicit in_place_t() = default;\n\t};\n\n\tEASTL_CPP17_INLINE_VARIABLE constexpr in_place_t in_place{};\n\n\ttemplate<typename>\n\tstruct in_place_type_t\n\t{\n\t\texplicit in_place_type_t() = default;\n\t};\n\n\ttemplate<typename T>\n\tconstexpr in_place_type_t<T> in_place_type{};\n\n\ttemplate<size_t>\n\tstruct in_place_index_t\n\t{\n\t\texplicit in_place_index_t() = default;\n\t};\n\n\ttemplate<size_t Idx>\n\tconstexpr in_place_index_t<Idx> in_place_index{};\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/integer_sequence.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_INTEGER_SEQUENCE_H\n#define EASTL_INTEGER_SEQUENCE_H\n\n#include <EABase/config/eacompiler.h>\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n\nnamespace eastl\n{\n\n#if EASTL_VARIADIC_TEMPLATES_ENABLED && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\n// integer_sequence\ntemplate <typename T, T... Ints>\nclass integer_sequence\n{\npublic:\n\ttypedef T value_type;\n\tstatic_assert(is_integral<T>::value, \"eastl::integer_sequence can only be instantiated with an integral type\");\n\tstatic EA_CONSTEXPR size_t size() EA_NOEXCEPT { return sizeof...(Ints); }\n};\n\ntemplate <size_t... Is>\nusing index_sequence = integer_sequence<size_t, Is...>;\n\n#if (defined(EA_COMPILER_GNUC) && EA_COMPILER_VERSION >= 8001)\n\ntemplate <typename T, T N>\nusing make_integer_sequence = integer_sequence<T, __integer_pack(N)...>;\n\n#elif (defined(EA_COMPILER_CLANG) && EA_COMPILER_HAS_BUILTIN(__make_integer_seq)) || (defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1910))\n\ntemplate <class T, T N>\nusing make_integer_sequence = __make_integer_seq<integer_sequence, T, N>;\n\n#else \n\ntemplate <size_t N, typename IndexSeq>\nstruct make_index_sequence_impl;\n\ntemplate <size_t N, size_t... Is>\nstruct make_index_sequence_impl<N, integer_sequence<size_t, Is...>>\n{\n\ttypedef typename make_index_sequence_impl<N - 1, integer_sequence<size_t, N - 1, Is...>>::type type;\n};\n\ntemplate <size_t... Is>\nstruct make_index_sequence_impl<0, integer_sequence<size_t, Is...>>\n{\n\ttypedef integer_sequence<size_t, Is...> type;\n};\n\ntemplate <typename Target, typename Seq>\nstruct integer_sequence_convert_impl;\n\ntemplate <typename Target, size_t... Is>\nstruct integer_sequence_convert_impl<Target, integer_sequence<size_t, Is...>>\n{\n\ttypedef integer_sequence<Target, Is...> type;\n};\n\ntemplate <typename T, T N>\nstruct make_integer_sequence_impl\n{\n\ttypedef typename integer_sequence_convert_impl<T, typename make_index_sequence_impl<N, integer_sequence<size_t>>::type>::type type;\n};\n\ntemplate <typename T, T N>\nusing make_integer_sequence = typename make_integer_sequence_impl<T, N>::type;\n\n#endif\n\ntemplate <size_t N>\nusing make_index_sequence = make_integer_sequence<size_t, N>;\n\n// Helper alias template that converts any type parameter pack into an index sequence of the same length\ntemplate<typename... T>\nusing index_sequence_for = make_index_sequence<sizeof...(T)>;\n\nnamespace internal\n{\n\ntemplate <typename T>\nstruct integer_sequence_size_helper;\n\ntemplate <typename T, T... Ints>\nstruct integer_sequence_size_helper<eastl::integer_sequence<T, Ints...>> : public integral_constant<size_t, sizeof...(Ints)>\n{\n};\n\ntemplate <typename T>\nstruct integer_sequence_size : public integer_sequence_size_helper<eastl::remove_cv_t<T>>\n{\n};\n\ntemplate <typename T>\nstruct index_sequence_size : public integer_sequence_size_helper<eastl::remove_cv_t<T>>\n{\n};\n\ntemplate <typename T>\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR size_t integer_sequence_size_v = integer_sequence_size<T>::value;\n\ntemplate <typename T>\nEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR size_t index_sequence_size_v = index_sequence_size<T>::value;\n\n\n} // namespace internal\n\n#endif  // EASTL_VARIADIC_TEMPLATES_ENABLED\n\n}  // namespace eastl\n\n#endif  // EASTL_INTEGER_SEQUENCE_H\n"
  },
  {
    "path": "include/EASTL/internal/intrusive_hashtable.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements an intrusive hash table, which is a hash table whereby\n// the container nodes are the hash table objects themselves. This has benefits\n// primarily in terms of memory management. There are some minor limitations\n// that result from this.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef EASTL_INTERNAL_INTRUSIVE_HASHTABLE_H\n#define EASTL_INTERNAL_INTRUSIVE_HASHTABLE_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/hashtable.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n#include <EASTL/algorithm.h>\n\nEA_DISABLE_ALL_VC_WARNINGS();\n#include <new>\n#include <stddef.h>\n#include <string.h>\nEA_RESTORE_ALL_VC_WARNINGS();\n\n\nnamespace eastl\n{\n\n\t/// intrusive_hash_node\n\t///\n\t/// A hash_node stores an element in a hash table, much like a \n\t/// linked list node stores an element in a linked list. \n\t/// An intrusive_hash_node additionally can, via template parameter,\n\t/// store a hash code in the node to speed up hash calculations \n\t/// and comparisons in some cases.\n\t///\n\t/// To consider: Make a version of intrusive_hash_node which is\n\t/// templated on the container type. This would allow for the \n\t/// mpNext pointer to be the container itself and thus allow\n\t/// for easier debugging. \n\t/// \n\t/// Example usage:\n\t///   struct Widget : public intrusive_hash_node{ ... };\n\t/// \n\t///   struct Dagget : public intrusive_hash_node_key<int>{ ... };\n\t/// \n\tstruct intrusive_hash_node\n\t{\n\t\tintrusive_hash_node* mpNext;\n\t};\n\n\n\ttemplate <typename Key>\n\tstruct intrusive_hash_node_key : public intrusive_hash_node\n\t{\n\t\ttypedef Key key_type;\n\t\tKey mKey;\n\t};\n\n\n\n\t/// intrusive_node_iterator\n\t///\n\t/// Node iterators iterate nodes within a given bucket.\n\t///\n\t/// The bConst parameter defines if the iterator is a const_iterator\n\t/// or an iterator.\n\t///\n\ttemplate <typename Value, bool bConst>\n\tstruct intrusive_node_iterator\n\t{\n\tpublic:\n\t\ttypedef intrusive_node_iterator<Value, bConst>                   this_type;\n\t\ttypedef Value                                                    value_type;\n\t\ttypedef Value                                                    node_type;\n\t\ttypedef ptrdiff_t                                                difference_type;\n\t\ttypedef typename conditional<bConst, const Value*, Value*>::type pointer;\n\t\ttypedef typename conditional<bConst, const Value&, Value&>::type reference;\n\t\ttypedef eastl::forward_iterator_tag                       iterator_category;\n\n\tpublic:\n\t\tnode_type* mpNode;\n\n\tpublic:\n\t\tintrusive_node_iterator()\n\t\t\t: mpNode(NULL) { }\n\n\t\texplicit intrusive_node_iterator(value_type* pNode)\n\t\t\t: mpNode(pNode) { }\n\n\t\tintrusive_node_iterator(const intrusive_node_iterator<Value, true>& x)\n\t\t\t: mpNode(x.mpNode) { }\n\n\t\treference operator*() const\n\t\t\t{ return *mpNode; }\n\n\t\tpointer operator->() const\n\t\t\t{ return mpNode; }\n\n\t\tthis_type& operator++()\n\t\t\t{ mpNode = static_cast<node_type*>(mpNode->mpNext); return *this; }\n\n\t\tthis_type operator++(int)\n\t\t\t{ this_type temp(*this); mpNode = static_cast<node_type*>(mpNode->mpNext); return temp; }\n\n\t}; // intrusive_node_iterator\n\n\n\n\n\t/// intrusive_hashtable_iterator_base\n\t///\n\t/// An intrusive_hashtable_iterator_base iterates the entire hash table and \n\t/// not just nodes within a single bucket. Users in general will use a hash\n\t/// table iterator much more often, as it is much like other container\n\t/// iterators (e.g. vector::iterator).\n\t///\n\t/// We define a base class here because it is shared by both const and\n\t/// non-const iterators.\n\t///\n\ttemplate <typename Value>\n\tstruct intrusive_hashtable_iterator_base\n\t{\n\tpublic:\n\t\ttypedef Value value_type;\n\n\tprotected:\n\t\ttemplate <typename, typename, typename, typename, size_t, bool, bool>\n\t\tfriend class intrusive_hashtable;\n\n\t\ttemplate <typename, bool>\n\t\tfriend struct intrusive_hashtable_iterator;\n\n\t\ttemplate <typename V>\n\t\tfriend bool operator==(const intrusive_hashtable_iterator_base<V>&, const intrusive_hashtable_iterator_base<V>&);\n\n\t\ttemplate <typename V>\n\t\tfriend bool operator!=(const intrusive_hashtable_iterator_base<V>&, const intrusive_hashtable_iterator_base<V>&);\n\n\t\tvalue_type*  mpNode;      // Current node within current bucket.\n\t\tvalue_type** mpBucket;    // Current bucket.\n\n\tpublic:\n\t\tintrusive_hashtable_iterator_base(value_type* pNode, value_type** pBucket)\n\t\t\t: mpNode(pNode), mpBucket(pBucket) { }\n\n\t\tvoid increment_bucket()\n\t\t{\n\t\t\t++mpBucket;\n\t\t\twhile(*mpBucket == NULL) // We store an extra bucket with some non-NULL value at the end \n\t\t\t\t++mpBucket;          // of the bucket array so that finding the end of the bucket\n\t\t\tmpNode = *mpBucket;      // array is quick and simple.\n\t\t}\n\n\t\tvoid increment()\n\t\t{\n\t\t\tmpNode = static_cast<value_type*>(mpNode->mpNext);\n\n\t\t\twhile(mpNode == NULL)\n\t\t\t\tmpNode = *++mpBucket;\n\t\t}\n\n\t}; // intrusive_hashtable_iterator_base\n\n\n\n\n\t/// intrusive_hashtable_iterator\n\t///\n\t/// An intrusive_hashtable_iterator iterates the entire hash table and not \n\t/// just nodes within a single bucket. Users in general will use a hash\n\t/// table iterator much more often, as it is much like other container\n\t/// iterators (e.g. vector::iterator).\n\t///\n\t/// The bConst parameter defines if the iterator is a const_iterator\n\t/// or an iterator.\n\t///\n\ttemplate <typename Value, bool bConst>\n\tstruct intrusive_hashtable_iterator : public intrusive_hashtable_iterator_base<Value>\n\t{\n\tpublic:\n\t\ttypedef intrusive_hashtable_iterator_base<Value>                    base_type;\n\t\ttypedef intrusive_hashtable_iterator<Value, bConst>                 this_type;\n\t\ttypedef intrusive_hashtable_iterator<Value, false>                  this_type_non_const;\n\t\ttypedef typename base_type::value_type                              value_type;\n\t\ttypedef typename conditional<bConst, const Value*, Value*>::type    pointer;\n\t\ttypedef typename conditional<bConst, const Value&, Value&>::type    reference;\n\t\ttypedef ptrdiff_t                                                   difference_type;\n\t\ttypedef eastl::forward_iterator_tag                          iterator_category;\n\n\tpublic:\n\t\tintrusive_hashtable_iterator()\n\t\t\t: base_type(NULL, NULL) { }\n\n\t\texplicit intrusive_hashtable_iterator(value_type* pNode, value_type** pBucket)\n\t\t\t: base_type(pNode, pBucket) { }\n\n\t\texplicit intrusive_hashtable_iterator(value_type** pBucket)\n\t\t\t: base_type(*pBucket, pBucket) { }\n\n\t\ttemplate <bool IsConst = bConst, typename enable_if<IsConst, bool>::type = false>\n\t\tintrusive_hashtable_iterator(const this_type_non_const& x)\n\t\t\t: base_type(x.mpNode, x.mpBucket) { }\n\n\t\treference operator*() const\n\t\t\t{ return *base_type::mpNode; }\n\n\t\tpointer operator->() const\n\t\t\t{ return base_type::mpNode; }\n\n\t\tthis_type& operator++()\n\t\t\t{ base_type::increment(); return *this; }\n\n\t\tthis_type operator++(int)\n\t\t\t{ this_type temp(*this); base_type::increment(); return temp; }\n\n\t}; // intrusive_hashtable_iterator\n\n\n\n\t/// use_intrusive_key\n\t///\n\t/// operator()(x) returns x.mKey. Used in maps, as opposed to sets.\n\t/// This is a template policy implementation; it is an alternative to \n\t/// the use_self template implementation, which is used for sets.\n\t///\n\ttemplate <typename Node, typename Key>\n\tstruct use_intrusive_key\n\t{\n\t\ttypedef Key result_type;\n\n\t\tconst result_type& operator()(const Node& x) const\n\t\t\t{ return x.mKey; }\n\t};\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t/// intrusive_hashtable\n\t///\n\ttemplate <typename Key, typename Value, typename Hash, typename Equal, \n\t\t\t  size_t bucketCount, bool bConstIterators, bool bUniqueKeys>\n\tclass intrusive_hashtable\n\t{\n\tpublic:\n\t\ttypedef intrusive_hashtable<Key, Value, Hash, Equal, \n\t\t\t\t\t\t\t\t\tbucketCount, bConstIterators, bUniqueKeys>            this_type;\n\t\ttypedef Key                                                                       key_type;\n\t\ttypedef Value                                                                     value_type;\n\t\ttypedef Value                                                                     mapped_type;\n\t\ttypedef Value                                                                     node_type;\n\t\ttypedef uint32_t                                                                  hash_code_t;\n\t\ttypedef Equal                                                                     key_equal;\n\t\ttypedef ptrdiff_t                                                                 difference_type;\n\t\ttypedef eastl_size_t                                                              size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef value_type&                                                               reference;\n\t\ttypedef const value_type&                                                         const_reference;\n\t\ttypedef intrusive_node_iterator<value_type, bConstIterators>                      local_iterator;\n\t\ttypedef intrusive_node_iterator<value_type, true>                                 const_local_iterator;\n\t\ttypedef intrusive_hashtable_iterator<value_type, bConstIterators>                 iterator;\n\t\ttypedef intrusive_hashtable_iterator<value_type, true>                            const_iterator;\n\t\ttypedef typename conditional<bUniqueKeys, pair<iterator, bool>, iterator>::type   insert_return_type;\n\t\ttypedef typename conditional<bConstIterators, eastl::use_self<Value>,\n\t\t\t\t\t\t\t\t\t\t\t\t eastl::use_intrusive_key<Value, key_type> >::type  extract_key;\n\n\t\tenum\n\t\t{\n\t\t\tkBucketCount = bucketCount\n\t\t};\n\n\tprotected:\n\t\tnode_type* mBucketArray[kBucketCount + 1]; // '+1' because we have an end bucket which is non-NULL so iterators always stop on it.\n\t\tsize_type  mnElementCount;\n\t\tHash       mHash;           // To do: Use base class optimization to make this go away when it is of zero size.\n\t\tEqual      mEqual;          // To do: Use base class optimization to make this go away when it is of zero size.\n\n\tpublic:\n\t\tintrusive_hashtable(const Hash&, const Equal&);\n\n\t\tvoid swap(this_type& x);\n\n\t\titerator begin() EA_NOEXCEPT\n\t\t{\n\t\t\t// Early out if the table is empty, increment_bucket() below will loop over the\n\t\t\t// entire bucket array, which is undesirable if we know there aren't any elements.\n\t\t\tif (mnElementCount == 0)\n\t\t\t{\n\t\t\t\treturn end();\n\t\t\t}\n\t\t\titerator i(mBucketArray);\n\t\t\tif (!i.mpNode)\n\t\t\t{\n\t\t\t\ti.increment_bucket();\n\t\t\t}\n\t\t\treturn i;\n\t\t}\n\n\t\tconst_iterator begin() const EA_NOEXCEPT\n\t\t{\n\t\t\t// Early out if the table is empty, increment_bucket() below will loop over the\n\t\t\t// entire bucket array, which is undesirable if we know there aren't any elements.\n\t\t\tif (mnElementCount == 0)\n\t\t\t{\n\t\t\t\treturn end();\n\t\t\t}\n\t\t\tconst_iterator i(const_cast<node_type**>(mBucketArray));\n\t\t\tif (!i.mpNode)\n\t\t\t{\n\t\t\t\ti.increment_bucket();\n\t\t\t}\n\t\t\treturn i;\n\t\t}\n\n\t\tconst_iterator cbegin() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn begin();\n\t\t}\n\n\t\titerator end() EA_NOEXCEPT\n\t\t\t{ return iterator(mBucketArray + kBucketCount); }\n\n\t\tconst_iterator end() const EA_NOEXCEPT\n\t\t\t{ return const_iterator(const_cast<node_type**>(mBucketArray) + kBucketCount); }\n\n\t\tconst_iterator cend() const EA_NOEXCEPT\n\t\t\t{ return const_iterator(const_cast<node_type**>(mBucketArray) + kBucketCount); }\n\n\t\tlocal_iterator begin(size_type n) EA_NOEXCEPT\n\t\t\t{ return local_iterator(mBucketArray[n]); }\n\n\t\tconst_local_iterator begin(size_type n) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(mBucketArray[n]); }\n\n\t\tconst_local_iterator cbegin(size_type n) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(mBucketArray[n]); }\n\n\t\tlocal_iterator end(size_type) EA_NOEXCEPT\n\t\t\t{ return local_iterator(NULL); }\n\n\t\tconst_local_iterator end(size_type) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(NULL); }\n\n\t\tconst_local_iterator cend(size_type) const EA_NOEXCEPT\n\t\t\t{ return const_local_iterator(NULL); }\n\n\t\tsize_type size() const EA_NOEXCEPT\n\t\t\t{ return mnElementCount; }\n\n\t\tbool empty() const EA_NOEXCEPT\n\t\t\t{ return mnElementCount == 0; }\n\n\t\tsize_type bucket_count() const  EA_NOEXCEPT // This function is unnecessary, as the user can directly reference\n\t\t\t{ return kBucketCount; }                // intrusive_hashtable::kBucketCount as a constant.\n\n\t\tsize_type bucket_size(size_type n) const EA_NOEXCEPT\n\t\t\t{ return (size_type)eastl::distance(begin(n), end(n)); }\n\n\t\tsize_type bucket(const key_type& k) const EA_NOEXCEPT\n\t\t\t{ return (size_type)(mHash(k) % kBucketCount); }\n\n\tpublic:\n\t\tfloat load_factor() const EA_NOEXCEPT\n\t\t\t{ return (float)mnElementCount / (float)kBucketCount; }\n\n\tpublic:\n\t\tinsert_return_type insert(value_type& value) \n\t\t\t{ return DoInsertValue(value, integral_constant<bool, bUniqueKeys>()); }\n\n\t\tinsert_return_type insert(const_iterator, value_type& value)\n\t\t\t{ return insert(value); } // To consider: We might be able to use the iterator argument to specify a specific insertion location.\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(InputIterator first, InputIterator last);\n\n\tpublic:\n\t\titerator  erase(const_iterator position);\n\t\titerator  erase(const_iterator first, const_iterator last);\n\t\tsize_type erase(const key_type& k);\n\t\titerator  remove(value_type& value);            // Removes by value instead of by iterator. This is an O(1) operation, due to this hashtable being 'intrusive'.\n\n\t\tvoid clear();\n\n\tpublic:\n\t\titerator       find(const key_type& k);\n\t\tconst_iterator find(const key_type& k) const;\n\n\t\t/// Implements a find whereby the user supplies a comparison of a different type\n\t\t/// than the hashtable value_type. A useful case of this is one whereby you have\n\t\t/// a container of string objects but want to do searches via passing in char pointers.\n\t\t/// The problem is that without this kind of find, you need to do the expensive operation\n\t\t/// of converting the char pointer to a string so it can be used as the argument to the \n\t\t/// find function.\n\t\t///\n\t\t/// Example usage:\n\t\t///     hash_set<string> hashSet;\n\t\t///     hashSet.find_as(\"hello\");    // Use default hash and compare.\n\t\t///\n\t\t/// Example usage (namespaces omitted for brevity):\n\t\t///     hash_set<string> hashSet;\n\t\t///     hashSet.find_as(\"hello\", hash<char*>(), equal_to<>());\n\t\t///\n\t\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\t\titerator       find_as(const U& u, UHash uhash, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\t\tconst_iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate) const;\n\n\t\t// Using default hash and equality objects may result in incorrect semantics (undefined behaviour).\n\t\t// Use find() with heterogenous lookup (ie. function objects with a is_transparent type member) or explicitly specify hash and equality objects.\n\t\t// See doc\\BestPractices.md#search-hash_mapstring-using-heterogeneous-lookup\n\t\ttemplate <typename U>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\t\titerator       find_as(const U& u);\n\n\t\t// Using default hash and equality objects may result in incorrect semantics (undefined behaviour).\n\t\t// Use find() with heterogenous lookup (ie. function objects with a is_transparent type member) or explicitly specify hash and equality objects.\n\t\t// See doc\\BestPractices.md#search-hash_mapstring-using-heterogeneous-lookup\n\t\ttemplate <typename U>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\t\tconst_iterator find_as(const U& u) const;\n\n\t\tsize_type      count(const key_type& k) const;\n\n\t\t// The use for equal_range in a hash_table seems somewhat questionable.\n\t\t// The primary reason for its existence is to replicate the interface of set/map.\n\t\teastl::pair<iterator, iterator>             equal_range(const key_type& k);\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;\n\n\t\t// todo: add heterogenous lookup support (using a heterogeneous comparator - a type 'Comp' where 'Comp::is_transparent' is valid and denotes a type):\n\t\t// template<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\t// iterator        find(const KX& key);\n\t\t//\n\t\t// ... also for count() and more ...\n\n\tpublic:\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\tpublic:\n\t\tHash hash_function() const\n\t\t\t{ return mHash; }\n\n\t\tconst key_equal& key_eq() const \n\t\t\t{ return mEqual; }\n\n\t\tkey_equal& key_eq()\n\t\t\t{ return mEqual; }\n\n\tprotected:\n\t\teastl::pair<iterator, bool> DoInsertValue(value_type&, true_type);  // true_type means bUniqueKeys is true.\n\t\titerator                    DoInsertValue(value_type&, false_type); // false_type means bUniqueKeys is false.\n\n\t\tnode_type* DoFindNode(node_type* pNode, const key_type& k) const;\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\tnode_type* DoFindNode(node_type* pNode, const U& u, BinaryPredicate predicate) const;\n\n\t}; // class intrusive_hashtable\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// node_iterator_base\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value, bool bConst>\n\tinline bool operator==(const intrusive_node_iterator<Value, bConst>& a, \n\t\t\t\t\t\t   const intrusive_node_iterator<Value, bConst>& b)\n\t\t{ return a.mpNode == b.mpNode; }\n\n\ttemplate <typename Value, bool bConst>\n\tinline bool operator!=(const intrusive_node_iterator<Value, bConst>& a,\n\t\t\t\t\t\t   const intrusive_node_iterator<Value, bConst>& b)\n\t\t{ return a.mpNode != b.mpNode; }\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// hashtable_iterator_base\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Value>\n\tinline bool operator==(const intrusive_hashtable_iterator_base<Value>& a,\n\t\t\t\t\t\t   const intrusive_hashtable_iterator_base<Value>& b)\n\t\t{ return a.mpNode == b.mpNode; }\n\n\n\ttemplate <typename Value>\n\tinline bool operator!=(const intrusive_hashtable_iterator_base<Value>& a,\n\t\t\t\t\t\t   const intrusive_hashtable_iterator_base<Value>& b)\n\t\t{ return a.mpNode != b.mpNode; }\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_hashtable\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::intrusive_hashtable(const H& h, const Eq& eq)\n\t\t: mnElementCount(0),\n\t\t  mHash(h),\n\t\t  mEqual(eq)\n\t{\n\t\tmemset(mBucketArray, 0, kBucketCount * sizeof(mBucketArray[0]));\n\t\tmBucketArray[kBucketCount] = reinterpret_cast<node_type*>((uintptr_t)~0);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tvoid intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::swap(this_type& x)\n\t{\n\t\tfor(size_t i = 0; i < kBucketCount; i++)\n\t\t\teastl::swap(mBucketArray[i], x.mBucketArray[i]);\n\n\t\teastl::swap(mnElementCount, x.mnElementCount);\n\t\teastl::swap(mHash,          x.mHash);\n\t\teastl::swap(mEqual,         x.mEqual);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::find(const key_type& k)\n\t{\n\t\tconst size_type n = (size_type)(mHash(k) % kBucketCount);\n\t\tnode_type* const pNode = DoFindNode(mBucketArray[n], k);\n\t\treturn pNode ? iterator(pNode, mBucketArray + n) : iterator(mBucketArray + kBucketCount);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::const_iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::find(const key_type& k) const\n\t{\n\t\tconst size_type n = (size_type)(mHash(k) % kBucketCount);\n\t\tnode_type* const pNode = DoFindNode(mBucketArray[n], k);\n\t\treturn pNode ? const_iterator(pNode, const_cast<node_type**>(mBucketArray) + n) : const_iterator(const_cast<node_type**>(mBucketArray) + kBucketCount);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::find_as(const U& other, UHash uhash, BinaryPredicate predicate)\n\t{\n\t\tconst size_type n = (size_type)(uhash(other) % kBucketCount);\n\t\tnode_type* const pNode = DoFindNode(mBucketArray[n], other, predicate);\n\t\treturn pNode ? iterator(pNode, mBucketArray + n) : iterator(mBucketArray + kBucketCount);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttemplate <typename U, typename UHash, typename BinaryPredicate>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::const_iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::find_as(const U& other, UHash uhash, BinaryPredicate predicate) const\n\t{\n\t\tconst size_type n = (size_type)(uhash(other) % kBucketCount);\n\t\tnode_type* const pNode = DoFindNode(mBucketArray[n], other, predicate);\n\t\treturn pNode ? const_iterator(pNode, const_cast<node_type**>(mBucketArray) + n) : const_iterator(const_cast<node_type**>(mBucketArray) + kBucketCount);\n\t}\n\n\n\t/// intrusive_hashtable_find\n\t///\n\t/// Deprecated: Using default hash and equality objects may result in\n\t/// incorrect semantics (undefined behaviour).\n\t/// Use find() with heterogenous lookup (ie. function objects with a\n\t/// is_transparent type member) or explicitly specify hash and equality\n\t/// objects.\n\t/// \n\t/// Helper function that defaults to using hash<U> and equal_to<>.\n\t/// This makes it so that by default you don't need to provide these.\n\t/// Note that the default hash functions may not be what you want, though.\n\t///\n\t/// Example usage. Instead of this:\n\t///     hash_set<string> hashSet;\n\t///     hashSet.find(\"hello\", hash<char*>(), equal_to<>());\n\t///\n\t/// You can use this:\n\t///     hash_set<string> hashSet;\n\t///     hashtable_find(hashSet, \"hello\");\n\t///\n\ttemplate <typename H, typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename H::iterator intrusive_hashtable_find(H& hashTable, const U& u)\n\t\t{ return hashTable.find_as(u, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\ttemplate <typename H, typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename H::const_iterator intrusive_hashtable_find(const H& hashTable, const U& u)\n\t\t{ return hashTable.find_as(u, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttemplate <typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::find_as(const U& other)\n\t{\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\treturn eastl::intrusive_hashtable_find(*this, other);\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t}\n\t\t// VC++ doesn't appear to like the following, though it seems correct to me.\n\t\t// So we implement the workaround above until we can straighten this out.\n\t\t//{ return find_as(other, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttemplate <typename U>\n\tEA_REMOVE_AT_2025_OCT_MSG(\"Use heterogeneous lookup instead (see EASTL Best Practices page) or explicitly specify hash and equality objects.\")\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::const_iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::find_as(const U& other) const\n\t{\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\treturn eastl::intrusive_hashtable_find(*this, other);\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t}\n\t\t// VC++ doesn't appear to like the following, though it seems correct to me.\n\t\t// So we implement the workaround above until we can straighten this out.\n\t\t//{ return find_as(other, eastl::hash<U>(), eastl::equal_to<>()); }\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttypename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::size_type\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::count(const key_type& k) const\n\t{\n\t\tconst size_type n = (size_type)(mHash(k) % kBucketCount);\n\t\tsize_type   result = 0;\n\t\textract_key extractKey; // extract_key is empty and thus this ctor is a no-op.\n\n\t\t// To do: Make a specialization for bU (unique keys) == true and take \n\t\t// advantage of the fact that the count will always be zero or one in that case. \n\t\tfor(node_type* pNode = mBucketArray[n]; pNode; pNode = static_cast<node_type*>(pNode->mpNext))\n\t\t{\n\t\t\tif(mEqual(k, extractKey(*pNode)))\n\t\t\t\t++result;\n\t\t}\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\teastl::pair<typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator,\n\t\t\t\ttypename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator>\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::equal_range(const key_type& k)\n\t{\n\t\tconst size_type n     = (size_type)(mHash(k) % kBucketCount);\n\t\tnode_type**     head  = mBucketArray + n;\n\t\tnode_type*      pNode = DoFindNode(*head, k);\n\t\textract_key     extractKey; // extract_key is empty and thus this ctor is a no-op.\n\n\t\tif(pNode)\n\t\t{\n\t\t\tnode_type* p1 = static_cast<node_type*>(pNode->mpNext);\n\n\t\t\tfor(; p1; p1 = static_cast<node_type*>(p1->mpNext))\n\t\t\t{\n\t\t\t\tif(!mEqual(k, extractKey(*p1)))\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\titerator first(pNode, head);\n\t\t\titerator last(p1, head);\n\n\t\t\tif(!p1)\n\t\t\t\tlast.increment_bucket();\n\n\t\t\treturn eastl::pair<iterator, iterator>(first, last);\n\t\t}\n\n\t\treturn eastl::pair<iterator, iterator>(iterator(mBucketArray + kBucketCount),\n\t\t\t\t\t\t\t\t\t\t\t   iterator(mBucketArray + kBucketCount));\n\t}\n\n\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\teastl::pair<typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::const_iterator,\n\t\t\t\ttypename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::const_iterator>\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::equal_range(const key_type& k) const\n\t{\n\t\tconst size_type n     = (size_type)(mHash(k) % kBucketCount);\n\t\tnode_type**     head  = const_cast<node_type**>(mBucketArray + n);\n\t\tnode_type*      pNode = DoFindNode(*head, k);\n\t\textract_key     extractKey; // extract_key is empty and thus this ctor is a no-op.\n\n\t\tif(pNode)\n\t\t{\n\t\t\tnode_type* p1 = static_cast<node_type*>(pNode->mpNext);\n\n\t\t\tfor(; p1; p1 = static_cast<node_type*>(p1->mpNext))\n\t\t\t{\n\t\t\t\tif(!mEqual(k, extractKey(*p1)))\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst_iterator first(pNode, head);\n\t\t\tconst_iterator last(p1, head);\n\n\t\t\tif(!p1)\n\t\t\t\tlast.increment_bucket();\n\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(first, last);\n\t\t}\n\n\t\treturn eastl::pair<const_iterator, const_iterator>(const_iterator(const_cast<node_type**>(mBucketArray) + kBucketCount),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   const_iterator(const_cast<node_type**>(mBucketArray) + kBucketCount));\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::node_type* \n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::DoFindNode(node_type* pNode, const key_type& k) const\n\t{\n\t\textract_key extractKey; // extract_key is empty and thus this ctor is a no-op.\n\n\t\tfor(; pNode; pNode = static_cast<node_type*>(pNode->mpNext))\n\t\t{\n\t\t\tif(mEqual(k, extractKey(*pNode)))\n\t\t\t\treturn pNode;\n\t\t}\n\t\treturn NULL;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::node_type* \n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::DoFindNode(node_type* pNode, const U& other, BinaryPredicate predicate) const\n\t{\n\t\textract_key extractKey; // extract_key is empty and thus this ctor is a no-op.\n\n\t\tfor(; pNode; pNode = static_cast<node_type*>(pNode->mpNext))\n\t\t{\n\t\t\tif(predicate(extractKey(*pNode), other)) // Intentionally compare with key as first arg and other as second arg.\n\t\t\t\treturn pNode;\n\t\t}\n\t\treturn NULL;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\teastl::pair<typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator, bool>\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::DoInsertValue(value_type& value, true_type) // true_type means bUniqueKeys is true.\n\t{\n\t\t// For sets (as opposed to maps), one could argue that all insertions are successful,\n\t\t// as all elements are unique. However, the equal function might not think so.\n\t\textract_key      extractKey; // extract_key is empty and thus this ctor is a no-op.\n\t\tconst size_type  n     = (size_type)(mHash(extractKey(value)) % kBucketCount);\n\t\tnode_type* const pNode = DoFindNode(mBucketArray[n], extractKey(value));\n\n\t\tif(pNode == NULL)\n\t\t{\n\t\t\tvalue.mpNext = mBucketArray[n];\n\t\t\tmBucketArray[n] = &value;\n\t\t\t++mnElementCount;\n\n\t\t\treturn eastl::pair<iterator, bool>(iterator(&value, mBucketArray + n), true);\n\t\t}\n\n\t\treturn eastl::pair<iterator, bool>(iterator(pNode, mBucketArray + n), false);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttypename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::DoInsertValue(value_type& value, false_type) // false_type means bUniqueKeys is false.\n\t{\n\t\textract_key      extractKey; // extract_key is empty and thus this ctor is a no-op.\n\t\tconst size_type  n         = (size_type)(mHash(extractKey(value)) % kBucketCount);\n\t\tnode_type* const pNodePrev = DoFindNode(mBucketArray[n], extractKey(value));\n\n\t\tif(pNodePrev == NULL)\n\t\t{\n\t\t\tvalue.mpNext    = mBucketArray[n];\n\t\t\tmBucketArray[n] = &value;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tvalue.mpNext      = pNodePrev->mpNext;\n\t\t\tpNodePrev->mpNext = &value;\n\t\t}\n\n\t\t++mnElementCount;\n\n\t\treturn iterator(&value, mBucketArray + n);\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttemplate <typename InputIterator>\n\tinline void intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::insert(InputIterator first, InputIterator last)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t\tinsert(*first);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttypename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::erase(const_iterator i)\n\t{\n\t\titerator iNext(i.mpNode, i.mpBucket);\n\t\t++iNext;\n\n\t\tnode_type* pNode        =  i.mpNode;\n\t\tnode_type* pNodeCurrent = *i.mpBucket;\n\n\t\tif(pNodeCurrent == pNode)\n\t\t\t*i.mpBucket = static_cast<node_type*>(pNodeCurrent->mpNext);\n\t\telse\n\t\t{\n\t\t\t// We have a singly-linked list, so we have no choice but to\n\t\t\t// walk down it till we find the node before the node at 'i'.\n\t\t\tnode_type* pNodeNext = static_cast<node_type*>(pNodeCurrent->mpNext);\n\n\t\t\twhile(pNodeNext != pNode)\n\t\t\t{\n\t\t\t\tpNodeCurrent = pNodeNext;\n\t\t\t\tpNodeNext    = static_cast<node_type*>(pNodeCurrent->mpNext);\n\t\t\t}\n\n\t\t\tpNodeCurrent->mpNext = static_cast<node_type*>(pNodeNext->mpNext);\n\t\t}\n\n\t\t// To consider: In debug builds set the node mpNext to NULL.\n\t\t--mnElementCount;\n\n\t\treturn iNext;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::erase(const_iterator first, const_iterator last)\n\t{\n\t\twhile(first != last)\n\t\t\tfirst = erase(first);\n\t\treturn iterator(first.mpNode, first.mpBucket);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\ttypename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::size_type \n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::erase(const key_type& k)\n\t{\n\t\tconst size_type n = (size_type)(mHash(k) % kBucketCount);\n\t\tconst size_type nElementCountSaved = mnElementCount;\n\t\tnode_type*&     pNodeBase = mBucketArray[n];\n\t\textract_key     extractKey; // extract_key is empty and thus this ctor is a no-op.\n\n\t\t// Note by Paul Pedriana:\n\t\t// We have two loops here, and I'm not finding any easy way to having just one\n\t\t// loop without changing the requirements of the hashtable node definition. \n\t\t// It's a problem of taking an address of a variable and converting it to the \n\t\t// address of another type without knowing what that type is. Perhaps I'm a \n\t\t// little overly tired, so if there is a simple solution I am probably missing it.\n\n\t\twhile(pNodeBase && mEqual(k, extractKey(*pNodeBase)))\n\t\t{\n\t\t\tpNodeBase = static_cast<node_type*>(pNodeBase->mpNext);\n\t\t\t--mnElementCount;\n\t\t}\n\n\t\tnode_type* pNodePrev = pNodeBase;\n\n\t\tif(pNodePrev)\n\t\t{\n\t\t\tnode_type* pNodeCur;\n\n\t\t\twhile((pNodeCur = static_cast<node_type*>(pNodePrev->mpNext)) != NULL)\n\t\t\t{\n\t\t\t\tif(mEqual(k, extractKey(*pNodeCur)))\n\t\t\t\t{\n\t\t\t\t\tpNodePrev->mpNext = static_cast<node_type*>(pNodeCur->mpNext);\n\t\t\t\t\t--mnElementCount; // To consider: In debug builds set the node mpNext to NULL.\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tpNodePrev = static_cast<node_type*>(pNodePrev->mpNext);\n\t\t\t}\n\t\t}\n\n\t\treturn nElementCountSaved - mnElementCount;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline typename intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::iterator\n\tintrusive_hashtable<K, V, H, Eq, bC, bM, bU>::remove(value_type& value)\n\t{\n\t\textract_key     extractKey; // extract_key is empty and thus this ctor is a no-op.\n\t\tconst size_type n = (size_type)(mHash(extractKey(value)) % kBucketCount);\n\n\t\treturn erase(iterator(&value, &mBucketArray[n]));\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline void intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::clear()\n\t{\n\t\t// To consider: In debug builds set the node mpNext to NULL.\n\t\tmemset(mBucketArray, 0, kBucketCount * sizeof(mBucketArray[0]));\n\t\tmnElementCount = 0;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline bool intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::validate() const\n\t{\n\t\t// Verify that the element count matches mnElementCount. \n\t\tsize_type nElementCount = 0;\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t\t++nElementCount;\n\n\t\tif(nElementCount != mnElementCount)\n\t\t\treturn false;\n\n\t\t// To do: Verify that individual elements are in the expected buckets.\n\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tint intrusive_hashtable<K, V, H, Eq, bC, bM, bU>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Come up with a more efficient mechanism of doing this.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline bool operator==(const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& a, \n\t\t\t\t\t\t   const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& b)\n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin());\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline bool operator!=(const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& a, \n\t\t\t\t\t\t   const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\t// Comparing hash tables for less-ness is an odd thing to do. We provide it for \n\t// completeness, though the user is advised to be wary of how they use this.\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline bool operator<(const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& a, \n\t\t\t\t\t\t  const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& b)\n\t{\n\t\t// This requires hash table elements to support operator<. Since the hash table\n\t\t// doesn't compare elements via less (it does so via equals), we must use the \n\t\t// globally defined operator less for the elements.\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline bool operator>(const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& a, \n\t\t\t\t\t\t  const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline bool operator<=(const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& a, \n\t\t\t\t\t\t   const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline bool operator>=(const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& a, \n\t\t\t\t\t\t   const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename K, typename V, typename H, typename Eq, size_t bC, bool bM, bool bU>\n\tinline void swap(const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& a, \n\t\t\t\t\t const intrusive_hashtable<K, V, H, Eq, bC, bM, bU>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/mem_fn.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_MEM_FN_H\n#define EASTL_INTERNAL_MEM_FN_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n#pragma once\n#endif\n\n#include <EABase/eadeprecated.h>\n\n////////////////////////////////////////////////////////////////////////////////\n// The code in this file is a modification of the libcxx implementation.  We copy\n// the license information here as required.\n//\n// We implement only enough of mem_fn to implement eastl::function.\n////////////////////////////////////////////////////////////////////////////////\n\n//===------------------------ functional ----------------------------------===//\n//\n//                     The LLVM Compiler Infrastructure\n//\n// This file is dual licensed under the MIT and the University of Illinois Open\n// Source Licenses. See LICENSE.TXT for details.\n//\n//===----------------------------------------------------------------------===//\n\nnamespace eastl\n{\n\t////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\t// mem_fn_impl\n\t//\n\ttemplate <class T>\n\tclass mem_fn_impl\n\t{\n\tpublic:\n\t\ttypedef T type;\n\n\tprivate:\n\t\ttype func;\n\n\tpublic:\n\t\tEASTL_FORCE_INLINE mem_fn_impl(type _func) : func(_func) {}\n\n#if EASTL_VARIADIC_TEMPLATES_ENABLED\n\t    template <class... ArgTypes>\n\t    typename invoke_result<type, ArgTypes...>::type operator()(ArgTypes&&... args) const\n\t    {\n\t\t    return invoke(func, eastl::forward<ArgTypes>(args)...);\n\t    }\n#else\n\t    typename invoke_result<type>::type operator()() const { return invoke_impl(func); }\n\n\t    template <class A0>\n\t    typename invoke_result0<type, A0>::type operator()(A0& a0) const\n\t    {\n\t\t    return invoke(func, a0);\n\t    }\n\n\t    template <class A0, class A1>\n\t    typename invoke_result1<type, A0, A1>::type operator()(A0& a0, A1& a1) const\n\t    {\n\t\t    return invoke(func, a0, a1);\n\t    }\n\n\t    template <class A0, class A1, class A2>\n\t    typename invoke_result2<type, A0, A1, A2>::type operator()(A0& a0, A1& a1, A2& a2) const\n\t    {\n\t\t    return invoke(func, a0, a1, a2);\n\t    }\n#endif\n    };  // mem_fn_impl\n\n\n\n\t////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\t// mem_fn -> mem_fn_impl adapters\n\t//\n\ttemplate <class R, class T>\n\tEASTL_FORCE_INLINE mem_fn_impl<R T::*> mem_fn(R T::*pm)\n\t{ return mem_fn_impl<R T::*>(pm); }\n\n\ttemplate <class R, class T>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)()> mem_fn(R (T::*pm)())\n\t{ return mem_fn_impl<R (T::*)()>(pm); }\n\n\ttemplate <class R, class T, class A0>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0)> mem_fn(R (T::*pm)(A0))\n\t{ return mem_fn_impl<R (T::*)(A0)>(pm); } \n\n\ttemplate <class R, class T, class A0, class A1>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1)> mem_fn(R (T::*pm)(A0, A1))\n\t{ return mem_fn_impl<R (T::*)(A0, A1)>(pm); }\n\n\ttemplate <class R, class T, class A0, class A1, class A2>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1, A2)> mem_fn(R (T::*pm)(A0, A1, A2))\n\t{ return mem_fn_impl<R (T::*)(A0, A1, A2)>(pm); }\n\n\ttemplate <class R, class T>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)() const> mem_fn(R (T::*pm)() const)\n\t{ return mem_fn_impl<R (T::*)() const>(pm); }\n\n\ttemplate <class R, class T, class A0>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0) const> mem_fn(R (T::*pm)(A0) const)\n\t{ return mem_fn_impl<R (T::*)(A0) const>(pm); }\n\n\ttemplate <class R, class T, class A0, class A1>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1) const> mem_fn(R (T::*pm)(A0, A1) const)\n\t{ return mem_fn_impl<R (T::*)(A0, A1) const>(pm); }\n\n\ttemplate <class R, class T, class A0, class A1, class A2>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1, A2) const> mem_fn(R (T::*pm)(A0, A1, A2) const)\n\t{ return mem_fn_impl<R (T::*)(A0, A1, A2) const>(pm); }\n\n\ttemplate <class R, class T>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)() volatile> mem_fn(R (T::*pm)() volatile)\n\t{ return mem_fn_impl<R (T::*)() volatile>(pm); }\n\n\ttemplate <class R, class T, class A0>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0) volatile> mem_fn(R (T::*pm)(A0) volatile)\n\t{ return mem_fn_impl<R (T::*)(A0) volatile>(pm); }\n\n\ttemplate <class R, class T, class A0, class A1>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1) volatile> mem_fn(R (T::*pm)(A0, A1) volatile)\n\t{ return mem_fn_impl<R (T::*)(A0, A1) volatile>(pm); }\n\n\ttemplate <class R, class T, class A0, class A1, class A2>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1, A2) volatile> mem_fn(R (T::*pm)(A0, A1, A2) volatile)\n\t{ return mem_fn_impl<R (T::*)(A0, A1, A2) volatile>(pm); }\n\n\ttemplate <class R, class T>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)() const volatile> mem_fn(R (T::*pm)() const volatile)\n\t{ return mem_fn_impl<R (T::*)() const volatile>(pm); }\n\n\ttemplate <class R, class T, class A0>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0) const volatile> mem_fn(R (T::*pm)(A0) const volatile)\n\t{ return mem_fn_impl<R (T::*)(A0) const volatile>(pm); }\n\n\ttemplate <class R, class T, class A0, class A1>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1) const volatile> mem_fn(R (T::*pm)(A0, A1) const volatile)\n\t{ return mem_fn_impl<R (T::*)(A0, A1) const volatile>(pm); }\n\n\ttemplate <class R, class T, class A0, class A1, class A2>\n\tEASTL_FORCE_INLINE mem_fn_impl<R (T::*)(A0, A1, A2) const volatile> mem_fn(R (T::*pm)(A0, A1, A2) const volatile)\n\t{ return mem_fn_impl<R (T::*)(A0, A1, A2) const volatile>(pm); }\n\n} // namespace eastl\n\n#endif // EASTL_INTERNAL_MEM_FN_H\n"
  },
  {
    "path": "include/EASTL/internal/memory_base.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_INTERNAL_MEMORY_BASE_H\n#define EASTL_INTERNAL_MEMORY_BASE_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/move_help.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n////////////////////////////////////////////////////////////////////////////////////////////\n// This file contains basic functionality found in the standard library 'memory' header that\n// have limited or no dependencies.  This allows us to utilize these utilize these functions\n// in other EASTL code while avoid circular dependencies.\n////////////////////////////////////////////////////////////////////////////////////////////\n\nnamespace eastl\n{\n\t/// addressof\n\t///\n\t/// From the C++11 Standard, section 20.6.12.1\n\t/// Returns the actual address of the object or function referenced by r, even in the presence of an overloaded operator&.\n\t///\n\ttemplate<typename T>\n\tT* addressof(T& value) EA_NOEXCEPT\n\t{\n\t\treturn reinterpret_cast<T*>(&const_cast<char&>(reinterpret_cast<const volatile char&>(value)));\n\t}\n\n\ttemplate<class T, class... Args>\n\tEA_CPP14_CONSTEXPR T* construct_at(T* p, Args&&... args)\n\t{\n\t\treturn ::new (static_cast<void*>(p)) T(eastl::forward<Args>(args)...);\n\t}\n\n} // namespace eastl\n\n#endif // EASTL_INTERNAL_MEMORY_BASE_H\n\n"
  },
  {
    "path": "include/EASTL/internal/memory_uses_allocator.h",
    "content": "// (c) 2024 Electronic Arts Inc.\n\n#pragma once\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/memory_base.h>\n#include <EASTL/tuple.h> // via its transitive includes, needs memory_base.h but *not* memory_uses_allocator.h\n#include <EASTL/type_traits.h>\n\nnamespace eastl\n{\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// uses_allocator\n\t//\n\t// Determines if the class T has an allocator_type member typedef\n\t// which Allocator is convertible to.\n\t//\n\t// http://en.cppreference.com/w/cpp/memory/uses_allocator\n\t//\n\t// A program may specialize this template to derive from true_type for a\n\t// user-defined type T that does not have a nested allocator_type but\n\t// nonetheless can be constructed with an allocator where either:\n\t//    - the first argument of a constructor has type allocator_arg_t and\n\t//      the second argument has type Allocator.\n\t//    or\n\t//    - the last argument of a constructor has type Allocator.\n\t//\n\t// Example behavilor:\n\t//     uses_allocator<vector>::value => true\n\t//     uses_allocator<int>::value    => false\n\t//\n\t// This is useful for writing generic code for containers when you can't\n\t// know ahead of time that the container has an allocator_type.\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T>\n\tstruct has_allocator_type_helper\n\t{\n\tprivate:\n\t\ttemplate <typename>\n\t\tstatic eastl::no_type test(...);\n\n\t\ttemplate <typename U>\n\t\tstatic eastl::yes_type test(typename U::allocator_type* = NULL);\n\n\tpublic:\n\t\tstatic const bool value = sizeof(test<T>(NULL)) == sizeof(eastl::yes_type);\n\t};\n\n\n\ttemplate <typename T, typename Allocator, bool = has_allocator_type_helper<T>::value>\n\tstruct uses_allocator_impl\n\t    : public integral_constant<bool, eastl::is_convertible<Allocator, typename T::allocator_type>::value>\n\t{\n\t};\n\n\ttemplate <typename T, typename Allocator>\n\tstruct uses_allocator_impl<T, Allocator, false> : public eastl::false_type\n\t{\n\t};\n\n\ttemplate <typename T, typename Allocator>\n\tstruct uses_allocator : public uses_allocator_impl<T, Allocator>\n\t{\n\t};\n\n\ttemplate <typename T, typename Allocator>\n\tconstexpr bool uses_allocator_v = uses_allocator<T, Allocator>::value;\n\n\tnamespace detail\n\t{\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct has_allocator_construct\n\t\t{\n\t\t\ttemplate <typename Allocator, typename = void>\n\t\t\tstruct inner : eastl::false_type\n\t\t\t{\n\t\t\t};\n\n\t\t\ttemplate <typename Allocator>\n\t\t\tstruct inner<Allocator,\n\t\t\t             eastl::void_t<decltype(eastl::declval<Allocator&>().construct(eastl::declval<T*>(),\n\t\t\t                                                                           eastl::declval<Args&&>()...))>>\n\t\t\t    : eastl::true_type\n\t\t\t{\n\t\t\t};\n\t\t};\n\n\t\t// equivalent to std::allocator_traits<Alloc>::construct\n\t\ttemplate <typename Allocator, typename T, typename... Args>\n\t\tEA_CPP14_CONSTEXPR\n\t\t    eastl::enable_if_t<has_allocator_construct<T, Args...>::template inner<Allocator>::value, void>\n\t\t    allocator_construct(Allocator& allocator, T* p, Args&&... args)\n\t\t{\n\t\t\tallocator.construct(p, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <typename Allocator, typename T, typename... Args>\n\t\tEA_CPP14_CONSTEXPR\n\t\t    eastl::enable_if_t<!has_allocator_construct<T, Args...>::template inner<Allocator>::value, void>\n\t\t    allocator_construct(Allocator&, T* p, Args&&... args)\n\t\t{\n\t\t\teastl::construct_at(p, eastl::forward<Args>(args)...);\n\t\t}\n\n\t} // namespace detail\n\n} // namespace eastl\n"
  },
  {
    "path": "include/EASTL/internal/move_help.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_MOVE_HELP_H\n#define EASTL_INTERNAL_MOVE_HELP_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n\n\n// C++11's rvalue references aren't supported by earlier versions of C++.\n// It turns out that in a number of cases under earlier C++ versions we can \n// write code that uses rvalues similar to lvalues. We have macros below for\n// such cases. For example, eastl::move (same as std::move) can be treated\n// as a no-op under C++03, though with the consequence that move functionality\n// isn't taken advantage of.\n\n\n/// EASTL_MOVE\n/// Acts like eastl::move when possible. Same as C++11 std::move.\n///\n/// EASTL_MOVE_INLINE\n/// Acts like eastl::move but is implemented inline instead of a function call.\n/// This allows code to be faster in debug builds in particular.\n/// Depends on C++ compiler decltype support or a similar extension.\n///\n/// EASTL_FORWARD\n/// Acts like eastl::forward when possible. Same as C++11 std::forward.\n///\n/// EASTL_FORWARD_INLINE\n/// Acts like eastl::forward but is implemented inline instead of a function call.\n/// This allows code to be faster in debug builds in particular.\n///\n#define EASTL_MOVE(x)              eastl::move(x)\n#if !defined(EA_COMPILER_NO_DECLTYPE)\n\t#define EASTL_MOVE_INLINE(x)   static_cast<typename eastl::remove_reference<decltype(x)>::type&&>(x)\n#elif defined(__GNUC__)\n\t#define EASTL_MOVE_INLINE(x)   static_cast<typename eastl::remove_reference<__typeof__(x)>::type&&>(x)\n#else\n\t#define EASTL_MOVE_INLINE(x)   eastl::move(x)\n#endif\n\n#define EASTL_FORWARD(T, x)        eastl::forward<T>(x)\n#define EASTL_FORWARD_INLINE(T, x) eastl::forward<T>(x)  // Need to investigate how to properly make a macro for this. (eastl::is_reference<T>::value ? static_cast<T&&>(static_cast<T&>(x)) : static_cast<T&&>(x))\n\n\n\n\n/// EASTL_MOVE_RANGE\n/// Acts like the eastl::move algorithm when possible. Same as C++11 std::move.\n/// Note to be confused with the single argument move: (typename remove_reference<T>::type&& move(T&& x))\n/// http://en.cppreference.com/w/cpp/algorithm/move\n/// http://en.cppreference.com/w/cpp/algorithm/move_backward\n///\n#define EASTL_MOVE_RANGE(first, last, result)             eastl::move(first, last, result)\n#define EASTL_MOVE_BACKWARD_RANGE(first, last, resultEnd) eastl::move_backward(first, last, resultEnd)\n\n\nnamespace eastl\n{\n\t// forward\n\t//\n\t// forwards the argument to another function exactly as it was passed to the calling function.\n\t// Not to be confused with move, this is specifically for echoing templated argument types\n\t// to another function. move is specifically about making a type be an rvalue reference (i.e. movable) type.\n\t//\n\t// Example usage:\n\t//     template <class T>\n\t//     void WrapperFunction(T&& arg)\n\t//         { foo(eastl::forward<T>(arg)); } \n\t//\n\t//     template <class... Args>\n\t//     void WrapperFunction(Args&&... args)\n\t//         { foo(eastl::forward<Args>(args)...); } \n\t//\n\t// See the C++ Standard, section 20.2.3\n\t// http://en.cppreference.com/w/cpp/utility/forward\n\t//\n\ttemplate <typename T>\n\tEA_CPP14_CONSTEXPR T&& forward(typename eastl::remove_reference<T>::type& x) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<T&&>(x);\n\t}\n\n\n\ttemplate <typename T>\n\tEA_CPP14_CONSTEXPR T&& forward(typename eastl::remove_reference<T>::type&& x) EA_NOEXCEPT\n\t{\n\t\tstatic_assert(!is_lvalue_reference<T>::value, \"forward T isn't lvalue reference\");\n\t\treturn static_cast<T&&>(x);\n\t}\n\n\n\t// move\n\t//\n\t// move obtains an rvalue reference to its argument and converts it to an xvalue.\n\t// Returns, by definition: static_cast<typename remove_reference<T>::type&&>(t).\n\t// The primary use of this is to pass a move'd type to a function which takes T&&,\n\t// and thus select that function instead of (e.g.) a function which takes T or T&.\n\t// See the C++ Standard, section 20.2.3\n\t// http://en.cppreference.com/w/cpp/utility/move\n\t//\n\ttemplate <typename T>\n\tEA_CPP14_CONSTEXPR typename eastl::remove_reference<T>::type&&\n\tmove(T&& x) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<typename eastl::remove_reference<T>::type&&>(x);\n\t}\n\n\n\t// move_if_noexcept\n\t//\n\t// Returns T&& if move-constructing T throws no exceptions. Instead returns const T& if\n\t// move-constructing T throws exceptions or has no accessible copy constructor.\n\t// The purpose of this is to use automatically use copy construction instead of move \n\t// construction when the move may possible throw an exception.\n\t// See the C++ Standard, section 20.2.3\n\t// http://en.cppreference.com/w/cpp/utility/move_if_noexcept\n\t//\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\ttemplate <typename T> \n\t\tEA_CPP14_CONSTEXPR typename eastl::conditional<!eastl::is_nothrow_move_constructible<T>::value && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\teastl::is_copy_constructible<T>::value, const T&, T&&>::type \n\t\tmove_if_noexcept(T& x) EA_NOEXCEPT\n\t\t{\n\t\t\treturn eastl::move(x);\n\t\t}\n\t#else\n\t\ttemplate <typename T> \n\t\tEA_CPP14_CONSTEXPR T&&\n\t\tmove_if_noexcept(T& x) EA_NOEXCEPT\n\t\t{\n\t\t\treturn eastl::move(x);\n\t\t}\n\t#endif\n\n} // namespace eastl\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/pair_fwd_decls.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_PAIR_FWD_DECLS_H\n#define EASTL_PAIR_FWD_DECLS_H\n\n#include <EASTL/internal/config.h>\n\nnamespace eastl\n{\n\ttemplate <typename T1, typename T2>\n\tstruct pair;\n}\n\n#endif // EASTL_PAIR_FWD_DECLS_H\n"
  },
  {
    "path": "include/EASTL/internal/piecewise_construct_t.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_PIECEWISE_CONSTRUCT_T_H\n#define EASTL_INTERNAL_PIECEWISE_CONSTRUCT_T_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////////\n\t/// piecewise_construct_t\n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/piecewise_construct_t\n\t///\n\tstruct piecewise_construct_t\n\t{\n\t\texplicit piecewise_construct_t() = default;\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t/// piecewise_construct\n\t/// \n\t/// A tag type used to disambiguate between function overloads that take two tuple arguments.\n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/piecewise_construct\n\t///\n\tEA_CONSTEXPR piecewise_construct_t piecewise_construct = eastl::piecewise_construct_t();\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/red_black_tree.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_RED_BLACK_TREE_H\n#define EASTL_RED_BLACK_TREE_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/allocator.h>\n#include <EASTL/iterator.h>\n#include <EASTL/utility.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/tuple.h>\n#include <EASTL/memory.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <new>\n#include <stddef.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n// 4512/4626 - 'class' : assignment operator could not be generated\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\nEA_DISABLE_VC_WARNING(4512 4626 4530 4571);\n\n\nnamespace eastl\n{\n\n\t/// EASTL_RBTREE_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_RBTREE_DEFAULT_NAME\n\t\t#define EASTL_RBTREE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" rbtree\" // Unless the user overrides something, this is \"EASTL rbtree\".\n\t#endif\n\n\n\t/// EASTL_RBTREE_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_RBTREE_DEFAULT_ALLOCATOR\n\t\t#define EASTL_RBTREE_DEFAULT_ALLOCATOR allocator_type(EASTL_RBTREE_DEFAULT_NAME)\n\t#endif\n\n\n\t/// EASTL_RBTREE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t///\n\t#ifndef EASTL_RBTREE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t\t#define EASTL_RBTREE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR 0\n\t#endif\n\n\n\t/// RBTreeColor\n\t///\n\tenum RBTreeColor\n\t{\n\t\tkRBTreeColorRed,\n\t\tkRBTreeColorBlack\n\t};\n\n\n\n\t/// RBTreeColor\n\t///\n\tenum RBTreeSide\n\t{\n\t\tkRBTreeSideLeft,\n\t\tkRBTreeSideRight\n\t};\n\n\n\n\t/// rbtree_node_base\n\t///\n\t/// We define a rbtree_node_base separately from rbtree_node (below), because it \n\t/// allows us to have non-templated operations, and it makes it so that the \n\t/// rbtree anchor node doesn't carry a T with it, which would waste space and \n\t/// possibly lead to surprising the user due to extra Ts existing that the user \n\t/// didn't explicitly create. The downside to all of this is that it makes debug \n\t/// viewing of an rbtree harder, given that the node pointers are of type \n\t/// rbtree_node_base and not rbtree_node.\n\t///\n\tstruct rbtree_node_base\n\t{\n\t\ttypedef rbtree_node_base this_type;\n\n\tpublic:\n\t\tthis_type* mpNodeRight;  // Declared first because it is used most often.\n\t\tthis_type* mpNodeLeft;\n\t\tthis_type* mpNodeParent;\n\t\tchar       mColor;       // We only need one bit here, would be nice if we could stuff that bit somewhere else.\n\t};\n\n\n\t/// rbtree_node\n\t///\n\ttemplate <typename Value>\n\tstruct rbtree_node : public rbtree_node_base\n\t{\n\t\tValue mValue; // For set and multiset, this is the user's value, for map and multimap, this is a pair of key/value.\n\n\t\t// This type is never constructed, so to avoid a MSVC warning we \"delete\" the copy constructor.\n\t\t//\n\t\t// Potentially we could provide a constructor that would satisfy the compiler and change the code to use this constructor\n\t\t// instead of constructing mValue in place within an unconstructed rbtree_node.\n\t\t#if defined(_MSC_VER)\n\t\t\trbtree_node(const rbtree_node&) = delete;\n\t\t#endif\n\t};\n\n\n\n\n\t// rbtree_node_base functions\n\t//\n\t// These are the fundamental functions that we use to maintain the \n\t// tree. The bulk of the work of the tree maintenance is done in \n\t// these functions.\n\t//\n\tEASTL_API rbtree_node_base* RBTreeIncrement    (const rbtree_node_base* pNode);\n\tEASTL_API rbtree_node_base* RBTreeDecrement    (const rbtree_node_base* pNode);\n\tEASTL_API rbtree_node_base* RBTreeGetMinChild  (const rbtree_node_base* pNode);\n\tEASTL_API rbtree_node_base* RBTreeGetMaxChild  (const rbtree_node_base* pNode);\n\tEASTL_API size_t            RBTreeGetBlackCount(const rbtree_node_base* pNodeTop,\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst rbtree_node_base* pNodeBottom);\n\tEASTL_API void              RBTreeInsert       (      rbtree_node_base* pNode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  rbtree_node_base* pNodeParent, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  rbtree_node_base* pNodeAnchor,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  RBTreeSide insertionSide);\n\tEASTL_API void              RBTreeErase        (      rbtree_node_base* pNode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  rbtree_node_base* pNodeAnchor); \n\n\n\n\n\n\n\n\t/// rbtree_iterator\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tstruct rbtree_iterator\n\t{\n\t\ttypedef rbtree_iterator<T, Pointer, Reference>      this_type;\n\t\ttypedef rbtree_iterator<T, T*, T&>                  iterator;\n\t\ttypedef rbtree_iterator<T, const T*, const T&>      const_iterator;\n\t\ttypedef eastl_size_t                                size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                   difference_type;\n\t\ttypedef T                                           value_type;\n\t\ttypedef rbtree_node_base                            base_node_type;\n\t\ttypedef rbtree_node<T>                              node_type;\n\t\ttypedef Pointer                                     pointer;\n\t\ttypedef Reference                                   reference;\n\t\ttypedef eastl::bidirectional_iterator_tag    iterator_category;\n\n\tprivate:\n\t\tbase_node_type* mpNode;\n\n\tpublic:\n\t\trbtree_iterator();\n\t\texplicit rbtree_iterator(const base_node_type* pNode);\n\t\t// Note: this isn't always a copy constructor, iterator is not always equal to this_type\n\t\trbtree_iterator(const iterator& x);\n\t\t// Note: this isn't always a copy assignment operator, iterator is not always equal to this_type\n\t\trbtree_iterator& operator=(const iterator& x);\n\n\t\t// Calling these on the end() of a tree invokes undefined behavior.\n\t\treference operator*() const;\n\t\tpointer   operator->() const;\n\n\t\trbtree_iterator& operator++();\n\t\trbtree_iterator  operator++(int);\n\n\t\trbtree_iterator& operator--();\n\t\trbtree_iterator  operator--(int);\n\tprivate:\n\n\t\ttemplate<class U, class PtrA, class RefA, class PtrB, class RefB>\n\t\tfriend bool operator==(const rbtree_iterator<U, PtrA, RefA>&, const rbtree_iterator<U, PtrB, RefB>&);\n\n\t\ttemplate<class U, class PtrA, class RefA, class PtrB, class RefB>\n\t\tfriend bool operator!=(const rbtree_iterator<U, PtrA, RefA>&, const rbtree_iterator<U, PtrB, RefB>&);\n\n\t\ttemplate<class U, class PtrA, class RefA>\n\t\tfriend bool operator!=(const rbtree_iterator<U, PtrA, RefA>&, const rbtree_iterator<U, PtrA, RefA>&);\n\n\t\t// rbtree uses mpNode.\n\t\ttemplate <class Key, class Value, class Compare, class Allocator,\n\t\t\t\t  class ExtractKey, bool bMutableIterators, bool bUniqueKeys>\n\t\tfriend class rbtree;\n\n\t\t// for the \"copy\" constructor, which uses non-const iterator even in the\n\t\t// const_iterator case.\n\t\tfriend iterator;\n\t\tfriend const_iterator;\n\t}; // rbtree_iterator\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// rb_base_compare_ebo\n\t//\n\t// Utilizes the \"empty base-class optimization\" to reduce the size of the rbtree\n\t// when its Compare template argument is an empty class.\n\t///////////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Compare, bool /*isEmpty*/ = is_empty<Compare>::value>\n\tstruct rb_base_compare_ebo\n\t{\n\tprotected:\n\t\trb_base_compare_ebo() : mCompare() {}\n\t\trb_base_compare_ebo(const Compare& compare) : mCompare(compare) {}\n\n\t\tCompare& get_compare() { return mCompare; }\n\t\tconst Compare& get_compare() const { return mCompare; }\n\n\t\ttemplate <typename T, typename U>\n\t\tbool compare(const T& lhs, const U& rhs) \n\t\t{\n\t\t\treturn mCompare(lhs, rhs);\n\t\t}\n\n\t\ttemplate <typename T, typename U>\n\t\tbool compare(const T& lhs, const U& rhs) const\n\t\t{\n\t\t\treturn mCompare(lhs, rhs);\n\t\t}\n\n\tprivate:\n\t\tCompare mCompare;\n\t};\n\n\ttemplate <typename Compare>\n\tstruct rb_base_compare_ebo<Compare, true> : private Compare\n\t{\n\tprotected:\n\t\trb_base_compare_ebo() {}\n\t\trb_base_compare_ebo(const Compare& compare) : Compare(compare) {}\n\n\t\tCompare& get_compare() { return *this; }\n\t\tconst Compare& get_compare() const { return *this; }\n\n\t\ttemplate <typename T, typename U>\n\t\tbool compare(const T& lhs, const U& rhs) \n\t\t{\n\t\t\treturn Compare::operator()(lhs, rhs);\n\t\t}\n\n\t\ttemplate <typename T, typename U>\n\t\tbool compare(const T& lhs, const U& rhs) const\n\t\t{\n\t\t\treturn Compare::operator()(lhs, rhs);\n\t\t}\n\t};\n\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n    // rb_base\n    //\n    // This class allows us to use a generic rbtree as the basis of map, multimap,\n    // set, and multiset transparently. The vital template parameters for this are \n    // the ExtractKey and the bUniqueKeys parameters.\n    //\n    // If the rbtree has a value type of the form pair<T1, T2> (i.e. it is a map or\n    // multimap and not a set or multiset) and a key extraction policy that returns \n    // the first part of the pair, the rbtree gets a mapped_type typedef. \n    // If it satisfies those criteria and also has unique keys, then it also gets an \n    // operator[] (which only map and set have and multimap and multiset don't have).\n    //\n    ///////////////////////////////////////////////////////////////////////////////\n\n\n\n\t/// rb_base\n\t/// This specialization is used for 'set'. In this case, Key and Value \n\t/// will be the same as each other and ExtractKey will be eastl::use_self.\n\t///\n\ttemplate <typename Key, typename Value, typename Compare, typename ExtractKey, bool bUniqueKeys, typename RBTree>\n\tstruct rb_base : public rb_base_compare_ebo<Compare>\n\t{\n\t\ttypedef ExtractKey extract_key;\n\n\tprotected:\n\t\tusing rb_base_compare_ebo<Compare>::compare;\n\t\tusing rb_base_compare_ebo<Compare>::get_compare;\n\n\tpublic:\n\t\trb_base() {}\n\t\trb_base(const Compare& compare) : rb_base_compare_ebo<Compare>(compare) {}\n\t};\n\n\n\t/// rb_base\n\t/// This class is used for 'multiset'.\n\t/// In this case, Key and Value will be the same as each \n\t/// other and ExtractKey will be eastl::use_self.\n\t///\n\ttemplate <typename Key, typename Value, typename Compare, typename ExtractKey, typename RBTree>\n\tstruct rb_base<Key, Value, Compare, ExtractKey, false, RBTree> : public rb_base_compare_ebo<Compare>\n\t{\n\t\ttypedef ExtractKey extract_key;\n\n\tprotected:\n\t\tusing rb_base_compare_ebo<Compare>::compare;\n\t\tusing rb_base_compare_ebo<Compare>::get_compare;\n\n\tpublic:\n\t\trb_base() {}\n\t\trb_base(const Compare& compare) : rb_base_compare_ebo<Compare>(compare) {}\n\t};\n\n\n\t/// rb_base\n\t/// This specialization is used for 'map'.\n\t///\n\ttemplate <typename Key, typename Pair, typename Compare, typename RBTree>\n\tstruct rb_base<Key, Pair, Compare, eastl::use_first<Pair>, true, RBTree> : public rb_base_compare_ebo<Compare>\n\t{\n\t\ttypedef eastl::use_first<Pair> extract_key;\n\n\t\tusing rb_base_compare_ebo<Compare>::compare;\n\t\tusing rb_base_compare_ebo<Compare>::get_compare;\n\n\tpublic:\n\t\trb_base() {}\n\t\trb_base(const Compare& compare) : rb_base_compare_ebo<Compare>(compare) {}\n\t};\n\n\n\t/// rb_base\n\t/// This specialization is used for 'multimap'.\n\t///\n\ttemplate <typename Key, typename Pair, typename Compare, typename RBTree>\n\tstruct rb_base<Key, Pair, Compare, eastl::use_first<Pair>, false, RBTree> : public rb_base_compare_ebo<Compare>\n\t{\n\t\ttypedef eastl::use_first<Pair> extract_key;\n\n\t\tusing rb_base_compare_ebo<Compare>::compare;\n\t\tusing rb_base_compare_ebo<Compare>::get_compare;\n\n\tpublic:\n\t\trb_base() {}\n\t\trb_base(const Compare& compare) : rb_base_compare_ebo<Compare>(compare) {}\n\t};\n\n\n\t/// rbtree\n\t///\n\t/// rbtree is the red-black tree basis for the map, multimap, set, and multiset \n\t/// containers. Just about all the work of those containers is done here, and \n\t/// they are merely a shell which sets template policies that govern the code\n\t/// generation for this rbtree.\n\t///\n\t/// This rbtree implementation is pretty much the same as all other modern \n\t/// rbtree implementations, as the topic is well known and researched. We may\n\t/// choose to implement a \"relaxed balancing\" option at some point in the \n\t/// future if it is deemed worthwhile. Most rbtree implementations don't do this.\n\t///\n\t/// The primary rbtree member variable is mAnchor, which is a node_type and \n\t/// acts as the end node. However, like any other node, it has mpNodeLeft,\n\t/// mpNodeRight, and mpNodeParent members. We do the conventional trick of \n\t/// assigning begin() (left-most rbtree node) to mpNodeLeft, assigning \n\t/// 'end() - 1' (a.k.a. rbegin()) to mpNodeRight, and assigning the tree root\n\t/// node to mpNodeParent. \n\t///\n\t/// Compare (functor): This is a comparison class which defaults to 'less'.\n\t/// It is a common STL thing which takes two arguments and returns true if  \n\t/// the first is less than the second.\n\t///\n\t/// ExtractKey (functor): This is a class which gets the key from a stored\n\t/// node. With map and set, the node is a pair, whereas with set and multiset\n\t/// the node is just the value. ExtractKey will be either eastl::use_first (map and multimap)\n\t/// or eastl::use_self (set and multiset).\n\t///\n\t/// bMutableIterators (bool): true if rbtree::iterator is a mutable\n\t/// iterator, false if iterator and const_iterator are both const iterators. \n\t/// It will be true for map and multimap and false for set and multiset.\n\t///\n\t/// bUniqueKeys (bool): true if the keys are to be unique, and false if there\n\t/// can be multiple instances of a given key. It will be true for set and map \n\t/// and false for multiset and multimap.\n\t///\n\t/// To consider: Add an option for relaxed tree balancing. This could result \n\t/// in performance improvements but would require a more complicated implementation.\n\t///\n\t///////////////////////////////////////////////////////////////////////\n\t/// Heterogeneous lookup, insertion and erasure\n\t/// See\n\t/// https://en.cppreference.com/w/cpp/utility/functional#Transparent_function_objects\n\t/// https://en.cppreference.com/w/cpp/utility/functional/less_void\n\t/// https://en.cppreference.com/w/cpp/container/set/find\n\t/// \n\t/// You can avoid creating key objects when calling member functions\n\t/// with a key_type parameter by declaring the container with\n\t/// transparent comparison type (eg. less<void>) and passing objects\n\t/// to be passed to this function object.\n\t/// \n\t/// This optimization is supported for member functions that take a\n\t/// key_type parameter, ie. heterogeneous lookup, insertion and erasure,\n\t/// not just find().\n\t/// \n\t/// Using transparent types is safer than using find_as because the\n\t/// latter requires the user specify comparison objects which must have\n\t/// the same semantics as the container's comparison object, otherwise\n\t/// the behaviour is undefined.\n\t/// \n\t/// find_as\n\t/// Note: Prefer heterogeneous lookup (see above).\n\t/// \n\t/// In order to support the ability to have a tree of strings but\n\t/// be able to do efficiently lookups via char pointers (i.e. so they\n\t/// aren't converted to string objects), we provide the find_as\n\t/// function. This function allows you to do a find with a key of a\n\t/// type other than the tree's key type. See the find_as function\n\t/// for more documentation on this.\n\t///\n\ttemplate <typename Key, typename Value, typename Compare, typename Allocator, \n\t\t\t  typename ExtractKey, bool bMutableIterators, bool bUniqueKeys>\n\tclass rbtree\n\t\t: public rb_base<Key, Value, Compare, ExtractKey, bUniqueKeys, \n\t\t\t\t\t\t\trbtree<Key, Value, Compare, Allocator, ExtractKey, bMutableIterators, bUniqueKeys> >\n\t{\n\tpublic:\n\t\ttypedef ptrdiff_t                                                                       difference_type;\n\t\ttypedef eastl_size_t                                                                    size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef Key                                                                             key_type;\n\t\ttypedef Value                                                                           value_type;\n\t\ttypedef rbtree_node<value_type>                                                         node_type;\n\t\ttypedef value_type&                                                                     reference;\n\t\ttypedef const value_type&                                                               const_reference;\n\t\ttypedef value_type*                                                                     pointer;\n\t\ttypedef const value_type*                                                               const_pointer;\n\n\t\ttypedef typename conditional<bMutableIterators,\n\t\t\t\t\trbtree_iterator<value_type, value_type*, value_type&>, \n\t\t\t\t\trbtree_iterator<value_type, const value_type*, const value_type&> >::type   iterator;\n\t\ttypedef rbtree_iterator<value_type, const value_type*, const value_type&>               const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>                                               reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>                                         const_reverse_iterator;\n\n\t\ttypedef Allocator                                                                       allocator_type;\n\t\ttypedef Compare                                                                         key_compare;\n\t\ttypedef typename conditional<bUniqueKeys, eastl::pair<iterator, bool>, iterator>::type  insert_return_type;  // map/set::insert return a pair, multimap/multiset::iterator return an iterator.\n\t\ttypedef rbtree<Key, Value, Compare, Allocator, \n\t\t\t\t\t\tExtractKey, bMutableIterators, bUniqueKeys>                             this_type;\n\t\ttypedef rb_base<Key, Value, Compare, ExtractKey, bUniqueKeys, this_type>                base_type;\n\t\ttypedef integral_constant<bool, bUniqueKeys>                                            has_unique_keys_type;\n\t\ttypedef typename base_type::extract_key                                                 extract_key;\n\n\tprotected:\n\t\tusing base_type::compare;\n\t\tusing base_type::get_compare;\n\n\tpublic:\n\t\trbtree_node_base  mAnchor;      /// This node acts as end() and its mpLeft points to begin(), and mpRight points to rbegin() (the last node on the right).\n\t\tsize_type         mnSize;       /// Stores the count of nodes in the tree (not counting the anchor node).\n\t\tallocator_type    mAllocator;   // To do: Use base class optimization to make this go away.\n\n\tpublic:\n\t\t// ctor/dtor\n\t\trbtree();\n\t\trbtree(const allocator_type& allocator);\n\t\trbtree(const Compare& compare, const allocator_type& allocator = EASTL_RBTREE_DEFAULT_ALLOCATOR);\n\t\trbtree(const this_type& x);\n\t\trbtree(this_type&& x);\n\t\trbtree(this_type&& x, const allocator_type& allocator);\n\n\t\ttemplate <typename InputIterator>\n\t\trbtree(InputIterator first, InputIterator last, const Compare& compare, const allocator_type& allocator = EASTL_RBTREE_DEFAULT_ALLOCATOR);\n\n\t   ~rbtree();\n\n\tpublic:\n\t\t// properties\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT;\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT;\n\t\tvoid                  set_allocator(const allocator_type& allocator);\n\n\t\tconst key_compare& key_comp() const { return get_compare(); }\n\t\tkey_compare&       key_comp()       { return get_compare(); }\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\tpublic: \n\t\t// iterators\n\t\titerator        begin() EA_NOEXCEPT;\n\t\tconst_iterator  begin() const EA_NOEXCEPT;\n\t\tconst_iterator  cbegin() const EA_NOEXCEPT;\n\n\t\titerator        end() EA_NOEXCEPT;\n\t\tconst_iterator  end() const EA_NOEXCEPT;\n\t\tconst_iterator  cend() const EA_NOEXCEPT;\n\n\t\treverse_iterator        rbegin() EA_NOEXCEPT;\n\t\tconst_reverse_iterator  rbegin() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator  crbegin() const EA_NOEXCEPT;\n\n\t\treverse_iterator        rend() EA_NOEXCEPT;\n\t\tconst_reverse_iterator  rend() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator  crend() const EA_NOEXCEPT;\n\n\tpublic:\n\t\tbool      empty() const EA_NOEXCEPT;\n\t\tsize_type size() const EA_NOEXCEPT;\n\n\t\ttemplate <class... Args>\n\t\tinsert_return_type emplace(Args&&... args);\n\n\t\ttemplate <class... Args> \n\t\titerator emplace_hint(const_iterator position, Args&&... args);\n\n\t\t// Currently limited to value_type instead of P because it collides with insert(InputIterator, InputIterator).\n\t\t// To allow this to work with templated P we need to implement a compile-time specialization for the\n\t\t// case that P&& is const_iterator and have that specialization handle insert(InputIterator, InputIterator)\n\t\t// instead of insert(InputIterator, InputIterator). Curiously, neither libstdc++ nor libc++\n\t\t// implement this function either, which suggests they ran into the same problem I did here\n\t\t// and haven't yet resolved it (at least as of March 2014, GCC 4.8.1).\n\t\titerator insert(const_iterator hint, value_type&& value);\n\n\t\t/// map::insert and set::insert return a pair, while multimap::insert and\n\t\t/// multiset::insert return an iterator.\n\t\tinsert_return_type insert(const value_type& value);\n\t\tinsert_return_type insert(value_type&& value);\n\n\t\t// C++ standard: inserts value if and only if there is no element with \n\t\t// key equivalent to the key of t in containers with unique keys; always \n\t\t// inserts value in containers with equivalent keys. Always returns the \n\t\t// iterator pointing to the element with key equivalent to the key of value. \n\t\t// iterator position is a hint pointing to where the insert should start\n\t\t// to search. However, there is a potential defect/improvement report on this behaviour:\n\t\t// LWG issue #233 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html)\n\t\t// We follow the same approach as SGI STL/STLPort and use the position as\n\t\t// a forced insertion position for the value when possible.\n\t\titerator insert(const_iterator position, const value_type& value);\n\n\t\tvoid insert(std::initializer_list<value_type> ilist);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(InputIterator first, InputIterator last);\n\n\t\t// TODO(rparolin):\n\t\t// insert_return_type insert(node_type&& nh);\n\t\t// iterator insert(const_iterator hint, node_type&& nh);\n\n\t\ttemplate <class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) { return DoInsertOrAssign(k, eastl::forward<M>(obj)); }\n\t\ttemplate <class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) { return DoInsertOrAssign(eastl::move(k), eastl::forward<M>(obj)); }\n\t\ttemplate<typename KX, typename M, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tpair<iterator, bool>\t\t\t\t\tinsert_or_assign(KX&& k, M&& obj) { return DoInsertOrAssign(eastl::forward<KX>(k), eastl::forward<M>(obj)); }\n\t\ttemplate <class M> iterator             insert_or_assign(const_iterator hint, const key_type& k, M&& obj) { return DoInsertOrAssign(hint, k, eastl::forward<M>(obj)); }\n\t\ttemplate <class M> iterator             insert_or_assign(const_iterator hint, key_type&& k, M&& obj) { return DoInsertOrAssign(hint, eastl::move(k), eastl::forward<M>(obj)); }\n\t\ttemplate<typename KX, typename M, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator\t\t\t\t\t\t\t\tinsert_or_assign(const_iterator hint, KX&& k, M&& obj) { return DoInsertOrAssign(hint, eastl::forward<KX>(k), eastl::forward<M>(obj)); }\n\n\t\ttemplate <typename Iter = iterator, typename eastl::enable_if<!eastl::is_same_v<Iter, const_iterator>, int>::type = 0>\n\t\titerator         erase(iterator position) { return erase(const_iterator(position)); }\n\t\titerator         erase(const_iterator position);\n\t\titerator         erase(const_iterator first, const_iterator last);\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\t// For some reason, multiple STL versions make a specialization \n\t\t// for erasing an array of key_types. I'm pretty sure we don't\n\t\t// need this, but just to be safe we will follow suit. \n\t\t// The implementation is trivial. Returns void because the values\n\t\t// could well be randomly distributed throughout the tree and thus\n\t\t// a return value would be nearly meaningless.\n\t\tvoid erase(const key_type* first, const key_type* last);\n\n\t\tvoid clear();\n\t\tvoid reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\titerator       find(const key_type& key) { return DoFind(key); }\n\t\tconst_iterator find(const key_type& key) const { return DoFind(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       find(const KX& key) { return DoFind(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator find(const KX& key) const { return DoFind(key); }\n\n\t\t/// Implements a find whereby the user supplies a comparison of a different type\n\t\t/// than the tree's value_type. A useful case of this is one whereby you have\n\t\t/// a container of string objects but want to do searches via passing in char pointers.\n\t\t/// The problem is that without this kind of find, you need to do the expensive operation\n\t\t/// of converting the char pointer to a string so it can be used as the argument to the\n\t\t/// find function.\n\t\t///\n\t\t/// Example usage (note that the compare uses string as first type and char* as second):\n\t\t///     set<string> strings;\n\t\t///     strings.find_as(\"hello\", less<>());\n\t\t///\n\t\ttemplate <typename U, typename Compare2> iterator       find_as(const U& u, Compare2 compare2);\n\t\ttemplate <typename U, typename Compare2> const_iterator find_as(const U& u, Compare2 compare2) const;\n\n\t\tbool contains(const key_type& key) const { return DoFind(key) != end(); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tbool contains(const KX& key) const { return DoFind(key) != end(); }\n\n\t\titerator       lower_bound(const key_type& key) { return DoLowerBound(key); }\n\t\tconst_iterator lower_bound(const key_type& key) const { return DoLowerBound(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       lower_bound(const KX& key) { return DoLowerBound(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator lower_bound(const KX& key) const { return DoLowerBound(key); }\n\n\t\titerator       upper_bound(const key_type& key) { return DoUpperBound(key); }\n\t\tconst_iterator upper_bound(const key_type& key) const { return DoUpperBound(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       upper_bound(const KX& key) { return DoUpperBound(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator upper_bound(const KX& key) const { return DoUpperBound(key); }\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\tprotected:\n\t\tnode_type* DoAllocateNode();\n\t\tvoid       DoFreeNode(node_type* pNode);\n\n\t\tnode_type* DoCreateNodeFromKey(const key_type& key);\n\n\t\ttemplate<class... Args>\n\t\tnode_type* DoCreateNode(Args&&... args);\n\t\tnode_type* DoCreateNode(const value_type& value);\n\t\tnode_type* DoCreateNode(value_type&& value);\n\t\tnode_type* DoCreateNode(const node_type* pNodeSource, rbtree_node_base* pNodeParent);\n\n\t\trbtree_node_base* DoCopySubtree(const node_type* pNodeSource, rbtree_node_base* pNodeDest);\n\t\tvoid       DoNukeSubtree(rbtree_node_base* pNode);\n\n\t\ttemplate <class... Args>\n\t\teastl::pair<iterator, bool> DoInsertValue(true_type, Args&&... args);\n\n\t\ttemplate <class... Args>\n\t\titerator DoInsertValue(false_type, Args&&... args);\n\n\t\teastl::pair<iterator, bool> DoInsertValue(true_type, value_type&& value);\n\t\titerator DoInsertValue(false_type, value_type&& value);\n\n\t\ttemplate <class... Args>\n\t\titerator DoInsertValueImpl(rbtree_node_base* pNodeParent, bool bForceToLeft, const key_type& key, Args&&... args);\n\t\titerator DoInsertValueImpl(rbtree_node_base* pNodeParent, bool bForceToLeft, const key_type& key, node_type* pNodeNew);\n\n\t\teastl::pair<iterator, bool> DoInsertKey(true_type, const key_type& key);\n\t\titerator                    DoInsertKey(false_type, const key_type& key);\n\n\t\ttemplate <class... Args>\n\t\titerator DoInsertValueHint(true_type, const_iterator position, Args&&... args);\n\n\t\ttemplate <class... Args>\n\t\titerator DoInsertValueHint(false_type, const_iterator position, Args&&... args);\n\n\t\titerator DoInsertValueHint(true_type, const_iterator position, value_type&& value);\n\t\titerator DoInsertValueHint(false_type, const_iterator position, value_type&& value);\n\n\t\titerator DoInsertKey(true_type, const_iterator position, const key_type& key);  // By design we return iterator and not a pair.\n\t\titerator DoInsertKey(false_type, const_iterator position, const key_type& key);\n\t\titerator DoInsertKeyImpl(rbtree_node_base* pNodeParent, bool bForceToLeft, const key_type& key);\n\n\t\ttemplate <typename KX>\n\t\trbtree_node_base* DoGetKeyInsertionPositionUniqueKeys(bool& canInsert, const KX& key);\n\t\trbtree_node_base* DoGetKeyInsertionPositionNonuniqueKeys(const key_type& key);\n\n\t\ttemplate <typename KX>\n\t\trbtree_node_base* DoGetKeyInsertionPositionUniqueKeysHint(const_iterator position, bool& bForceToLeft, const KX& key);\n\t\trbtree_node_base* DoGetKeyInsertionPositionNonuniqueKeysHint(const_iterator position, bool& bForceToLeft, const key_type& key);\n\n\t\ttemplate<typename KX, typename M>\n\t\tpair<iterator, bool>\tDoInsertOrAssign(KX&& k, M&& obj);\n\t\ttemplate<typename KX, typename M>\n\t\titerator\t\t\t\tDoInsertOrAssign(const_iterator hint, KX&& k, M&& obj);\n\n\t\ttemplate<typename KX>\n\t\titerator DoFind(const KX& key);\n\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoFind(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\titerator DoLowerBound(const KX& key);\n\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoLowerBound(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\titerator DoUpperBound(const KX& key);\n\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoUpperBound(const KX& key) const;\n\n\t}; // rbtree\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// rbtree_node_base functions\n\t///////////////////////////////////////////////////////////////////////\n\n\tEASTL_API inline rbtree_node_base* RBTreeGetMinChild(const rbtree_node_base* pNodeBase)\n\t{\n\t\twhile(pNodeBase->mpNodeLeft) \n\t\t\tpNodeBase = pNodeBase->mpNodeLeft;\n\t\treturn const_cast<rbtree_node_base*>(pNodeBase);\n\t}\n\n\tEASTL_API inline rbtree_node_base* RBTreeGetMaxChild(const rbtree_node_base* pNodeBase)\n\t{\n\t\twhile(pNodeBase->mpNodeRight) \n\t\t\tpNodeBase = pNodeBase->mpNodeRight;\n\t\treturn const_cast<rbtree_node_base*>(pNodeBase);\n\t}\n\n\t// The rest of the functions are non-trivial and are found in \n\t// the corresponding .cpp file to this file.\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// rbtree_iterator functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\trbtree_iterator<T, Pointer, Reference>::rbtree_iterator()\n\t\t: mpNode(NULL) { }\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\trbtree_iterator<T, Pointer, Reference>::rbtree_iterator(const base_node_type* pNode)\n\t\t: mpNode(const_cast<base_node_type*>(pNode)) { }\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\trbtree_iterator<T, Pointer, Reference>::rbtree_iterator(const iterator& x)\n\t\t: mpNode(x.mpNode) { }\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\ttypename rbtree_iterator<T, Pointer, Reference>::this_type&\n\trbtree_iterator<T, Pointer, Reference>::operator=(const iterator& x)\n\t{\n\t\tmpNode = x.mpNode;\n\t\treturn *this;\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\ttypename rbtree_iterator<T, Pointer, Reference>::reference\n\trbtree_iterator<T, Pointer, Reference>::operator*() const\n\t{\n\t\treturn static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\ttypename rbtree_iterator<T, Pointer, Reference>::pointer\n\trbtree_iterator<T, Pointer, Reference>::operator->() const\n\t{\n\t\treturn &static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\ttypename rbtree_iterator<T, Pointer, Reference>::this_type&\n\trbtree_iterator<T, Pointer, Reference>::operator++()\n\t{\n\t\tmpNode = RBTreeIncrement(mpNode);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\ttypename rbtree_iterator<T, Pointer, Reference>::this_type\n\trbtree_iterator<T, Pointer, Reference>::operator++(int)\n\t{\n\t\tthis_type temp(*this);\n\t\tmpNode = RBTreeIncrement(mpNode);\n\t\treturn temp;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\ttypename rbtree_iterator<T, Pointer, Reference>::this_type&\n\trbtree_iterator<T, Pointer, Reference>::operator--()\n\t{\n\t\tmpNode = RBTreeDecrement(mpNode);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\ttypename rbtree_iterator<T, Pointer, Reference>::this_type\n\trbtree_iterator<T, Pointer, Reference>::operator--(int)\n\t{\n\t\tthis_type temp(*this);\n\t\tmpNode = RBTreeDecrement(mpNode);\n\t\treturn temp;\n\t}\n\n\n\t// The C++ defect report #179 requires that we support comparisons between const and non-const iterators.\n\t// Thus we provide additional template paremeters here to support this. The defect report does not\n\t// require us to support comparisons between reverse_iterators and const_reverse_iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator==(const rbtree_iterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const rbtree_iterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode == b.mpNode;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator!=(const rbtree_iterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const rbtree_iterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\t// We provide a version of operator!= for the case where the iterators are of the \n\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline bool operator!=(const rbtree_iterator<T, Pointer, Reference>& a, \n\t\t\t\t\t\t   const rbtree_iterator<T, Pointer, Reference>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// rbtree functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline rbtree<K, V, C, A, E, bM, bU>::rbtree()\n\t\t: mAnchor(),\n\t\t  mnSize(0),\n\t\t  mAllocator(EASTL_RBTREE_DEFAULT_NAME)\n\t{\n\t\treset_lose_memory();\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline rbtree<K, V, C, A, E, bM, bU>::rbtree(const allocator_type& allocator)\n\t\t: mAnchor(),\n\t\t  mnSize(0),\n\t\t  mAllocator(allocator)\n\t{\n\t\treset_lose_memory();\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline rbtree<K, V, C, A, E, bM, bU>::rbtree(const C& compare, const allocator_type& allocator)\n\t\t: base_type(compare),\n\t\t  mAnchor(),\n\t\t  mnSize(0),\n\t\t  mAllocator(allocator)\n\t{\n\t\treset_lose_memory();\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline rbtree<K, V, C, A, E, bM, bU>::rbtree(const this_type& x)\n\t\t: base_type(x.get_compare()),\n\t\t  mAnchor(),\n\t\t  mnSize(0),\n\t\t  mAllocator(x.mAllocator)\n\t{\n\t\treset_lose_memory();\n\n\t\tif(x.mAnchor.mpNodeParent) // mAnchor.mpNodeParent is the rb_tree root node.\n\t\t{\n\t\t\tmAnchor.mpNodeParent = DoCopySubtree((const node_type*)x.mAnchor.mpNodeParent, &mAnchor);\n\t\t\tmAnchor.mpNodeRight  = RBTreeGetMaxChild(mAnchor.mpNodeParent);\n\t\t\tmAnchor.mpNodeLeft   = RBTreeGetMinChild(mAnchor.mpNodeParent);\n\t\t\tmnSize               = x.mnSize;\n\t\t}\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline rbtree<K, V, C, A, E, bM, bU>::rbtree(this_type&& x)\n\t\t: base_type(x.get_compare()),\n\t\t  mAnchor(),\n\t\t  mnSize(0),\n\t\t  mAllocator(x.mAllocator)\n\t{\n\t\treset_lose_memory();\n\t\tswap(x);\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline rbtree<K, V, C, A, E, bM, bU>::rbtree(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(x.get_compare()),\n\t\t  mAnchor(),\n\t\t  mnSize(0),\n\t\t  mAllocator(allocator)\n\t{\n\t\treset_lose_memory();\n\t\tswap(x); // swap will directly or indirectly handle the possibility that mAllocator != x.mAllocator.\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename InputIterator>\n\tinline rbtree<K, V, C, A, E, bM, bU>::rbtree(InputIterator first, InputIterator last, const C& compare, const allocator_type& allocator)\n\t\t: base_type(compare),\n\t\t  mAnchor(),\n\t\t  mnSize(0),\n\t\t  mAllocator(allocator)\n\t{\n\t\treset_lose_memory();\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tfor(; first != last; ++first)\n\t\t\t\t\tinsert(*first);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tclear();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline rbtree<K, V, C, A, E, bM, bU>::~rbtree()\n\t{\n\t\t// Erase the entire tree. DoNukeSubtree is not a \n\t\t// conventional erase function, as it does no rebalancing.\n\t\tDoNukeSubtree((node_type*)mAnchor.mpNodeParent);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline const typename rbtree<K, V, C, A, E, bM, bU>::allocator_type&\n\trbtree<K, V, C, A, E, bM, bU>::get_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn mAllocator;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::allocator_type&\n\trbtree<K, V, C, A, E, bM, bU>::get_allocator() EA_NOEXCEPT\n\t{\n\t\treturn mAllocator;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline void rbtree<K, V, C, A, E, bM, bU>::set_allocator(const allocator_type& allocator)\n\t{\n\t\tif(mnSize > 0 && mAllocator != allocator)\n\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"rbtree::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\tmAllocator = allocator;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::size_type\n\trbtree<K, V, C, A, E, bM, bU>::size() const EA_NOEXCEPT\n\t\t{ return mnSize; }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline bool rbtree<K, V, C, A, E, bM, bU>::empty() const EA_NOEXCEPT\n\t\t{ return (mnSize == 0); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::begin() EA_NOEXCEPT\n\t\t{ return iterator(mAnchor.mpNodeLeft); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::begin() const EA_NOEXCEPT\n\t\t{ return const_iterator(mAnchor.mpNodeLeft); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::cbegin() const EA_NOEXCEPT\n\t\t{ return const_iterator(mAnchor.mpNodeLeft); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::end() EA_NOEXCEPT\n\t\t{ return iterator(&mAnchor); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::end() const EA_NOEXCEPT\n\t\t{ return const_iterator(&mAnchor); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::cend() const EA_NOEXCEPT\n\t\t{ return const_iterator(&mAnchor); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::rbegin() EA_NOEXCEPT\n\t\t{ return reverse_iterator(end()); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::rbegin() const EA_NOEXCEPT\n\t\t{ return const_reverse_iterator(end()); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::crbegin() const EA_NOEXCEPT\n\t\t{ return const_reverse_iterator(end()); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::rend() EA_NOEXCEPT\n\t\t{ return reverse_iterator(begin()); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::rend() const EA_NOEXCEPT\n\t\t{ return const_reverse_iterator(begin()); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::crend() const EA_NOEXCEPT\n\t\t{ return const_reverse_iterator(begin()); }\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::this_type&\n\trbtree<K, V, C, A, E, bM, bU>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tmAllocator = x.mAllocator;\n\t\t\t#endif\n\n\t\t\tget_compare() = x.get_compare();\n\n\t\t\tif(x.mAnchor.mpNodeParent) // mAnchor.mpNodeParent is the rb_tree root node.\n\t\t\t{\n\t\t\t\tmAnchor.mpNodeParent = DoCopySubtree((const node_type*)x.mAnchor.mpNodeParent, &mAnchor);\n\t\t\t\tmAnchor.mpNodeRight  = RBTreeGetMaxChild(mAnchor.mpNodeParent);\n\t\t\t\tmAnchor.mpNodeLeft   = RBTreeGetMinChild(mAnchor.mpNodeParent);\n\t\t\t\tmnSize               = x.mnSize;\n\t\t\t}\n\t\t}\n\t\treturn *this;\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::this_type&\n\trbtree<K, V, C, A, E, bM, bU>::operator=(this_type&& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();        // To consider: Are we really required to clear here? x is going away soon and will clear itself in its dtor.\n\t\t\tswap(x);        // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t\t}\n\t\treturn *this; \n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::this_type&\n\trbtree<K, V, C, A, E, bM, bU>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\t// The simplest means of doing this is to clear and insert. There probably isn't a generic\n\t\t// solution that's any more efficient without having prior knowledge of the ilist contents.\n\t\tclear();\n\n\t\tfor(typename std::initializer_list<value_type>::iterator it = ilist.begin(), itEnd = ilist.end(); it != itEnd; ++it)\n\t\t\tDoInsertValue(has_unique_keys_type(), eastl::move(*it));\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tvoid rbtree<K, V, C, A, E, bM, bU>::swap(this_type& x)\n\t{\n\t#if EASTL_RBTREE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t\tif(mAllocator == x.mAllocator) // If allocators are equivalent...\n\t#endif\n\t\t{\n\t\t\t// Most of our members can be exchaged by a basic swap:\n\t\t\t// We leave mAllocator as-is.\n\t\t\teastl::swap(mnSize,        x.mnSize);\n\t\t\teastl::swap(get_compare(), x.get_compare());\n\t\t#if !EASTL_RBTREE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t\t\teastl::swap(mAllocator,          x.mAllocator);\n\t\t#endif\n\n\n\t\t\t// However, because our anchor node is a part of our class instance and not \n\t\t\t// dynamically allocated, we can't do a swap of it but must do a more elaborate\n\t\t\t// procedure. This is the downside to having the mAnchor be like this, but \n\t\t\t// otherwise we consider it a good idea to avoid allocating memory for a \n\t\t\t// nominal container instance.\n\n\t\t\t// We optimize for the expected most common case: both pointers being non-null.\n\t\t\tif(mAnchor.mpNodeParent && x.mAnchor.mpNodeParent) // If both pointers are non-null...\n\t\t\t{\n\t\t\t\teastl::swap(mAnchor.mpNodeRight,  x.mAnchor.mpNodeRight);\n\t\t\t\teastl::swap(mAnchor.mpNodeLeft,   x.mAnchor.mpNodeLeft);\n\t\t\t\teastl::swap(mAnchor.mpNodeParent, x.mAnchor.mpNodeParent);\n\n\t\t\t\t// We need to fix up the anchors to point to themselves (we can't just swap them).\n\t\t\t\tmAnchor.mpNodeParent->mpNodeParent   = &mAnchor;\n\t\t\t\tx.mAnchor.mpNodeParent->mpNodeParent = &x.mAnchor;\n\t\t\t}\n\t\t\telse if(mAnchor.mpNodeParent)\n\t\t\t{\n\t\t\t\tx.mAnchor.mpNodeRight  = mAnchor.mpNodeRight;\n\t\t\t\tx.mAnchor.mpNodeLeft   = mAnchor.mpNodeLeft;\n\t\t\t\tx.mAnchor.mpNodeParent = mAnchor.mpNodeParent;\n\t\t\t\tx.mAnchor.mpNodeParent->mpNodeParent = &x.mAnchor;\n\n\t\t\t\t// We need to fix up our anchor to point it itself (we can't have it swap with x).\n\t\t\t\tmAnchor.mpNodeRight  = &mAnchor;\n\t\t\t\tmAnchor.mpNodeLeft   = &mAnchor;\n\t\t\t\tmAnchor.mpNodeParent = NULL;\n\t\t\t}\n\t\t\telse if(x.mAnchor.mpNodeParent)\n\t\t\t{\n\t\t\t\tmAnchor.mpNodeRight  = x.mAnchor.mpNodeRight;\n\t\t\t\tmAnchor.mpNodeLeft   = x.mAnchor.mpNodeLeft;\n\t\t\t\tmAnchor.mpNodeParent = x.mAnchor.mpNodeParent;\n\t\t\t\tmAnchor.mpNodeParent->mpNodeParent = &mAnchor;\n\n\t\t\t\t// We need to fix up x's anchor to point it itself (we can't have it swap with us).\n\t\t\t\tx.mAnchor.mpNodeRight  = &x.mAnchor;\n\t\t\t\tx.mAnchor.mpNodeLeft   = &x.mAnchor;\n\t\t\t\tx.mAnchor.mpNodeParent = NULL;\n\t\t\t} // Else both are NULL and there is nothing to do.\n\t\t}\n\t#if EASTL_RBTREE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t\telse\n\t\t{\n\t\t\tconst this_type temp(*this); // Can't call eastl::swap because that would\n\t\t\t*this = x;                   // itself call this member swap function.\n\t\t\tx     = temp;\n\t\t}\n\t#endif\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <class... Args>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::insert_return_type // map/set::insert return a pair, multimap/multiset::iterator return an iterator.\n\trbtree<K, V, C, A, E, bM, bU>::emplace(Args&&... args)\n\t{\n\t\treturn DoInsertValue(has_unique_keys_type(), eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <class... Args> \n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::emplace_hint(const_iterator position, Args&&... args)\n\t{\n\t\treturn DoInsertValueHint(has_unique_keys_type(), position, eastl::forward<Args>(args)...);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::iterator \n\trbtree<K, V, C, A, E, bM, bU>::insert(const_iterator position, value_type&& value)\n\t{\n\t\treturn DoInsertValueHint(has_unique_keys_type(), position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::insert_return_type // map/set::insert return a pair, multimap/multiset::iterator return an iterator.\n\trbtree<K, V, C, A, E, bM, bU>::insert(const value_type& value)\n\t{\n\t\treturn DoInsertValue(has_unique_keys_type(), value);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::insert_return_type // map/set::insert return a pair, multimap/multiset::iterator return an iterator.\n\trbtree<K, V, C, A, E, bM, bU>::insert(value_type&& value)\n\t{\n\t\treturn DoInsertValue(has_unique_keys_type(), eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::insert(const_iterator position, const value_type& value)\n\t{\n\t\treturn DoInsertValueHint(has_unique_keys_type(), position, value);\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX, typename M>\n\teastl::pair<typename rbtree<K, V, C, A, E, bM, bU>::iterator, bool>\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertOrAssign(KX&& k, M&& obj)\n\t{\n\t\tauto iter = find(k);\n\n\t\tif(iter == end())\n\t\t{\n\t\t\treturn insert(value_type(eastl::forward<KX>(k), eastl::forward<M>(obj)));\n\t\t}\n\t\telse\n\t\t{\n\t\t\titer->second = eastl::forward<M>(obj);\n\t\t\treturn {iter, false};\n\t\t}\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX, typename M>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertOrAssign(const_iterator hint, KX&& k, M&& obj)\n\t{\n\t\tauto iter = find(k);\n\n\t\tif(iter == end())\n\t\t{\n\t\t\treturn insert(hint, value_type(eastl::forward<KX>(k), eastl::forward<M>(obj)));\n\t\t}\n\t\telse\n\t\t{\n\t\t\titer->second = eastl::forward<M>(obj);\n\t\t\treturn iter;\n\t\t}\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\trbtree_node_base*\n\trbtree<K, V, C, A, E, bM, bU>::DoGetKeyInsertionPositionUniqueKeys(bool& canInsert, const KX& key)\n\t{\n\t\t// This code is essentially a slightly modified copy of the the rbtree::insert \n\t\t// function whereby this version takes a key and not a full value_type.\n\t\textract_key extractKey;\n\n\t\trbtree_node_base* pCurrent    = mAnchor.mpNodeParent; // Start with the root node.\n\t\trbtree_node_base* pLowerBound = &mAnchor;             // Set it to the container end for now.\n\t\trbtree_node_base* pParent;                            // This will be where we insert the new node.\n\n\t\tbool bValueLessThanNode = true; // If the tree is empty, this will result in an insertion at the front.\n\n\t\t// Find insertion position of the value. This will either be a position which \n\t\t// already contains the value, a position which is greater than the value or\n\t\t// end(), which we treat like a position which is greater than the value.\n\t\twhile(EASTL_LIKELY(pCurrent)) // Do a walk down the tree.\n\t\t{\n\t\t\tbValueLessThanNode = compare(key, extractKey(static_cast<node_type*>(pCurrent)->mValue));\n\t\t\tpLowerBound        = pCurrent;\n\n\t\t\tif(bValueLessThanNode)\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(extractKey(static_cast<node_type*>(pCurrent)->mValue), key)); // Validate that the compare function is sane.\n\t\t\t\tpCurrent = pCurrent->mpNodeLeft;\n\t\t\t}\n\t\t\telse\n\t\t\t\tpCurrent = pCurrent->mpNodeRight;\n\t\t}\n\n\t\tpParent = pLowerBound; // pLowerBound is actually upper bound right now (i.e. it is > value instead of <=), but we will make it the lower bound below.\n\n\t\tif(bValueLessThanNode) // If we ended up on the left side of the last parent node...\n\t\t{\n\t\t\tif(EASTL_LIKELY(pLowerBound != mAnchor.mpNodeLeft)) // If the tree was empty or if we otherwise need to insert at the very front of the tree...\n\t\t\t{\n\t\t\t\t// At this point, pLowerBound points to a node which is > than value.\n\t\t\t\t// Move it back by one, so that it points to a node which is <= value.\n\t\t\t\tpLowerBound = RBTreeDecrement(pLowerBound);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcanInsert = true;\n\t\t\t\treturn pLowerBound;\n\t\t\t}\n\t\t}\n\n\t\t// Since here we require values to be unique, we will do nothing if the value already exists.\n\t\tnode_type* const pLowerBoundFullNode = static_cast<node_type*>(pLowerBound);\n\t\tif(compare(extractKey(pLowerBoundFullNode->mValue), key)) // If the node is < the value (i.e. if value is >= the node)...\n\t\t{\n\t\t\tEASTL_VALIDATE_COMPARE(!compare(key, extractKey(pLowerBoundFullNode->mValue))); // Validate that the compare function is sane.\n\t\t\tcanInsert = true;\n\t\t\treturn pParent;\n\t\t}\n\n\t\t// The item already exists (as found by the compare directly above), so return false.\n\t\tcanInsert = false;\n\t\treturn pLowerBound;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\trbtree_node_base*\n\trbtree<K, V, C, A, E, bM, bU>::DoGetKeyInsertionPositionNonuniqueKeys(const key_type& key)\n\t{\n\t\t// This is the pathway for insertion of non-unique keys (multimap and multiset, but not map and set).\n\t\trbtree_node_base* pCurrent  = mAnchor.mpNodeParent; // Start with the root node.\n\t\trbtree_node_base* pRangeEnd = &mAnchor;             // Set it to the container end for now.\n\t\textract_key extractKey;\n\n\t\twhile(pCurrent)\n\t\t{\n\t\t\tpRangeEnd = pCurrent;\n\n\t\t\tif(compare(key, extractKey(static_cast<node_type*>(pCurrent)->mValue)))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(extractKey(static_cast<node_type*>(pCurrent)->mValue), key)); // Validate that the compare function is sane.\n\t\t\t\tpCurrent = pCurrent->mpNodeLeft;\n\t\t\t}\n\t\t\telse\n\t\t\t\tpCurrent = pCurrent->mpNodeRight;\n\t\t}\n\n\t\treturn pRangeEnd;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\teastl::pair<typename rbtree<K, V, C, A, E, bM, bU>::iterator, bool> \n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValue(true_type, value_type&& value)\n\t{\n\t\textract_key extractKey;\n\t\tkey_type    key(extractKey(value));\n\t\tbool        canInsert;\n\t\trbtree_node_base*  pPosition = DoGetKeyInsertionPositionUniqueKeys(canInsert, key);\n\n\t\tif(canInsert)\n\t\t{\n\t\t\tconst iterator itResult(DoInsertValueImpl(pPosition, false, key, eastl::move(value)));\n\t\t\treturn pair<iterator, bool>(itResult, true);\n\t\t}\n\n\t\treturn pair<iterator, bool>(iterator(pPosition), false);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator \n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValue(false_type, value_type&& value)\n\t{\n\t\textract_key extractKey;\n\t\tkey_type    key(extractKey(value));\n\t\trbtree_node_base*  pPosition = DoGetKeyInsertionPositionNonuniqueKeys(key);\n\n\t\treturn DoInsertValueImpl(pPosition, false, key, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <class... Args>\n\teastl::pair<typename rbtree<K, V, C, A, E, bM, bU>::iterator, bool>\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValue(true_type, Args&&... args) // true_type means keys are unique.\n\t{\n\t\t// This is the pathway for insertion of unique keys (map and set, but not multimap and multiset).\n\t\t// Note that we return a pair and not an iterator. This is because the C++ standard for map\n\t\t// and set is to return a pair and not just an iterator.\n\n\t\tnode_type* pNodeNew = DoCreateNode(eastl::forward<Args>(args)...); // Note that pNodeNew->mpLeft, mpRight, mpParent, will be uninitialized.\n\t\tconst key_type& key = extract_key{}(pNodeNew->mValue);\n\n\t\tbool        canInsert;\n\t\trbtree_node_base*  pPosition = DoGetKeyInsertionPositionUniqueKeys(canInsert, key);\n\n\t\tif(canInsert)\n\t\t{\n\t\t\titerator itResult(DoInsertValueImpl(pPosition, false, key, pNodeNew));\n\t\t\treturn pair<iterator, bool>(itResult, true);\n\t\t}\n\n\t\tDoFreeNode(pNodeNew);\n\t\treturn pair<iterator, bool>(iterator(pPosition), false);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <class... Args>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValue(false_type, Args&&... args) // false_type means keys are not unique.\n\t{\n\t\t// We have a problem here if sizeof(value_type) is too big for the stack. We may want to consider having a specialization for large value_types.\n\t\t// To do: Change this so that we call DoCreateNode(eastl::forward<Args>(args)...) here and use the value from the resulting pNode to get the \n\t\t// key, and make DoInsertValueImpl take that node as an argument. That way there is no value created on the stack.\n\n\t\tnode_type* const pNodeNew = DoCreateNode(eastl::forward<Args>(args)...); // Note that pNodeNew->mpLeft, mpRight, mpParent, will be uninitialized.\n\t\tconst key_type& key = extract_key{}(pNodeNew->mValue);\n\n\t\trbtree_node_base* pPosition = DoGetKeyInsertionPositionNonuniqueKeys(key);\n\n\t\treturn DoInsertValueImpl(pPosition, false, key, pNodeNew);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <class... Args>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValueImpl(rbtree_node_base* pNodeParent, bool bForceToLeft, const key_type& key, Args&&... args)\n\t{\n\t\tnode_type* const pNodeNew = DoCreateNode(eastl::forward<Args>(args)...); // Note that pNodeNew->mpLeft, mpRight, mpParent, will be uninitialized.\n\t\treturn DoInsertValueImpl(pNodeParent, bForceToLeft, key, pNodeNew);\n\t}\n\n\t\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValueImpl(rbtree_node_base* pNodeParent, bool bForceToLeft, const key_type& key, node_type* pNodeNew)\n\t{\n\t\tEASTL_ASSERT_MSG(pNodeNew != nullptr, \"node to insert to the rbtree must not be null\");\n\n\t\tRBTreeSide  side;\n\t\textract_key extractKey;\n\n\t\t// The reason we may want to have bForceToLeft == true is that pNodeParent->mValue and value may be equal.\n\t\t// In that case it doesn't matter what side we insert on, except that the C++ LWG #233 improvement report\n\t\t// suggests that we should use the insert hint position to force an ordering. So that's what we do.\n\t\tif(bForceToLeft || (pNodeParent == &mAnchor) || compare(key, extractKey(static_cast<node_type*>(pNodeParent)->mValue)))\n\t\t\tside = kRBTreeSideLeft;\n\t\telse\n\t\t\tside = kRBTreeSideRight;\n\n\t\tRBTreeInsert(pNodeNew, pNodeParent, &mAnchor, side);\n\t\tmnSize++;\n\n\t\treturn iterator(pNodeNew);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\teastl::pair<typename rbtree<K, V, C, A, E, bM, bU>::iterator, bool>\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertKey(true_type, const key_type& key) // true_type means keys are unique.\n\t{\n\t\t// This is the pathway for insertion of unique keys (map and set, but not multimap and multiset).\n\t\t// Note that we return a pair and not an iterator. This is because the C++ standard for map\n\t\t// and set is to return a pair and not just an iterator.\n\t\tbool       canInsert;\n\t\trbtree_node_base* pPosition = DoGetKeyInsertionPositionUniqueKeys(canInsert, key);\n\n\t\tif(canInsert)\n\t\t{\n\t\t\tconst iterator itResult(DoInsertKeyImpl(pPosition, false, key));\n\t\t\treturn pair<iterator, bool>(itResult, true);\n\t\t}\n\n\t\treturn pair<iterator, bool>(iterator(pPosition), false);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertKey(false_type, const key_type& key) // false_type means keys are not unique.\n\t{\n\t\trbtree_node_base* pPosition = DoGetKeyInsertionPositionNonuniqueKeys(key);\n\t\treturn DoInsertKeyImpl(pPosition, false, key);\n\t}\n\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\trbtree_node_base*\n\trbtree<K, V, C, A, E, bM, bU>::DoGetKeyInsertionPositionUniqueKeysHint(const_iterator position, bool& bForceToLeft, const KX& key)\n\t{\n\t\textract_key extractKey;\n\n\t\tif((position.mpNode != mAnchor.mpNodeRight) && (position.mpNode != &mAnchor)) // If the user specified a specific insertion position...\n\t\t{\n\t\t\titerator itNext(position.mpNode);\n\t\t\t++itNext;\n\n\t\t\t// To consider: Change this so that 'position' specifies the position after \n\t\t\t// where the insertion goes and not the position before where the insertion goes.\n\t\t\t// Doing so would make this more in line with user expectations and with LWG #233.\n\t\t\tconst bool bPositionLessThanValue = compare(extractKey(*position), key);\n\n\t\t\tif(bPositionLessThanValue) // If (value > *position)...\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(key, extractKey(*position))); // Validate that the compare function is sane.\n\n\t\t\t\tconst bool bValueLessThanNext = compare(key, extractKey(*itNext));\n\n\t\t\t\tif(bValueLessThanNext) // If value < *itNext...\n\t\t\t\t{\n\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(extractKey(*itNext), key)); // Validate that the compare function is sane.\n\n\t\t\t\t\tif(position.mpNode->mpNodeRight)\n\t\t\t\t\t{\n\t\t\t\t\t\tbForceToLeft = true; // Specifically insert in front of (to the left of) itNext (and thus after 'position').\n\t\t\t\t\t\treturn itNext.mpNode;\n\t\t\t\t\t}\n\n\t\t\t\t\tbForceToLeft = false;\n\t\t\t\t\treturn position.mpNode;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbForceToLeft = false;\n\t\t\treturn nullptr;  // The above specified hint was not useful, then we do a regular insertion.\n\t\t}\n\n\t\tif(mnSize && compare(extractKey(static_cast<node_type*>(mAnchor.mpNodeRight)->mValue), key))\n\t\t{\n\t\t\tEASTL_VALIDATE_COMPARE(!compare(key, extractKey(static_cast<node_type*>(mAnchor.mpNodeRight)->mValue))); // Validate that the compare function is sane.\n\t\t\tbForceToLeft = false;\n\t\t\treturn mAnchor.mpNodeRight;\n\t\t}\n\n\t\tbForceToLeft = false;\n\t\treturn NULL; // The caller can do a default insert.\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\trbtree_node_base*\n\trbtree<K, V, C, A, E, bM, bU>::DoGetKeyInsertionPositionNonuniqueKeysHint(const_iterator position, bool& bForceToLeft, const key_type& key)\n\t{\n\t\textract_key extractKey;\n\n\t\tif((position.mpNode != mAnchor.mpNodeRight) && (position.mpNode != &mAnchor)) // If the user specified a specific insertion position...\n\t\t{\n\t\t\titerator itNext(position.mpNode);\n\t\t\t++itNext;\n\n\t\t\t// To consider: Change this so that 'position' specifies the position after \n\t\t\t// where the insertion goes and not the position before where the insertion goes.\n\t\t\t// Doing so would make this more in line with user expectations and with LWG #233.\n\t\t\tif(!compare(key, extractKey(*position)) && // If value >= *position &&\n\t\t\t   !compare(extractKey(*itNext), key))     // if value <= *itNext...\n\t\t\t{\n\t\t\t\tif(position.mpNode->mpNodeRight) // If there are any nodes to the right... [this expression will always be true as long as we aren't at the end()]\n\t\t\t\t{\n\t\t\t\t\tbForceToLeft = true; // Specifically insert in front of (to the left of) itNext (and thus after 'position').\n\t\t\t\t\treturn itNext.mpNode;\n\t\t\t\t}\n\n\t\t\t\tbForceToLeft = false;\n\t\t\t\treturn position.mpNode;\n\t\t\t}\n\n\t\t\tbForceToLeft = false;\n\t\t\treturn nullptr; // The above specified hint was not useful, then we do a regular insertion.\n\t\t}\n\n\t\t// This pathway shouldn't be commonly executed, as the user shouldn't be calling \n\t\t// this hinted version of insert if the user isn't providing a useful hint.\n\t\tif(mnSize && !compare(key, extractKey(static_cast<node_type*>(mAnchor.mpNodeRight)->mValue))) // If we are non-empty and the value is >= the last node...\n\t\t{\n\t\t\tbForceToLeft =false;\n\t\t\treturn mAnchor.mpNodeRight;\n\t\t}\n\n\t\tbForceToLeft = false;\n\t\treturn nullptr;\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <class... Args>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValueHint(true_type, const_iterator position, Args&&... args) // true_type means keys are unique.\n\t{\n\t\t// This is the pathway for insertion of unique keys (map and set, but not multimap and multiset).\n\t\t//\n\t\t// We follow the same approach as SGI STL/STLPort and use the position as\n\t\t// a forced insertion position for the value when possible.\n\n\t\tnode_type* pNodeNew = DoCreateNode(eastl::forward<Args>(args)...); // Note that pNodeNew->mpLeft, mpRight, mpParent, will be uninitialized.\n\t\tconst key_type& key(extract_key{}(pNodeNew->mValue));\n\n\t\tbool       bForceToLeft;\n\t\trbtree_node_base* pPosition = DoGetKeyInsertionPositionUniqueKeysHint(position, bForceToLeft, key);\n\n\t\tif (!pPosition)\n\t\t{\n\t\t\tbool        canInsert;\n\t\t\tpPosition = DoGetKeyInsertionPositionUniqueKeys(canInsert, key);\n\n\t\t\tif (!canInsert)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNodeNew);\n\t\t\t\treturn iterator(pPosition);\n\t\t\t}\n\n\t\t\tbForceToLeft = false;\n\t\t}\n\n\t\treturn DoInsertValueImpl(pPosition, bForceToLeft, key, pNodeNew);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <class... Args>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValueHint(false_type, const_iterator position, Args&&... args) // false_type means keys are not unique.\n\t{\n\t\t// This is the pathway for insertion of non-unique keys (multimap and multiset, but not map and set).\n\t\t//\n\t\t// We follow the same approach as SGI STL/STLPort and use the position as\n\t\t// a forced insertion position for the value when possible.\n\n\t\tnode_type* pNodeNew = DoCreateNode(eastl::forward<Args>(args)...); // Note that pNodeNew->mpLeft, mpRight, mpParent, will be uninitialized.\n\t\tconst key_type& key(extract_key{}(pNodeNew->mValue));\n\n\t\tbool        bForceToLeft;\n\t\trbtree_node_base*  pPosition = DoGetKeyInsertionPositionNonuniqueKeysHint(position, bForceToLeft, key);\n\n\t\tif (!pPosition)\n\t\t{\n\t\t\tpPosition = DoGetKeyInsertionPositionNonuniqueKeys(key);\n\t\t\tbForceToLeft = false;\n\t\t}\n\n\t\treturn DoInsertValueImpl(pPosition, bForceToLeft, key, pNodeNew);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValueHint(true_type, const_iterator position, value_type&& value) // true_type means keys are unique.\n\t{\n\t\t// This is the pathway for insertion of unique keys (map and set, but not multimap and multiset).\n\t\t//\n\t\t// We follow the same approach as SGI STL/STLPort and use the position as\n\t\t// a forced insertion position for the value when possible.\n\n\t\textract_key extractKey;\n\t\tkey_type    key(extractKey(value));\n\t\tbool        bForceToLeft;\n\t\trbtree_node_base*  pPosition = DoGetKeyInsertionPositionUniqueKeysHint(position, bForceToLeft, key);\n\n\t\tif(pPosition)\n\t\t\treturn DoInsertValueImpl(pPosition, bForceToLeft, key, eastl::move(value));\n\t\telse\n\t\t\treturn DoInsertValue(has_unique_keys_type(), eastl::move(value)).first;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertValueHint(false_type, const_iterator position, value_type&& value) // false_type means keys are not unique.\n\t{\n\t\t// This is the pathway for insertion of non-unique keys (multimap and multiset, but not map and set).\n\t\t//\n\t\t// We follow the same approach as SGI STL/STLPort and use the position as\n\t\t// a forced insertion position for the value when possible.\n\t\textract_key extractKey;\n\t\tkey_type    key(extractKey(value));\n\t\tbool        bForceToLeft;\n\t\trbtree_node_base*  pPosition = DoGetKeyInsertionPositionNonuniqueKeysHint(position, bForceToLeft, key);\n\n\t\tif(pPosition)\n\t\t\treturn DoInsertValueImpl(pPosition, bForceToLeft, key, eastl::move(value));\n\t\telse\n\t\t\treturn DoInsertValue(has_unique_keys_type(), eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertKey(true_type, const_iterator position, const key_type& key) // true_type means keys are unique.\n\t{\n\t\tbool       bForceToLeft;\n\t\trbtree_node_base* pPosition = DoGetKeyInsertionPositionUniqueKeysHint(position, bForceToLeft, key);\n\n\t\tif(pPosition)\n\t\t\treturn DoInsertKeyImpl(pPosition, bForceToLeft, key);\n\t\telse\n\t\t\treturn DoInsertKey(has_unique_keys_type(), key).first;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertKey(false_type, const_iterator position, const key_type& key) // false_type means keys are not unique.\n\t{\n\t\t// This is the pathway for insertion of non-unique keys (multimap and multiset, but not map and set).\n\t\t//\n\t\t// We follow the same approach as SGI STL/STLPort and use the position as\n\t\t// a forced insertion position for the value when possible.\n\t\tbool       bForceToLeft;\n\t\trbtree_node_base* pPosition = DoGetKeyInsertionPositionNonuniqueKeysHint(position, bForceToLeft, key);\n\n\t\tif(pPosition)\n\t\t\treturn DoInsertKeyImpl(pPosition, bForceToLeft, key);\n\t\telse\n\t\t\treturn DoInsertKey(has_unique_keys_type(), key); // We are empty or we are inserting at the end.\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoInsertKeyImpl(rbtree_node_base* pNodeParent, bool bForceToLeft, const key_type& key)\n\t{\n\t\tRBTreeSide  side;\n\t\textract_key extractKey;\n\n\t\t// The reason we may want to have bForceToLeft == true is that pNodeParent->mValue and value may be equal.\n\t\t// In that case it doesn't matter what side we insert on, except that the C++ LWG #233 improvement report\n\t\t// suggests that we should use the insert hint position to force an ordering. So that's what we do.\n\t\tif(bForceToLeft || (pNodeParent == &mAnchor) || compare(key, extractKey(static_cast<node_type*>(pNodeParent)->mValue)))\n\t\t\tside = kRBTreeSideLeft;\n\t\telse\n\t\t\tside = kRBTreeSideRight;\n\n\t\tnode_type* const pNodeNew = DoCreateNodeFromKey(key); // Note that pNodeNew->mpLeft, mpRight, mpParent, will be uninitialized.\n\t\tRBTreeInsert(pNodeNew, pNodeParent, &mAnchor, side);\n\t\tmnSize++;\n\n\t\treturn iterator(pNodeNew);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tvoid rbtree<K, V, C, A, E, bM, bU>::insert(std::initializer_list<value_type> ilist)\n\t{\n\t\tfor(typename std::initializer_list<value_type>::iterator it = ilist.begin(), itEnd = ilist.end(); it != itEnd; ++it)\n\t\t\tDoInsertValue(has_unique_keys_type(), eastl::move(*it));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename InputIterator>\n\tvoid rbtree<K, V, C, A, E, bM, bU>::insert(InputIterator first, InputIterator last)\n\t{\n\t\tfor( ; first != last; ++first)\n\t\t\tDoInsertValue(has_unique_keys_type(), *first); // Or maybe we should call 'insert(end(), *first)' instead. If the first-last range was sorted then this might make some sense.\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline void rbtree<K, V, C, A, E, bM, bU>::clear()\n\t{\n\t\t// Erase the entire tree. DoNukeSubtree is not a \n\t\t// conventional erase function, as it does no rebalancing.\n\t\tDoNukeSubtree((node_type*)mAnchor.mpNodeParent);\n\t\treset_lose_memory();\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline void rbtree<K, V, C, A, E, bM, bU>::reset_lose_memory()\n\t{\n\t\t// The reset_lose_memory function is a special extension function which unilaterally \n\t\t// resets the container to an empty state without freeing the memory of \n\t\t// the contained objects. This is useful for very quickly tearing down a \n\t\t// container built into scratch memory.\n\t\tmAnchor.mpNodeRight  = &mAnchor;\n\t\tmAnchor.mpNodeLeft   = &mAnchor;\n\t\tmAnchor.mpNodeParent = NULL;\n\t\tmAnchor.mColor       = kRBTreeColorRed;\n\t\tmnSize               = 0;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::erase(const_iterator position)\n\t{\n\t\tconst iterator iErase(position.mpNode);\n\t\t--mnSize; // Interleave this between the two references to itNext. We expect no exceptions to occur during the code below.\n\t\t++position;\n\t\tRBTreeErase(iErase.mpNode, &mAnchor);\n\t\tDoFreeNode(static_cast<node_type*>(iErase.mpNode));\n\t\treturn iterator(position.mpNode);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::erase(const_iterator first, const_iterator last)\n\t{\n\t\t// We expect that if the user means to clear the container, they will call clear.\n\t\tif(EASTL_LIKELY((first.mpNode != mAnchor.mpNodeLeft) || (last.mpNode != &mAnchor))) // If (first != begin or last != end) ...\n\t\t{\n\t\t\t// Basic implementation:\n\t\t\twhile(first != last)\n\t\t\t\tfirst = erase(first);\n\t\t\treturn iterator(first.mpNode);\n\n\t\t\t// Inlined implementation:\n\t\t\t//size_type n = 0;\n\t\t\t//while(first != last)\n\t\t\t//{\n\t\t\t//    const iterator itErase(first);\n\t\t\t//    ++n;\n\t\t\t//    ++first;\n\t\t\t//    RBTreeErase(itErase.mpNode, &mAnchor);\n\t\t\t//    DoFreeNode(itErase.mpNode);\n\t\t\t//}\n\t\t\t//mnSize -= n;\n\t\t\t//return first;\n\t\t}\n\n\t\tclear();\n\t\treturn iterator(&mAnchor); // Same as: return end();\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::reverse_iterator\n\trbtree<K, V, C, A, E, bM, bU>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline void rbtree<K, V, C, A, E, bM, bU>::erase(const key_type* first, const key_type* last)\n\t{\n\t\t// We have no choice but to run a loop like this, as the first/last range could\n\t\t// have values that are discontiguously located in the tree. And some may not \n\t\t// even be in the tree.\n\t\twhile(first != last)\n\t\t\terase(*first++);\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoFind(const KX& key)\n\t{\n\t\textract_key extractKey;\n\n\t\trbtree_node_base* pCurrent = mAnchor.mpNodeParent; // Start with the root node.\n\t\trbtree_node_base* pRangeEnd = &mAnchor;             // Set it to the container end for now.\n\n\t\twhile (EASTL_LIKELY(pCurrent)) // Do a walk down the tree.\n\t\t{\n\t\t\tif (EASTL_LIKELY(!compare(extractKey(static_cast<node_type*>(pCurrent)->mValue), key))) // If pCurrent is >= key...\n\t\t\t{\n\t\t\t\tpRangeEnd = pCurrent;\n\t\t\t\tpCurrent = pCurrent->mpNodeLeft;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(key, extractKey(static_cast<node_type*>(pCurrent)->mValue))); // Validate that the compare function is sane.\n\t\t\t\tpCurrent = pCurrent->mpNodeRight;\n\t\t\t}\n\t\t}\n\n\t\tif (EASTL_LIKELY((pRangeEnd != &mAnchor) && !compare(key, extractKey(static_cast<node_type*>(pRangeEnd)->mValue))))\n\t\t\treturn iterator(pRangeEnd);\n\t\treturn iterator(&mAnchor);\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoFind(const KX& key) const\n\t{\n\t\ttypedef rbtree<K, V, C, A, E, bM, bU> rbtree_type;\n\t\treturn const_iterator(const_cast<rbtree_type*>(this)->find(key));\n\t}\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename U, typename Compare2>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::find_as(const U& u, Compare2 compare2)\n\t{\n\t\textract_key extractKey;\n\n\t\trbtree_node_base* pCurrent  = mAnchor.mpNodeParent; // Start with the root node.\n\t\trbtree_node_base* pRangeEnd = &mAnchor;             // Set it to the container end for now.\n\n\t\twhile(EASTL_LIKELY(pCurrent)) // Do a walk down the tree.\n\t\t{\n\t\t\tif(EASTL_LIKELY(!compare2(extractKey(static_cast<node_type*>(pCurrent)->mValue), u))) // If pCurrent is >= u...\n\t\t\t{\n\t\t\t\tpRangeEnd = pCurrent;\n\t\t\t\tpCurrent  = pCurrent->mpNodeLeft;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare2(u, extractKey(static_cast<node_type*>(pCurrent)->mValue))); // Validate that the compare function is sane.\n\t\t\t\tpCurrent  = pCurrent->mpNodeRight;\n\t\t\t}\n\t\t}\n\n\t\tif(EASTL_LIKELY((pRangeEnd != &mAnchor) && !compare2(u, extractKey(static_cast<node_type*>(pRangeEnd)->mValue))))\n\t\t\treturn iterator(pRangeEnd);\n\t\treturn iterator(&mAnchor);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename U, typename Compare2>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::find_as(const U& u, Compare2 compare2) const\n\t{\n\t\ttypedef rbtree<K, V, C, A, E, bM, bU> rbtree_type;\n\t\treturn const_iterator(const_cast<rbtree_type*>(this)->find_as(u, compare2));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoLowerBound(const KX& key)\n\t{\n\t\textract_key extractKey;\n\n\t\trbtree_node_base* pCurrent  = mAnchor.mpNodeParent; // Start with the root node.\n\t\trbtree_node_base* pRangeEnd = &mAnchor;             // Set it to the container end for now.\n\n\t\twhile(EASTL_LIKELY(pCurrent)) // Do a walk down the tree.\n\t\t{\n\t\t\tif(EASTL_LIKELY(!compare(extractKey(static_cast<node_type*>(pCurrent)->mValue), key))) // If pCurrent is >= key...\n\t\t\t{\n\t\t\t\tpRangeEnd = pCurrent;\n\t\t\t\tpCurrent  = pCurrent->mpNodeLeft;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(key, extractKey(static_cast<node_type*>(pCurrent)->mValue))); // Validate that the compare function is sane.\n\t\t\t\tpCurrent  = pCurrent->mpNodeRight;\n\t\t\t}\n\t\t}\n\n\t\treturn iterator(pRangeEnd);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoLowerBound(const KX& key) const\n\t{\n\t\ttypedef rbtree<K, V, C, A, E, bM, bU> rbtree_type;\n\t\treturn const_iterator(const_cast<rbtree_type*>(this)->lower_bound(key));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoUpperBound(const KX& key)\n\t{\n\t\textract_key extractKey;\n\n\t\trbtree_node_base* pCurrent  = mAnchor.mpNodeParent; // Start with the root node.\n\t\trbtree_node_base* pRangeEnd = &mAnchor;             // set it to the container end for now.\n\n\t\twhile(EASTL_LIKELY(pCurrent)) // Do a walk down the tree.\n\t\t{\n\t\t\tif(EASTL_LIKELY(compare(key, extractKey(static_cast<node_type*>(pCurrent)->mValue)))) // If key is < pCurrent...\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(extractKey(static_cast<node_type*>(pCurrent)->mValue), key)); // Validate that the compare function is sane.\n\t\t\t\tpRangeEnd = pCurrent;\n\t\t\t\tpCurrent  = pCurrent->mpNodeLeft;\n\t\t\t}\n\t\t\telse\n\t\t\t\tpCurrent  = pCurrent->mpNodeRight;\n\t\t}\n\n\t\treturn iterator(pRangeEnd);\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate <typename KX>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::const_iterator\n\trbtree<K, V, C, A, E, bM, bU>::DoUpperBound(const KX& key) const\n\t{\n\t\ttypedef rbtree<K, V, C, A, E, bM, bU> rbtree_type;\n\t\treturn const_iterator(const_cast<rbtree_type*>(this)->upper_bound(key));\n\t}\n\n\n\t// To do: Move this validate function entirely to a template-less implementation.\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tbool rbtree<K, V, C, A, E, bM, bU>::validate() const\n\t{\n\t\t// Red-black trees have the following canonical properties which we validate here:\n\t\t//   1 Every node is either red or black.\n\t\t//   2 Every leaf (NULL) is black by defintion. Any number of black nodes may appear in a sequence. \n\t\t//   3 If a node is red, then both its children are black. Thus, on any path from \n\t\t//     the root to a leaf, red nodes must not be adjacent.\n\t\t//   4 Every simple path from a node to a descendant leaf contains the same number of black nodes.\n\t\t//   5 The mnSize member of the tree must equal the number of nodes in the tree.\n\t\t//   6 The tree is sorted as per a conventional binary tree.\n\t\t//   7 The comparison function is sane; it obeys strict weak ordering. If compare(a,b) is true, then compare(b,a) must be false. Both cannot be true.\n\n\t\textract_key extractKey;\n\n\t\tif(mnSize)\n\t\t{\n\t\t\t// Verify basic integrity.\n\t\t\t//if(!mAnchor.mpNodeParent || (mAnchor.mpNodeLeft == mAnchor.mpNodeRight))\n\t\t\t//    return false;             // Fix this for case of empty tree.\n\n\t\t\tif(mAnchor.mpNodeLeft != RBTreeGetMinChild(mAnchor.mpNodeParent))\n\t\t\t\treturn false;\n\n\t\t\tif(mAnchor.mpNodeRight != RBTreeGetMaxChild(mAnchor.mpNodeParent))\n\t\t\t\treturn false;\n\n\t\t\tconst size_t nBlackCount   = RBTreeGetBlackCount(mAnchor.mpNodeParent, mAnchor.mpNodeLeft);\n\t\t\tsize_type    nIteratedSize = 0;\n\n\t\t\tfor(const_iterator it = begin(); it != end(); ++it, ++nIteratedSize)\n\t\t\t{\n\t\t\t\tconst node_type* const pNode      = (const node_type*)it.mpNode;\n\t\t\t\tconst node_type* const pNodeRight = (const node_type*)pNode->mpNodeRight;\n\t\t\t\tconst node_type* const pNodeLeft  = (const node_type*)pNode->mpNodeLeft;\n\n\t\t\t\t// Verify #7 above.\n\t\t\t\tif(pNodeRight && compare(extractKey(pNodeRight->mValue), extractKey(pNode->mValue)) && compare(extractKey(pNode->mValue), extractKey(pNodeRight->mValue))) // Validate that the compare function is sane.\n\t\t\t\t\treturn false;\n\n\t\t\t\t// Verify #7 above.\n\t\t\t\tif(pNodeLeft && compare(extractKey(pNodeLeft->mValue), extractKey(pNode->mValue)) && compare(extractKey(pNode->mValue), extractKey(pNodeLeft->mValue))) // Validate that the compare function is sane.\n\t\t\t\t\treturn false;\n\n\t\t\t\t// Verify item #1 above.\n\t\t\t\tif((pNode->mColor != kRBTreeColorRed) && (pNode->mColor != kRBTreeColorBlack))\n\t\t\t\t\treturn false;\n\n\t\t\t\t// Verify item #3 above.\n\t\t\t\tif(pNode->mColor == kRBTreeColorRed)\n\t\t\t\t{\n\t\t\t\t\tif((pNodeRight && (pNodeRight->mColor == kRBTreeColorRed)) ||\n\t\t\t\t\t   (pNodeLeft  && (pNodeLeft->mColor  == kRBTreeColorRed)))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Verify item #6 above.\n\t\t\t\tif(pNodeRight && compare(extractKey(pNodeRight->mValue), extractKey(pNode->mValue)))\n\t\t\t\t\treturn false;\n\n\t\t\t\tif(pNodeLeft && compare(extractKey(pNode->mValue), extractKey(pNodeLeft->mValue)))\n\t\t\t\t\treturn false;\n\n\t\t\t\tif(!pNodeRight && !pNodeLeft) // If we are at a bottom node of the tree...\n\t\t\t\t{\n\t\t\t\t\t// Verify item #4 above.\n\t\t\t\t\tif(RBTreeGetBlackCount(mAnchor.mpNodeParent, pNode) != nBlackCount)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Verify item #5 above.\n\t\t\tif(nIteratedSize != mnSize)\n\t\t\t\treturn false;\n\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif((mAnchor.mpNodeLeft != &mAnchor) || (mAnchor.mpNodeRight != &mAnchor))\n\t\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline int rbtree<K, V, C, A, E, bM, bU>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Come up with a more efficient mechanism of doing this.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline typename rbtree<K, V, C, A, E, bM, bU>::node_type*\n\trbtree<K, V, C, A, E, bM, bU>::DoAllocateNode()\n\t{\n\t\tauto* pNode = (node_type*)allocate_memory(mAllocator, sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT_MSG(pNode != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tinline void rbtree<K, V, C, A, E, bM, bU>::DoFreeNode(node_type* pNode)\n\t{\n\t\tpNode->~node_type();\n\t\tEASTLFree(mAllocator, pNode, sizeof(node_type));\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::node_type*\n\trbtree<K, V, C, A, E, bM, bU>::DoCreateNodeFromKey(const key_type& key)\n\t{\n\t\t// Note that this function intentionally leaves the node pointers uninitialized.\n\t\t// The caller would otherwise just turn right around and modify them, so there's\n\t\t// no point in us initializing them to anything (except in a debug build).\n\t\tnode_type* const pNode = DoAllocateNode();\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\t::new (eastl::addressof(pNode->mValue)) value_type(pair_first_construct, key);\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\n\t\t#if EASTL_DEBUG\n\t\t\tpNode->mpNodeRight  = NULL;\n\t\t\tpNode->mpNodeLeft   = NULL;\n\t\t\tpNode->mpNodeParent = NULL;\n\t\t\tpNode->mColor       = kRBTreeColorBlack;\n\t\t#endif\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::node_type*\n\trbtree<K, V, C, A, E, bM, bU>::DoCreateNode(const value_type& value)\n\t{\n\t\t// Note that this function intentionally leaves the node pointers uninitialized.\n\t\t// The caller would otherwise just turn right around and modify them, so there's\n\t\t// no point in us initializing them to anything (except in a debug build).\n\t\tnode_type* const pNode = DoAllocateNode();\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), value);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\n\t\t#if EASTL_DEBUG\n\t\t\tpNode->mpNodeRight  = NULL;\n\t\t\tpNode->mpNodeLeft   = NULL;\n\t\t\tpNode->mpNodeParent = NULL;\n\t\t\tpNode->mColor       = kRBTreeColorBlack;\n\t\t#endif\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::node_type*\n\trbtree<K, V, C, A, E, bM, bU>::DoCreateNode(value_type&& value)\n\t{\n\t\t// Note that this function intentionally leaves the node pointers uninitialized.\n\t\t// The caller would otherwise just turn right around and modify them, so there's\n\t\t// no point in us initializing them to anything (except in a debug build).\n\t\tnode_type* const pNode = DoAllocateNode();\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), eastl::move(value));\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\n\t\t#if EASTL_DEBUG\n\t\t\tpNode->mpNodeRight  = NULL;\n\t\t\tpNode->mpNodeLeft   = NULL;\n\t\t\tpNode->mpNodeParent = NULL;\n\t\t\tpNode->mColor       = kRBTreeColorBlack;\n\t\t#endif\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttemplate<class... Args>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::node_type*\n\trbtree<K, V, C, A, E, bM, bU>::DoCreateNode(Args&&... args)\n\t{\n\t\t// Note that this function intentionally leaves the node pointers uninitialized.\n\t\t// The caller would otherwise just turn right around and modify them, so there's\n\t\t// no point in us initializing them to anything (except in a debug build).\n\t\tnode_type* const pNode = DoAllocateNode();\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\tdetail::allocator_construct(mAllocator, eastl::addressof(pNode->mValue), eastl::forward<Args>(args)...);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\n\t\t#if EASTL_DEBUG\n\t\t\tpNode->mpNodeRight  = NULL;\n\t\t\tpNode->mpNodeLeft   = NULL;\n\t\t\tpNode->mpNodeParent = NULL;\n\t\t\tpNode->mColor       = kRBTreeColorBlack;\n\t\t#endif\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\ttypename rbtree<K, V, C, A, E, bM, bU>::node_type*\n\trbtree<K, V, C, A, E, bM, bU>::DoCreateNode(const node_type* pNodeSource, rbtree_node_base* pNodeParent)\n\t{\n\t\tnode_type* const pNode = DoCreateNode(pNodeSource->mValue);\n\n\t\tpNode->mpNodeRight  = NULL;\n\t\tpNode->mpNodeLeft   = NULL;\n\t\tpNode->mpNodeParent = pNodeParent;\n\t\tpNode->mColor       = pNodeSource->mColor;\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\trbtree_node_base*\n\trbtree<K, V, C, A, E, bM, bU>::DoCopySubtree(const node_type* pNodeSource, rbtree_node_base* pNodeDest)\n\t{\n\t\tnode_type* const pNewNodeRoot = DoCreateNode(pNodeSource, pNodeDest);\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\t// Copy the right side of the tree recursively.\n\t\t\t\tif(pNodeSource->mpNodeRight)\n\t\t\t\t\tpNewNodeRoot->mpNodeRight = DoCopySubtree(static_cast<const node_type*>(pNodeSource->mpNodeRight), pNewNodeRoot);\n\n\t\t\t\trbtree_node_base* pNewNodeLeft;\n\n\t\t\t\tfor(pNodeSource = static_cast<const node_type*>(pNodeSource->mpNodeLeft), pNodeDest = pNewNodeRoot;\n\t\t\t\t\tpNodeSource;\n\t\t\t\t\tpNodeSource = static_cast<const node_type*>(pNodeSource->mpNodeLeft), pNodeDest = pNewNodeLeft)\n\t\t\t\t{\n\t\t\t\t\tpNewNodeLeft = DoCreateNode(pNodeSource, pNodeDest);\n\n\t\t\t\t\tpNodeDest->mpNodeLeft = pNewNodeLeft;\n\n\t\t\t\t\t// Copy the right side of the tree recursively.\n\t\t\t\t\tif(pNodeSource->mpNodeRight)\n\t\t\t\t\t\tpNewNodeLeft->mpNodeRight = DoCopySubtree(static_cast<const node_type*>(pNodeSource->mpNodeRight), pNewNodeLeft);\n\t\t\t\t}\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoNukeSubtree(pNewNodeRoot);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\n\t\treturn pNewNodeRoot;\n\t}\n\n\n\ttemplate <typename K, typename V, typename C, typename A, typename E, bool bM, bool bU>\n\tvoid rbtree<K, V, C, A, E, bM, bU>::DoNukeSubtree(rbtree_node_base* pNode)\n\t{\n\t\twhile(pNode) // Recursively traverse the tree and destroy items as we go.\n\t\t{\n\t\t\tDoNukeSubtree(pNode->mpNodeRight);\n\n\t\t\tnode_type* const pNodeLeft = static_cast<node_type*>(pNode->mpNodeLeft);\n\t\t\tDoFreeNode(static_cast<node_type*>(pNode));\n\t\t\tpNode = pNodeLeft;\n\t\t}\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename V, typename A, typename C, typename E, bool bM, bool bU>\n\tinline bool operator==(const rbtree<K, V, C, A, E, bM, bU>& a, const rbtree<K, V, C, A, E, bM, bU>& b)\n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin());\n\t}\n\n\n\t// Note that in operator< we do comparisons based on the tree value_type with operator<() of the\n\t// value_type instead of the tree's Compare function. For set/multiset, the value_type is T, while\n\t// for map/multimap the value_type is a pair<Key, T>. operator< for pair can be seen by looking\n\t// utility.h, but it basically is uses the operator< for pair.first and pair.second. The C++ standard\n\t// appears to require this behaviour, whether intentionally or not. If anything, a good reason to do\n\t// this is for consistency. A map and a vector that contain the same items should compare the same.\n\ttemplate <typename K, typename V, typename A, typename C, typename E, bool bM, bool bU>\n\tinline bool operator<(const rbtree<K, V, C, A, E, bM, bU>& a, const rbtree<K, V, C, A, E, bM, bU>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename C, typename E, bool bM, bool bU>\n\tinline bool operator!=(const rbtree<K, V, C, A, E, bM, bU>& a, const rbtree<K, V, C, A, E, bM, bU>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename C, typename E, bool bM, bool bU>\n\tinline bool operator>(const rbtree<K, V, C, A, E, bM, bU>& a, const rbtree<K, V, C, A, E, bM, bU>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename C, typename E, bool bM, bool bU>\n\tinline bool operator<=(const rbtree<K, V, C, A, E, bM, bU>& a, const rbtree<K, V, C, A, E, bM, bU>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename C, typename E, bool bM, bool bU>\n\tinline bool operator>=(const rbtree<K, V, C, A, E, bM, bU>& a, const rbtree<K, V, C, A, E, bM, bU>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename K, typename V, typename A, typename C, typename E, bool bM, bool bU>\n\tinline void swap(rbtree<K, V, C, A, E, bM, bU>& a, rbtree<K, V, C, A, E, bM, bU>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/smart_ptr.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_SMART_PTR_H\n#define EASTL_INTERNAL_SMART_PTR_H\n\n\n#include <EABase/eabase.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/memory.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\nnamespace eastl\n{\n\n\tnamespace Internal\n\t{\n\t\t// Tells if the Deleter type has a typedef for pointer to T. If so then return it, \n\t\t// else return T*. The large majority of the time the pointer type will be T*.\n\t\t// The C++11 Standard requires that scoped_ptr let the deleter define the pointer type.\n\t\t//\n\t\t// Example usage:\n\t\t//     typedef typename unique_pointer_type<int, SomeDeleter>::type pointer\n\t\t//\n\t\ttemplate <typename T, typename Deleter>\n\t\tclass unique_pointer_type\n\t\t{\n\t\t\ttemplate <typename U>\n\t\t\tstatic typename U::pointer test(typename U::pointer*);\n\n\t\t\ttemplate <typename U>\n\t\t\tstatic T* test(...);\n\n\t\tpublic:\n\t\t\ttypedef decltype(test<typename eastl::remove_reference<Deleter>::type>(0)) type;\n\t\t};\n\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// is_array_cv_convertible\n\t\t//\n\t\t// Tells if the array pointer P1 is cv-convertible to array pointer P2.\n\t\t// The two types have two be equivalent pointer types and be convertible\n\t\t// when you consider const/volatile properties of them.\n\t\t//\n\t\t// Example usage:\n\t\t//     is_array_cv_convertible<int, Base*>::value             => false\n\t\t//     is_array_cv_convertible<Base, Base*>::value            => false\n\t\t//     is_array_cv_convertible<double*, bool*>::value         => false\n\t\t//     is_array_cv_convertible<Subclass*, Base*>::value       => false\n\t\t//     is_array_cv_convertible<const Base*, Base*>::value     => false\n\t\t//     is_array_cv_convertible<Base*, Base*>::value           => true\n\t\t//     is_array_cv_convertible<Base*, const Base*>::value     => true\n\t\t//     is_array_cv_convertible<Base*, volatile Base*>::value  => true\n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\t#define EASTL_TYPE_TRAIT_is_array_cv_convertible_CONFORMANCE 1\n\n\t\ttemplate <typename P1, typename P2, bool = eastl::is_same_v<eastl::remove_cv_t<typename pointer_traits<P1>::element_type>,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t    eastl::remove_cv_t<typename pointer_traits<P2>::element_type>>>\n\t\tstruct is_array_cv_convertible_impl \n\t\t\t: public eastl::is_convertible<P1, P2> {};  // Return true if P1 is convertible to P2.\n\n\t\ttemplate <typename P1, typename P2>\n\t\tstruct is_array_cv_convertible_impl<P1, P2, false> \n\t\t\t: public eastl::false_type {};              // P1's underlying type is not the same as P2's, so it can't be converted, even if P2 refers to a subclass of P1. Parent == Child, but Parent[] != Child[]\n\n\t\ttemplate <typename P1, typename P2, bool = eastl::is_scalar_v<P1> && !eastl::is_pointer_v<P1>>\n\t\tstruct is_array_cv_convertible\n\t\t\t: public is_array_cv_convertible_impl<P1, P2> {};\n\n\t\ttemplate <typename P1, typename P2>\n\t\tstruct is_array_cv_convertible<P1, P2, true>\n\t\t\t: public eastl::false_type {};              // P1 is scalar not a pointer, so it can't be converted to a pointer.\n\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// is_derived\n\t\t//\n\t\t// Given two (possibly identical) types Base and Derived, is_base_of<Base, Derived>::value == true \n\t\t// if and only if Base is a direct or indirect base class of Derived. This is like is_base_of<Base, Derived> \n\t\t// but returns false if Derived is the same as Base. So is_derived is true only if Derived is actually a subclass \n\t\t// of Base and not Base itself.\n\t\t//\n\t\t// is_derived may only be applied to complete types.\n\t\t//\n\t\t// Example usage:\n\t\t//     is_derived<int, int>::value             => false\n\t\t//     is_derived<int, bool>::value            => false\n\t\t//     is_derived<Parent, Child>::value        => true\n\t\t//     is_derived<Child, Parent>::value        => false\n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\t#if EASTL_TYPE_TRAIT_is_base_of_CONFORMANCE\n\t\t\t#define EASTL_TYPE_TRAIT_is_derived_CONFORMANCE 1\n\n\t\t\ttemplate <typename Base, typename Derived>\n\t\t\tstruct is_derived : public eastl::integral_constant<bool, eastl::is_base_of<Base, Derived>::value && !eastl::is_same<typename eastl::remove_cv<Base>::type, typename eastl::remove_cv<Derived>::type>::value> {};\n\t\t#else\n\t\t\t#define EASTL_TYPE_TRAIT_is_derived_CONFORMANCE 0\n\n\t\t\ttemplate <typename Base, typename Derived> // This returns true if Derived is unrelated to Base. That's a wrong answer, but is better for us than returning false for compilers that don't support is_base_of.\n\t\t\tstruct is_derived : public eastl::integral_constant<bool, !eastl::is_same<typename eastl::remove_cv<Base>::type, typename eastl::remove_cv<Derived>::type>::value> {};\n\t\t#endif\n\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// is_safe_array_conversion\n\t\t//\n\t\t// Say you have two array types: T* t and U* u. You want to assign the u to t but only if \n\t\t// that's a safe thing to do. As shown in the logic below, the array conversion\n\t\t// is safe if U* and T* are convertible, if U is an array, and if either U or T is not \n\t\t// a pointer or U is not derived from T.\n\t\t//\n\t\t// Note: Usage of this class could be replaced with is_array_cv_convertible usage.\n\t\t// To do: Do this replacement and test it.\n\t\t// \n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\ttemplate <typename T, typename T_pointer, typename U, typename U_pointer>\n\t\tstruct is_safe_array_conversion : public eastl::integral_constant<bool, eastl::is_convertible<U_pointer, T_pointer>::value &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\teastl::is_array<U>::value && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(!eastl::is_pointer<U_pointer>::value || !is_pointer<T_pointer>::value || !Internal::is_derived<T, typename eastl::remove_extent<U>::type>::value)> {};\n\n\t} // namespace Internal\n\n\n\n\t\n\n\n\n\t/// default_delete\n\t///\n\t/// C++11 smart pointer default delete function class.\n\t///\n\t/// Provides a default way to delete an object. This default is simply to call delete on the \n\t/// object pointer. You can provide an alternative to this class or you can override this on \n\t/// a class-by-class basis like the following:\n\t///     template <>\n\t///     struct smart_ptr_deleter<MyClass>\n\t///     {\n\t///         void operator()(MyClass* p) const\n\t///            { SomeCustomFunction(p); }\n\t///     };\n\t///\n\ttemplate <typename T>\n\tstruct default_delete\n\t{\n\t\t#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION <= 4006) // GCC prior to 4.7 has a bug with noexcept here.\n\t\t\tEA_CONSTEXPR default_delete() = default;\n\t\t#else\n\t\t\tEA_CONSTEXPR default_delete() EA_NOEXCEPT = default;\n\t\t#endif\n\n\t\ttemplate <typename U>  // Enable if T* can be constructed with U* (i.e. U* is convertible to T*).\n\t\tdefault_delete(const default_delete<U>&, typename eastl::enable_if<is_convertible<U*, T*>::value>::type* = 0) EA_NOEXCEPT {}\n\n\t\tvoid operator()(T* p) const EA_NOEXCEPT\n\t\t{\n\t\t\tstatic_assert(eastl::internal::is_complete_type_v<T>, \"Attempting to call the destructor of an incomplete type\");\n\t\t\tdelete p;\n\t\t}\n\t};\n\n\n\ttemplate <typename T>\n\tstruct default_delete<T[]> // Specialization for arrays.\n\t{\n\t\t#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION <= 4006) // GCC prior to 4.7 has a bug with noexcept here.\n\t\t\tEA_CONSTEXPR default_delete() = default;\n\t\t#else\n\t\t\tEA_CONSTEXPR default_delete() EA_NOEXCEPT = default;\n\t\t#endif\n\n\t\ttemplate <typename U> // This ctor is enabled if T is equal to or a base of U, and if U is less or equal const/volatile-qualified than T.\n\t\tdefault_delete(const default_delete<U[]>&, typename eastl::enable_if<Internal::is_array_cv_convertible<U*, T*>::value>::type* = 0) EA_NOEXCEPT {}\n\n\t\tvoid operator()(T* p) const EA_NOEXCEPT\n\t\t\t{ delete[] p; }\n\t};\n\n\n\n\n\t/// smart_ptr_deleter\n\t///\n\t/// Deprecated in favor of the C++11 name: default_delete\n\t///\n\ttemplate <typename T>\n\tstruct smart_ptr_deleter\n\t{\n\t\ttypedef T value_type;\n\n\t\tvoid operator()(const value_type* p) const // We use a const argument type in order to be most flexible with what types we accept. \n\t\t\t{ delete const_cast<value_type*>(p); }\n\t};\n\n\ttemplate <>\n\tstruct smart_ptr_deleter<void>\n\t{\n\t\ttypedef void value_type;\n\n\t\tvoid operator()(const void* p) const\n\t\t\t{ delete[] (char*)p; } // We don't seem to have much choice but to cast to a scalar type.\n\t};\n\n\ttemplate <>\n\tstruct smart_ptr_deleter<const void>\n\t{\n\t\ttypedef void value_type;\n\n\t\tvoid operator()(const void* p) const\n\t\t\t{ delete[] (char*)p; } // We don't seem to have much choice but to cast to a scalar type.\n\t};\n\n\n\n\t/// smart_array_deleter\n\t///\n\t/// Deprecated in favor of the C++11 name: default_delete\n\t///\n\ttemplate <typename T>\n\tstruct smart_array_deleter\n\t{\n\t\ttypedef T value_type;\n\n\t\tvoid operator()(const value_type* p) const // We use a const argument type in order to be most flexible with what types we accept. \n\t\t\t{ delete[] const_cast<value_type*>(p); }\n\t};\n\n\ttemplate <>\n\tstruct smart_array_deleter<void>\n\t{\n\t\ttypedef void value_type;\n\n\t\tvoid operator()(const void* p) const\n\t\t\t{ delete[] (char*)p; } // We don't seem to have much choice but to cast to a scalar type.\n\t};\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/special_member_functions.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <EASTL/internal/type_pod.h>\n#include <EASTL/type_traits.h>\n\nEA_DISABLE_VC_WARNING(4623) // * was implicitly defined as deleted\n\nnamespace eastl\n{\nnamespace internal\n{\n\n// Helper types for optional<T>, variant<Ts> and expected<T, E> that need to enable and disable special member functions\n// (ie. copy/move constructor & assignment) based on member types (Ts).\n//\n// Requirements for Base, using C++20 concepts notation:\n// ConstructFrom and AssignFrom are the implementation for the constructor and assignment of the type being implemented.\n// \n// template<typename SMFBase> concept SpecialMemberFunctions = requires(const SMFBase& base)\n// {\n//  { SMFBase::ConstructFrom(base) };\n//  { SMFBase::ConstructFrom(eastl::move(base)) };\n//  { SMFBase::AssignFrom(base) };\n//  { SMFBase::AssignFrom(eastl::move(base)) };\n// };\n\n\ntemplate <class Base> // requires SpecialMemberFunctions<Base>\nstruct NonTrivialCopyCtor : Base\n{\n\tusing Base::Base;\n\n\tNonTrivialCopyCtor() = default;\n\tNonTrivialCopyCtor(const NonTrivialCopyCtor& other) noexcept(\n\t\tnoexcept(eastl::declval<Base>().ConstructFrom(static_cast<const Base&>(other))))\n\t{\n\t\tBase::ConstructFrom(static_cast<const Base&>(other));\n\t}\n\tNonTrivialCopyCtor(NonTrivialCopyCtor&&) = default;\n\tNonTrivialCopyCtor& operator=(const NonTrivialCopyCtor&) = default;\n\tNonTrivialCopyCtor& operator=(NonTrivialCopyCtor&&) = default;\n};\n\ntemplate <class Base> // requires SpecialMemberFunctions<Base>\nstruct DeletedCopyCtor : Base\n{\n\tusing Base::Base;\n\n\tDeletedCopyCtor() = default;\n\tDeletedCopyCtor(const DeletedCopyCtor&) = delete;\n\tDeletedCopyCtor(DeletedCopyCtor&&) = default;\n\tDeletedCopyCtor& operator=(const DeletedCopyCtor&) = default;\n\tDeletedCopyCtor& operator=(DeletedCopyCtor&&) = default;\n};\n\ntemplate <class CopyBase> // requires SpecialMemberFunctions<CopyBase>\nstruct NonTrivialMoveCtor : CopyBase\n{\n\tusing SelectedBase = CopyBase;\n\tusing SelectedBase::SelectedBase;\n\n\tNonTrivialMoveCtor() = default;\n\tNonTrivialMoveCtor(const NonTrivialMoveCtor&) = default;\n\tNonTrivialMoveCtor(NonTrivialMoveCtor&& other) noexcept(\n\t\tnoexcept(eastl::declval<SelectedBase>().ConstructFrom(static_cast<SelectedBase&&>(other))))\n\t{\n\t\tSelectedBase::ConstructFrom(static_cast<SelectedBase&&>(other));\n\t}\n\tNonTrivialMoveCtor& operator=(const NonTrivialMoveCtor&) = default;\n\tNonTrivialMoveCtor& operator=(NonTrivialMoveCtor&&) = default;\n};\n\ntemplate <class CopyBase> // requires SpecialMemberFunctions<CopyBase>\nstruct DeletedMoveCtor : CopyBase\n{\n\tusing SelectedBase = CopyBase;\n\tusing SelectedBase::SelectedBase;\n\n\tDeletedMoveCtor() = default;\n\tDeletedMoveCtor(const DeletedMoveCtor&) = default;\n\tDeletedMoveCtor(DeletedMoveCtor&& other) = delete;\n\tDeletedMoveCtor& operator=(const DeletedMoveCtor&) = default;\n\tDeletedMoveCtor& operator=(DeletedMoveCtor&&) = default;\n};\n\ntemplate <class MoveBase> // requires SpecialMemberFunctions<MoveBase>\nstruct NonTrivialCopyAssign : MoveBase\n{\n\tusing SelectedBase = MoveBase;\n\tusing SelectedBase::SelectedBase;\n\n\tNonTrivialCopyAssign() = default;\n\tNonTrivialCopyAssign(const NonTrivialCopyAssign&) = default;\n\tNonTrivialCopyAssign(NonTrivialCopyAssign&&) = default;\n\n\tNonTrivialCopyAssign& operator=(const NonTrivialCopyAssign& other) noexcept(\n\t\tnoexcept(eastl::declval<SelectedBase>().AssignFrom(static_cast<const SelectedBase&>(other))))\n\t{\n\t\tSelectedBase::AssignFrom(static_cast<const SelectedBase&>(other));\n\t\treturn *this;\n\t}\n\tNonTrivialCopyAssign& operator=(NonTrivialCopyAssign&&) = default;\n};\n\ntemplate <class MoveBase> // requires SpecialMemberFunctions<MoveBase>\nstruct DeletedCopyAssign : MoveBase\n{\n\tusing SelectedBase = MoveBase;\n\tusing SelectedBase::SelectedBase;\n\n\tDeletedCopyAssign() = default;\n\tDeletedCopyAssign(const DeletedCopyAssign&) = default;\n\tDeletedCopyAssign(DeletedCopyAssign&&) = default;\n\tDeletedCopyAssign& operator=(const DeletedCopyAssign&) = delete;\n\tDeletedCopyAssign& operator=(DeletedCopyAssign&&) = default;\n};\n\ntemplate <class CopyAssignBase> // requires SpecialMemberFunctions<CopyAssignBase>\nstruct NonTrivialMoveAssign : CopyAssignBase\n{\n\tusing SelectedBase = CopyAssignBase;\n\tusing SelectedBase::SelectedBase;\n\n\tNonTrivialMoveAssign() = default;\n\tNonTrivialMoveAssign(const NonTrivialMoveAssign&) = default;\n\tNonTrivialMoveAssign(NonTrivialMoveAssign&&) = default;\n\tNonTrivialMoveAssign& operator=(const NonTrivialMoveAssign&) = default;\n\n\tNonTrivialMoveAssign& operator=(NonTrivialMoveAssign&& other) noexcept(\n\t\tnoexcept(eastl::declval<SelectedBase>().AssignFrom(static_cast<SelectedBase&&>(other))))\n\t{\n\t\tSelectedBase::AssignFrom(static_cast<SelectedBase&&>(other));\n\t\treturn *this;\n\t}\n};\n\ntemplate <class CopyAssignBase> // requires SpecialMemberFunctions<CopyAssignBase>\nstruct DeletedMoveAssign : CopyAssignBase\n{\n\tusing SelectedBase = CopyAssignBase;\n\tusing SelectedBase::SelectedBase;\n\n\tDeletedMoveAssign() = default;\n\tDeletedMoveAssign(const DeletedMoveAssign&) = default;\n\tDeletedMoveAssign(DeletedMoveAssign&&) = default;\n\tDeletedMoveAssign& operator=(const DeletedMoveAssign&) = default;\n\tDeletedMoveAssign& operator=(DeletedMoveAssign&&) = delete;\n};\n\n} // namespace internal\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING()\n\n"
  },
  {
    "path": "include/EASTL/internal/special_member_functions_expected.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n#pragma once\n\n#include <EABase/eabase.h>\n\n// We use a few c++17 features in the implementation of eastl::expceted, so we only provide\n// it from c++17 onwards.\n#if EA_COMPILER_CPP17_ENABLED\n\n#include <EASTL/internal/type_pod.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/internal/special_member_functions.h>\n\nnamespace eastl\n{\nnamespace internal\n{\n// From https://eel.is/c++draft/expected.object.cons#10\n//\n// This constructor is trivial if\n// is_trivially_copy_constructible_v<T> is true and\n// is_trivially_copy_constructible_v<E> is true\n//\n// From https://eel.is/c++draft/expected.object.cons#9\n//\n// Remarks: This constructor is defined as deleted unless\n// is_copy_constructible_v<T> is true and\n// is_copy_constructible_v<E> is true.\ntemplate <class Base, class... Ts>\nusing ExpectedCopyLayer =\nconditional_t<(is_copy_constructible_v<Ts> && ...),\n\tconditional_t<(is_trivially_copy_constructible_v<Ts> && ...), Base, NonTrivialCopyCtor<Base>>,\n\tDeletedCopyCtor<Base>>;\n\n// From https://eel.is/c++draft/expected.object.cons#16\n//\n// This constructor is trivial if\n// is_trivially_move_constructible_v<T> is true and\n// is_trivially_move_constructible_v<E> is true.\ntemplate <class Base, class... Ts>\nusing ExpectedMoveLayer = conditional_t<(is_move_constructible_v<Ts> && ...),\n\tconditional_t<(is_trivially_move_constructible_v<Ts> && ...),\n\tExpectedCopyLayer<Base, Ts...>,\n\tNonTrivialMoveCtor<ExpectedCopyLayer<Base, Ts...>>>,\n\tDeletedMoveCtor<ExpectedCopyLayer<Base, Ts...>>>;\n\n// NOTE: The fact that we have a nothrow check here might be annoying, but\n// it's in the standard, so it'll make the eventual aliasing easier.\n//\n// From https://eel.is/c++draft/expected.object.assign#4\n//\n// Remarks: This operator is defined as deleted unless:\n// is_copy_assignable_v<T> is true and\n// is_copy_constructible_v<T> is true and\n// is_copy_assignable_v<E> is true and\n// is_copy_constructible_v<E> is true and\n// is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.\ntemplate <class Base, class... Ts>\nusing ExpectedCopyAssignLayer =\nconditional_t<((is_copy_constructible_v<Ts> && ...) && (is_copy_assignable_v<Ts> && ...) &&\n\t(is_nothrow_move_constructible_v<Ts> || ...)),\n\tNonTrivialCopyAssign<ExpectedMoveLayer<Base, Ts...>>,\n\tDeletedCopyAssign<ExpectedMoveLayer<Base, Ts...>>>;\n\n// NOTE: The fact that we have a nothrow check here might be annoying, but\n// it's in the standard, so it'll make the eventual aliasing easier.\n//\n// From https://eel.is/c++draft/expected.object.assign#5\n//\n// Constraints:\n// is_move_constructible_v<T> is true and\n// is_move_assignable_v<T> is true and\n// is_move_constructible_v<E> is true and\n// is_move_assignable_v<E> is true and\n// is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.\n//\n// NOTE: in the standard, it doesn't say that the move assignment should be `deleted`\n// only that it should be constrained (i.e. should not be declared if the constraints\n// are not satisfied), so what we're doing here might seem incorrect. In practice, if\n// the constraints aren't satisified, then eastl::expcted (which will inherit from\n// this) will have an implicitly deleted move assignment, however, implicitly deleted\n// move assigment operators are ignored by overload resolution (see\n// https://eel.is/c++draft/class.copy.assign#note-4), which is equivalent to it being\n// constrained. This, in particular, means that an expression `x = move(y)` could still\n// compile and call the copy assignment operator (if that exists) instead, exactly as\n// if the move assignment was constrained instead of deleted.\ntemplate <class Base, class... Ts>\nusing ExpectedMoveAssignLayer =\nconditional_t<((is_move_constructible_v<Ts> && ...) && (is_move_assignable_v<Ts> && ...) &&\n\t(is_nothrow_move_constructible_v<Ts> || ...)),\n\tNonTrivialMoveAssign<ExpectedCopyAssignLayer<Base, Ts...>>,\n\tDeletedMoveAssign<ExpectedCopyAssignLayer<Base, Ts...>>>;\n\n// EnableExpectedSpecialMemberFunctions<Base, Ts...> is a helper for expected<T> that need to enable and disable special member functions\n// (ie. copy/move constructor & assignment) based on member types (Ts). The type being implemented (expected)\n// omits defining its special members and instead inherits from EnableExpectedSpecialMemberFunctions<Base, Ts...>. The reason\n// this is necessary is because conditionally disabling special member functions using SFINAE (enable_if) allows the\n// special member function to be *implicitly* generated instead, which is undesirable and breaks standard conformance.\n//\n// None of this would be necessary if we could use C++20 requires clauses instead.\n//\n// Using a C++20 requires clause would work as intended instead, but we can't require C++20 (yet).\n//\ntemplate <class Base, class... Ts> // requires SpecialMemberFunctions<base>\nusing EnableExpectedSpecialMemberFunctions = ExpectedMoveAssignLayer<Base, Ts...>;\n} // namespace internal\n} // namespace eastl\n\n#endif\n"
  },
  {
    "path": "include/EASTL/internal/special_member_functions_variant_optional.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <EASTL/internal/special_member_functions.h>\n\nEA_DISABLE_VC_WARNING(4623) // * was implicitly defined as deleted\n\nnamespace eastl\n{\n\tnamespace internal\n\t{\n\n\t\t// https://eel.is/c++draft/optional#ctor-7\n\t\t// https://eel.is/c++draft/variant#ctor-9\n\t\ttemplate <class Base, class... Ts>\n\t\tusing VariantOptionalCopyCtorLayer = conditional_t<\n\t\t    conjunction_v<is_copy_constructible<Ts>...>,\n\t\t    conditional_t<conjunction_v<is_trivially_copy_constructible<Ts>...>, Base, NonTrivialCopyCtor<Base>>,\n\t\t    DeletedCopyCtor<Base>>;\n\n\t\t// https://eel.is/c++draft/optional#ctor-12\n\t\t// https://eel.is/c++draft/variant#ctor-13\n\t\ttemplate <class Base, class... Ts>\n\t\tusing VariantOptionalMoveCtorLayer =\n\t\t    conditional_t<conjunction_v<is_nothrow_move_constructible<Ts>...>,\n\t\t                  conditional_t<conjunction_v<is_trivially_move_constructible<Ts>...>,\n\t\t                                VariantOptionalCopyCtorLayer<Base, Ts...>,\n\t\t                                NonTrivialMoveCtor<VariantOptionalCopyCtorLayer<Base, Ts...>>>,\n\t\t                  DeletedMoveCtor<VariantOptionalCopyCtorLayer<Base, Ts...>>>;\n\n\t\t// https://eel.is/c++draft/optional.assign#7\n\t\t// https://eel.is/c++draft/variant.assign#5\n\t\ttemplate <class Base, class... Ts>\n\t\tusing VariantOptionalCopyAssignLayer =\n\t\t    conditional_t<conjunction_v<is_copy_constructible<Ts>...> && conjunction_v<is_copy_assignable<Ts>...>,\n\t\t                  conditional_t<conjunction_v<is_trivially_copy_constructible<Ts>...> &&\n\t\t                                    conjunction_v<is_trivially_copy_assignable<Ts>...> &&\n\t\t                                    conjunction_v<is_trivially_destructible<Ts>...>,\n\t\t                                VariantOptionalMoveCtorLayer<Base, Ts...>,\n\t\t                                NonTrivialCopyAssign<VariantOptionalMoveCtorLayer<Base, Ts...>>>,\n\t\t                  DeletedCopyAssign<VariantOptionalMoveCtorLayer<Base, Ts...>>>;\n\n\t\t// https://eel.is/c++draft/optional#assign-8\n\t\t// https://eel.is/c++draft/optional#assign-13\n\t\t// https://eel.is/c++draft/variant#assign-7\n\t\t// https://eel.is/c++draft/variant#assign-10\n\t\ttemplate <class Base, class... Ts>\n\t\tusing VariantOptionalMoveAssignLayer =\n\t\t    conditional_t<conjunction_v<is_move_constructible<Ts>...> && conjunction_v<is_move_assignable<Ts>...>,\n\t\t                  conditional_t<conjunction_v<is_trivially_move_constructible<Ts>...> &&\n\t\t                                    conjunction_v<is_trivially_move_assignable<Ts>...> &&\n\t\t                                    conjunction_v<is_trivially_destructible<Ts>...>,\n\t\t                                VariantOptionalCopyAssignLayer<Base, Ts...>,\n\t\t                                NonTrivialMoveAssign<VariantOptionalCopyAssignLayer<Base, Ts...>>>,\n\t\t                  DeletedMoveAssign<VariantOptionalCopyAssignLayer<Base, Ts...>>>;\n\n\t\t// EnableSpecialMemberFunctions<Base, Ts...> is a helper class for optional<T> and variant<T> that need to\n\t\t// enable and disable special member functions (ie. copy/move constructor & assignment) based on member types\n\t\t// (Ts). The type being implemented (eg. variant) omits defining its special members and instead inherits from\n\t\t// EnableSpecialMemberFunctions<Base, Ts...>. The reason this is necessary is because conditionally disabling\n\t\t// special member functions using SFINAE (enable_if) allows the special member function to be *implicitly*\n\t\t// generated instead, which is undesirable and breaks standard conformance.\n\t\t//\n\t\t// None of this would be necessary if we could use C++20 requires clauses instead.\n\t\t//\n\t\t// Using a C++20 requires clause would work as intended instead, but we can't require C++20 (yet).\n\t\t//\n\t\ttemplate <class Base, class... Ts> // requires SpecialMemberFunctions<base>\n\t\tusing EnableVariantOptionalSpecialMemberFunctions = VariantOptionalMoveAssignLayer<Base, Ts...>;\n\t} // namespace internal\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING()\n"
  },
  {
    "path": "include/EASTL/internal/thread_support.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_THREAD_SUPPORT_H\n#define EASTL_INTERNAL_THREAD_SUPPORT_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n#include <EASTL/internal/config.h>\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////\n// NOTE(rparolin): We need a fallback mutex implementation because the Microsoft implementation \n// of std::mutex can not be included in managed-cpp code.\n//\n// fatal error C1189: <mutex> is not supported when compiling with /clr or /clr:pure \n/////////////////////////////////////////////////////////////////////////////////////////////////////\n#if !defined(EASTL_CPP11_MUTEX_ENABLED)\n\t#if defined(EA_HAVE_CPP11_MUTEX) && !defined(EA_COMPILER_MANAGED_CPP)\n\t\t#define EASTL_CPP11_MUTEX_ENABLED 1\n\t#else\n\t\t#define EASTL_CPP11_MUTEX_ENABLED 0\n\t#endif\n#endif\n\n#if EASTL_CPP11_MUTEX_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <mutex>\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\n#if defined(EA_PLATFORM_MICROSOFT)\n\t// Cannot include Windows headers in our headers, as they kill builds with their #defines.\n#elif defined(EA_PLATFORM_POSIX)\n\t#include <pthread.h>\n#endif\n\n// copy constructor could not be generated because a base class copy constructor is inaccessible or deleted.\n// assignment operator could not be generated because a base class assignment operator is inaccessible or deleted.\n// non dll-interface class used as base for DLL-interface classkey 'identifier'.\nEA_DISABLE_VC_WARNING(4625 4626 4275);\n\n\n#if defined(EA_PLATFORM_MICROSOFT)\n\t#if defined(EA_PROCESSOR_POWERPC)\n\t\textern \"C\" long  __stdcall _InterlockedIncrement(long volatile* Addend);\n\t\t#pragma intrinsic (_InterlockedIncrement)\n\n\t\textern \"C\" long  __stdcall _InterlockedDecrement(long volatile* Addend);\n\t\t#pragma intrinsic (_InterlockedDecrement)\n\n\t\textern \"C\" long  __stdcall _InterlockedCompareExchange(long volatile* Dest, long Exchange, long Comp);\n\t\t#pragma intrinsic (_InterlockedCompareExchange)\n\t#else\n\t\textern \"C\" long  _InterlockedIncrement(long volatile* Addend);\n\t\t#pragma intrinsic (_InterlockedIncrement)\n\n\t\textern \"C\" long _InterlockedDecrement(long volatile* Addend);\n\t\t#pragma intrinsic (_InterlockedDecrement)\n\n\t\textern \"C\" long _InterlockedCompareExchange(long volatile* Dest, long Exchange, long Comp);\n\t\t#pragma intrinsic (_InterlockedCompareExchange)\n\t#endif\n#endif\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_THREAD_SUPPORT_AVAILABLE\n//\n// Defined as 0 or 1, based on existing support.\n// Identifies if thread support (e.g. atomics, mutexes) is available for use.\n// The large majority of EASTL doesn't use thread support, but a few parts \n// of it (e.g. shared_ptr) do.\n///////////////////////////////////////////////////////////////////////////////\n\n#if !defined(EASTL_THREAD_SUPPORT_AVAILABLE)\n\t#if defined(__clang__) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4003))\n\t\t#define EASTL_THREAD_SUPPORT_AVAILABLE 1\n\t#elif defined(EA_COMPILER_MSVC)\n\t\t#define EASTL_THREAD_SUPPORT_AVAILABLE 1\n\t#else\n\t\t#define EASTL_THREAD_SUPPORT_AVAILABLE 0\n\t#endif\n#endif\n\n\nnamespace eastl\n{\n\tnamespace Internal\n\t{\n\t\t// mutex\n\t\t#if EASTL_CPP11_MUTEX_ENABLED\n\t\t\tusing std::mutex;\n\t\t#else\n\t\t\tclass EASTL_API mutex\n\t\t\t{\n\t\t\tpublic:\n\t\t\t\tmutex();\n\t\t\t   ~mutex();\n\n\t\t\t\tvoid lock();\n\t\t\t\tvoid unlock();\n\n\t\t\tprotected:\n\t\t\t\t#if defined(EA_PLATFORM_MICROSOFT)\n\t\t\t\t\t#if defined(_WIN64)\n\t\t\t\t\t\tuint64_t mMutexBuffer[40 / sizeof(uint64_t)]; // CRITICAL_SECTION is 40 bytes on Win64.\n\t\t\t\t\t#elif defined(_WIN32)\n\t\t\t\t\t\tuint32_t mMutexBuffer[24 / sizeof(uint32_t)]; // CRITICAL_SECTION is 24 bytes on Win32.\n\t\t\t\t\t#endif\n\t\t\t\t#elif defined(EA_PLATFORM_POSIX)\n\t\t\t\t\tpthread_mutex_t mMutex;\n\t\t\t\t#endif\n\t\t\t};\n\t\t#endif\n\n\n\t\t// auto_mutex\n\t\tclass EASTL_API auto_mutex\n\t\t{\n\t\tpublic:\n\t\t\tEA_FORCE_INLINE auto_mutex(mutex& mutex) : pMutex(&mutex)\n\t\t\t\t{ pMutex->lock(); }\n\n\t\t\tEA_FORCE_INLINE ~auto_mutex()\n\t\t\t\t{ pMutex->unlock(); }\n\n\t\tprotected:\n\t\t\tmutex* pMutex;\n\n\t\t\tauto_mutex(const auto_mutex&) = delete;\n\t\t\tvoid operator=(const auto_mutex&) = delete;\n\t\t};\n\n\n\t\t// shared_ptr_auto_mutex\n\t\tclass EASTL_API shared_ptr_auto_mutex : public auto_mutex\n\t\t{\n\t\tpublic:\n\t\t\tshared_ptr_auto_mutex(const void* pSharedPtr);\n\n\t\t\tshared_ptr_auto_mutex(const shared_ptr_auto_mutex&) = delete;\n\t\t\tvoid operator=(shared_ptr_auto_mutex&&) = delete;\n\t\t};\n\n\n\t} // namespace Internal\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/tuple_fwd_decls.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_TUPLE_FWD_DECLS_H\n#define EASTL_TUPLE_FWD_DECLS_H\n\n#include <EASTL/internal/config.h>\n\n#if EASTL_TUPLE_ENABLED\n\nnamespace eastl\n{\n\ttemplate <typename... T>\n\tclass tuple;\n\n\ttemplate <typename Tuple>\n\tstruct tuple_size;\n\n#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\ttemplate <class T>\n\tEA_CONSTEXPR size_t tuple_size_v = tuple_size<T>::value;\n#endif\n\n\ttemplate <size_t I, typename Tuple>\n\tstruct tuple_element;\n\n\ttemplate <size_t I, typename Tuple>\n\tusing tuple_element_t = typename tuple_element<I, Tuple>::type;\n\n\ttemplate<typename T> struct is_lvalue_reference;\n\n\ttemplate<bool B, typename T, typename F>\n\tstruct conditional;\n\n\ttemplate <typename T> struct add_lvalue_reference;\n\n\ttemplate <typename T> struct remove_reference;\n\n\t// const typename for tuple_element_t, for when tuple or TupleImpl cannot itself be const\n\ttemplate <size_t I, typename Tuple>\n\tusing const_tuple_element_t = typename conditional<\n\t\t\t\t\t\tis_lvalue_reference<tuple_element_t<I, Tuple>>::value,\n\t\t\t\t\t\t\t typename add_lvalue_reference<const typename remove_reference<tuple_element_t<I, Tuple>>::type>::type,\n\t\t\t\t\t\t\t const tuple_element_t<I, Tuple>\n\t\t\t\t\t\t>::type;\n\n\t// get\n\ttemplate <size_t I, typename... Ts_>\n\ttuple_element_t<I, tuple<Ts_...>>& get(tuple<Ts_...>& t);\n\n\ttemplate <size_t I, typename... Ts_>\n\tconst_tuple_element_t<I, tuple<Ts_...>>& get(const tuple<Ts_...>& t);\n\n\ttemplate <size_t I, typename... Ts_>\n\ttuple_element_t<I, tuple<Ts_...>>&& get(tuple<Ts_...>&& t);\n\n\ttemplate <typename T, typename... ts_>\n\tT& get(tuple<ts_...>& t);\n\n\ttemplate <typename T, typename... ts_>\n\tconst T& get(const tuple<ts_...>& t);\n\n\ttemplate <typename T, typename... ts_>\n\tT&& get(tuple<ts_...>&& t);\n}\n\n#endif  // EASTL_VARIADIC_TEMPLATES_ENABLED\n\n#endif  // EASTL_TUPLE_FWD_DECLS_H\n"
  },
  {
    "path": "include/EASTL/internal/type_compound.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_TYPE_COMPOUND_H\n#define EASTL_INTERNAL_TYPE_COMPOUND_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n// Until we revise the code below to handle EDG warnings, we don't have much choice but to disable them.\n#if defined(__EDG_VERSION__)\n\t#pragma diag_suppress=1931 // operand of sizeof is not a type, variable, or dereferenced pointer expression\n#endif\n\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////\n\t// extent\n\t//\n\t// extent<T, I>::value is an integral type representing the number of \n\t// elements in the Ith dimension of array type T.\n\t// \n\t// For a given array type T[N], extent<T[N]>::value == N.\n\t// For a given multi-dimensional array type T[M][N], extent<T[M][N], 0>::value == N.\n\t// For a given multi-dimensional array type T[M][N], extent<T[M][N], 1>::value == M.\n\t// For a given array type T and a given dimension I where I >= rank<T>::value, extent<T, I>::value == 0.\n\t// For a given array type of unknown extent T[], extent<T[], 0>::value == 0.\n\t// For a given non-array type T and an arbitrary dimension I, extent<T, I>::value == 0.\n\t// \n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_extent_CONFORMANCE 1    // extent is conforming.\n\n\ttemplate<typename T, unsigned N> \n\tstruct extent_help : public eastl::integral_constant<size_t, 0> {};\n\n\ttemplate<typename T, unsigned I>\n\tstruct extent_help<T[I], 0> : public eastl::integral_constant<size_t, I> {};\n\n\ttemplate<typename T, unsigned N, unsigned I>\n\tstruct extent_help<T[I], N> : public eastl::extent_help<T, N - 1> { };\n\n\ttemplate<typename T, unsigned N>\n\tstruct extent_help<T[], N> : public eastl::extent_help<T, N - 1> {};\n\n\ttemplate<typename T, unsigned N = 0> // extent uses unsigned instead of size_t.\n\tstruct extent : public eastl::extent_help<T, N> { };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T, unsigned N = 0> \n\t\tEA_CONSTEXPR auto extent_v = extent<T, N>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_array\n\t//\n\t// is_array<T>::value == true if and only if T is an array type, \n\t// including unbounded array types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_array_CONFORMANCE 1    // is_array is conforming; doesn't make mistakes.\n\n\ttemplate<typename T>\n\tstruct is_array : public eastl::false_type {};\n\n\ttemplate<typename T>\n\tstruct is_array<T[]> : public eastl::true_type {};\n\n\ttemplate<typename T, size_t N>\n\tstruct is_array<T[N]> : public eastl::true_type {};\n\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_array_v = is_array<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_member_function_pointer\n\t//\n\t// is_member_function_pointer<T>::value == true if and only if T is a \n\t// pointer to member function type.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\t// We detect member functions with 0 to N arguments. We can extend this\n\t// for additional arguments if necessary.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_member_function_pointer_CONFORMANCE 1    // is_member_function_pointer is conforming; doesn't make mistakes.\n\n\tnamespace internal\n\t{\n\t\ttemplate<typename T>\n\t\tstruct is_member_function_pointer_helper : false_type {};\n\n\t\ttemplate<typename T, typename U>\n\t\tstruct is_member_function_pointer_helper<T U::*> : is_function<T> {};\n\t}\n\n\ttemplate<typename T>\n\tstruct is_member_function_pointer\n\t\t: internal::is_member_function_pointer_helper<typename remove_cv<T>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_member_function_pointer_v = is_member_function_pointer<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_member_pointer\n\t//\n\t// is_member_pointer<T>::value == true if and only if:\n\t//    is_member_object_pointer<T>::value == true, or\n\t//    is_member_function_pointer<T>::value == true\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_member_pointer_CONFORMANCE 1    // is_member_pointer is conforming; doesn't make mistakes.\n\n\tnamespace internal {\n\t\ttemplate <typename T>\n\t\tstruct is_member_pointer_helper\n\t\t\t: public eastl::false_type {};\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_member_pointer_helper<U T::*>\n\t\t\t: public eastl::true_type {};\n\t}\n\n\ttemplate<typename T>\n\tstruct is_member_pointer\n\t\t: public internal::is_member_pointer_helper<typename remove_cv<T>::type>::type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_member_pointer_v = is_member_pointer<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_member_object_pointer\n\t//\n\t// is_member_object_pointer<T>::value == true if and only if T is a \n\t// pointer to data member type.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_member_object_pointer_CONFORMANCE 1    // is_member_object_pointer is conforming; doesn't make mistakes.\n\n\ttemplate<typename T>\n\tstruct is_member_object_pointer : public eastl::integral_constant<bool,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  eastl::is_member_pointer<T>::value &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t !eastl::is_member_function_pointer<T>::value\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t > {};\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_member_object_pointer_v = is_member_object_pointer<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_pointer\n\t//\n\t// is_pointer<T>::value == true if and only if T is a pointer type. \n\t// This category includes function pointer types, but not pointer to \n\t// member types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_pointer_CONFORMANCE 1    // is_pointer is conforming; doesn't make mistakes.\n\n\ttemplate <typename T> struct is_pointer_helper : public false_type{};\n\n\ttemplate <typename T> struct is_pointer_helper<T*>                : public true_type{};\n\ttemplate <typename T> struct is_pointer_helper<T* const>          : public true_type{};\n\ttemplate <typename T> struct is_pointer_helper<T* volatile>       : public true_type{};\n\ttemplate <typename T> struct is_pointer_helper<T* const volatile> : public true_type{};\n\n\ttemplate <typename T>\n\tstruct is_pointer_value : public bool_constant<is_pointer_helper<T>::value && !is_member_pointer<T>::value> {};\n\n\ttemplate <typename T> \n\tstruct is_pointer : public integral_constant<bool, is_pointer_value<T>::value>{};\n\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_pointer_v = is_pointer<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_convertible\n\t//\n\t// Given two (possible identical) types From and To, is_convertible<From, To>::value == true \n\t// if and only if an lvalue of type From can be implicitly converted to type To, \n\t// or is_void<To>::value == true\n\t// \n\t// An instance of the type predicate holds true if the expression To to = from;, where from is an object of type From, is well-formed.\n\t//\n\t// is_convertible may only be applied to complete types.\n\t// Type To may not be an abstract type. \n\t// If the conversion is ambiguous, the program is ill-formed. \n\t// If either or both of From and To are class types, and the conversion would invoke \n\t// non-public member functions of either From or To (such as a private constructor of To, \n\t// or a private conversion operator of From), the program is ill-formed.\n\t//\n\t// Note that without compiler help, both is_convertible and is_base \n\t// can produce compiler errors if the conversion is ambiguous. \n\t// Example:\n\t//    struct A {};\n\t//    struct B : A {};\n\t//    struct C : A {};\n\t//    struct D : B, C {};\n\t//    is_convertible<D*, A*>::value; // Generates compiler error.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_convertible_to)))\n\t\t#define EASTL_TYPE_TRAIT_is_convertible_CONFORMANCE 1    // is_convertible is conforming.\n\n\t\t// Problem: VC++ reports that int is convertible to short, yet if you construct a short from an int then VC++ generates a warning:\n\t\t//          warning C4242: 'initializing' : conversion from 'int' to 'short', possible loss of data. We can deal with this by making\n\t\t//          is_convertible be false for conversions that could result in loss of data. Or we could make another trait called is_lossless_convertible\n\t\t//          and use that appropriately in our code. Or we could put the onus on the user to work around such warnings.\n\t\ttemplate <typename From, typename To>\n\t\tstruct is_convertible : public integral_constant<bool, __is_convertible_to(From, To)>{};\n\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_convertible_CONFORMANCE 1\n\n\t\ttemplate<typename From, typename To, bool = eastl::is_void<From>::value || eastl::is_function<To>::value || eastl::is_array<To>::value >\n\t\tstruct is_convertible_helper // Anything is convertible to void. Nothing is convertible to a function or an array.\n\t\t\t{ static const bool value = eastl::is_void<To>::value; };\n\n\t\ttemplate<typename From, typename To>\n\t\tclass is_convertible_helper<From, To, false>\n\t\t{\n\t\t\ttemplate<typename To1>\n\t\t\tstatic void ToFunction(To1);    // We try to call this function with an instance of From. It is valid if From can be converted to To.\n\n\t\t\ttemplate<typename /*From1*/, typename /*To1*/>\n\t\t\tstatic eastl::no_type is(...);\n\n\t\t\ttemplate<typename From1, typename To1>\n\t\t\tstatic decltype(ToFunction<To1>(eastl::declval<From1>()), eastl::yes_type()) is(int);\n\n\t\tpublic:\n\t\t\tstatic const bool value = sizeof(is<From, To>(0)) == 1;\n\t\t};\n\n\t\ttemplate<typename From, typename To>\n\t\tstruct is_convertible\n\t\t\t: public integral_constant<bool, is_convertible_helper<From, To>::value> {};\n\n\t#endif\n\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate<typename From, typename To>\n\t\tEA_CONSTEXPR bool is_convertible_v = is_convertible<From, To>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_convertible\n\t// \n\t// https://en.cppreference.com/w/cpp/types/is_convertible\n\t//\n\t// template<typename From, typename To>\n\t// struct is_explicitly_convertible\n\t//     : public is_constructible<To, From> {};\n\t///////////////////////////////////////////////////////////////////////\n\t// TODO(rparolin):  implement type-trait\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_explicitly_convertible\n\t// \n\t// This sometime-seen extension trait is the same as is_constructible\n\t// and so we don't define it.\n\t//\n\t// template<typename From, typename To>\n\t// struct is_explicitly_convertible\n\t//     : public is_constructible<To, From> {};\n\t///////////////////////////////////////////////////////////////////////\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_union\n\t//\n\t// is_union<T>::value == true if and only if T is a union type.\n\t//\n\t// There is no way to tell if a type is a union without compiler help.\n\t// As of this writing, only Metrowerks v8+ supports such functionality\n\t// via 'msl::is_union<T>::value'.\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_union)))\n\t\t#define EASTL_TYPE_TRAIT_is_union_CONFORMANCE 1    // is_union is conforming.\n\n\t\ttemplate <typename T> \n\t\tstruct is_union : public integral_constant<bool, __is_union(T)>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_union_CONFORMANCE 0    // is_union is not fully conforming.\n\n\t\ttemplate <typename T> struct is_union : public false_type{};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_union_v = is_union<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_class\n\t//\n\t// is_class<T>::value == true if and only if T is a class or struct \n\t// type (and not a union type).\n\t//\n\t// Without specific compiler help, it is not possible to \n\t// distinguish between unions and classes. As a result, is_class\n\t// will erroneously evaluate to true for union types.\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_class)))\n\t\t#define EASTL_TYPE_TRAIT_is_class_CONFORMANCE 1    // is_class is conforming.\n\n\t\ttemplate <typename T> \n\t\tstruct is_class : public integral_constant<bool, __is_class(T)>{};\n\t#elif defined(__EDG__)\n\t\t#define EASTL_TYPE_TRAIT_is_class_CONFORMANCE   EASTL_TYPE_TRAIT_is_union_CONFORMANCE\n\t   \n\t\ttypedef char yes_array_type[1];\n\t\ttypedef char no_array_type[2];\n\t\ttemplate <typename U> static yes_array_type& is_class_helper(void (U::*)());\n\t\ttemplate <typename U> static no_array_type& is_class_helper(...);\n\n\t\ttemplate <typename T> \n\t\tstruct is_class : public integral_constant<bool,\n\t\t\tsizeof(is_class_helper<T>(0)) == sizeof(yes_array_type) && !is_union<T>::value\n\t\t>{};\n\t#elif !defined(__GNUC__) || (((__GNUC__ * 100) + __GNUC_MINOR__) >= 304) // Not GCC or GCC 3.4+\n\t\t#define EASTL_TYPE_TRAIT_is_class_CONFORMANCE   EASTL_TYPE_TRAIT_is_union_CONFORMANCE\n\n\t\ttemplate <typename U> static yes_type is_class_helper(void (U::*)());\n\t\ttemplate <typename U> static no_type  is_class_helper(...);\n\n\t\ttemplate <typename T> \n\t\tstruct is_class : public integral_constant<bool,\n\t\t\tsizeof(is_class_helper<T>(0)) == sizeof(yes_type) && !is_union<T>::value\n\t\t>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_class_CONFORMANCE 0    // is_class is not fully conforming.\n\n\t\t// GCC 2.x version, due to GCC being broken.\n\t\ttemplate <typename T> \n\t\tstruct is_class : public false_type{};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_class_v = is_class<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_polymorphic\n\t// \n\t// is_polymorphic<T>::value == true if and only if T is a class or struct \n\t// that declares or inherits a virtual function. is_polymorphic may only \n\t// be applied to complete types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_polymorphic)))\n\t\t#define EASTL_TYPE_TRAIT_is_polymorphic_CONFORMANCE 1    // is_polymorphic is conforming. \n\n\t\ttemplate <typename T> \n\t\tstruct is_polymorphic : public integral_constant<bool, __is_polymorphic(T)>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_polymorphic_CONFORMANCE 1    // is_polymorphic is conforming.\n\n\t\ttemplate <typename T>\n\t\tstruct is_polymorphic_imp1\n\t\t{\n\t\t\ttypedef typename remove_cv<T>::type t;\n\n\t\t\tstruct helper_1 : public t\n\t\t\t{\n\t\t\t\thelper_1();\n\t\t\t\t~helper_1() throw();\n\t\t\t\tchar pad[64];\n\t\t\t};\n\n\t\t\tstruct helper_2 : public t\n\t\t\t{\n\t\t\t\thelper_2();\n\t\t\t\tvirtual ~helper_2() throw();\n\t\t\t\t#ifndef _MSC_VER\n\t\t\t\t\tvirtual void foo();\n\t\t\t\t#endif\n\t\t\t\tchar pad[64];\n\t\t\t};\n\n\t\t\tstatic const bool value = (sizeof(helper_1) == sizeof(helper_2));\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct is_polymorphic_imp2{ static const bool value = false; };\n\n\t\ttemplate <bool is_class>\n\t\tstruct is_polymorphic_selector{ template <typename T> struct rebind{ typedef is_polymorphic_imp2<T> type; }; };\n\n\t\ttemplate <>\n\t\tstruct is_polymorphic_selector<true>{ template <typename T> struct rebind{ typedef is_polymorphic_imp1<T> type; }; };\n\n\t\ttemplate <typename T>\n\t\tstruct is_polymorphic_value{\n\t\t\ttypedef is_polymorphic_selector<is_class<T>::value> selector;\n\t\t\ttypedef typename selector::template rebind<T> binder;\n\t\t\ttypedef typename binder::type imp_type;\n\t\t\tstatic const bool value = imp_type::value;\n\t\t};\n\n\t\ttemplate <typename T> \n\t\tstruct is_polymorphic : public integral_constant<bool, is_polymorphic_value<T>::value>{};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_polymorphic_v = is_polymorphic<T>::value;\n\t#endif\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_object\n\t//\n\t// is_object<T>::value == true if and only if:\n\t//    is_reference<T>::value == false, and\n\t//    is_function<T>::value == false, and\n\t//    is_void<T>::value == false\n\t//\n\t// The C++ standard, section 3.9p9, states: \"An object type is a\n\t// (possibly cv-qualified) type that is not a function type, not a \n\t// reference type, and not incomplete (except for an incompletely\n\t// defined object type).\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_object_CONFORMANCE  (EASTL_TYPE_TRAIT_is_reference_CONFORMANCE && EASTL_TYPE_TRAIT_is_void_CONFORMANCE && EASTL_TYPE_TRAIT_is_function_CONFORMANCE)\n\n\ttemplate <typename T> \n\tstruct is_object : public integral_constant<bool,\n\t\t!is_reference<T>::value && !is_void<T>::value && !is_function<T>::value\n\t>{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_object_v = is_object<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_scalar\n\t//\n\t// is_scalar<T>::value == true if and only if:\n\t//    is_arithmetic<T>::value == true, or\n\t//    is_enum<T>::value == true, or\n\t//    is_pointer<T>::value == true, or\n\t//    is_member_pointer<T>::value == true, or\n\t//    is_null_pointer<T>::value == true\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_scalar_CONFORMANCE 1    // is_scalar is conforming.\n\n\ttemplate <typename T>\n\tstruct is_scalar : public integral_constant<bool,\n\t                                            is_arithmetic<T>::value || is_enum<T>::value || is_pointer<T>::value ||\n\t                                                is_member_pointer<T>::value ||\n\t                                                is_null_pointer<T>::value> {};\n\n\ttemplate <typename T> struct is_scalar<T*>                : public true_type {};\n\ttemplate <typename T> struct is_scalar<T* const>          : public true_type {};\n\ttemplate <typename T> struct is_scalar<T* volatile>       : public true_type {};\n\ttemplate <typename T> struct is_scalar<T* const volatile> : public true_type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_scalar_v = is_scalar<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_compound\n\t//\n\t// Compound means anything but fundamental. See C++ standard, section 3.9.2.\n\t//\n\t// is_compound<T>::value == true if and only if:\n\t//    is_fundamental<T>::value == false\n\t//\n\t// Thus, is_compound<T>::value == true if and only if:\n\t//    is_floating_point<T>::value == false, and\n\t//    is_integral<T>::value == false, and\n\t//    is_void<T>::value == false\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_compound_CONFORMANCE  EASTL_TYPE_TRAIT_is_fundamental_CONFORMANCE\n\n\ttemplate <typename T> \n\tstruct is_compound : public integral_constant<bool, !is_fundamental<T>::value>{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_compound_v = is_compound<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// decay\n\t//\n\t// Converts the type T to its decayed equivalent. That means doing \n\t// lvalue to rvalue, array to pointer, function to pointer conversions,\n\t// and removal of const and volatile.\n\t// This is the type conversion silently applied by the compiler to \n\t// all function arguments when passed by value. \n\n\t#define EASTL_TYPE_TRAIT_decay_CONFORMANCE 1    // decay is conforming.\n\n\ttemplate<typename T>\n\tstruct decay\n\t{\n\t\ttypedef typename eastl::remove_reference<T>::type U;\n\n\t\ttypedef typename eastl::conditional< \n\t\t\teastl::is_array<U>::value,\n\t\t\ttypename eastl::remove_extent<U>::type*,\n\t\t\ttypename eastl::conditional< \n\t\t\t\teastl::is_function<U>::value,\n\t\t\t\ttypename eastl::add_pointer<U>::type,\n\t\t\t\ttypename eastl::remove_cv<U>::type\n\t\t\t>::type\n\t\t>::type type;\n\t};\n\n\n\t// decay_t is the C++14 using typedef for typename decay<T>::type, though\n\t// it requires only C++11 compiler functionality to implement.\n\t// We provide a backwards-compatible means to access it through a macro for pre-C++11 compilers.\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t#define EASTL_DECAY_T(T) typename decay<T>::type\n\t#else\n\t\ttemplate<typename T>\n\t\tusing decay_t = typename decay<T>::type;\n\t\t#define EASTL_DECAY_T(T) decay_t<T>\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// common_type\n\t// \n\t// Determines the common type among all types T..., that is the type all T... \n\t// can be implicitly converted to.\n\t//\n\t// It is intended that this be specialized by the user for cases where it\n\t// is useful to do so. Example specialization:\n\t//     template <typename Class1, typename Class2>\n\t//     struct common_type<MyClass1, MyClass2>{ typedef MyBaseClassB type; };\n\t//\n\t// The member typedef type shall be defined as set out in 20.9.7.6,p3. All types in\n\t// the parameter pack T shall be complete or (possibly cv) void. A program may \n\t// specialize this trait if at least one template parameter in the specialization \n\t// is a user-defined type. Note: Such specializations are needed when only  \n\t// explicit conversions are desired among the template arguments.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_common_type_CONFORMANCE 1    // common_type is conforming.\n\n\ttemplate<typename... T>\n\tstruct common_type;\n\n\ttemplate<typename T>\n\tstruct common_type<T>\n\t\t{ typedef decay_t<T> type; }; // Question: Should we use T or decay_t<T> here? The C++11 Standard specifically (20.9.7.6,p3) specifies that it be without decay, but libc++ uses decay.\n\n\ttemplate<typename T, typename U>\n\tstruct common_type<T, U>\n\t{\n\t\ttypedef decay_t<decltype(true ? declval<T>() : declval<U>())> type; // The type of a tertiary expression is set by the compiler to be the common type of the two result types.\n\t};\n\n\ttemplate<typename T, typename U, typename... V>\n\tstruct common_type<T, U, V...>\n\t\t{ typedef typename common_type<typename common_type<T, U>::type, V...>::type type; };\n\n\n\t// common_type_t is the C++14 using typedef for typename common_type<T...>::type.\n\t// We provide a backwards-compatible means to access it through a macro for pre-C++11 compilers.\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t#define EASTL_COMMON_TYPE_T(...) typename common_type<__VA_ARGS__>::type\n\t#else\n\t\ttemplate <typename... T>\n\t\tusing common_type_t = typename common_type<T...>::type;\n\t\t#define EASTL_COMMON_TYPE_T(...) common_type_t<__VA_ARGS__>\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_final\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_IS_FINAL_AVAILABLE == 1\n\t\ttemplate <typename T>\n\t\tstruct is_final : public integral_constant<bool, __is_final(T)> {};\n\t#else\n\t\t// no compiler support so we always return false\n\t\ttemplate <typename T>\n\t\tstruct is_final : public false_type {};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_final_v = is_final<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_aggregate\n\t//\n\t// https://en.cppreference.com/w/cpp/language/aggregate_initialization\n\t//\n\t// An aggregate is one of the following types:\n\t// * array type\n\t// * class type (typically, struct or union), that has\n\t//     * no private or protected non-static data members\n\t//     * no user-provided constructors (explicitly defaulted or deleted constructors are allowed)\n\t//     * no user-provided, inherited, or explicit constructors \n\t//         * (explicitly defaulted or deleted constructors are allowed)\n\t//     * no virtual, private, or protected (since C++17) base classes\n\t//     * no virtual member functions\n\t//     * no default member initializers\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_IS_AGGREGATE_AVAILABLE == 1\n\t\t#define EASTL_TYPE_TRAIT_is_aggregate_CONFORMANCE 1  \n\n\t\ttemplate <typename T>\n\t\tstruct is_aggregate : public integral_constant<bool, __is_aggregate(T)> {};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_aggregate_CONFORMANCE 0 \n\n\t\t// no compiler support so we always return false\n\t\ttemplate <typename T>\n\t\tstruct is_aggregate : public false_type {};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <typename T>\n\t\tEA_CONSTEXPR bool is_aggregate_v = is_aggregate<T>::value;\n\t#endif\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/type_detected.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_TYPE_DETECTED_H\n#define EASTL_INTERNAL_TYPE_DETECTED_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n#pragma once\n#endif\n\n#include <EASTL/type_traits.h>\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////\n\t// nonesuch\n\t//\n\t// Type given as a result from detected_t if the supplied arguments does not respect the constraint.\n\t//\n\t// https://en.cppreference.com/w/cpp/experimental/nonesuch\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\tstruct nonesuch\n\t{\n\t\t~nonesuch() = delete;\n\t\tnonesuch(nonesuch const&) = delete;\n\t\tvoid operator=(nonesuch const&) = delete;\n\t};\n\n\tnamespace internal\n\t{\n\t\ttemplate <class Default, class AlwaysVoid, template <class...> class Op, class... Args>\n\t\tstruct detector\n\t\t{\n\t\t\tusing type = Default;\n\t\t\tusing value_t = false_type;\n\t\t};\n\n\t\ttemplate <class Default, template <class...> class Op, class... Args>\n\t\tstruct detector<Default, void_t<Op<Args...>>, Op, Args...>\n\t\t{\n\t\t\tusing type = Op<Args...>;\n\t\t\tusing value_t = true_type;\n\t\t};\n\t} // namespace internal\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_detected\n\t//\n\t// Checks if some supplied arguments (Args) respect a constraint (Op).\n\t// is_detected expands to true_type if the arguments respect the constraint, false_type otherwise.\n\t// This helper is convenient to use for compile time introspection.\n\t//\n\t// https://en.cppreference.com/w/cpp/experimental/is_detected\n\t//\n\t// Example:\n\t// template <class T, class U>\n\t// using detect_can_use_addition_operator = decltype(declval<T>() + declval<U>());\n\t//\n\t// template <class T, class U>\n\t// void sum(const T& t, const U& u)\n\t// {\n\t// \t    static_assert(is_detected<detect_can_use_addition_operator, T, U>::value, \"Supplied types cannot be summedtogether.\");\n\t//      // or...\n\t// \t    static_assert(is_detected_v<detect_can_use_addition_operator, T, U>, \"Supplied types cannot be summedtogether.\");\n\t//      return t + u;\n\t// }\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <template <class...> class Op, class... Args>\n\tusing is_detected = typename internal::detector<nonesuch, void, Op, Args...>::value_t;\n\n#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\ttemplate <template <class...> class Op, class... Args>\n\tEA_CONSTEXPR bool is_detected_v = is_detected<Op, Args...>::value;\n#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// detected_t\n\t//\n\t// Check which type we obtain after expanding some arguments (Args) over a constraint (Op).\n\t// If the constraint cannot be applied, the result type will be nonesuch.\n\t//\n\t// https://en.cppreference.com/w/cpp/experimental/is_detected\n\t//\n\t// Example:\n\t// template <class T, class U>\n\t// using detect_can_use_addition_operator = decltype(declval<T>() + declval<U>());\n\t//\n\t// using result_type = detected_t<detect_can_use_addition_operator, int, int>;\n\t// // result_type == int\n\t// using failed_result_type = detected_t<detect_can_use_addition_operator, int, string>;\n\t// // failed_result_type == nonesuch\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <template <class...> class Op, class... Args>\n\tusing detected_t = typename internal::detector<nonesuch, void, Op, Args...>::type;\n\n\t///////////////////////////////////////////////////////////////////////\n\t// detected_or\n\t//\n\t// Checks if some supplied arguments (Args) respect a constraint (Op).\n\t// Expand to a struct that contains two type aliases:\n\t// - type: the type we obtain after expanding some arguments (Args) over a constraint (Op).\n\t// If the constraint cannot be applied, the result type will be the suplied Default type.\n\t// - value_t: true_type if the arguments respect the constraint, false_type otherwise.\n\t//\n\t// https://en.cppreference.com/w/cpp/experimental/is_detected\n\t//\n\t// Example:\n\t// template <class T, class U>\n\t// using detected_calling_foo = decltype(declval<T>().foo());\n\t//\n\t// using result = detected_or<bool, detected_calling_foo, std::string>; // std::string doesn't have foo member.\n\t// function.\n\t// // result::type == bool\n\t// // result::value_t == false_type\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class Default, template <class...> class Op, class... Args>\n\tusing detected_or = internal::detector<Default, void, Op, Args...>;\n\n\t///////////////////////////////////////////////////////////////////////\n\t// detected_or_t\n\t//\n\t// Equivalent to detected_or<Default, Op, Args...>::type.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class Default, template <class...> class Op, class... Args>\n\tusing detected_or_t = typename detected_or<Default, Op, Args...>::type;\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_detected_exact\n\t//\n\t// Check that the type we obtain after expanding some arguments (Args) over a constraint (Op) is equivalent to\n\t// Expected.\n\t//\n\t// template <class T, class U>\n\t// using detected_calling_size = decltype(declval<T>().size());\n\t//\n\t// using result = is_detected_exact<int, detected_calling_size, std::string>;\n\t// result == false_type // std::string::size returns eastl_size_t which is not the same as int.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class Expected, template <class...> class Op, class... Args>\n\tusing is_detected_exact = is_same<Expected, detected_t<Op, Args...>>;\n\n#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\ttemplate <class Expected, template <class...> class Op, class... Args>\n\tEA_CONSTEXPR bool is_detected_exact_v = is_detected_exact<Expected, Op, Args...>::value;\n#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_detected_convertible\n\t//\n\t// Check that the type we obtain after expanding some arguments (Args) over a constraint (Op) is convertible to\n\t// Expected.\n\t//\n\t// template <class T, class U>\n\t// using detected_calling_size = decltype(declval<T>().size());\n\t//\n\t// using result = is_detected_convertible<int, detected_calling_size, std::string>;\n\t// result == true_type // std::string::size returns eastl_size_t which is convertible to int.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class To, template <class...> class Op, class... Args>\n\tusing is_detected_convertible = is_convertible<detected_t<Op, Args...>, To>;\n\n#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\ttemplate <class To, template <class...> class Op, class... Args>\n\tEA_CONSTEXPR bool is_detected_convertible_v = is_detected_convertible<To, Op, Args...>::value;\n#endif\n\n} // namespace eastl\n\n#endif // EASTL_INTERNAL_TYPE_DETECTED_H"
  },
  {
    "path": "include/EASTL/internal/type_fundamental.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_TYPE_FUNDAMENTAL_H\n#define EASTL_INTERNAL_TYPE_FUNDAMENTAL_H\n\n\n#include <EABase/eabase.h>\n#include <EABase/nullptr.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\nnamespace eastl\n{\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_void\n\t//\n\t// is_void<T>::value == true if and only if T is one of the following types:\n\t//    [const][volatile] void\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_void_CONFORMANCE 1    // is_void is conforming.\n\n\ttemplate <typename T> struct is_void : public false_type{};\n\n\ttemplate <> struct is_void<void>                : public true_type{};\n\ttemplate <> struct is_void<void const>          : public true_type{};\n\ttemplate <> struct is_void<void volatile>       : public true_type{};\n\ttemplate <> struct is_void<void const volatile> : public true_type{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_void_v = is_void<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// has_void_arg\n\t//\n\t// utility which identifies if any of the given template arguments is void.\n\t//\n\t// TODO(rparolin):  refactor with fold expressions when C++17 compilers are widely available.\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename ...Args> \n\tstruct has_void_arg;\n\n\ttemplate <> \n\tstruct has_void_arg<> \n\t\t: public eastl::false_type {};\n\n\ttemplate <typename A0, typename ...Args>\n\tstruct has_void_arg<A0, Args...>\n\t\t{ static const bool value = (eastl::is_void<A0>::value || eastl::has_void_arg<Args...>::value); };\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_null_pointer\n\t//\n\t// C++14 type trait. Refers only to nullptr_t and not NULL (0).\n\t// eastl::is_null_pointer<nullptr>::value == true\n\t// eastl::is_null_pointer<std::nullptr_t>::value == true\n\t// eastl::is_null_pointer<void*>::value == false\n\t// eastl::is_null_pointer<NULL>::value == [cannot compile]\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if defined(EA_COMPILER_CPP11_ENABLED) && !defined(EA_COMPILER_NO_DECLTYPE) && !defined(_MSC_VER) // VC++'s handling of decltype(nullptr) is broken.\n\t\t#define EASTL_TYPE_TRAIT_is_null_pointer_CONFORMANCE 1\n\n\t\ttemplate <typename T> \n\t\tstruct is_null_pointer : public eastl::is_same<typename eastl::remove_cv<T>::type, decltype(nullptr)> {}; // A C++11 compiler defines nullptr, but you need a C++11 standard library to declare std::nullptr_t. So it's safer to compare against decltype(nullptr) than to use std::nullptr_t, because we may have a C++11 compiler but C++98 library (happens with Apple frequently).\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_null_pointer_CONFORMANCE 1\n\n\t\ttemplate <typename T> \n\t\tstruct is_null_pointer : public eastl::is_same<typename eastl::remove_cv<T>::type, std::nullptr_t> {};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_null_pointer_v = is_null_pointer<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_integral\n\t//\n\t// is_integral<T>::value == true if and only if T  is one of the following types:\n\t//    [const] [volatile] bool\n\t//    [const] [volatile] char\n\t//    [const] [volatile] signed char\n\t//    [const] [volatile] unsigned char\n\t//    [const] [volatile] wchar_t\n\t//    [const] [volatile] short\n\t//    [const] [volatile] int\n\t//    [const] [volatile] long\n\t//    [const] [volatile] long long\n\t//    [const] [volatile] unsigned short\n\t//    [const] [volatile] unsigned int\n\t//    [const] [volatile] unsigned long\n\t//    [const] [volatile] unsigned long long\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_integral_CONFORMANCE 1    // is_integral is conforming.\n\n\ttemplate <typename T> struct is_integral_helper           : public false_type{};\n\n\ttemplate <> struct is_integral_helper<unsigned char>      : public true_type{};\n\ttemplate <> struct is_integral_helper<unsigned short>     : public true_type{};\n\ttemplate <> struct is_integral_helper<unsigned int>       : public true_type{};\n\ttemplate <> struct is_integral_helper<unsigned long>      : public true_type{};\n\ttemplate <> struct is_integral_helper<unsigned long long> : public true_type{};\n\n\ttemplate <> struct is_integral_helper<signed char>        : public true_type{};\n\ttemplate <> struct is_integral_helper<signed short>       : public true_type{};\n\ttemplate <> struct is_integral_helper<signed int>         : public true_type{};\n\ttemplate <> struct is_integral_helper<signed long>        : public true_type{};\n\ttemplate <> struct is_integral_helper<signed long long>   : public true_type{};\n\n\ttemplate <> struct is_integral_helper<bool>               : public true_type{};\n\ttemplate <> struct is_integral_helper<char>               : public true_type{};\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\t\ttemplate <> struct is_integral_helper<char8_t>        : public true_type{};\n\t#endif\n\t#if defined(EA_CHAR16_NATIVE) && EA_CHAR16_NATIVE\n\t\ttemplate <> struct is_integral_helper<char16_t>       : public true_type{};\n\t#endif\n\t#if defined(EA_CHAR32_NATIVE) && EA_CHAR32_NATIVE\n\t\ttemplate <> struct is_integral_helper<char32_t>       : public true_type{};\n\t#endif\n\t#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type which is already handled above...\n\t\ttemplate <> struct is_integral_helper<wchar_t>        : public true_type{};\n\t#endif\n\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\ttemplate <> struct is_integral_helper<__int128_t>     : public true_type{};\n\t\ttemplate <> struct is_integral_helper<__uint128_t>    : public true_type{};\n\t#endif\n\n\ttemplate <typename T>\n\tstruct is_integral : public eastl::is_integral_helper<typename eastl::remove_cv<T>::type>{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_integral_v = is_integral<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_floating_point\n\t//\n\t// is_floating_point<T>::value == true if and only if T is one of the following types:\n\t//    [const] [volatile] float\n\t//    [const] [volatile] double\n\t//    [const] [volatile] long double\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_floating_point_CONFORMANCE 1    // is_floating_point is conforming.\n\n\ttemplate <typename T> struct is_floating_point_helper    : public false_type{};\n\n\ttemplate <> struct is_floating_point_helper<float>       : public true_type{};\n\ttemplate <> struct is_floating_point_helper<double>      : public true_type{};\n\ttemplate <> struct is_floating_point_helper<long double> : public true_type{};\n\n\ttemplate <typename T>\n\tstruct is_floating_point : public eastl::is_floating_point_helper<typename eastl::remove_cv<T>::type>{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_floating_point_v = is_floating_point<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_arithmetic\n\t//\n\t// is_arithmetic<T>::value == true if and only if:\n\t//    is_floating_point<T>::value == true, or\n\t//    is_integral<T>::value == true\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_arithmetic_CONFORMANCE 1    // is_arithmetic is conforming.\n\n\ttemplate <typename T>\n\tstruct is_arithmetic \n\t\t: public integral_constant<bool, is_integral<T>::value || is_floating_point<T>::value> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_arithmetic_v = is_arithmetic<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_fundamental\n\t//\n\t// is_fundamental<T>::value == true if and only if:\n\t//    is_floating_point<T>::value == true, or\n\t//    is_integral<T>::value == true, or\n\t//    is_void<T>::value == true\n\t//    is_null_pointer<T>::value == true\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_fundamental_CONFORMANCE 1    // is_fundamental is conforming.\n\n\ttemplate <typename T>\n\tstruct is_fundamental\n\t\t: public bool_constant<is_void_v<T> || is_integral_v<T> || is_floating_point_v<T> || is_null_pointer_v<T>> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_fundamental_v = is_fundamental<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_hat_type\n\t//\n\t// is_hat_type<T>::value == true if and only if:\n\t//    underlying type is a C++/CX '^' type such as: Foo^\n\t//\t  meaning the type is heap allocated and ref-counted\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T> struct is_hat_type_helper : public false_type {};\n\n\t#if (EABASE_VERSION_N > 20607 && defined(EA_COMPILER_WINRTCX_ENABLED)) || defined(__cplusplus_winrt)\n\t\ttemplate <typename T> struct is_hat_type_helper<T^> : public true_type{};\n\t#endif \n\n\ttemplate <typename T>\n\tstruct is_hat_type : public eastl::is_hat_type_helper<T> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_hat_type_v = is_hat_type<T>::value;\n\t#endif\n\n\t\t\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_enum\n\t//\n\t// is_enum<T>::value == true if and only if T is an enumeration type.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_enum)))\n\t\t#define EASTL_TYPE_TRAIT_is_enum_CONFORMANCE 1     // is_enum is conforming. \n\n\t\ttemplate <typename T> \n\t\tstruct is_enum : public integral_constant<bool, __is_enum(T)>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_enum_CONFORMANCE 1    // is_enum is conforming.\n\n\t\tstruct int_convertible{ int_convertible(int); };\n\n\t\ttemplate <bool is_arithmetic_or_reference>\n\t\tstruct is_enum_helper { template <typename T> struct nest : public is_convertible<T, int_convertible>{}; };\n\n\t\ttemplate <>\n\t\tstruct is_enum_helper<true> { template <typename T> struct nest : public false_type {}; };\n\n\t\ttemplate <typename T>\n\t\tstruct is_enum_helper2\n\t\t{\n\t\t\ttypedef disjunction<is_arithmetic<T>, is_reference<T>, is_class<T>> selector;\n\t\t\ttypedef is_enum_helper<selector::value> helper_t;\n\t\t\ttypedef typename add_lvalue_reference<T>::type ref_t;\n\t\t\ttypedef typename helper_t::template nest<ref_t> result;\n\t\t};\n\n\t\ttemplate <typename T> \n\t\tstruct is_enum : public integral_constant<bool, is_enum_helper2<T>::result::value>{};\n\n\t\ttemplate <> struct is_enum<void> : public false_type {};\n\t\ttemplate <> struct is_enum<void const> : public false_type {};\n\t\ttemplate <> struct is_enum<void volatile> : public false_type {};\n\t\ttemplate <> struct is_enum<void const volatile> : public false_type {};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_enum_v = is_enum<T>::value;\n\t#endif\n\n\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/type_pod.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n// Implementation Notes:\n// The compiler builtins (Clang terminology) and intrinsics (MSVC terminology) are documented here (as of 2023):\n//\tClang:\n//\t\thttps://clang.llvm.org/docs/LanguageExtensions.html#type-trait-primitives\n//\tGCC:\n//\t\thttps://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Type-Traits.html#Type-Traits\n//\tMSVC (no actual documentation, but searchable here):\n//\t\thttps://github.com/microsoft/STL/blob/main/stl/inc/type_traits\n\n#ifndef EASTL_INTERNAL_TYPE_POD_H\n#define EASTL_INTERNAL_TYPE_POD_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <limits.h>\n#include <EASTL/type_traits.h>\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////\n\t// is_empty\n\t//\n\t// is_empty<T>::value == true if and only if T is an empty class or struct.\n\t// is_empty may only be applied to complete types.\n\t//\n\t// is_empty cannot be used with union types until is_union can be made to work.\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_empty)))\n\t\t#define EASTL_TYPE_TRAIT_is_empty_CONFORMANCE 1    // is_empty is conforming.\n\n\t\ttemplate <typename T>\n\t\tstruct is_empty : public integral_constant<bool, __is_empty(T)>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_empty_CONFORMANCE 1    // is_empty is fully conforming.\n\n\t\ttemplate <typename T>\n\t\tstruct is_empty_helper_t1 : public T { char m[64]; };\n\t\tstruct is_empty_helper_t2            { char m[64]; };\n\n\t\t// The inheritance in empty_helper_t1 will not work with non-class types\n\t\ttemplate <typename T, bool is_a_class = false>\n\t\tstruct is_empty_helper : public eastl::false_type{};\n\n\t\ttemplate <typename T>\n\t\tstruct is_empty_helper<T, true> : public eastl::integral_constant<bool,\n\t\t\tsizeof(is_empty_helper_t1<T>) == sizeof(is_empty_helper_t2)\n\t\t>{};\n\n\t\ttemplate <typename T>\n\t\tstruct is_empty_helper2\n\t\t{\n\t\t\ttypedef typename eastl::remove_cv<T>::type _T;\n\t\t\ttypedef eastl::is_empty_helper<_T, eastl::is_class<_T>::value> type;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct is_empty : public eastl::is_empty_helper2<T>::type {};\n\t#endif\n\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_empty_v = is_empty<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_pod\n\t//\n\t// is_pod<T>::value == true if and only if, for a given type T:\n\t//    - is_scalar<T>::value == true, or\n\t//    - T is a class or struct that has no user-defined copy assignment\n\t//      operator or destructor, and T has no non-static data members M for\n\t//      which is_pod<M>::value == false, and no members of reference type, or\n\t//    - T is the type of an array of objects E for which is_pod<E>::value == true\n\t//\n\t// is_pod may only be applied to complete types.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if defined(EA_COMPILER_MSVC) && !defined(EA_COMPILER_CLANG_CL)\n\t\t#define EASTL_TYPE_TRAIT_is_pod_CONFORMANCE 1    // is_pod is conforming. Actually as of VS2008 it is apparently not fully conforming, as it flags the following as a non-pod: struct Pod{ Pod(){} };\n\n\t\tEA_DISABLE_VC_WARNING(4647)\n\t\ttemplate <typename T> // We check for __has_trivial_constructor (which should be equivalent to is_trivially_default_constructible) only because the VC++ is_pod does. Is it due to some compiler bug?\n\t\tstruct is_pod : public eastl::integral_constant<bool, (__has_trivial_constructor(T) && __is_pod(T) && !eastl::is_hat_type<T>::value) || eastl::is_void<T>::value || eastl::is_scalar<T>::value>{};\n\t\tEA_RESTORE_VC_WARNING()\n\n\t#elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(EA_COMPILER_GNUC) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_pod)))\n\t\t#define EASTL_TYPE_TRAIT_is_pod_CONFORMANCE 1    // is_pod is conforming.\n\n\t\ttemplate <typename T>\n\t\tstruct is_pod : public eastl::integral_constant<bool, __is_pod(T) || eastl::is_void<T>::value || eastl::is_scalar<T>::value>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_pod_CONFORMANCE 0    // is_pod is not conforming. Can return false negatives.\n\n\t\ttemplate <typename T> // There's not much we can do here without some compiler extension.\n\t\tstruct is_pod : public eastl::integral_constant<bool, eastl::is_void<T>::value || eastl::is_scalar<typename eastl::remove_all_extents<T>::type>::value>{};\n\t#endif\n\n\ttemplate <typename T, size_t N>\n\tstruct is_pod<T[N]> : public is_pod<T>{};\n\n\ttemplate <typename T>\n\tstruct is_POD : public is_pod<T>{};  // Backwards compatibility.\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_pod_v = is_pod<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_standard_layout\n\t//\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && ((defined(EA_COMPILER_MSVC) && (_MSC_VER >= 1700)) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006)) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_standard_layout)))\n\t\t#define EASTL_TYPE_TRAIT_is_standard_layout_CONFORMANCE 1    // is_standard_layout is conforming.\n\n\t\ttemplate <typename T>\n\t\tstruct is_standard_layout : public eastl::integral_constant<bool, __is_standard_layout(T) || eastl::is_void<T>::value || eastl::is_scalar<T>::value>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_standard_layout_CONFORMANCE 0    // is_standard_layout is not conforming. Can return false negatives.\n\n\t\ttemplate <typename T> // There's not much we can do here without some compiler extension.\n\t\tstruct is_standard_layout : public eastl::integral_constant<bool, is_void<T>::value || is_scalar<T>::value>{};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_standard_layout_v = is_standard_layout<T>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// has_virtual_destructor\n\t//\n\t// has_virtual_destructor<T>::value == true if and only if T is a class\n\t// or struct with a virtual destructor.\n\t//\n\t// has_virtual_destructor may only be applied to complete types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || defined(__clang__))\n\t\t#define EASTL_TYPE_TRAIT_has_virtual_destructor_CONFORMANCE 1\n\n\t\ttemplate <typename T>\n\t\tstruct has_virtual_destructor : public eastl::integral_constant<bool, __has_virtual_destructor(T)>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_has_virtual_destructor_CONFORMANCE 0   // has_virtual_destructor is not fully conforming. Can return false negatives.\n\n\t\ttemplate <typename T>\n\t\tstruct has_virtual_destructor : public eastl::false_type{};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool has_virtual_destructor_v = has_virtual_destructor<T>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_abstract\n\t//\n\t// is_abstract<T>::value == true if and only if T is a class or struct\n\t// that has at least one pure virtual function. is_abstract may only\n\t// be applied to complete types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_abstract)))\n\t\t#define EASTL_TYPE_TRAIT_is_abstract_CONFORMANCE 1    // is_abstract is conforming.\n\n\t\ttemplate <typename T>\n\t\tstruct is_abstract : public integral_constant<bool, __is_abstract(T)>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_abstract_CONFORMANCE 0\n\n\t\ttemplate<typename T, bool = !eastl::is_object<T>::value>\n\t\tclass is_abstract_helper\n\t\t{\n\t\t\ttemplate<typename>\n\t\t\tstatic eastl::yes_type test(...);\n\n\t\t\ttemplate<typename T1>\n\t\t\tstatic eastl::no_type test(T1(*)[1]);  // The following: 'typedef SomeAbstractClass (*SomeFunctionType)[1];' is invalid (can't have an array of abstract types) and thus doesn't choose this path.\n\n\t\tpublic:\n\t\t\tstatic const bool value = (sizeof(test<T>(NULL)) == sizeof(eastl::yes_type));\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct is_abstract_helper<T, true>\n\t\t\t{ static const bool value = false; };\n\n\t\ttemplate <typename T>\n\t\tstruct is_abstract\n\t\t\t: public integral_constant<bool, is_abstract_helper<T>::value> { };\n\n\t#endif\n\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_abstract_v = is_abstract<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_copyable\n\t//\n\t// T is a trivially copyable type (3.9) T shall be a complete type,\n\t// (possibly cv-qualified) void, or an array of unknown bound.\n\t//\n\t// 3.9,p3: For any trivially copyable type T, if two pointers to T\n\t// point to distinct T objects obj1 and obj2, where neither obj1 nor\n\t// obj2 is a base-class subobject, if the underlying bytes making\n\t// up obj1 are copied into obj2, obj2 shall subsequently hold the\n\t// same value as obj1. In other words, you can memcpy/memmove it.\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && ((defined(_MSC_VER) && (_MSC_VER >= 1700)) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 5003)) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_trivially_copyable)))\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_copyable_CONFORMANCE 1\n\n\t\t// https://connect.microsoft.com/VisualStudio/feedback/details/808827/c-std-is-trivially-copyable-produces-wrong-result-for-arrays\n\t\t//\n\t\t// From Microsoft:\n\t\t//   We're working on fixing this. When overhauling <type_traits> in VC 2013, I incorrectly believed that is_trivially_copyable was a synonym\n\t\t//   for is_trivially_copy_constructible. I've asked the compiler team to provide a compiler hook with 100% accurate answers. (Currently, the\n\t\t//   compiler hook has incorrect answers for volatile scalars, volatile data members, and various scenarios for defaulted/deleted/private\n\t\t//   special member functions - I wrote an exhaustive test case to exercise the complicated Standardese.) When the compiler hook is fixed,\n\t\t//   I'll change <type_traits> to invoke it.\n\t\t//\n\t\t// Microsoft broken VS2013 STL implementation:\n\t\t//   template<class _Ty>\n\t\t//   struct is_trivially_copyable\n\t\t//       : is_trivially_copy_constructible<_Ty>::type\n\t\t//   {   // determine whether _Ty has a trivial copy constructor\n\t\t//   };\n\t\t//\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_copyable : public bool_constant<__is_trivially_copyable(T)> {};\n\n\t#elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_GNUC))\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_copyable_CONFORMANCE 1\n\n\t\t// Micrsoft (prior to VS2012) and GCC have __has_trivial_copy, but it may not be identical with the goals of this type trait.\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_copyable : public integral_constant<bool, (__has_trivial_copy(T) || eastl::is_pod<typename eastl::remove_all_extents<T>::type>::value) && (!eastl::is_void<T>::value && !eastl::is_volatile<T>::value && !eastl::is_reference<T>::value)>{};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_copyable_CONFORMANCE 0  // Generates false negatives.\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_copyable { static const bool value = eastl::is_scalar<typename eastl::remove_all_extents<T>::type>::value; };\n\t#endif\n\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_copyable_v = is_trivially_copyable<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_constructible\n\t//\n\t// See the C++11 Standard, section 20.9.4.3,p6.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_constructible_CONFORMANCE 1\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_constructible)) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >  8001)))\n\t\ttemplate<typename T, typename... Args>\n\t\tstruct is_constructible : public bool_constant<__is_constructible(T, Args...) > {};\n\t#else\n\t\t// We implement a copy of move here has move_internal. We are currently stuck doing this because our move\n\t\t// implementation is in <utility.h> and <utility.h> currently #includes us, and so we have a header\n\t\t// chicken-and-egg problem. To do: Resolve this, probably by putting eastl::move somewhere else.\n\t\ttemplate <typename T>\n\t\tinline typename eastl::remove_reference<T>::type&& move_internal(T&& x) EA_NOEXCEPT\n\t\t{ return ((typename eastl::remove_reference<T>::type&&)x); }\n\n\t\ttemplate <typename T, class ...Args>\n\t\ttypename first_type_select<eastl::true_type, decltype(eastl::move_internal(T(eastl::declval<Args>()...)))>::type is(T&&, Args&& ...);\n\n\t\ttemplate <typename T>\n\t\tstruct can_construct_scalar_helper\n\t\t{\n\t\t\tstatic eastl::true_type can(T);\n\t\t\tstatic eastl::false_type can(...);\n\t\t};\n\n\t\ttemplate <typename ...Args>\n\t\teastl::false_type is(argument_sink, Args&& ...);\n\n\t\t// Except for scalars and references (handled below), check for constructibility via decltype.\n\t\ttemplate <bool, typename T, typename... Args>\n\t\tstruct is_constructible_helper_2    // argument_sink will catch all T that is not constructible from the Args and denote false_type\n\t\t\t: public eastl::type_identity<decltype(is(eastl::declval<T>(), eastl::declval<Args>()...))>::type {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_constructible_helper_2<true, T>\n\t\t\t: public eastl::is_scalar<T> {};\n\n\t\ttemplate <typename T, typename Arg0> // We handle the case of multiple arguments below (by disallowing them).\n\t\tstruct is_constructible_helper_2<true, T, Arg0>\n\t\t\t: public eastl::type_identity<decltype(can_construct_scalar_helper<T>::can(eastl::declval<Arg0>()))>::type {};\n\n\t\t// Scalars and references can be constructed only with 0 or 1 argument. e.g the following is an invalid expression: int(17, 23)\n\t\ttemplate <typename T, typename Arg0, typename ...Args>\n\t\tstruct is_constructible_helper_2<true, T, Arg0, Args...>\n\t\t\t: public eastl::false_type {};\n\n\t\ttemplate <bool, typename T, typename... Args>\n\t\tstruct is_constructible_helper_1\n\t\t\t: public is_constructible_helper_2<eastl::is_scalar<T>::value || eastl::is_reference<T>::value, T, Args...> {};\n\n\t\t// Unilaterally dismiss void, abstract, unknown bound arrays, and function types as not constructible.\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_constructible_helper_1<true, T, Args...>\n\t\t\t: public false_type {};\n\n\t\t// is_constructible\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_constructible\n\t\t\t: public is_constructible_helper_1<(eastl::is_abstract<typename eastl::remove_all_extents<T>::type>::value ||\n\t\t\t\t\t\t\t\t\t\t\t\teastl::is_unbounded_array<T>::value\t\t\t\t\t\t\t\t\t   ||\n\t\t\t\t\t\t\t\t\t\t\t\teastl::is_function<typename eastl::remove_all_extents<T>::type>::value ||\n\t\t\t\t\t\t\t\t\t\t\t\teastl::has_void_arg<T, Args...>::value),\n\t\t\t\t\t\t\t\t\t\t\t\tT, Args...> {};\n\n\t\t// Array types are constructible if constructed with no arguments and if their element type is default-constructible\n\t\ttemplate <typename Array, size_t N>\n\t\tstruct is_constructible_helper_2<false, Array[N]>\n\t\t\t: public eastl::is_constructible<typename eastl::remove_all_extents<Array>::type> {};\n\n\t\t// Arrays with arguments are not constructible. e.g. the following is an invalid expression: int[3](37, 34, 12)\n\t\ttemplate <typename Array, size_t N, typename ...Args>\n\t\tstruct is_constructible_helper_2<false, Array[N], Args...>\n\t\t\t: public eastl::false_type {};\n\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T, class... Args>\n\t\tEA_CONSTEXPR bool is_constructible_v = is_constructible<T, Args...>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_constructible\n\t//\n\t// is_constructible<T, Args...>::value is true and the variable definition\n\t// for is_constructible, as defined below, is known to call no operation\n\t// that is not trivial (3.9, 12). T and all types in the parameter pack\n\t// Args shall be complete types, (possibly cv-qualified) void, or arrays\n\t// of unknown bound.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if defined(EA_COMPILER_NO_VARIADIC_TEMPLATES)\n\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE 0\n\n\t\t// In this version we allow only zero or one argument (Arg). We can add more arguments\n\t\t// by creating a number of extra specializations. It's probably not possible to\n\t\t// simplify the implementation with recursive templates because ctor argument\n\t\t// presence is specific.\n\t\t//\n\t\t// To consider: we can fold the two implementations below by making a macro that's defined\n\t\t// as __is_trivially_constructible(T) or eastl::is_trivially_copy_constructible<T>::value, depending on\n\t\t// whether the __is_trivially_constructible compiler intrinsic is available.\n\n\t\t// If the compiler has this trait built-in (which ideally all compilers would have since it's necessary for full conformance) use it.\n\t\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && ((defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_trivially_constructible)) || defined(EA_COMPILER_MSVC))\n\n\t\t\ttemplate <typename T, typename Arg0 = eastl::unused>\n\t\t\tstruct is_trivially_constructible\n\t\t\t\t: public eastl::false_type {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, eastl::unused>\n\t\t\t\t: public eastl::integral_constant<bool, __is_trivially_constructible(T)> {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, T>\n\t\t\t\t: public eastl::integral_constant<bool, __is_trivially_constructible(T)> {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, T&>\n\t\t\t\t: public eastl::integral_constant<bool, __is_trivially_constructible(T)> {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, const T&>\n\t\t\t\t: public eastl::integral_constant<bool, __is_trivially_constructible(T)> {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, volatile T&>\n\t\t\t\t: public eastl::integral_constant<bool, __is_trivially_constructible(T)> {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, const volatile T&>\n\t\t\t\t: public eastl::integral_constant<bool, __is_trivially_constructible(T)> {};\n\n\t\t#else\n\n\t\t\ttemplate <typename T, typename Arg0 = eastl::unused>\n\t\t\tstruct is_trivially_constructible\n\t\t\t\t: public eastl::false_type {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, eastl::unused>\n\t\t\t\t: public eastl::false_type {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, T>\n\t\t\t\t: public eastl::false_type {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, T&>\n\t\t\t\t: public eastl::false_type {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, const T&>\n\t\t\t\t: public eastl::false_type {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, volatile T&>\n\t\t\t\t: public eastl::false_type {};\n\n\t\t\ttemplate <typename T>\n\t\t\tstruct is_trivially_constructible<T, const volatile T&>\n\t\t\t\t: public eastl::false_type {};\n\n\t\t#endif\n\n\t#else\n\n\t\t// If the compiler has this trait built-in (which ideally all compilers would have since it's necessary for full conformance) use it.\n\t\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && ((EASTL_HAS_INTRINSIC(is_trivially_constructible)) || defined(EA_COMPILER_MSVC))\n\t\t\t#define EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE 1\n\n\t\t\t// We have a problem with clang here as of clang 3.4: __is_trivially_constructible(int[]) is false, yet I believe it should be true.\n\t\t\t// Until it gets resolved, what we do is check for is_constructible along with __is_trivially_constructible().\n\t\t\ttemplate <typename T, typename... Args>\n\t\t\tstruct is_trivially_constructible\n\t\t\t\t: public eastl::integral_constant<bool, eastl::is_constructible<T, Args...>::value && __is_trivially_constructible(T, Args...)> {};\n\n\t\t#else\n\n\t\t\t#define EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE 0   // This is 0 but in fact it will work for most real-world cases due to the is_trivially_default_constructible specialization below.\n\n\t\t\ttemplate <typename T, typename... Args>\n\t\t\tstruct is_trivially_constructible\n\t\t\t\t: public eastl::false_type {};\n\n\t\t#endif\n\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_constructible_v = is_trivially_constructible<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_default_constructible\n\t//\n\t// is_trivially_constructible<T>::value is true.\n\t// This is thus identical to is_trivially_constructible<T>::value.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_trivially_default_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_trivially_default_constructible\n\t\t: public eastl::is_trivially_constructible<T> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_default_constructible_v = is_trivially_default_constructible<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivial\n\t//\n\t// is_trivial<T>::value == true if T is a scalar type, a trivially copyable\n\t// class with a trivial default constructor, or array of such type/class,\n\t// possibly cv-qualified), provides the member constant value equal true.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_trivial_CONFORMANCE ((EASTL_TYPE_TRAIT_is_trivially_default_constructible_CONFORMANCE && EASTL_TYPE_TRAIT_is_trivially_copyable_CONFORMANCE) ? 1 : 0)\n\n\t#if defined(_MSC_VER) && _MSC_VER == 1800\n\t\ttemplate<bool, typename T>\n\t\tstruct is_trivial_helper\n\t\t\t: public eastl::integral_constant<bool, eastl::is_trivially_copyable<T>::value && eastl::is_trivially_default_constructible<T>::value>{};\n\n\t\ttemplate<typename T>\n\t\tstruct is_trivial_helper<true, T>\n\t\t\t: public false_type{};\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivial\n\t\t\t: public is_trivial_helper<(EA_ALIGN_OF(T) > EA_PLATFORM_MIN_MALLOC_ALIGNMENT), T>::type{};\n\t#else\n\t\t// All other compilers seem to be able to handle aligned types passed as value\n\t\ttemplate <typename T>\n\t\tstruct is_trivial\n\t\t\t: public eastl::integral_constant<bool, eastl::is_trivially_copyable<T>::value && eastl::is_trivially_default_constructible<T>::value> {};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivial_v = is_trivial<T>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_constructible\n\t//\n\t// is_constructible<T, Args...>::value is true and the variable definition\n\t// for is_constructible, as defined below, is known not to throw any\n\t// exceptions (5.3.7). T and all types in the parameter pack Args shall\n\t// be complete types, (possibly cv-qualified) void, or arrays of unknown bound.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 11001)) || (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_nothrow_constructible)))\n\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE 1\n\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_nothrow_constructible : public bool_constant<__is_nothrow_constructible(T, Args...)> {};\n\n\t#elif defined(EA_COMPILER_NO_NOEXCEPT)\n\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE 0\n\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_nothrow_constructible\n\t\t\t: public eastl::false_type {};\n\n\t#else\n\n\t\t#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION < 4008)\n\t\t\t#define EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE 0 // GCC up to v4.7's noexcept is broken and fails to generate true for the case of compiler-generated constructors.\n\t\t#else\n\t\t\t#define EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_constructible_CONFORMANCE\n\t\t#endif\n\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// *_noexcept_wrapper implements a workaround for VS2015 preview.  A standards conforming noexcept operator allows variadic template expansion.\n\t\t// There appears to be an issue with VS2015 preview that prevents variadic template expansion into a noexcept operator that is passed directly\n\t\t// to a template parameter.\n\t\t//\n\t\t// The fix hoists the noexcept expression into a separate struct and caches the result of the expression.  This result is then passed to integral_constant.\n\t\t//\n\t\t// Example code from Clang libc++\n\t\t// template <class _Tp, class... _Args>\n\t\t// struct __libcpp_is_nothrow_constructible<[>is constructible*/true, /*is reference<]false, _Tp, _Args...>\n\t\t//     : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))> { };\n\t\t//\n\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_nothrow_constructible_helper_noexcept_wrapper\n\t\t\t{ static const bool value = noexcept(T(eastl::declval<Args>()...)); };\n\n\t\ttemplate <bool, typename T, typename... Args>\n\t\tstruct is_nothrow_constructible_helper;\n\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_nothrow_constructible_helper<true, T, Args...>\n\t\t\t: public eastl::integral_constant<bool, is_nothrow_constructible_helper_noexcept_wrapper<T, Args...>::value> {};\n\n\t\ttemplate<typename T, typename Arg>\n\t\tstruct is_nothrow_constructible_helper<true, T, Arg>\n\t\t\t: public eastl::integral_constant<bool, noexcept(T(eastl::declval<Arg>()))> {};\n\n\t\ttemplate<typename T>\n\t\tstruct is_nothrow_constructible_helper<true, T>\n\t\t\t: public eastl::integral_constant<bool, noexcept(T())> {};\n\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_nothrow_constructible_helper<false, T, Args...>\n\t\t\t: public eastl::false_type {};\n\n\t\ttemplate <typename T, typename... Args>\n\t\tstruct is_nothrow_constructible\n\t\t\t: public eastl::is_nothrow_constructible_helper<eastl::is_constructible<T, Args...>::value, T, Args...> {};\n\n\t\ttemplate <typename T, size_t N>\n\t\tstruct is_nothrow_constructible<T[N]>\n\t\t\t: public eastl::is_nothrow_constructible_helper<eastl::is_constructible<T>::value, T> {};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T, typename... Args>\n\t\tEA_CONSTEXPR bool is_nothrow_constructible_v = is_nothrow_constructible<T, Args...>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_default_constructible\n\t//\n\t// is_constructible<T>::value is true.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_default_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_default_constructible\n\t\t: public eastl::is_constructible<T> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_default_constructible_v = is_default_constructible<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_copy_constructible\n\t//\n\t// is_constructible<T, const T&>::value is true.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_copy_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_copy_constructible\n\t\t: public eastl::is_constructible<T, typename eastl::add_lvalue_reference<typename eastl::add_const<T>::type>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_copy_constructible_v = is_copy_constructible<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_copy_constructible\n\t//\n\t// is_trivially_constructible<T, const T&>::value is true.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_trivially_copy_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_trivially_copy_constructible\n\t\t: public eastl::is_trivially_constructible<T, typename eastl::add_lvalue_reference<typename eastl::add_const<T>::type>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_copy_constructible\n\t//\n\t// is_nothrow_-constructible<T, const T&>::value is true.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_nothrow_copy_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_nothrow_copy_constructible\n\t\t: public is_nothrow_constructible<T, typename eastl::add_lvalue_reference<typename eastl::add_const<T>::type>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_move_constructible\n\t//\n\t// is_constructible<T, T&&>::value is true.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_move_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_move_constructible\n\t\t: public eastl::is_constructible<T, typename eastl::add_rvalue_reference<T>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_move_constructible_v = is_move_constructible<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_move_constructible\n\t//\n\t// is_trivially_constructible<T, T&&>::value is true.\n\t// T shall be a complete type, (possibly cv-qualified) void, or an\n\t// array of unknown bound.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_trivially_move_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_trivially_move_constructible\n\t\t: public eastl::is_trivially_constructible<T, typename eastl::add_rvalue_reference<T>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_move_constructible_v = is_trivially_move_constructible<T>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_assignable\n\t//\n\t// The expression declval<T>() = declval<U>() is well-formed when treated as an unevaluated operand.\n\t// Access checking is performed as if in a context unrelated to T and U. Only the validity of\n\t// the immediate context of the assignment expression is considered. The compilation of the expression\n\t// can result in side effects such as the instantiation of class template specializations and function\n\t// template specializations, the generation of implicitly-defined functions, and so on. Such side\n\t// effects are not in the \"immediate context\" and can result in the program being ill-formed.\n\t//\n\t// Note:\n\t// This type trait has a misleading and counter-intuitive name. It does not indicate whether an instance\n\t// of U can be assigned to an instance of T (e.g. t = u). Instead it indicates whether the assignment can be\n\t// done after adding rvalue references to both, as in add_rvalue_reference<T>::type = add_rvalue_reference<U>::type.\n\t// A counterintuitive result of this is that is_assignable<int, int>::value == false. The is_copy_assignable\n\t// trait indicates if a type can be assigned to its own type, though there isn't a standard C++ way to tell\n\t// if an arbitrary type is assignable to another type.\n\t// http://stackoverflow.com/questions/19920213/why-is-stdis-assignable-counter-intuitive\n\t//\n\t// Note:\n\t// A true is_assignable value doesn't guarantee that the expression is compile-able, the compiler checks\n\t// only that the assignment matches before compilation. In particular, if you have templated operator=\n\t// for a class, the compiler will always say is_assignable is true, regardless of what's being tested\n\t// on the right hand side of the expression. It may actually turn out during compilation that the\n\t// templated operator= fails to compile because in practice it doesn't accept every possible type for\n\t// the right hand side of the expression.\n\t//\n\t// Expected results:\n\t//     is_assignable<void, void>::value             == false\n\t//     is_assignable<int&, int>::value              == true\n\t//     is_assignable<int, int>::value               == false\n\t//     is_assignable<int, int&>::value              == false\n\t//     is_assignable<bool, bool>::value             == false\n\t//     is_assignable<int, float>::value             == false\n\t//     is_assignable<int[], int[]>::value           == false\n\t//     is_assignable<char*, int*>::value            == false\n\t//     is_assignable<char*, const char*>::value     == false\n\t//     is_assignable<const char*, char*>::value     == false\n\t//     is_assignable<PodA, PodB*>::value            == false\n\t//     is_assignable<Assignable, Assignable>::value == true\n\t//     is_assignable<Assignable, Unrelated>::value  == false\n\t//\n\t// Note:\n\t// Our implementation here yields different results than does the std::is_assignable from Dinkumware-based Standard\n\t// Libraries, but yields similar results to the std::is_assignable from GCC's libstdc++ and clang's libc++. It may\n\t// possibly be that the Dinkumware results are intentionally different for some practical purpose or because they\n\t// represent the spirit or the Standard but not the letter of the Standard.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\t#define EASTL_TYPE_TRAIT_is_assignable_CONFORMANCE 1\n\n\ttemplate<typename T, typename U>\n\tstruct is_assignable_helper\n\t{\n\t\ttemplate<typename, typename>\n\t\tstatic eastl::no_type is(...);\n\n\t\ttemplate<typename T1, typename U1>\n\t\tstatic decltype(eastl::declval<T1>() = eastl::declval<U1>(), eastl::yes_type()) is(int);\n\n\t\tstatic const bool value = (sizeof(is<T, U>(0)) == sizeof(eastl::yes_type));\n\t};\n\n\ttemplate<typename T, typename U>\n\tstruct is_assignable :\n\t\tpublic eastl::integral_constant<bool, eastl::is_assignable_helper<T, U>::value> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T, class U>\n\t\tEA_CONSTEXPR bool is_assignable_v = is_assignable<T, U>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_assignable\n\t//\n\t// is_assignable<T, U>::value is true and the assignment, as defined by\n\t// is_assignable, is known to call no operation that is not trivial (3.9, 12).\n\t// T and U shall be complete types, (possibly cv-qualified) void, or\n\t// arrays of unknown bound\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(__clang__) && EA_COMPILER_HAS_FEATURE(is_trivially_assignable) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION > 5001)))\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_assignable_CONFORMANCE 1\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_trivially_assignable\n\t\t\t: eastl::integral_constant<bool, __is_trivially_assignable(T, U)> {};\n\n\t#elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) && (_MSC_VER >= 1800))\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_assignable_CONFORMANCE\n\n\t\t// This code path is attempting to work around the issue with VS2013 __is_trivially_assignable compiler intrinsic documented in the link\n\t\t// below.  todo: Re-evaluate in VS2014.\n\t\t//\n\t\t// https://connect.microsoft.com/VisualStudio/feedback/details/806233/std-is-trivially-copyable-const-int-n-and-std-is-trivially-copyable-int-n-incorrect\n\n\t\ttemplate <bool A, typename T, typename U>\n\t\tstruct is_trivially_assignable_helper;\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_trivially_assignable_helper<true, T, U> : eastl::integral_constant<bool, __is_trivially_assignable(T, U)>{};\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_trivially_assignable_helper<false, T, U> : false_type{};\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_trivially_assignable\n\t\t\t: eastl::integral_constant<bool, is_trivially_assignable_helper< eastl::is_assignable<T, U>::value, T, U >::value> {};\n\n\t#elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_GNUC))\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_assignable_CONFORMANCE\n\n\t\t// Micrsoft (up till at least VS2012) and GCC have __has_trivial_assign, but it may not be identical with the goals of this type trait.\n\t\t// The Microsoft type trait headers suggest that a future version of VS will have a __is_trivially_assignable intrinsic, but we\n\t\t// need to come up with something in the meantime. To do: Re-evalulate this for VS2013+ when it becomes available.\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_trivially_assignable\n\t\t\t: eastl::integral_constant<bool, eastl::is_assignable<T, U>::value &&\n\t\t\t\t\t\t\t\t\t   (eastl::is_pod<typename eastl::remove_reference<T>::type>::value || __has_trivial_assign(typename eastl::remove_reference<T>::type))> {};\n\t#else\n\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_assignable_CONFORMANCE 0  // Generates false negatives.\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_trivially_assignable\n\t\t\t: public eastl::false_type {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_assignable<T&, T>\n\t\t\t: public eastl::integral_constant<bool, eastl::is_scalar<T>::value> {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_assignable<T&, T&>\n\t\t\t: public eastl::integral_constant<bool, eastl::is_scalar<T>::value> {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_assignable<T&, const T&>\n\t\t\t: public eastl::integral_constant<bool, eastl::is_scalar<T>::value> {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_assignable<T&, T&&>\n\t\t\t: public eastl::integral_constant<bool, eastl::is_scalar<T>::value> {};\n\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T, class U>\n\t\tEA_CONSTEXPR bool is_trivially_assignable_v = is_trivially_assignable<T, U>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_assignable\n\t//\n\t// is_assignable<T, U>::value is true and the assignment is known\n\t// not to throw any exceptions (5.3.7). T and U shall be complete\n\t// types, (possibly cv-qualified) void, or arrays of unknown bound.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if defined(_MSC_VER) && (_MSC_VER >= 1800) // VS2013+\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_assignable_CONFORMANCE 1\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_nothrow_assignable\n\t\t\t: eastl::integral_constant<bool, __is_nothrow_assignable(T, U)> {};\n\n\t#elif defined(EA_COMPILER_NO_NOEXCEPT) || defined(__EDG_VERSION__) // EDG mis-compiles the conforming code below and so must be placed here.\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_assignable_CONFORMANCE 0\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_nothrow_assignable\n\t\t\t: public false_type {};\n\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_assignable_CONFORMANCE 1\n\n\t\ttemplate <bool, typename T, typename U>\n\t\tstruct is_nothrow_assignable_helper;\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_nothrow_assignable_helper<false, T, U>\n\t\t\t: public false_type {};\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_nothrow_assignable_helper<true, T, U> // Set to true if the assignment (same as is_assignable) cannot generate an exception.\n\t\t\t: public eastl::integral_constant<bool, noexcept(eastl::declval<T>() = eastl::declval<U>()) >\n\t\t{\n\t\t};\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_nothrow_assignable\n\t\t\t: public eastl::is_nothrow_assignable_helper<eastl::is_assignable<T, U>::value, T, U>\n\t\t{\n\t\t};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T, class U>\n\t\tEA_CONSTEXPR bool is_nothrow_assignable_v = is_nothrow_assignable<T, U>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_copy_assignable\n\t//\n\t// is_assignable<T&, const T&>::value is true. T shall be a complete type,\n\t// (possibly cv -qualified) void, or an array of unknown bound.\n\t//\n\t// This (and not is_assignable) is the type trait you use to tell if you\n\t// can do an arbitrary assignment. is_assignable tells if you can do an\n\t// assignment specifically to an rvalue and not in general.\n\t// http://stackoverflow.com/a/19921030/725009\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_copy_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_assignable_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_copy_assignable\n\t\t: public eastl::is_assignable<typename eastl::add_lvalue_reference<T>::type,\n\t\t\t\t\t\t\t\t\t  typename eastl::add_lvalue_reference<typename eastl::add_const<T>::type>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_copy_assignable_v = is_copy_assignable<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_copy_assignable\n\t//\n\t// is_trivially_assignable<T&, const T&>::value is true. T shall be a\n\t// complete type, (possibly cv-qualified) void, or an array of unknown bound.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_trivially_copy_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_trivially_assignable_CONFORMANCE\n\n#if EASTL_TYPE_TRAIT_is_trivially_copy_assignable_CONFORMANCE\n\ttemplate <typename T>\n\tstruct is_trivially_copy_assignable\n\t\t: public eastl::is_trivially_assignable<typename eastl::add_lvalue_reference<T>::type,\n\t\t\t\t\t\t\t\t\t\t\t\ttypename eastl::add_lvalue_reference<typename eastl::add_const<T>::type>::type> {};\n#else\n\ttemplate <typename T>\n\tstruct is_trivially_copy_assignable\n\t\t: public integral_constant<bool,\n\t\t\teastl::is_scalar<T>::value || eastl::is_pod<T>::value || eastl::is_trivially_assignable<typename eastl::add_lvalue_reference<T>::type, typename eastl::add_lvalue_reference<typename eastl::add_const<T>::type>::type>::value\n\t\t> {};\n#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<T>::value;\n    #endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_copy_assignable\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_nothrow_copy_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_nothrow_assignable_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_nothrow_copy_assignable\n\t\t: public eastl::is_nothrow_assignable<typename eastl::add_lvalue_reference<T>::type,\n\t\t\t\t\t\t\t\t\t\t\t  typename eastl::add_lvalue_reference<typename eastl::add_const<T>::type>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<T>::value;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_move_assignable\n\t//\n\t// is_assignable<T&, T&&>::value is true. T shall be a complete type,\n\t// (possibly cv -qualified) void, or an array of unknown bound.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_move_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_assignable_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_move_assignable\n\t\t: public eastl::is_assignable<typename eastl::add_lvalue_reference<T>::type,\n\t\t\t\t\t\t\t\t\t  typename eastl::add_rvalue_reference<T>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_move_assignable_v = is_move_assignable<T>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_move_assignable\n\t//\n\t// is_trivially_-assignable<T&, T&&>::value is true. T shall be a complete type,\n\t// (possibly cv-qualified) void, or an array of unknown bound.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_trivially_move_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_trivially_assignable_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_trivially_move_assignable\n\t\t: public eastl::is_trivially_assignable<typename eastl::add_lvalue_reference<T>::type,\n\t\t\t\t\t\t\t\t\t\t\t\ttypename eastl::add_rvalue_reference<T>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_move_assignable_v = is_trivially_move_assignable<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_move_assignable\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_nothrow_move_assignable_CONFORMANCE EASTL_TYPE_TRAIT_is_nothrow_assignable_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_nothrow_move_assignable\n\t\t: public eastl::is_nothrow_assignable<typename eastl::add_lvalue_reference<T>::type,\n\t\t\t\t\t\t\t\t\t\t\t  typename eastl::add_rvalue_reference<T>::type> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<T>::value;\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_destructible\n\t//\n\t// For a complete type T and given\n\t//     template <class U>\n\t//     struct test { U u; };\n\t// test<T>::~test() is not deleted (C++11 \"= delete\").\n\t// T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if defined(_MSC_VER) && (_MSC_VER >= 1920)\n\t\t#define EASTL_TYPE_TRAIT_is_destructible_CONFORMANCE 1\n\n\t\ttemplate <typename T>\n\t\tstruct is_destructible\n\t\t\t: integral_constant<bool, __is_destructible(T)> {};\n\n\t#elif defined(EA_COMPILER_NO_DECLTYPE) || defined(EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) || defined(_MSC_VER) || defined(__EDG_VERSION__) // VS2012 and EDG mis-compile the conforming code below and so must be placed here.\n\t\t#define EASTL_TYPE_TRAIT_is_destructible_CONFORMANCE 0\n\n\t\t// This implementation works for almost all cases, with the primary exception being the\n\t\t// case that the user declared the destructor as deleted.\n\n\t\ttemplate <typename T>\n\t\tstruct is_destructible\n\t\t\t: public eastl::integral_constant<bool, !eastl::is_unbounded_array<T>::value &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t!eastl::is_void<T>::value            &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t!eastl::is_function<T>::value> {};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_destructible_CONFORMANCE 1\n\n\t\ttemplate <typename>\n\t\teastl::false_type destructible_test_function(...);\n\n\t\ttemplate <typename T, typename U = typename eastl::remove_all_extents<T>::type, typename V = decltype(eastl::declval<U&>().~U())>\n\t\teastl::true_type destructible_test_function(int);\n\n\t\ttemplate <typename T, bool = eastl::is_unbounded_array<T>::value || // Exclude these types from being considered destructible.\n\t\t\t\t\t\t\t\t\t eastl::is_void<T>::value            ||\n\t\t\t\t\t\t\t\t\t eastl::is_function<T>::value>\n\t\tstruct is_destructible_helper\n\t\t\t: public eastl::type_identity<decltype(eastl::destructible_test_function<T>(0))>::type {}; // Need to wrap decltype with identity because some compilers otherwise don't like the bare decltype usage.\n\n\t\ttemplate <typename T>\n\t\tstruct is_destructible_helper<T, true>\n\t\t\t: public eastl::false_type {};\n\n\t\ttemplate <typename T, bool Whatever>\n\t\tstruct is_destructible_helper<T&, Whatever> // Reference are trivially destructible.\n\t\t\t: public eastl::true_type {};\n\n\t\ttemplate <typename T, bool Whatever>\n\t\tstruct is_destructible_helper<T&&, Whatever> // Reference are trivially destructible.\n\t\t\t: public eastl::true_type {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_destructible\n\t\t\t: public is_destructible_helper<T> {};\n\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_destructible_v = is_destructible<T>::value;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_trivially_destructible\n\t//\n\t// is_destructible<T>::value is true and the indicated destructor is\n\t// known to be trivial. T shall be a complete type, (possibly cv-qualified)\n\t// void, or an array of unknown bound.\n\t//\n\t// A destructor is trivial if it is not user-provided and if:\n\t//    - the destructor is not virtual,\n\t//    - all of the direct base classes of its class have trivial destructors, and\n\t//    - for all of the non-static data members of its class that are of\n\t//      class type (or array thereof), each such class has a trivial destructor.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && ((defined(_MSC_VER) && (_MSC_VER >= 1920)) || (defined(__clang__) && EASTL_HAS_INTRINSIC(is_trivially_destructible)))\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_destructible_CONFORMANCE 1\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_destructible\n\t\t\t: integral_constant<bool, __is_trivially_destructible(T)> {};\n\n\t#elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || defined(__clang__))\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_destructible_CONFORMANCE EASTL_TYPE_TRAIT_is_destructible_CONFORMANCE\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_destructible // Can't use just __has_trivial_destructor(T) because some compilers give it slightly different meaning, and are just plain broken, such as VC++'s __has_trivial_destructor, which says false for fundamental types.\n\t\t\t: public integral_constant<bool, eastl::is_destructible<T>::value && ((__has_trivial_destructor(T) && !eastl::is_hat_type<T>::value)|| eastl::is_scalar<typename eastl::remove_all_extents<T>::type>::value)> {};\n\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_trivially_destructible_CONFORMANCE 0\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_destructible_helper\n\t\t\t: public integral_constant<bool, (eastl::is_pod<T>::value || eastl::is_scalar<T>::value || eastl::is_reference<T>::value) && !eastl::is_void<T>::value> {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_trivially_destructible\n\t\t\t: public eastl::is_trivially_destructible_helper<typename eastl::remove_all_extents<T>::type> {};\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_trivially_destructible_v = is_trivially_destructible<T>::value;\n    #endif\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_destructible\n\t//\n\t// is_destructible<T>::value is true and the indicated destructor is\n\t// known not to throw any exceptions (5.3.7). T shall be a complete type,\n\t// (possibly cv-qualified) void, or an array of unknown bound.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if defined(_MSC_VER) && (_MSC_VER >= 1920)\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_destructible_CONFORMANCE ((_MSC_VER >= 1900) ? 1 : 0) // VS2013 (1800) doesn't support noexcept and so can't support all usage of this properly (in particular default exception specifications defined in [C++11 Standard, 15.4 paragraph 14].\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible\n\t\t\t: integral_constant<bool, __is_nothrow_destructible(T)> {};\n\n\t#elif defined(EA_COMPILER_NO_NOEXCEPT)\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_destructible_CONFORMANCE 0\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible_helper\n\t\t\t: public eastl::integral_constant<bool, eastl::is_scalar<T>::value || eastl::is_reference<T>::value> {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible\n\t\t\t: public eastl::is_nothrow_destructible_helper<typename eastl::remove_all_extents<T>::type> {};\n\n\t#else\n\t\t#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION < 4008)\n\t\t\t#define EASTL_TYPE_TRAIT_is_nothrow_destructible_CONFORMANCE 0 // GCC up to v4.7's noexcept is broken and fails to generate true for the case of compiler-generated destructors.\n\t\t#else\n\t\t\t#define EASTL_TYPE_TRAIT_is_nothrow_destructible_CONFORMANCE EASTL_TYPE_TRAIT_is_destructible_CONFORMANCE\n\t\t#endif\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// *_noexcept_wrapper implements a workaround for VS2015.  A standards conforming noexcept operator allows variadic template expansion.\n\t\t// There appears to be an issue with VS2015 that prevents variadic template expansion into a noexcept operator that is passed directly\n\t\t// to a template parameter.\n\t\t//\n\t\t// The fix hoists the noexcept expression into a separate struct and caches the result of the expression.  This result is then passed to integral_constant.\n\t\t//\n\t\t// Example code from Clang libc++\n\t\t// template <class _Tp, class... _Args>\n\t\t// struct __libcpp_is_nothrow_constructible<[>is constructible*/true, /*is reference<]false, _Tp, _Args...>\n\t\t//     : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))> { };\n\t\t//\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible_helper_noexcept_wrapper\n\t\t\t{ static const bool value = noexcept(eastl::declval<T&>().~T()); };\n\n\t\ttemplate <typename T, bool>\n\t\tstruct is_nothrow_destructible_helper;\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible_helper<T, false>\n\t\t\t: public eastl::false_type {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible_helper<T, true>     // If the expression T::~T is a noexcept expression then it's nothrow.\n\t\t\t: public eastl::integral_constant<bool, is_nothrow_destructible_helper_noexcept_wrapper<T>::value > {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible                      // A type needs to at least be destructible before it could be nothrow destructible.\n\t\t\t: public eastl::is_nothrow_destructible_helper<T, eastl::is_destructible<T>::value> {};\n\n\t\ttemplate <typename T, size_t N>                     // An array is nothrow destructible if its element type is nothrow destructible.\n\t\tstruct is_nothrow_destructible<T[N]>                // To consider: Replace this with a remove_all_extents pathway.\n\t\t\t: public eastl::is_nothrow_destructible<T> {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible<T&>                  // A reference type cannot throw while being destructed. It's just a reference.\n\t\t\t: public eastl::true_type {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_nothrow_destructible<T&&>                 // An rvalue reference type cannot throw while being destructed.\n\t\t\t: public eastl::true_type {};\n\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_nothrow_destructible_v = is_nothrow_destructible<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_default_constructible\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\t#define EASTL_TYPE_TRAIT_is_nothrow_default_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_nothrow_default_constructible\n\t\t: public eastl::is_nothrow_constructible<T> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_nothrow_default_constructible_v = is_nothrow_default_constructible<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_nothrow_move_constructible\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\t#define EASTL_TYPE_TRAIT_is_nothrow_move_constructible_CONFORMANCE EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_nothrow_move_constructible\n\t    : public eastl::is_nothrow_constructible<T, typename eastl::add_rvalue_reference<T>::type> {};\n\n    #if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<T>::value;\n\t#endif\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/type_properties.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_TYPE_PROPERTIES_H\n#define EASTL_INTERNAL_TYPE_PROPERTIES_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <limits.h>\n#include <EASTL/internal/type_compound.h>\n\n\nnamespace eastl\n{\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// underlying_type\n\t//\n\t// Defines a member typedef type of type that is the underlying type for the enumeration T.\n\t// Requires explicit compiler support to implement.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && ((defined(_MSC_VER) && (_MSC_VER >= 1700)) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007)) || defined(__clang__)) // VS2012+\n\t\t#define EASTL_TYPE_TRAIT_underlying_type_CONFORMANCE 1    // underlying_type is conforming.\n\n\t\ttemplate <typename T>\n\t\tstruct underlying_type{ typedef __underlying_type(T) type; };\n\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_underlying_type_CONFORMANCE 0\n\n\t\ttemplate <typename T>\n\t\tstruct underlying_type{ typedef int type; };    // This is of course wrong, but we emulate libstdc++ and typedef it as int.\n\t#endif\n\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename T>\n\t\tusing underlying_type_t = typename underlying_type<T>::type;\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// to_underlying\n\t//\n\t// Cast a enum value to its underlying type.\n\t// For example:\n\t//\n\t// enum class MyEnum : uint8_t { Value = 0; }\n\t// auto x = MyEnum::Value;\n\t// std::cout << to_underlying(x); // equivalent to  sts::cout << static_cast<uint8_t>(x);\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate<class T>\n\t\tconstexpr underlying_type_t<T> to_underlying(T value) noexcept\n\t\t{\n\t\t\treturn static_cast<underlying_type_t<T>>(value);\n\t\t}\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// has_unique_object_representations\n\t//\n\t// If T is TriviallyCopyable and if any two objects of type T with the same\n\t// value have the same object representation, value is true. For any other\n\t// type, value is false.\n\t//\n\t// http://en.cppreference.com/w/cpp/types/has_unique_object_representations\n\t///////////////////////////////////////////////////////////////////////\n\t#if EASTL_HAS_UNIQUE_OBJECT_REPRESENTATIONS_AVAILABLE\n\t\t#define EASTL_TYPE_TRAIT_has_unique_object_representations_CONFORMANCE 1\n\n\t\ttemplate <typename T>\n\t\tstruct has_unique_object_representations\n\t\t\t: public integral_constant<bool, __has_unique_object_representations(remove_cv_t<remove_all_extents_t<T>>)>\n\t\t{\n\t\t};\n\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_has_unique_object_representations_CONFORMANCE 0\n\n\t\ttemplate <typename T>\n\t\tstruct has_unique_object_representations\n\t\t\t: public integral_constant<bool, is_integral_v<remove_cv_t<remove_all_extents_t<T>>>> // only integral types (floating point types excluded).\n\t\t{\n\t\t};\n\n\t#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR auto has_unique_object_representations_v = has_unique_object_representations<T>::value;\n\t#endif\n\n\n    ///////////////////////////////////////////////////////////////////////\n\t// is_signed\n\t//\n\t// is_signed<T>::value == true if T is a (possibly cv-qualified) floating-point or signed integer type.\n\t//\n\t// Used to determine if a type is signed.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_signed_CONFORMANCE 1    // is_signed is conforming.\n\n#ifdef _MSC_VER\n\t#pragma warning(push)\n\t#pragma warning(disable: 4296)  // '<': expression is always false\n#endif\n\ttemplate<typename T, bool = is_arithmetic<T>::value>\n\tstruct is_signed_helper : bool_constant<T(-1) < T(0)> {};\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\ttemplate<typename T>\n\tstruct is_signed_helper<T, false> : false_type {};\n\n\ttemplate <typename T>\n\tstruct is_signed : public eastl::is_signed_helper<T>::type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_signed_v = is_signed<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_unsigned\n\t//\n\t// is_unsigned<T>::value == true if T is a (possibly cv-qualified) bool or unsigned integer type.\n\t//\n\t// Used to determine if a type is unsigned.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_unsigned_CONFORMANCE 1    // is_unsigned is conforming.\n\n#ifdef _MSC_VER\n\t#pragma warning(push)\n\t#pragma warning(disable: 4296)  // '<': expression is always false\n#endif\n\ttemplate<typename T, bool = is_arithmetic<T>::value>\n\tstruct is_unsigned_helper : integral_constant<bool, T(0) < T(-1)> {};\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\ttemplate<typename T>\n\tstruct is_unsigned_helper<T, false> : false_type {};\n\n\ttemplate <typename T>\n\tstruct is_unsigned : public eastl::is_unsigned_helper<T>::type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_unsigned_v = is_unsigned<T>::value;\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_bounded_array\n\t//\n\t// is_bounded_array<T>::value == true if T is an array type of known bound.\n\t//\n\t// is_bounded_array<int>::value is false.\n\t// is_bounded_array<int[5]>::value is true.\n\t// is_bounded_array<int[]>::value is false.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_bounded_array_CONFORMANCE 1    // is_bounded_array is conforming.\n\n\ttemplate<class T>\n\tstruct is_bounded_array: eastl::false_type {};\n\n\ttemplate<class T, size_t N>\n\tstruct is_bounded_array<T[N]> : eastl::true_type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_bounded_array_v = is_bounded_array<T>::value;\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_unbounded_array\n\t//\n\t// is_unbounded_array<T>::value == true if T is an array type of known bound.\n\t//\n\t// is_unbounded_array<int>::value is false.\n\t// is_unbounded_array<int[5]>::value is false.\n\t// is_unbounded_array<int[]>::value is true.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_unbounded_array_CONFORMANCE 1    // is_unbounded_array is conforming.\n\n\ttemplate<class T>\n\tstruct is_unbounded_array: eastl::false_type {};\n\n\ttemplate<class T>\n\tstruct is_unbounded_array<T[]> : eastl::true_type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_unbounded_array_v = is_unbounded_array<T>::value;\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// alignment_of\n\t//\n\t// alignment_of<T>::value is an integral value representing, in bytes,\n\t// the memory alignment of objects of type T.\n\t//\n\t// alignment_of may only be applied to complete types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_alignment_of_CONFORMANCE 1    // alignment_of is conforming.\n\n\ttemplate <typename T>\n\tstruct alignment_of_value{ static const size_t value = EASTL_ALIGN_OF(T); };\n\n\ttemplate <typename T>\n\tstruct alignment_of : public integral_constant<size_t, alignment_of_value<T>::value>{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR size_t alignment_of_v = alignment_of<T>::value;\n\t#endif\n\n\n    ///////////////////////////////////////////////////////////////////////\n\t// is_aligned\n\t//\n\t// Defined as true if the type has alignment requirements greater\n\t// than default alignment, which is taken to be 8. This allows for\n\t// doing specialized object allocation and placement for such types.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_aligned_CONFORMANCE 1    // is_aligned is conforming.\n\n\ttemplate <typename T>\n\tstruct is_aligned_value{ static const bool value = (EASTL_ALIGN_OF(T) > 8); };\n\n\ttemplate <typename T>\n\tstruct is_aligned : public integral_constant<bool, is_aligned_value<T>::value>{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR size_t is_aligned_v = is_aligned<T>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// rank\n\t//\n\t// rank<T>::value is an integral value representing the number of\n\t// dimensions possessed by an array type. For example, given a\n\t// multi-dimensional array type T[M][N], std::tr1::rank<T[M][N]>::value == 2.\n\t// For a given non-array type T, std::tr1::rank<T>::value == 0.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_rank_CONFORMANCE 1    // rank is conforming.\n\n\ttemplate<typename T>\n\tstruct rank : public eastl::integral_constant<size_t, 0> {};\n\n\ttemplate<typename T>\n\tstruct rank<T[]> : public eastl::integral_constant<size_t, rank<T>::value + 1> {};\n\n\ttemplate<typename T, size_t N>\n\tstruct rank<T[N]> : public eastl::integral_constant<size_t, rank<T>::value + 1> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR auto rank_v = rank<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_base_of\n\t//\n\t// Given two (possibly identical) types Base and Derived, is_base_of<Base, Derived>::value == true\n\t// if and only if Base is a direct or indirect base class of Derived,\n\t// or Base and Derived are the same type.\n\t//\n\t// is_base_of may only be applied to complete types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || ((defined(__clang__)) && EA_COMPILER_HAS_FEATURE(is_base_of)))\n\t\t#define EASTL_TYPE_TRAIT_is_base_of_CONFORMANCE 1    // is_base_of is conforming.\n\n\t\ttemplate <typename Base, typename Derived>\n\t\tstruct is_base_of : public eastl::integral_constant<bool, __is_base_of(Base, Derived) || eastl::is_same<Base, Derived>::value>{};\n\n\t\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\t\ttemplate <typename Base, typename Derived>\n\t\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_base_of_v = is_base_of<Base, Derived>::value;\n\t\t#endif\n\t#else\n\t\t// Not implemented yet.\n\t\t// This appears to be implementable.\n\t\t#define EASTL_TYPE_TRAIT_is_base_of_CONFORMANCE 0\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_lvalue_reference\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_lvalue_reference_CONFORMANCE 1    // is_lvalue_reference is conforming.\n\n\ttemplate<typename T> struct is_lvalue_reference     : public eastl::false_type {};\n\ttemplate<typename T> struct is_lvalue_reference<T&> : public eastl::true_type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_lvalue_reference_v = is_lvalue_reference<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_rvalue_reference\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_rvalue_reference_CONFORMANCE 1    // is_rvalue_reference is conforming.\n\n\ttemplate <typename T> struct is_rvalue_reference      : public eastl::false_type {};\n\ttemplate <typename T> struct is_rvalue_reference<T&&> : public eastl::true_type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_rvalue_reference_v = is_rvalue_reference<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// has_equality\n\t//\n\t// Determines if the specified type can be tested for equality.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <typename, typename = eastl::void_t<>>\n\tstruct has_equality : eastl::false_type {};\n\n\ttemplate <typename T>\n\tstruct has_equality<T, eastl::void_t<decltype(eastl::declval<T>() == eastl::declval<T>())>> : eastl::true_type\n\t{\n\t};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR auto has_equality_v = has_equality<T>::value;\n\t#endif\n\n\tnamespace internal\n\t{\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// is_complete_type\n\t\t//\n\t\t// Determines if the specified type is complete\n\t\t//\n\t\t// Warning: Be careful when using is_complete_type since the value is fixed at first instantiation.\n\t\t// Consider the following:\n\t\t//\n\t\t// struct Foo;\n\t\t// is_complete_type_v<Foo> // false\n\t\t// struct Foo {};\n\t\t// is_complete_type_v<Foo> // still false\n\t\t///////////////////////////////////////////////////////////////////////\n\n\t\ttemplate<typename T, typename = void>\n\t\tstruct is_complete_type : public false_type {};\n\n\t\ttemplate<typename T>\n\t\tstruct is_complete_type<T, eastl::void_t<decltype(sizeof(T) != 0)>> : public true_type {};\n\n\t\ttemplate<>\n\t\tstruct is_complete_type<const volatile void> : public false_type {};\n\t\ttemplate<>\n\t\tstruct is_complete_type<const void> : public false_type {};\n\t\ttemplate<>\n\t\tstruct is_complete_type<volatile void> : public false_type {};\n\t\ttemplate<>\n\t\tstruct is_complete_type<void> : public false_type {};\n\n\t\ttemplate<typename T>\n\t\tstruct is_complete_type<T, eastl::enable_if_t<eastl::is_function_v<T>>> : public true_type {};\n\n\t\ttemplate <typename T>\n\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool is_complete_type_v = is_complete_type<T, void>::value;\n\t}\n\n} // namespace eastl\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/internal/type_transformations.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_TYPE_TRANFORMATIONS_H\n#define EASTL_INTERNAL_TYPE_TRANFORMATIONS_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <limits.h>\n\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////\n\t// add_const\n\t//\n\t// Add const to a type.\n\t//\n\t// Tor a given type T, add_const<T>::type is equivalent to T \n\t// const if is_const<T>::value == false, and\n\t//    - is_void<T>::value == true, or\n\t//    - is_object<T>::value == true.\n\t//\n\t// Otherwise, add_const<T>::type is equivalent to T.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_add_const_CONFORMANCE 1    // add_const is conforming.   \n\n\ttemplate <typename T, bool = eastl::is_const<T>::value || eastl::is_reference<T>::value || eastl::is_function<T>::value>\n\tstruct add_const_helper\n\t\t{ typedef T type; };\n\n\ttemplate <typename T>\n\tstruct add_const_helper<T, false>\n\t\t{ typedef const T type; };\n\n\ttemplate <typename T>\n\tstruct  add_const\n\t\t{ typedef typename eastl::add_const_helper<T>::type type; };\n\t\n\t// add_const_t is the C++17 using typedef for typename add_const<T>::type.\n\t// We provide a backwards-compatible means to access it through a macro for pre-C++11 compilers.\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t#define EASTL_ADD_CONST_T(T) typename add_const<T>::type\n\t#else\n\t\ttemplate <typename T>\n\t\tusing add_const_t = typename add_const<T>::type;\n\t\t#define EASTL_ADD_CONST_T(T) add_const_t<T>\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// add_volatile\n\t//\n\t// Add volatile to a type.\n\t// \n\t// For a given type T, add_volatile<T>::type is equivalent to T volatile \n\t// if is_volatile<T>::value == false, and\n\t//   - is_void<T>::value == true, or\n\t//   - is_object<T>::value == true.\n\t//\n\t// Otherwise, add_volatile<T>::type is equivalent to T.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_add_volatile_CONFORMANCE 1    // add_volatile is conforming.\n\n\ttemplate <typename T, bool = eastl::is_volatile<T>::value || eastl::is_reference<T>::value || eastl::is_function<T>::value>\n\tstruct add_volatile_helper\n\t\t{ typedef T type; };\n\n\ttemplate <typename T>\n\tstruct add_volatile_helper<T, false>\n\t\t{ typedef volatile T type; };\n\n\ttemplate <typename T> struct add_volatile\n\t\t{ typedef typename eastl::add_volatile_helper<T>::type type; };\n\n\ttemplate <class T> using add_volatile_t = typename add_volatile<T>::type;\n\n\n    ///////////////////////////////////////////////////////////////////////\n\t// add_cv\n\t//\n\t// The add_cv transformation trait adds const and volatile qualification \n\t// to the type to which it is applied. For a given type T, \n\t// add_volatile<T>::type is equivalent to add_const<add_volatile<T>::type>::type.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_add_cv_CONFORMANCE 1    // add_cv is conforming.\n\n\ttemplate<typename T>\n\tstruct add_cv\n\t{\n\t\ttypedef typename add_const<typename add_volatile<T>::type>::type type;\n\t};\n\n\ttemplate <class T> using add_cv_t = typename add_cv<T>::type;\n\n\n    ///////////////////////////////////////////////////////////////////////\n\t// make_signed\n\t//\n\t// Used to convert an integral type to its signed equivalent, if not already.\n\t// T shall be a (possibly const and/or volatile-qualified) integral type\n\t// or enumeration but not a bool type.;\n\t//\n\t// The user can define their own make_signed overrides for their own\n\t// types by making a template specialization like done below and adding\n\t// it to the user's code.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_make_signed_CONFORMANCE 1\n\n\tnamespace internal\n\t{\n\t\ttemplate <typename T, bool = eastl::is_enum_v<T> || eastl::is_integral_v<T>>\n\t\tstruct make_signed_helper_0\n\t\t{\n\t\t\tstruct char_helper\n\t\t\t{\n\t\t\t\ttypedef signed char type;\n\t\t\t};\n\n\t\t\tstruct short_helper\n\t\t\t{\n\t\t\t\ttypedef signed short type;\n\t\t\t};\n\n\t\t\tstruct int_helper\n\t\t\t{\n\t\t\t\ttypedef signed int type;\n\t\t\t};\n\n\t\t\tstruct long_helper\n\t\t\t{\n\t\t\t\ttypedef signed long type;\n\t\t\t};\n\n\t\t\tstruct longlong_helper\n\t\t\t{\n\t\t\t\ttypedef signed long long type;\n\t\t\t};\n\n\t\t\tstruct int128_helper\n\t\t\t{\n\t\t\t\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\t\t\t\ttypedef __int128_t type;\n\t\t\t\t#endif\n\t\t\t};\n\n\t\t\tstruct no_type_helper\n\t\t\t{\n\t\t\t};\n\n\t\t\ttypedef typename\n\t\t\teastl::conditional<sizeof(T) <= sizeof(signed char), char_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(signed short), short_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(signed int), int_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(signed long), long_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(signed long long), longlong_helper,\n\t\t\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\t\t\teastl::conditional_t<sizeof(T) <= sizeof(__int128_t), int128_helper,\n\t\t\t\t\tno_type_helper\n\t\t\t\t>\n\t\t\t#else\n\t\t\t\tno_type_helper\n\t\t\t#endif\n\t\t\t>\n\t\t\t>\n\t\t\t>\n\t\t\t>\n\t\t    >::type type;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct make_signed_helper_0<T, false>\n\t\t{\n\t\t\tstruct no_type_helper\n\t\t\t{\n\t\t\t};\n\n\t\t\ttypedef no_type_helper type;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct make_signed_helper_1\n\t\t{\n\t\t\ttypedef typename T::type type;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct make_signed_helper\n\t\t{\n\t\t\ttypedef typename eastl::internal::make_signed_helper_1<typename eastl::internal::make_signed_helper_0<T>::type>::type type;\n\t\t};\n\n\t} // namespace internal\n\n\ttemplate <typename T>\n\tstruct make_signed\n\t{\n\t\ttypedef typename eastl::internal::make_signed_helper<T>::type type;\n\t};\n\n\ttemplate <> struct make_signed<bool> {};\n\ttemplate <> struct make_signed<signed char>              { typedef signed char            type; };\n\ttemplate <> struct make_signed<unsigned char>            { typedef signed char            type; };\n\ttemplate <> struct make_signed<signed short>             { typedef signed short           type; };\n\ttemplate <> struct make_signed<unsigned short>           { typedef signed short           type; };\n\ttemplate <> struct make_signed<signed int>               { typedef signed int             type; };\n\ttemplate <> struct make_signed<unsigned int>             { typedef signed int             type; };\n\ttemplate <> struct make_signed<signed long>              { typedef signed long            type; };\n\ttemplate <> struct make_signed<unsigned long>            { typedef signed long            type; };\n\ttemplate <> struct make_signed<signed long long>         { typedef signed long long       type; };\n\ttemplate <> struct make_signed<unsigned long long>       { typedef signed long long       type; };\n\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\ttemplate <> struct make_signed<__int128_t>           { typedef __int128_t\t\t\t  type; };\n\t\ttemplate <> struct make_signed<__uint128_t>          { typedef __int128_t\t\t\t  type; };\n\t#endif\n\n\n\t#if (defined(CHAR_MAX) && defined(UCHAR_MAX) && (CHAR_MAX == UCHAR_MAX)) // If char is unsigned, we convert char to signed char. However, if char is signed then make_signed returns char itself and not signed char.\n\t\ttemplate <> struct make_signed<char>                 { typedef signed char            type; };\n\t#endif\n\n\ttemplate <typename T>\n\tstruct make_signed<const T>\n\t{\n\t\ttypedef eastl::add_const_t<typename eastl::make_signed<T>::type> type;\n\t};\n\n\ttemplate <typename T>\n\tstruct make_signed<volatile T>\n\t{\n\t\ttypedef eastl::add_volatile_t<typename eastl::make_signed<T>::type> type;\n\t};\n\n\ttemplate <typename T>\n\tstruct make_signed<const volatile T>\n\t{\n\t\ttypedef eastl::add_cv_t<typename eastl::make_signed<T>::type> type;\n\t};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <typename T>\n\t\tusing make_signed_t = typename make_signed<T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// make_unsigned\n\t//\n\t// Used to convert an integral type to its unsigned equivalent, if not already.\n\t// T shall be a (possibly const and/or volatile-qualified) integral type\n\t// or enumeration but not a bool type.;\n\t//\n\t// The user can define their own make_unsigned overrides for their own\n\t// types by making a template specialization like done below and adding\n\t// it to the user's code.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_make_unsigned_CONFORMANCE 1\n\n\tnamespace internal\n\t{\n\n\t\ttemplate <typename T, bool = eastl::is_enum<T>::value || eastl::is_integral<T>::value>\n\t\tstruct make_unsigned_helper_0\n\t\t{\n\t\t\tstruct char_helper\n\t\t\t{\n\t\t\t\ttypedef unsigned char type;\n\t\t\t};\n\n\t\t\tstruct short_helper\n\t\t\t{\n\t\t\t\ttypedef unsigned short type;\n\t\t\t};\n\n\t\t\tstruct int_helper\n\t\t\t{\n\t\t\t\ttypedef unsigned int type;\n\t\t\t};\n\n\t\t\tstruct long_helper\n\t\t\t{\n\t\t\t\ttypedef unsigned long type;\n\t\t\t};\n\n\t\t\tstruct longlong_helper\n\t\t\t{\n\t\t\t\ttypedef unsigned long long type;\n\t\t\t};\n\n\t\t\tstruct int128_helper\n\t\t\t{\n\t\t\t\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\t\t\t\ttypedef __uint128_t type;\n\t\t\t\t#endif\n\t\t\t};\n\n\t\t\tstruct no_type_helper\n\t\t\t{\n\t\t\t};\n\n\n\t\t\ttypedef typename\n\t\t\teastl::conditional<sizeof(T) <= sizeof(unsigned char), char_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(unsigned short), short_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(unsigned int), int_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(unsigned long), long_helper,\n\t\t\teastl::conditional_t<sizeof(T) <= sizeof(unsigned long long), longlong_helper,\n\t\t\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\t\t\teastl::conditional_t<sizeof(T) <= sizeof(__uint128_t), int128_helper,\n\t\t\t\t\tno_type_helper\n\t\t\t\t>\n\t\t\t#else\n\t\t\t\t no_type_helper\n\t\t\t#endif\n\t\t\t  >\n\t\t\t  >\n\t\t\t  >\n\t\t\t  >\n\t\t\t  >::type type;\n\t\t};\n\n\n\t\ttemplate <typename T>\n\t\tstruct make_unsigned_helper_0<T, false>\n\t\t{\n\t\t\tstruct no_type_helper\n\t\t\t{\n\t\t\t};\n\n\t\t\ttypedef no_type_helper type;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct make_unsigned_helper_1\n\t\t{\n\t\t\ttypedef typename T::type type;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct make_unsigned_helper\n\t\t{\n\t\t\ttypedef typename eastl::internal::make_unsigned_helper_1<typename eastl::internal::make_unsigned_helper_0<T>::type>::type type;\n\t\t};\n\n\t} // namespace internal\n\n\ttemplate <typename T>\n\tstruct make_unsigned\n\t{\n\t\ttypedef typename eastl::internal::make_unsigned_helper<T>::type type;\n\t};\n\n\ttemplate <> struct make_unsigned<bool> {};\n\ttemplate <> struct make_unsigned<signed char>            { typedef unsigned char            type; };\n\ttemplate <> struct make_unsigned<unsigned char>          { typedef unsigned char            type; };\n\ttemplate <> struct make_unsigned<signed short>           { typedef unsigned short           type; };\n\ttemplate <> struct make_unsigned<unsigned short>         { typedef unsigned short           type; };\n\ttemplate <> struct make_unsigned<signed int>             { typedef unsigned int             type; };\n\ttemplate <> struct make_unsigned<unsigned int>           { typedef unsigned int             type; };\n\ttemplate <> struct make_unsigned<signed long>            { typedef unsigned long            type; };\n\ttemplate <> struct make_unsigned<unsigned long>          { typedef unsigned long            type; };\n\ttemplate <> struct make_unsigned<signed long long>       { typedef unsigned long long       type; };\n\ttemplate <> struct make_unsigned<unsigned long long>     { typedef unsigned long long       type; };\n\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\ttemplate <> struct make_unsigned<__int128_t>         { typedef __uint128_t\t\t\t\ttype; };\n\t\ttemplate <> struct make_unsigned<__uint128_t>        { typedef __uint128_t\t\t\t\ttype; };\n\t#endif\n\n\t#if (CHAR_MIN < 0) // If char is signed, we convert char to unsigned char. However, if char is unsigned then make_unsigned returns char itself and not unsigned char.\n\t\ttemplate <> struct make_unsigned<char>                 { typedef unsigned char          type; };\n\t#endif\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\ttemplate <> struct make_unsigned<char8_t>                 { typedef unsigned char           type; };\n\t#endif\n\n\ttemplate <typename T>\n\tstruct make_unsigned<const T>\n\t{\n\t\ttypedef eastl::add_const_t<typename eastl::make_unsigned<T>::type> type;\n\t};\n\n\ttemplate <typename T>\n\tstruct make_unsigned<volatile T>\n\t{\n\t\ttypedef eastl::add_volatile_t<typename eastl::make_unsigned<T>::type> type;\n\t};\n\n\ttemplate <typename T>\n\tstruct make_unsigned<const volatile T>\n\t{\n\t\ttypedef eastl::add_cv_t<typename eastl::make_unsigned<T>::type> type;\n\t};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <typename T>\n\t\tusing make_unsigned_t = typename make_unsigned<T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_pointer\n\t//\n\t// Remove pointer from a type.\n\t//\n\t// The remove_pointer transformation trait removes top-level indirection \n\t// by pointer (if any) from the type to which it is applied. Pointers to \n\t// members are not affected. For a given type T, remove_pointer<T*>::type \n\t// is equivalent to T.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_pointer_CONFORMANCE 1\n\n\ttemplate<typename T> struct remove_pointer                    { typedef T type; };\n\ttemplate<typename T> struct remove_pointer<T*>                { typedef T type; };\n\ttemplate<typename T> struct remove_pointer<T* const>          { typedef T type; };\n\ttemplate<typename T> struct remove_pointer<T* volatile>       { typedef T type; };\n\ttemplate<typename T> struct remove_pointer<T* const volatile> { typedef T type; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tusing remove_pointer_t = typename remove_pointer<T>::type;\n    #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// add_pointer\n\t//\n\t// Add pointer to a type.\n\t// Provides the member typedef type which is the type T*.\n\t// \n\t// If T is a reference type,\n\t//\t\ttype member is a pointer to the referred type.\n\t// If T is an object type, a function type that is not cv- or ref-qualified,\n\t// or a (possibly cv-qualified) void type,\n\t//\t\ttype member is T*.\n\t// Otherwise (T is a cv- or ref-qualified function type),\n\t//\t\ttype member is T (ie. not a pointer).\n\t//\n\t// cv- and ref-qualified function types are invalid, which is why there is a specific clause for it.\n\t// See https://cplusplus.github.io/LWG/issue2101 for more.\n\t// \n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_add_pointer_CONFORMANCE 1\n\n\tnamespace internal\n\t{\n\t\ttemplate <typename T>\n\t\tauto try_add_pointer(int) -> type_identity<typename eastl::remove_reference<T>::type*>;\n\t\ttemplate <typename T>\n\t\tauto try_add_pointer(...) -> type_identity<T>;\n\t}\n \n\ttemplate <typename T>\n\tstruct add_pointer : decltype(internal::try_add_pointer<T>(0)) {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tusing add_pointer_t = typename add_pointer<T>::type;\n    #endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_extent\n\t//\n\t// The remove_extent transformation trait removes a dimension from an array.\n\t// For a given non-array type T, remove_extent<T>::type is equivalent to T.\n\t// For a given array type T[N], remove_extent<T[N]>::type is equivalent to T.\n\t// For a given array type const T[N], remove_extent<const T[N]>::type is equivalent to const T.\n\t// For example, given a multi-dimensional array type T[M][N], remove_extent<T[M][N]>::type is equivalent to T[N].\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_extent_CONFORMANCE 1    // remove_extent is conforming.\n\n\ttemplate<class T>           struct remove_extent       { typedef T type; };\n\ttemplate<class T>           struct remove_extent<T[]>  { typedef T type; };\n\ttemplate<class T, size_t N> struct remove_extent<T[N]> { typedef T type; };\n\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename T>\n\t\tusing remove_extent_t = typename remove_extent<T>::type;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_all_extents\n\t//\n\t// The remove_all_extents transformation trait removes all dimensions from an array.\n\t// For a given non-array type T, remove_all_extents<T>::type is equivalent to T.\n\t// For a given array type T[N], remove_all_extents<T[N]>::type is equivalent to T.\n\t// For a given array type const T[N], remove_all_extents<const T[N]>::type is equivalent to const T.\n\t// For example, given a multi-dimensional array type T[M][N], remove_all_extents<T[M][N]>::type is equivalent to T.\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_all_extents_CONFORMANCE 1    // remove_all_extents is conforming.\n\n\ttemplate<typename T>           struct remove_all_extents       { typedef T type; };\n\ttemplate<typename T, size_t N> struct remove_all_extents<T[N]> { typedef typename eastl::remove_all_extents<T>::type type; };\n\ttemplate<typename T>           struct remove_all_extents<T[]>  { typedef typename eastl::remove_all_extents<T>::type type; };\n\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename T>\n\t\tusing remove_all_extents_t = typename remove_all_extents<T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// aligned_storage\n\t// \n\t// Deprecated in C++23.\n\t//\n\t// The aligned_storage transformation trait provides a type that is \n\t// suitably aligned to store an object whose size is does not exceed length \n\t// and whose alignment is a divisor of alignment. When using aligned_storage, \n\t// length must be non-zero, and alignment must >= alignment_of<T>::value \n\t// for some type T. We require the alignment value to be a power-of-two.\n\t//\n\t// GCC versions prior to 4.4 don't properly support this with stack-based\n\t// variables. The EABase EA_ALIGN_MAX_AUTOMATIC define identifies the \n\t// extent to which stack (automatic) variables can be aligned for the \n\t// given compiler/platform combination.\n\t//\n\t// Example usage:\n\t//     aligned_storage<sizeof(Widget), alignment_of(Widget)>::type widget;\n\t//     Widget* pWidget = new(&widget) Widget;\n\t//\n\t//     aligned_storage<sizeof(Widget), 64>::type widgetAlignedTo64;\n\t//     Widget* pWidget = new(&widgetAlignedTo64) Widget;\n\t//\n\t//     aligned_storage<sizeof(Widget), alignment_of(Widget)>::type widgetArray[37];\n\t//     Widget* pWidgetArray = new(widgetArray) Widget[37];\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_aligned_storage_CONFORMANCE 1    // aligned_storage is conforming.\n\n\t#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4008)\n\t\t// New versions of GCC do not support using 'alignas' with a value greater than 128.\n\t\t// However, this code using the GNU standard alignment attribute works properly.\n\t\ttemplate<size_t N, size_t Align = EASTL_ALIGN_OF(double)>\n\t\tstruct aligned_storage\n\t\t{\n\t\t\tstruct type { unsigned char mCharData[N]; } EA_ALIGN(Align);\n\t\t};\n\t#elif (EABASE_VERSION_N >= 20040) && !defined(EA_COMPILER_NO_ALIGNAS) // If C++11 alignas is supported...\n\t\ttemplate<size_t N, size_t Align = EASTL_ALIGN_OF(double)>\n\t\tstruct aligned_storage\n\t\t{\n\t\t\ttypedef struct {\n\t\t\t\talignas(Align) unsigned char mCharData[N];\n\t\t\t} type;\n\t\t};\n\n\t#elif defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION < 4007)) || defined(EA_COMPILER_EDG) // At some point GCC fixed their attribute(align) to support non-literals, though it's not clear what version aside from being no later than 4.7 and no earlier than 4.2.\n\t\t// Some compilers don't allow you to to use EA_ALIGNED with anything by a numeric literal, \n\t\t// so we can't use the simpler code like we do further below for other compilers. We support\n\t\t// only up to so much of an alignment value here.\n\t\ttemplate<size_t N, size_t Align>\n\t\tstruct aligned_storage_helper { struct type{ unsigned char mCharData[N]; }; };\n\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,    2> { struct EA_ALIGN(   2) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,    4> { struct EA_ALIGN(   4) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,    8> { struct EA_ALIGN(   8) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,   16> { struct EA_ALIGN(  16) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,   32> { struct EA_ALIGN(  32) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,   64> { struct EA_ALIGN(  64) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,  128> { struct EA_ALIGN( 128) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,  256> { struct EA_ALIGN( 256) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N,  512> { struct EA_ALIGN( 512) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N, 1024> { struct EA_ALIGN(1024) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N, 2048> { struct EA_ALIGN(2048) type{ unsigned char mCharData[N]; }; };\n\t\ttemplate<size_t N> struct aligned_storage_helper<N, 4096> { struct EA_ALIGN(4096) type{ unsigned char mCharData[N]; }; };\n\n\t\ttemplate<size_t N, size_t Align = EASTL_ALIGN_OF(double)>\n\t\tstruct aligned_storage\n\t\t{\n\t\t\ttypedef typename aligned_storage_helper<N, Align>::type type;\n\t\t};\n\n\t#else\n\t\ttemplate<size_t N, size_t Align = EASTL_ALIGN_OF(double)>\n\t\tstruct aligned_storage\n\t\t{\n\t\t\tunion type\n\t\t\t{\n\t\t\t\tunsigned char mCharData[N];\n\t\t\t\tstruct EA_ALIGN(Align) mStruct{ }; \n\t\t\t};\n\t\t};\n\t#endif\n\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t#define EASTL_ALIGNED_STORAGE_T(N, Align) typename eastl::aligned_storage_t<N, Align>::type\n\t#else\n\t\ttemplate <size_t N, size_t Align = EASTL_ALIGN_OF(double)>\n\t\tusing aligned_storage_t = typename aligned_storage<N, Align>::type;\n\t\t#define EASTL_ALIGNED_STORAGE_T(N, Align) eastl::aligned_storage_t<N, Align>\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// aligned_union\n\t// \n\t// Deprecated in C++23.\n\t//\n\t// The member typedef type shall be a POD type suitable for use as\n\t// uninitialized storage for any object whose type is listed in Types; \n\t// its size shall be at least Len. The static member alignment_value \n\t// shall be an integral constant of type std::size_t whose value is \n\t// the strictest alignment of all types listed in Types.\n\t// Note that the resulting type is not a C/C++ union, but simply memory \n\t// block (of pod type) that can be used to placement-new an actual \n\t// C/C++ union of the types. The actual union you declare can be a non-POD union.\n\t//\n\t// Example usage:\n\t//     union MyUnion {\n\t//         char  c;\n\t//         int   i;\n\t//         float f;\n\t//\n\t//         MyUnion(float fValue) : f(fValue) {}\n\t//     };\n\t// \n\t//     aligned_union<sizeof(MyUnion), char, int, float>::type myUnionStorage;\n\t//     MyUnion* pMyUnion = new(&myUnionStorage) MyUnion(21.4f);\n\t//     pMyUnion->i = 37;\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#if defined(EA_COMPILER_NO_VARIADIC_TEMPLATES) || !EASTL_TYPE_TRAIT_static_max_CONFORMANCE\n\t\t#define EASTL_TYPE_TRAIT_aligned_union_CONFORMANCE 0    // aligned_union is not conforming, as it supports only a two-member unions.\n\n\t\t// To consider: Expand this to include more possible types. We may want to convert this to be a recursive \n\t\t//              template instead of like below.\n\t\ttemplate <size_t minSize, typename Type0, typename Type1 = char, typename Type2 = char, typename Type3 = char>\n\t\tstruct aligned_union\n\t\t{\n\t\t\tstatic const size_t size0           = eastl::static_max<minSize, sizeof(Type0)>::value;\n\t\t\tstatic const size_t size1           = eastl::static_max<size0,   sizeof(Type1)>::value;\n\t\t\tstatic const size_t size2           = eastl::static_max<size1,   sizeof(Type2)>::value;\n\t\t\tstatic const size_t size            = eastl::static_max<size2,   sizeof(Type3)>::value;\n\n\t\t\tstatic const size_t alignment0      = eastl::static_max<EA_ALIGN_OF(Type0), EA_ALIGN_OF(Type1)>::value;\n\t\t\tstatic const size_t alignment1      = eastl::static_max<alignment0,         EA_ALIGN_OF(Type2)>::value;\n\t\t\tstatic const size_t alignment_value = eastl::static_max<alignment1,         EA_ALIGN_OF(Type3)>::value;\n\n\t\t\ttypedef typename eastl::aligned_storage<size, alignment_value>::type type;\n\t\t};\n\n\t\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t\t// To do: define macro.\n\t\t#else\n\t\t\ttemplate <size_t minSize, typename Type0, typename Type1 = char, typename Type2 = char, typename Type3 = char>\n\t\t\tusing aligned_union_t = typename aligned_union<minSize, Type0, Type1, Type2, Type3>::type;\n\t\t#endif\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_aligned_union_CONFORMANCE 1    // aligned_union is conforming.\n\n\t\ttemplate <size_t minSize, typename Type0, typename ...TypeN>\n\t\tstruct aligned_union\n\t\t{\n\t\t\tstatic const size_t size            = eastl::static_max<minSize, sizeof(Type0), sizeof(TypeN)...>::value;\n\t\t\tstatic const size_t alignment_value = eastl::static_max<EA_ALIGN_OF(Type0), EA_ALIGN_OF(TypeN)...>::value;\n\n\t\t\ttypedef typename eastl::aligned_storage<size, alignment_value>::type type;\n\t\t};\n\n\t\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t\t// To do: define macro.\n\t\t#else\n\t\t\ttemplate <size_t minSize, typename... TypeN>\n\t\t\tusing aligned_union_t = typename aligned_union<minSize, TypeN...>::type;\n        #endif\n\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// union_cast\n\t//\n\t// Safely converts between unrelated types that have a binary equivalency.\n\t// This appoach is required by strictly conforming C++ compilers because\n\t// directly using a C or C++ cast between unrelated types is fraught with \n\t// the possibility of undefined runtime behavior due to type aliasing.\n\t// The Source and Dest types must be POD types due to the use of a union \n\t// in C++ versions prior to C++11. C++11 relaxes the definition of a POD\n\t// such that it allows a classes with trivial default constructors whereas \n\t// previous versions did not, so beware of this when writing portable code.\n\t//\n\t// Example usage:\n\t//    float f32 = 1.234f;\n\t//    uint32_t n32 = union_cast<uint32_t>(f32);\n\t//\n\t// Example possible mis-usage:\n\t// The following is valid only if you are aliasing the pointer value and \n\t// not what it points to. Most of the time the user intends the latter, \n\t// which isn't strictly possible.\n\t//    Widget* pWidget = CreateWidget();\n\t//    Foo*    pFoo    = union_cast<Foo*>(pWidget);\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename DestType, typename SourceType>\n\tDestType union_cast(SourceType sourceValue)\n\t{\n\t\tEASTL_CT_ASSERT((sizeof(DestType) == sizeof(SourceType)) && \n\t\t\t\t\t\t(EA_ALIGN_OF(DestType) == EA_ALIGN_OF(SourceType)));               // To support differening alignments, we would need to use a memcpy-based solution or find a way to make the two union members align with each other.\n\t\t//EASTL_CT_ASSERT(is_pod<DestType>::value && is_pod<SourceType>::value);           // Disabled because we don't want to restrict what the user can do, as some compiler's definitions of is_pod aren't up to C++11 Standards.\n\t\t//EASTL_CT_ASSERT(!is_pointer<DestType>::value && !is_pointer<SourceType>::value); // Disabled because it's valid to alias pointers as long as you are aliasong the pointer value and not what it points to.\n\n\t\tunion {\n\t\t\tSourceType sourceValue;\n\t\t\tDestType   destValue;\n\t\t} u;\n\t\tu.sourceValue = sourceValue;\n\n\t\treturn u.destValue;\n\t}\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/internal/type_void_t.h",
    "content": "﻿/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTERNAL_TYPE_VOID_T_H\n#define EASTL_INTERNAL_TYPE_VOID_T_H\n\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////\n\t// void_t \n\t//\n\t// Maps a sequence of any types to void.  This utility class is used in\n\t// template meta programming to simplify compile time reflection mechanisms\n\t// required by the standard library.\n\t//\n\t// http://en.cppreference.com/w/cpp/types/void_t\n\t//\n\t// Example:\n\t//    template <typename T, typename = void>\n\t//    struct is_iterable : false_type {};\n\t//\n\t//    template <typename T>\n\t//    struct is_iterable<T, void_t<decltype(declval<T>().begin()), \n\t//                                 decltype(declval<T>().end())>> : true_type {};\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class...>\n\tusing void_t = void;\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/intrusive_hash_map.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_INTRUSIVE_HASH_MAP_H\n#define EASTL_INTRUSIVE_HASH_MAP_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/intrusive_hashtable.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// intrusive_hash_map\n\t///\n\t/// Template parameters:\n\t///     Key             The key object (key in the key/value pair). T must contain a member of type Key named mKey.\n\t///     T               The type of object the map holds (a.k.a. value).\n\t///     bucketCount     The number of buckets to use. Best if it's a prime number.\n\t///     Hash            Hash function. See functional.h for examples of hash functions.\n\t///     Equal           Equality testing predicate; tells if two elements are equal.\n\t///\n\ttemplate <typename Key, typename T, size_t bucketCount, typename Hash = eastl::hash<Key>, typename Equal = eastl::equal_to<Key> >\n\tclass intrusive_hash_map : public intrusive_hashtable<Key, T, Hash, Equal, bucketCount, false, true>\n\t{\n\tpublic:\n\t\ttypedef intrusive_hashtable<Key, T, Hash, Equal, bucketCount, false, true>  base_type;\n\t\ttypedef intrusive_hash_map<Key, T, bucketCount, Hash, Equal>                this_type;\n\n\tpublic:\n\t\texplicit intrusive_hash_map(const Hash& h = Hash(), const Equal& eq = Equal())\n\t\t\t: base_type(h, eq)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea?\n\t\t//intrusive_hash_map(std::initializer_list<value_type> ilist);\n\n\t}; // intrusive_hash_map\n\n\n\n\n\t/// intrusive_hash_multimap\n\t///\n\t/// Implements a intrusive_hash_multimap, which is the same thing as a intrusive_hash_map \n\t/// except that contained elements need not be unique. See the documentation \n\t/// for intrusive_hash_map for details.\n\t///\n\t/// Template parameters:\n\t///     Key             The key object (key in the key/value pair). T must contain a member of type Key named mKey.\n\t///     T               The type of object the map holds (a.k.a. value).\n\t///     bucketCount     The number of buckets to use. Best if it's a prime number.\n\t///     Hash            Hash function. See functional.h for examples of hash functions.\n\t///     Equal           Equality testing predicate; tells if two elements are equal.\n\t///\n\ttemplate <typename Key, typename T, size_t bucketCount, typename Hash = eastl::hash<Key>, typename Equal = eastl::equal_to<Key> >\n\tclass intrusive_hash_multimap : public intrusive_hashtable<Key, T, Hash, Equal, bucketCount, false, false>\n\t{\n\tpublic:\n\t\ttypedef intrusive_hashtable<Key, T, Hash, Equal, bucketCount, false, false>  base_type;\n\t\ttypedef intrusive_hash_multimap<Key, T, bucketCount, Hash, Equal>            this_type;\n\n\tpublic:\n\t\texplicit intrusive_hash_multimap(const Hash& h = Hash(), const Equal& eq = Equal())\n\t\t\t: base_type(h, eq)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea?\n\t\t//intrusive_hash_multimap(std::initializer_list<value_type> ilist);\n\n\t}; // intrusive_hash_multimap\n\n\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/intrusive_hash_set.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_INTRUSIVE_HASH_SET_H\n#define EASTL_INTRUSIVE_HASH_SET_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/intrusive_hashtable.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// intrusive_hash_set\n\t///\n\t/// Template parameters:\n\t///     T               The type of object the set holds (a.k.a. value).\n\t///     bucketCount     The number of buckets to use. Best if it's a prime number.\n\t///     Hash            Hash function. See functional.h for examples of hash functions.\n\t///     Equal           Equality testing predicate; tells if two elements are equal.\n\t///\n\ttemplate <typename T, size_t bucketCount, typename Hash = eastl::hash<T>, typename Equal = eastl::equal_to<T> >\n\tclass intrusive_hash_set : public intrusive_hashtable<T, T, Hash, Equal, bucketCount, true, true>\n\t{\n\tpublic:\n\t\ttypedef intrusive_hashtable<T, T, Hash, Equal, bucketCount, true, true>     base_type;\n\t\ttypedef intrusive_hash_set<T, bucketCount, Hash, Equal>                     this_type;\n\n\tpublic:\n\t\texplicit intrusive_hash_set(const Hash& h = Hash(), const Equal& eq = Equal())\n\t\t\t: base_type(h, eq)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea?\n\t\t//intrusive_hash_set(std::initializer_list<value_type> ilist);\n\n\t}; // intrusive_hash_set\n\n\n\n\n\t/// intrusive_hash_multiset\n\t///\n\t/// Implements a intrusive_hash_multiset, which is the same thing as a intrusive_hash_set \n\t/// except that contained elements need not be unique. See the documentation \n\t/// for intrusive_hash_set for details.\n\t///\n\t/// Template parameters:\n\t///     T               The type of object the set holds (a.k.a. value).\n\t///     bucketCount     The number of buckets to use. Best if it's a prime number.\n\t///     Hash            Hash function. See functional.h for examples of hash functions.\n\t///     Equal           Equality testing predicate; tells if two elements are equal.\n\t///\n\ttemplate <typename T, size_t bucketCount, typename Hash = eastl::hash<T>, typename Equal = eastl::equal_to<T> >\n\tclass intrusive_hash_multiset : public intrusive_hashtable<T, T, Hash, Equal, bucketCount, true, false>\n\t{\n\tpublic:\n\t\ttypedef intrusive_hashtable<T, T, Hash, Equal, bucketCount, true, false>    base_type;\n\t\ttypedef intrusive_hash_multiset<T, bucketCount, Hash, Equal>                this_type;\n\n\tpublic:\n\t\texplicit intrusive_hash_multiset(const Hash& h = Hash(), const Equal& eq = Equal())\n\t\t\t: base_type(h, eq)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t// To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea?\n\t\t//intrusive_hash_multiset(std::initializer_list<value_type> ilist);\n\n\t}; // intrusive_hash_multiset\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/intrusive_list.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// The intrusive list container is similar to a list, with the primary\n// different being that intrusive lists allow you to control memory\n// allocation.\n//\n// * Intrusive lists store the nodes directly in the data items. This\n//   is done by deriving the object from intrusive_list_node.\n//\n// * The container does no memory allocation -- it works entirely with\n//   the submitted nodes. This does mean that it is the client's job to \n//   free the nodes in an intrusive list, though.\n//\n// * Valid node pointers can be converted back to iterators in O(1).\n//   This is because objects in the list are also nodes in the list.\n//\n// * intrusive_list does not support copy construction or assignment; \n//   the push, pop, and insert operations take ownership of the \n//   passed object.\n//\n// Usage notes:\n//\n// * You can use an intrusive_list directly with the standard nodes\n//   if you have some other way of converting the node pointer back\n//   to your data pointer.\n//\n// * Remember that the list destructor doesn't deallocate nodes -- it can't.\n//\n// * The size is not cached; this makes size() linear time but splice() is\n//   constant time. This does mean that you can remove() an element without\n//   having to figure out which list it is in, however.\n//\n// * You can insert a node into multiple intrusive_lists. One way to do so\n//   is to (ab)use inheritance:\n//\n//      struct NodeA : public intrusive_list_node {};\n//      struct NodeB : public intrusive_list_node {};\n//      struct Object : public NodeA, nodeB {};\n//\n//      intrusive_list<NodeA> listA;\n//      intrusive_list<NodeB> listB;\n//\n//      listA.push_back(obj);\n//      listB.push_back(obj);\n//\n// * find() vs. locate()\n//   The find(v) algorithm returns an iterator p such that *p == v; intrusive_list::locate(v) \n//   returns an iterator p such that &*p == &v. intrusive_list<> doesn't have find() mainly \n//   because list<> doesn't have it either, but there's no reason it couldn't. intrusive_list\n//   uses the name 'find' because:\n//      - So as not to confuse the member function with the well-defined free function from algorithm.h.\n//      - Because it is not API-compatible with eastl::find().\n//      - Because it simply locates an object within the list based on its node entry and doesn't perform before any value-based searches or comparisons.\n//\n// Differences between intrusive_list and std::list:\n//\n// Issue                            std::list       intrusive_list\n// --------------------------------------------------------------\n// Automatic node ctor/dtor         Yes             No\n// Can memmove() container          Maybe*          No\n// Same item in list twice          Yes(copy/byref) No\n// Can store non-copyable items     No              Yes\n// size()                           O(1) or O(n)    O(n)\n// clear()                          O(n)            O(1)\n// erase(range)                     O(n)            O(1)\n// splice(range)                    O(1) or O(n)    O(1)\n// Convert reference to iterator    No              O(1)\n// Remove without container         No              O(1)\n// Nodes in mixed allocators        No              Yes\n//\n// *) Not required by standard but can be done with some STL implementations.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTRUSIVE_LIST_H\n#define EASTL_INTRUSIVE_LIST_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\ttemplate<class T>\n\tclass intrusive_list;\n\n\t/// intrusive_list_node\n\t///\n\t/// By design this must be a POD, as user structs will be inheriting from \n\t/// it and they may wish to remain POD themselves. However, if the \n\t/// EASTL_VALIDATE_INTRUSIVE_LIST option is enabled\n\t/// \n\tstruct intrusive_list_node\n\t{\n\t\tintrusive_list_node* mpNext;\n\t\tintrusive_list_node* mpPrev;\n\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\tintrusive_list_node()       // Implemented inline because GCC can't deal with member functions\n\t\t\t{                           // of may-alias classes being defined outside the declaration.\n\t\t\t\tmpNext = mpPrev = nullptr;\n\t\t\t}\n\n\t\t\t~intrusive_list_node()\n\t\t\t{\n\t\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t\t\tif(mpNext || mpPrev)\n\t\t\t\t\t\tEASTL_FAIL_MSG(\"~intrusive_list_node(): List is non-empty.\");\n\t\t\t\t#endif\n\t\t\t}\n\t\t#endif\n\t} EASTL_MAY_ALIAS;  // It's not clear if this really should be needed. An old GCC compatible compiler is generating some crashing optimized code when strict aliasing is enabled, but analysis of it seems to blame the compiler. However, this topic can be tricky.\n\n\n\n\t/// intrusive_list_iterator\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tclass intrusive_list_iterator\n\t{\n\tpublic:\n\t\ttypedef intrusive_list_iterator<T, Pointer, Reference>   this_type;\n\t\ttypedef intrusive_list_iterator<T, T*, T&>               iterator;\n\t\ttypedef intrusive_list_iterator<T, const T*, const T&>   const_iterator;\n\t\ttypedef T                                                value_type;\n\t\ttypedef T                                                node_type;\n\t\ttypedef intrusive_list_node                              base_node_type;\n\t\ttypedef ptrdiff_t                                        difference_type;\n\t\ttypedef Pointer                                          pointer;\n\t\ttypedef Reference                                        reference;\n\t\ttypedef eastl::bidirectional_iterator_tag         iterator_category;\n\tprivate:\n\t\tbase_node_type* mpNode;\n\n\tpublic:\n\t\tintrusive_list_iterator();\n\n\t\t// Note: you can also construct an iterator from T* via this, since T should inherit from\n\t\t// intrusive_list_node.\n\t\texplicit intrusive_list_iterator(const base_node_type* pNode);\n\t\t// Note: this isn't always a copy constructor, iterator is not always equal to this_type\n\t\tintrusive_list_iterator(const iterator& x);\n\t\t// Note: this isn't always a copy assignment operator, iterator is not always equal to this_type\n\t\tintrusive_list_iterator& operator=(const iterator& x);\n\n\t\t// Calling these on the end() of a list invokes undefined behavior.\n\t\treference operator*() const;\n\t\tpointer   operator->() const;\n\n\t\t// Returns a pointer to the fully typed node (the same as operator->) this is useful when\n\t\t// iterating a list to destroy all the nodes, calling this on the end() of a list results in\n\t\t// undefined behavior.\n\t\tpointer nodePtr() const;\n\n\t\tintrusive_list_iterator& operator++();\n\t\tintrusive_list_iterator& operator--();\n\n\t\tintrusive_list_iterator operator++(int);\n\t\tintrusive_list_iterator operator--(int);\n\n\t\t// The C++ defect report #179 requires that we support comparisons between const and non-const iterators.\n\t\t// Thus we provide additional template paremeters here to support this. The defect report does not\n\t\t// require us to support comparisons between reverse_iterators and const_reverse_iterators.\n\t\ttemplate <class PointerB, class ReferenceB>\n\t\tbool operator==(const intrusive_list_iterator<T, PointerB, ReferenceB>& other) const\n\t\t{\n\t\t\treturn mpNode == other.mpNode;\n\t\t}\n\n\t\ttemplate <typename PointerB, typename ReferenceB>\n\t\tinline bool operator!=(const intrusive_list_iterator<T, PointerB, ReferenceB>& other) const\n\t\t{\n\t\t\treturn mpNode != other.mpNode;\n\t\t}\n\n\t\t// We provide a version of operator!= for the case where the iterators are of the\n\t\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\t\tinline bool operator!=(const intrusive_list_iterator other) const { return mpNode != other.mpNode; }\n\n\tprivate:\n\n\t\t// for the \"copy\" constructor, which uses non-const iterator even in the\n\t\t// const_iterator case.  Also, some of the internal member functions in\n\t\t// intrusive_list<T> want to use mpNode.\n\t\tfriend const_iterator;\n\t\tfriend intrusive_list<T>;\n\n\t\t// for the comparison operators.\n\t\ttemplate<class U, class Pointer1, class Reference1>\n\t\tfriend class intrusive_list_iterator;\n\t}; // class intrusive_list_iterator\n\n\n\n\t/// intrusive_list_base\n\t///\n\tclass intrusive_list_base\n\t{\n\tpublic:\n\t\ttypedef eastl_size_t size_type;     // See config.h for the definition of this, which defaults to size_t.\n\t\ttypedef ptrdiff_t    difference_type;\n\n\tprotected:\n\t\tintrusive_list_node mAnchor;          ///< Sentinel node (end). All data nodes are linked in a ring from this node.\n\n\tpublic:\n\t\tintrusive_list_base();\n\t   ~intrusive_list_base();\n\n\t\tbool            empty() const EA_NOEXCEPT;\n\t\teastl_size_t    size() const EA_NOEXCEPT;  ///< Returns the number of elements in the list; O(n).\n\t\tvoid            clear() EA_NOEXCEPT;       ///< Clears the list; O(1). No deallocation occurs.\n\t\tvoid            pop_front();               ///< Removes an element from the front of the list; O(1). The element must exist, but is not deallocated.\n\t\tvoid            pop_back();                ///< Removes an element from the back of the list; O(1). The element must exist, but is not deallocated.\n\t\tEASTL_API void  reverse() EA_NOEXCEPT;     ///< Reverses a list so that front and back are swapped; O(n).\n\n\t\tEASTL_API bool  validate() const;          ///< Scans a list for linkage inconsistencies; O(n) time, O(1) space. Returns false if errors are detected, such as loops or branching.\n\n\t}; // class intrusive_list_base\n\n\n\n\t/// intrusive_list\n\t///\n\t/// Example usage:\n\t///    struct IntNode : public eastl::intrusive_list_node {\n\t///        int mX;\n\t///        IntNode(int x) : mX(x) { }\n\t///    };\n\t///    \n\t///    IntNode nodeA(0);\n\t///    IntNode nodeB(1);\n\t///    \n\t///    intrusive_list<IntNode> intList;\n\t///    intList.push_back(nodeA);\n\t///    intList.push_back(nodeB);\n\t///    intList.remove(nodeA);\n\t///    \n\ttemplate <typename T = intrusive_list_node>\n\tclass intrusive_list : public intrusive_list_base\n\t{\n\tpublic:\n\t\ttypedef intrusive_list<T>                               this_type;\n\t\ttypedef intrusive_list_base                             base_type;\n\t\ttypedef T                                               node_type;\n\t\ttypedef T                                               value_type;\n\t\ttypedef typename base_type::size_type                   size_type;\n\t\ttypedef typename base_type::difference_type             difference_type;\n\t\ttypedef T&                                              reference;\n\t\ttypedef const T&                                        const_reference;\n\t\ttypedef T*                                              pointer;\n\t\ttypedef const T*                                        const_pointer;\n\t\ttypedef intrusive_list_iterator<T, T*, T&>              iterator;\n\t\ttypedef intrusive_list_iterator<T, const T*, const T&>  const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>               reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>         const_reverse_iterator;\n\n\tpublic:\n\t\tintrusive_list();                                ///< Creates an empty list.\n\t\tintrusive_list(const this_type& x);              ///< Creates an empty list; ignores the argument.\n\t  //intrusive_list(std::initializer_list<value_type> ilist); To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea?\n\n\t\tthis_type&  operator=(const this_type& x);       ///< Clears the list; ignores the argument.\n\t\tvoid        swap(this_type&);                    ///< Swaps the contents of two intrusive lists; O(1).\n\n\t\titerator                begin() EA_NOEXCEPT;                 ///< Returns an iterator pointing to the first element in the list.\n\t\tconst_iterator          begin() const EA_NOEXCEPT;           ///< Returns a const_iterator pointing to the first element in the list.\n\t\tconst_iterator          cbegin() const EA_NOEXCEPT;          ///< Returns a const_iterator pointing to the first element in the list.\n\n\t\titerator                end() EA_NOEXCEPT;                   ///< Returns an iterator pointing one-after the last element in the list.\n\t\tconst_iterator          end() const EA_NOEXCEPT;             ///< Returns a const_iterator pointing one-after the last element in the list.\n\t\tconst_iterator          cend() const EA_NOEXCEPT;            ///< Returns a const_iterator pointing one-after the last element in the list.\n\n\t\treverse_iterator        rbegin() EA_NOEXCEPT;                ///< Returns a reverse_iterator pointing at the end of the list (start of the reverse sequence).\n\t\tconst_reverse_iterator  rbegin() const EA_NOEXCEPT;          ///< Returns a const_reverse_iterator pointing at the end of the list (start of the reverse sequence).\n\t\tconst_reverse_iterator  crbegin() const EA_NOEXCEPT;         ///< Returns a const_reverse_iterator pointing at the end of the list (start of the reverse sequence).\n\n\t\treverse_iterator        rend() EA_NOEXCEPT;                  ///< Returns a reverse_iterator pointing at the start of the list (end of the reverse sequence).\n\t\tconst_reverse_iterator  rend() const EA_NOEXCEPT;            ///< Returns a const_reverse_iterator pointing at the start of the list (end of the reverse sequence).\n\t\tconst_reverse_iterator  crend() const EA_NOEXCEPT;           ///< Returns a const_reverse_iterator pointing at the start of the list (end of the reverse sequence).\n\t\t\n\t\treference               front();                 ///< Returns a reference to the first element. The list must be non-empty.\n\t\tconst_reference         front() const;           ///< Returns a const reference to the first element. The list must be non-empty.\n\t\treference               back();                  ///< Returns a reference to the last element. The list must be non-empty.\n\t\tconst_reference         back() const;            ///< Returns a const reference to the last element. The list must be non-empty.\n\n\t\tvoid        push_front(value_type& x);             ///< Adds an element to the front of the list; O(1). The element is not copied. The element must not be in any other list.\n\t\tvoid        push_back(value_type& x);              ///< Adds an element to the back of the list; O(1). The element is not copied. The element must not be in any other list.\n\n\t\tbool        contains(const value_type& x) const;   ///< Returns true if the given element is in the list; O(n). Equivalent to (locate(x) != end()).\n\n\t\titerator        locate(value_type& x);             ///< Converts a reference to an object in the list back to an iterator, or returns end() if it is not part of the list. O(n)\n\t\tconst_iterator  locate(const value_type& x) const; ///< Converts a const reference to an object in the list back to a const iterator, or returns end() if it is not part of the list. O(n)\n\n\t\titerator    insert(const_iterator pos, value_type& x);   ///< Inserts an element before the element pointed to by the iterator. O(1)\n\t\titerator    erase(const_iterator pos);                   ///< Erases the element pointed to by the iterator. O(1)\n\t\titerator    erase(const_iterator pos, const_iterator last);    ///< Erases elements within the iterator range [pos, last). O(1)\n\n\t\treverse_iterator erase(const_reverse_iterator pos);\n\t\treverse_iterator erase(const_reverse_iterator pos, const_reverse_iterator last);\n\n\t\tstatic void remove(value_type& value);                    ///< Erases an element from a list; O(1). Note that this is static so you don't need to know which list the element, although it must be in some list.\n\n\t\tvoid               splice(const_iterator pos, value_type& x);\n\t\t\t\t///< Moves the given element into this list before the element pointed to by pos; O(1).\n\t\t\t\t///< Required: x must be in some list or have first/next pointers that point it itself.\n\n\t\tvoid               splice(const_iterator pos, intrusive_list& x);\n\t\t\t\t///< Moves the contents of a list into this list before the element pointed to by pos; O(1).\n\t\t\t\t///< Required: &x != this (same as std::list).\n\n\t\tvoid               splice(const_iterator pos, intrusive_list& x, const_iterator i);\n\t\t\t\t///< Moves the given element pointed to i within the list x into the current list before\n\t\t\t\t///< the element pointed to by pos; O(1).\n\n\t\tvoid               splice(const_iterator pos, intrusive_list& x, const_iterator first, const_iterator last);\n\t\t\t\t///< Moves the range of elements [first, last) from list x into the current list before\n\t\t\t\t///< the element pointed to by pos; O(1).\n\t\t\t\t///< Required: pos must not be in [first, last). (same as std::list).\n\n\tpublic:\n\t\t// Sorting functionality\n\t\t// This is independent of the global sort algorithms, as lists are \n\t\t// linked nodes and can be sorted more efficiently by moving nodes\n\t\t// around in ways that global sort algorithms aren't privy to.\n\n\t\tvoid merge(this_type& x);\n\n\t\ttemplate <typename Compare>\n\t\tvoid merge(this_type& x, Compare compare);\n\n\t\tvoid unique();\n\n\t\ttemplate <typename BinaryPredicate>\n\t\tvoid unique(BinaryPredicate);\n\n\t\tvoid sort();\n\n\t\ttemplate<typename Compare>\n\t\tvoid sort(Compare compare);\n\n\tpublic:\n\t\t// bool validate() const; // Inherited from parent.\n\t\tint     validate_iterator(const_iterator i) const;\n\n\t}; // intrusive_list\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_list_node\n\t///////////////////////////////////////////////////////////////////////\n\n\t// Moved to be inline within the class because the may-alias attribute is\n\t// triggering what appears to be a bug in GCC that effectively requires \n\t// may-alias structs to implement inline member functions within the class\n\t// declaration. We don't have a .cpp file for \n\t// #if EASTL_VALIDATE_INTRUSIVE_LIST\n\t//     inline intrusive_list_node::intrusive_list_node()\n\t//     {\n\t//         mpNext = mpPrev = nullptr;\n\t//     }\n\t//\n\t//     inline intrusive_list_node::~intrusive_list_node()\n\t//     {\n\t//         #if EASTL_ASSERT_ENABLED\n\t//             if(mpNext || mpPrev)\n\t//                 EASTL_FAIL_MSG(\"~intrusive_list_node(): List is non-empty.\");\n\t//         #endif\n\t//     }\n\t// #endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_list_iterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline intrusive_list_iterator<T, Pointer, Reference>::intrusive_list_iterator()\n\t{\n\t\t#if EASTL_DEBUG\n\t\t\tmpNode = nullptr;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline intrusive_list_iterator<T, Pointer, Reference>::intrusive_list_iterator(const base_node_type* pNode)\n\t\t: mpNode(const_cast<base_node_type*>(pNode))\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline intrusive_list_iterator<T, Pointer, Reference>::intrusive_list_iterator(const iterator& x)\n\t\t: mpNode(x.mpNode)\n\t{\n\t\t// Empty\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::this_type&\n\tintrusive_list_iterator<T, Pointer, Reference>::operator=(const iterator& x)\n\t{\n\t    mpNode = x.mpNode;\n\t    return *this;\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::reference\n\tintrusive_list_iterator<T, Pointer, Reference>::operator*() const\n\t{\n\t\treturn *static_cast<pointer>(mpNode);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::pointer\n\tintrusive_list_iterator<T, Pointer, Reference>::operator->() const\n\t{\n\t\treturn static_cast<pointer>(mpNode);\n\t}\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::pointer\n\tintrusive_list_iterator<T, Pointer, Reference>::nodePtr() const\n\t{\n\t\treturn static_cast<pointer>(mpNode);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::this_type&\n\tintrusive_list_iterator<T, Pointer, Reference>::operator++()\n\t{\n\t\tmpNode = mpNode->mpNext;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::this_type\n\tintrusive_list_iterator<T, Pointer, Reference>::operator++(int)\n\t{\n\t\tintrusive_list_iterator it(*this);\n\t\tmpNode = mpNode->mpNext;\n\t\treturn it;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::this_type&\n\tintrusive_list_iterator<T, Pointer, Reference>::operator--()\n\t{\n\t\tmpNode = mpNode->mpPrev;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename intrusive_list_iterator<T, Pointer, Reference>::this_type\n\tintrusive_list_iterator<T, Pointer, Reference>::operator--(int)\n\t{\n\t\tintrusive_list_iterator it(*this);\n\t\tmpNode = mpNode->mpPrev;\n\t\treturn it;\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_list_base\n\t///////////////////////////////////////////////////////////////////////\n\n\tinline intrusive_list_base::intrusive_list_base() \n\t{\n\t\tmAnchor.mpNext = mAnchor.mpPrev = &mAnchor;\n\t}\n\n\tinline intrusive_list_base::~intrusive_list_base()\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\tclear();\n\t\t\tmAnchor.mpNext = mAnchor.mpPrev = nullptr;\n\t\t#endif\n\t}\n\n\n\tinline bool intrusive_list_base::empty() const EA_NOEXCEPT\n\t{\n\t\treturn mAnchor.mpPrev == &mAnchor;\n\t}\n\n\n\tinline intrusive_list_base::size_type intrusive_list_base::size() const EA_NOEXCEPT\n\t{\n\t\tconst intrusive_list_node* p = &mAnchor;\n\t\tsize_type n = (size_type)-1;\n\n\t\tdo {\n\t\t\t++n;\n\t\t\tp = p->mpNext;\n\t\t} while(p != &mAnchor);\n\n\t\treturn n;\n\t}\n\n\n\tinline void intrusive_list_base::clear() EA_NOEXCEPT\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\t// Need to clear out all the next/prev pointers in the elements;\n\t\t\t// this makes this operation O(n) instead of O(1).\n\t\t\tintrusive_list_node* pNode = mAnchor.mpNext;\n\n\t\t\twhile(pNode != &mAnchor)\n\t\t\t{\n\t\t\t\tintrusive_list_node* const pNextNode = pNode->mpNext;\n\t\t\t\tpNode->mpNext = pNode->mpPrev = nullptr;\n\t\t\t\tpNode = pNextNode;\n\t\t\t}\n\t\t#endif\n\n\t\tmAnchor.mpNext = mAnchor.mpPrev = &mAnchor;\n\t}\n\n\n\tinline void intrusive_list_base::pop_front()\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\tintrusive_list_node* const pNode = mAnchor.mpNext;\n\t\t#endif\n\n\t\tmAnchor.mpNext->mpNext->mpPrev = &mAnchor;\n\t\tmAnchor.mpNext = mAnchor.mpNext->mpNext;\n\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\tif(pNode != &mAnchor)\n\t\t\t\tpNode->mpNext = pNode->mpPrev = nullptr;\n\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\telse\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::pop_front(): empty list.\");\n\t\t\t#endif\n\t\t#endif\n\t}\n\n\n\tinline void intrusive_list_base::pop_back()\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\tintrusive_list_node* const pNode = mAnchor.mpPrev;\n\t\t#endif\n\n\t\tmAnchor.mpPrev->mpPrev->mpNext = &mAnchor;\n\t\tmAnchor.mpPrev = mAnchor.mpPrev->mpPrev;\n\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\tif(pNode != &mAnchor)\n\t\t\t\tpNode->mpNext = pNode->mpPrev = nullptr;\n\t\t\t#if EASTL_ASSERT_ENABLED\n\t\t\telse\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::pop_back(): empty list.\");\n\t\t\t#endif\n\t\t#endif\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// intrusive_list\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T>\n\tinline intrusive_list<T>::intrusive_list()\n\t{\n\t}\n\n\n\ttemplate <typename T>\n\tinline intrusive_list<T>::intrusive_list(const this_type& /*x*/)\n\t  : intrusive_list_base()\n\t{\n\t\t// We intentionally ignore argument x.\n\t\t// To consider: Shouldn't this function simply not exist? Is there a useful purpose for having this function?\n\t\t// There should be a comment here about it, though my first guess is that this exists to quell VC++ level 4/-Wall compiler warnings.\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::this_type& intrusive_list<T>::operator=(const this_type& /*x*/)\n\t{ \n\t\t// We intentionally ignore argument x.\n\t\t// See notes above in the copy constructor about questioning the existence of this function.\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::iterator intrusive_list<T>::begin() EA_NOEXCEPT\n\t{\n\t\treturn iterator(mAnchor.mpNext);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_iterator intrusive_list<T>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mAnchor.mpNext);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_iterator intrusive_list<T>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(mAnchor.mpNext);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::iterator intrusive_list<T>::end() EA_NOEXCEPT\n\t{\n\t\treturn iterator(&mAnchor);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_iterator intrusive_list<T>::end() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&mAnchor);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_iterator intrusive_list<T>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&mAnchor);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::reverse_iterator intrusive_list<T>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(iterator(&mAnchor));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(&mAnchor));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(&mAnchor));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::reverse_iterator intrusive_list<T>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(iterator(mAnchor.mpNext));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(mAnchor.mpNext));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(const_iterator(mAnchor.mpNext));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::reference intrusive_list<T>::front()\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST && EASTL_ASSERT_ENABLED\n\t\t\tif(mAnchor.mpNext == &mAnchor)\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::front(): empty list.\");\n\t\t#endif\n\n\t\treturn *static_cast<T*>(mAnchor.mpNext);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_reference intrusive_list<T>::front() const\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST && EASTL_ASSERT_ENABLED\n\t\t\tif(mAnchor.mpNext == &mAnchor)\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::front(): empty list.\");\n\t\t#endif\n\n\t\treturn *static_cast<const T*>(mAnchor.mpNext);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::reference intrusive_list<T>::back()\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST && EASTL_ASSERT_ENABLED\n\t\t\tif(mAnchor.mpNext == &mAnchor)\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::back(): empty list.\");\n\t\t#endif\n\n\t\treturn *static_cast<T*>(mAnchor.mpPrev);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_reference intrusive_list<T>::back() const\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST && EASTL_ASSERT_ENABLED\n\t\t\tif(mAnchor.mpNext == &mAnchor)\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::back(): empty list.\");\n\t\t#endif\n\n\t\treturn *static_cast<const T*>(mAnchor.mpPrev);\n\t}\n\n\n\ttemplate <typename T>\n\tinline void intrusive_list<T>::push_front(value_type& x)\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST && EASTL_ASSERT_ENABLED\n\t\t\tif(x.mpNext || x.mpPrev)\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::push_front(): element already on a list.\");\n\t\t#endif\n\n\t\tx.mpNext = mAnchor.mpNext;\n\t\tx.mpPrev = &mAnchor;\n\t\tmAnchor.mpNext = &x;\n\t\tx.mpNext->mpPrev = &x;\n\t}\n\n\n\ttemplate <typename T>\n\tinline void intrusive_list<T>::push_back(value_type& x)\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST && EASTL_ASSERT_ENABLED\n\t\t\tif(x.mpNext || x.mpPrev)\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::push_back(): element already on a list.\");\n\t\t#endif\n\n\t\tx.mpPrev = mAnchor.mpPrev;\n\t\tx.mpNext = &mAnchor;\n\t\tmAnchor.mpPrev = &x;\n\t\tx.mpPrev->mpNext = &x;\n\t}\n\n\n\ttemplate <typename T>\n\tinline bool intrusive_list<T>::contains(const value_type& x) const\n\t{\n\t\tfor(const intrusive_list_node* p = mAnchor.mpNext; p != &mAnchor; p = p->mpNext)\n\t\t{\n\t\t\tif(p == &x)\n\t\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::iterator intrusive_list<T>::locate(value_type& x)\n\t{\n\t\tfor(intrusive_list_node* p = (T*)mAnchor.mpNext; p != &mAnchor; p = p->mpNext)\n\t\t{\n\t\t\tif(p == &x)\n\t\t\t\treturn iterator(p);\n\t\t}\n\n\t\treturn iterator(&mAnchor);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::const_iterator intrusive_list<T>::locate(const value_type& x) const\n\t{\n\t\tfor(const intrusive_list_node* p = mAnchor.mpNext; p != &mAnchor; p = p->mpNext)\n\t\t{\n\t\t\tif(p == &x)\n\t\t\t\treturn const_iterator(p);\n\t\t}\n\n\t\treturn const_iterator(&mAnchor);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::iterator intrusive_list<T>::insert(const_iterator pos, value_type& x)\n\t{\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST && EASTL_ASSERT_ENABLED\n\t\t\tif(x.mpNext || x.mpPrev)\n\t\t\t\tEASTL_FAIL_MSG(\"intrusive_list::insert(): element already on a list.\");\n\t\t#endif\n\n\t\tintrusive_list_node& next = *pos.mpNode;\n\t\tintrusive_list_node& prev = *next.mpPrev;\n\n\t\tprev.mpNext = next.mpPrev = &x;\n\t\tx.mpPrev    = &prev;\n\t\tx.mpNext    = &next;\n\n\t\treturn iterator(&x);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::iterator\n\tintrusive_list<T>::erase(const_iterator pos)\n\t{\n\t\tintrusive_list_node& prev = *pos.mpNode->mpPrev;\n\t\tintrusive_list_node& next = *pos.mpNode->mpNext;\n\t\tprev.mpNext = &next;\n\t\tnext.mpPrev = &prev;\n\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\titerator ii(pos.mpNode);\n\t\t\tii.mpNode->mpPrev = ii.mpNode->mpNext = nullptr;\n\t\t#endif\n\n\t\treturn iterator(&next);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::iterator\n\tintrusive_list<T>::erase(const_iterator first, const_iterator last)\n\t{\n\t\tintrusive_list_node& prev = *(first.mpNode->mpPrev);\n\t\tintrusive_list_node& next = *last.mpNode;\n\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\t// need to clear out all the next/prev pointers in the elements;\n\t\t\t// this makes this operation O(n) instead of O(1), sadly, although\n\t\t\t// it's technically amortized O(1) since you could count yourself\n\t\t\t// as paying this cost with each insert.\n\t\t\tintrusive_list_node* pCur = first.mpNode;\n\n\t\t\twhile(pCur != &next)\n\t\t\t{\n\t\t\t\tintrusive_list_node* const pCurNext = pCur->mpNext;\n\t\t\t\tpCur->mpPrev = pCur->mpNext = nullptr;\n\t\t\t\tpCur = pCurNext;\n\t\t\t}\n\t\t#endif\n\n\t\tprev.mpNext = &next;\n\t\tnext.mpPrev = &prev;\n\n\t\treturn iterator(last.mpNode);\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::reverse_iterator\n\tintrusive_list<T>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename T>\n\tinline typename intrusive_list<T>::reverse_iterator\n\tintrusive_list<T>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::swap(intrusive_list& x)\n\t{\n\t\t// swap anchors\n\t\tintrusive_list_node temp(mAnchor);\n\t\tmAnchor   = x.mAnchor;\n\t\tx.mAnchor = temp;\n\n\t\t// Fixup node pointers into the anchor, since the addresses of \n\t\t// the anchors must stay the same with each list.\n\t\tif(mAnchor.mpNext == &x.mAnchor)\n\t\t\tmAnchor.mpNext = mAnchor.mpPrev = &mAnchor;\n\t\telse\n\t\t\tmAnchor.mpNext->mpPrev = mAnchor.mpPrev->mpNext = &mAnchor;\n\n\t\tif(x.mAnchor.mpNext == &mAnchor)\n\t\t\tx.mAnchor.mpNext = x.mAnchor.mpPrev = &x.mAnchor;\n\t\telse\n\t\t\tx.mAnchor.mpNext->mpPrev = x.mAnchor.mpPrev->mpNext = &x.mAnchor;\n\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\ttemp.mpPrev = temp.mpNext = nullptr;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::splice(const_iterator pos, value_type& value)\n\t{\n\t\t// Note that splice(pos, x, pos) and splice(pos+1, x, pos)\n\t\t// are valid and need to be handled correctly.\n\n\t\tif(pos.mpNode != &value)\n\t\t{\n\t\t\t// Unlink item from old list.\n\t\t\tintrusive_list_node& oldNext = *value.mpNext;\n\t\t\tintrusive_list_node& oldPrev = *value.mpPrev;\n\t\t\toldNext.mpPrev = &oldPrev;\n\t\t\toldPrev.mpNext = &oldNext;\n\n\t\t\t// Relink item into new list.\n\t\t\tintrusive_list_node& newNext = *pos.mpNode;\n\t\t\tintrusive_list_node& newPrev = *newNext.mpPrev;\n\n\t\t\tnewPrev.mpNext = &value;\n\t\t\tnewNext.mpPrev = &value;\n\t\t\tvalue.mpPrev = &newPrev;\n\t\t\tvalue.mpNext = &newNext;\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::splice(const_iterator pos, intrusive_list& x)\n\t{\n\t\t// Note: &x == this is prohibited, so self-insertion is not a problem.\n\t\tif(x.mAnchor.mpNext != &x.mAnchor) // If the list 'x' isn't empty...\n\t\t{\n\t\t\tintrusive_list_node& next       = *pos.mpNode;\n\t\t\tintrusive_list_node& prev       = *next.mpPrev;\n\t\t\tintrusive_list_node& insertPrev = *x.mAnchor.mpNext;\n\t\t\tintrusive_list_node& insertNext = *x.mAnchor.mpPrev;\n\n\t\t\tprev.mpNext       = &insertPrev;\n\t\t\tinsertPrev.mpPrev = &prev;\n\t\t\tinsertNext.mpNext = &next;\n\t\t\tnext.mpPrev       = &insertNext;\n\t\t\tx.mAnchor.mpPrev  = x.mAnchor.mpNext = &x.mAnchor;\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::splice(const_iterator pos, intrusive_list& /*x*/, const_iterator i)\n\t{\n\t\t// Note: &x == this is prohibited, so self-insertion is not a problem.\n\n\t\t// Note that splice(pos, x, pos) and splice(pos + 1, x, pos)\n\t\t// are valid and need to be handled correctly.\n\n\t\t// We don't need to check if the source list is empty, because \n\t\t// this function expects a valid iterator from the source list,\n\t\t// and thus the list cannot be empty in such a situation.\n\n\t\titerator ii(i.mpNode); // Make a temporary non-const version.\n\n\t\tif(pos != ii)\n\t\t{\n\t\t\t// Unlink item from old list.\n\t\t\tintrusive_list_node& oldNext = *ii.mpNode->mpNext;\n\t\t\tintrusive_list_node& oldPrev = *ii.mpNode->mpPrev;\n\t\t\toldNext.mpPrev = &oldPrev;\n\t\t\toldPrev.mpNext = &oldNext;\n\n\t\t\t// Relink item into new list.\n\t\t\tintrusive_list_node& newNext = *pos.mpNode;\n\t\t\tintrusive_list_node& newPrev = *newNext.mpPrev;\n\n\t\t\tnewPrev.mpNext = ii.mpNode;\n\t\t\tnewNext.mpPrev = ii.mpNode;\n\t\t\tii.mpNode->mpPrev = &newPrev;\n\t\t\tii.mpNode->mpNext = &newNext;\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::splice(const_iterator pos, intrusive_list& /*x*/, const_iterator first, const_iterator last)\n\t{\n\t\t// Note: &x == this is prohibited, so self-insertion is not a problem.\n\t\tif(first != last)\n\t\t{\n\t\t\tintrusive_list_node& insertPrev = *first.mpNode;\n\t\t\tintrusive_list_node& insertNext = *last.mpNode->mpPrev;\n\n\t\t\t// remove from old list\n\t\t\tinsertNext.mpNext->mpPrev = insertPrev.mpPrev;\n\t\t\tinsertPrev.mpPrev->mpNext = insertNext.mpNext;\n\n\t\t\t// insert into this list\n\t\t\tintrusive_list_node& next = *pos.mpNode;\n\t\t\tintrusive_list_node& prev = *next.mpPrev;\n\n\t\t\tprev.mpNext       = &insertPrev;\n\t\t\tinsertPrev.mpPrev = &prev;\n\t\t\tinsertNext.mpNext = &next;\n\t\t\tnext.mpPrev       = &insertNext;\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\tinline void intrusive_list<T>::remove(value_type& value)\n\t{\n\t\tintrusive_list_node& prev = *value.mpPrev;\n\t\tintrusive_list_node& next = *value.mpNext;\n\t\tprev.mpNext = &next;\n\t\tnext.mpPrev = &prev;\n\n\t\t#if EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\tvalue.mpPrev = value.mpNext = nullptr;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::merge(this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\titerator       first(begin());\n\t\t\titerator       firstX(x.begin());\n\t\t\tconst iterator last(end());\n\t\t\tconst iterator lastX(x.end());\n\n\t\t\twhile((first != last) && (firstX != lastX))\n\t\t\t{\n\t\t\t\tif(*firstX < *first)\n\t\t\t\t{\n\t\t\t\t\titerator next(firstX);\n\n\t\t\t\t\tsplice(first, x, firstX, ++next);\n\t\t\t\t\tfirstX = next;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++first;\n\t\t\t}\n\n\t\t\tif(firstX != lastX)\n\t\t\t\tsplice(last, x, firstX, lastX);\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\ttemplate <typename Compare>\n\tvoid intrusive_list<T>::merge(this_type& x, Compare compare)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\titerator       first(begin());\n\t\t\titerator       firstX(x.begin());\n\t\t\tconst iterator last(end());\n\t\t\tconst iterator lastX(x.end());\n\n\t\t\twhile((first != last) && (firstX != lastX))\n\t\t\t{\n\t\t\t\tif(compare(*firstX, *first))\n\t\t\t\t{\n\t\t\t\t\titerator next(firstX);\n\n\t\t\t\t\tsplice(first, x, firstX, ++next);\n\t\t\t\t\tfirstX = next;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++first;\n\t\t\t}\n\n\t\t\tif(firstX != lastX)\n\t\t\t\tsplice(last, x, firstX, lastX);\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::unique()\n\t{\n\t\titerator       first(begin());\n\t\tconst iterator last(end());\n\n\t\tif(first != last)\n\t\t{\n\t\t\titerator next(first);\n\n\t\t\twhile(++next != last)\n\t\t\t{\n\t\t\t\tif(*first == *next)\n\t\t\t\t\terase(next);\n\t\t\t\telse\n\t\t\t\t\tfirst = next;\n\t\t\t\tnext = first;\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\ttemplate <typename BinaryPredicate>\n\tvoid intrusive_list<T>::unique(BinaryPredicate predicate)\n\t{\n\t\titerator       first(begin());\n\t\tconst iterator last(end());\n\n\t\tif(first != last)\n\t\t{\n\t\t\titerator next(first);\n\n\t\t\twhile(++next != last)\n\t\t\t{\n\t\t\t\tif(predicate(*first, *next))\n\t\t\t\t\terase(next);\n\t\t\t\telse\n\t\t\t\t\tfirst = next;\n\t\t\t\tnext = first;\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\tvoid intrusive_list<T>::sort()\n\t{\n\t\t// We implement the algorithm employed by Chris Caulfield whereby we use recursive\n\t\t// function calls to sort the list. The sorting of a very large list may fail due to stack overflow\n\t\t// if the stack is exhausted. The limit depends on the platform and the avaialble stack space.\n\n\t\t// Easier-to-understand version of the 'if' statement:\n\t\t// iterator i(begin());\n\t\t// if((i != end()) && (++i != end())) // If the size is >= 2 (without calling the more expensive size() function)...\n\n\t\t// Faster, more inlinable version of the 'if' statement:\n\t\tif ((mAnchor.mpNext != &mAnchor) && (mAnchor.mpNext != mAnchor.mpPrev))\n\t\t{\n\t\t\t// Split the array into 2 roughly equal halves.\n\t\t\tthis_type leftList;     // This should cause no memory allocation.\n\t\t\tthis_type rightList;\n\n\t\t\t// We find an iterator which is in the middle of the list. The fastest way to do \n\t\t\t// this is to iterate from the base node both forwards and backwards with two \n\t\t\t// iterators and stop when they meet each other. Recall that our size() function \n\t\t\t// is not O(1) but is instead O(n), at least when EASTL_LIST_SIZE_CACHE is disabled.\n\t\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t\titerator mid(begin());\n\t\t\t\teastl::advance(mid, size() / 2);\n\t\t\t#else\n\t\t\t\titerator mid(begin()), tail(end());\n\n\t\t\t\twhile((mid != tail) && (++mid != tail))\n\t\t\t\t\t--tail;\n\t\t\t#endif\n\n\t\t\t// Move the left half of this into leftList and the right half into rightList.\n\t\t\tleftList.splice(leftList.begin(), *this, begin(), mid);\n\t\t\trightList.splice(rightList.begin(), *this);\n\n\t\t\t// Sort the sub-lists.\n\t\t\tleftList.sort();\n\t\t\trightList.sort();\n\n\t\t\t// Merge the two halves into this list.\n\t\t\tsplice(begin(), leftList);\n\t\t\tmerge(rightList);\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\ttemplate<typename Compare>\n\tvoid intrusive_list<T>::sort(Compare compare)\n\t{\n\t\t// We implement the algorithm employed by Chris Caulfield whereby we use recursive\n\t\t// function calls to sort the list. The sorting of a very large list may fail due to stack overflow\n\t\t// if the stack is exhausted. The limit depends on the platform and the avaialble stack space.\n\n\t\t// Easier-to-understand version of the 'if' statement:\n\t\t// iterator i(begin());\n\t\t// if((i != end()) && (++i != end())) // If the size is >= 2 (without calling the more expensive size() function)...\n\n\t\t// Faster, more inlinable version of the 'if' statement:\n\t\tif ((mAnchor.mpNext != &mAnchor) && (mAnchor.mpNext != mAnchor.mpPrev))\n\t\t{\n\t\t\t// Split the array into 2 roughly equal halves.\n\t\t\tthis_type leftList;     // This should cause no memory allocation.\n\t\t\tthis_type rightList;\n\n\t\t\t// We find an iterator which is in the middle of the list. The fastest way to do \n\t\t\t// this is to iterate from the base node both forwards and backwards with two \n\t\t\t// iterators and stop when they meet each other. Recall that our size() function \n\t\t\t// is not O(1) but is instead O(n), at least when EASTL_LIST_SIZE_CACHE is disabled.\n\t\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t\titerator mid(begin());\n\t\t\t\teastl::advance(mid, size() / 2);\n\t\t\t#else\n\t\t\t\titerator mid(begin()), tail(end());\n\n\t\t\t\twhile((mid != tail) && (++mid != tail))\n\t\t\t\t\t--tail;\n\t\t\t#endif\n\n\t\t\t// Move the left half of this into leftList and the right half into rightList.\n\t\t\tleftList.splice(leftList.begin(), *this, begin(), mid);\n\t\t\trightList.splice(rightList.begin(), *this);\n\n\t\t\t// Sort the sub-lists.\n\t\t\tleftList.sort(compare);\n\t\t\trightList.sort(compare);\n\n\t\t\t// Merge the two halves into this list.\n\t\t\tsplice(begin(), leftList);\n\t\t\tmerge(rightList, compare);\n\t\t}\n\t}\n\n\n\ttemplate <typename T>\n\tinline int intrusive_list<T>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Come up with a more efficient mechanism of doing this.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T>\n\tbool operator==(const intrusive_list<T>& a, const intrusive_list<T>& b)\n\t{\n\t\t// If we store an mSize member for intrusive_list, we want to take advantage of it here.\n\t\ttypename intrusive_list<T>::const_iterator ia   = a.begin();\n\t\ttypename intrusive_list<T>::const_iterator ib   = b.begin();\n\t\ttypename intrusive_list<T>::const_iterator enda = a.end();\n\t\ttypename intrusive_list<T>::const_iterator endb = b.end();\n\n\t\twhile((ia != enda) && (ib != endb) && (*ia == *ib))\n\t\t{\n\t\t\t++ia;\n\t\t\t++ib;\n\t\t}\n\t\treturn (ia == enda) && (ib == endb);\n\t}\n\n\ttemplate <typename T>\n\tbool operator!=(const intrusive_list<T>& a, const intrusive_list<T>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\ttemplate <typename T>\n\tbool operator<(const intrusive_list<T>& a, const intrusive_list<T>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\ttemplate <typename T>\n\tbool operator>(const intrusive_list<T>& a, const intrusive_list<T>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\ttemplate <typename T>\n\tbool operator<=(const intrusive_list<T>& a, const intrusive_list<T>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate <typename T>\n\tbool operator>=(const intrusive_list<T>& a, const intrusive_list<T>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\ttemplate <typename T>\n\tvoid swap(intrusive_list<T>& a, intrusive_list<T>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/intrusive_ptr.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_INTRUSIVE_PTR_H\n#define EASTL_INTRUSIVE_PTR_H\n\n\n#include <EASTL/internal/config.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t// We provide default implementations of AddRef and Release in the eastl namespace.\n\t// The user can override these on a per-class basis by defining their own specialized\n\t// intrusive_ptr_add_ref and intrusive_ptr_release functions. User-defined specializations\n\t// do not need to exist in the eastl namespace, but should preferably be in the namespace \n\t// of the templated class T.\n\ttemplate <typename T>\n\tvoid intrusive_ptr_add_ref(T* p)\n\t{\n\t\tp->AddRef();\n\t}\n\t \n\ttemplate <typename T>\n\tvoid intrusive_ptr_release(T* p)\n\t{\n\t\tp->Release();\n\t}\n\n\n\t//////////////////////////////////////////////////////////////////////////////\n\t/// intrusive_ptr\n\t/// \n\t/// This is a class that acts like the C++ auto_ptr class except that instead\n\t/// of deleting its member data when it goes out of scope, it releases its\n\t/// member data when it goes out of scope. This class thus requires that the \n\t/// templated data type have an AddRef and Release function (or whatever is\n\t/// configured to be the two refcount functions).\n\t/// \n\t/// This class is useful for automatically releasing an object when this \n\t/// class goes out of scope. See below for some usage.\n\t/// You should be careful about putting instances of this class as members of \n\t/// another class. If you do so, then the intrusive_ptr destructor will only\n\t/// be called if the object that owns it is destructed. This creates a potential\n\t/// chicken-and-egg situation. What if the intrusive_ptr member contains a \n\t/// pointer to an object that has a reference on the object that owns the \n\t/// intrusive_ptr member? The answer is that the neither object can ever be\n\t/// destructed. The solution is to:\n\t///    1) Be very careful about what objects you put into member intrusive_ptr objects.\n\t///    2) Clear out your intrusive_ptr members in your shutdown function.\n\t///    3) Simply don't use intrusive_ptr objects as class members.\n\t///\n\t/// Example usage:\n\t///    intrusive_ptr<IWidget> pWidget = new Widget;\n\t///    pWidget = new Widget;\n\t///    pWidget->Reset();\n\t///\n\ttemplate <typename T>\n\tclass intrusive_ptr\n\t{\n\tprotected:\n\t\t// Friend declarations.\n\t\ttemplate <typename U> friend class intrusive_ptr;\n\t\ttypedef intrusive_ptr<T> this_type;\n\n\t\tT* mpObject;\n\n\tpublic:\n\t\t/// element_type\n\t\t/// This typedef is present for consistency with the C++ standard library \n\t\t/// auto_ptr template. It allows users to refer to the templated type via\n\t\t/// a typedef. This is sometimes useful to be able to do.\n\t\t/// \n\t\t/// Example usage:\n\t\t///    intrusive_ptr<IWidget> ip;\n\t\t///    void DoSomething(intrusive_ptr<IWidget>::element_type someType);\n\t\t///\n\t\ttypedef T element_type;\n\n\t\t/// intrusive_ptr\n\t\t/// Default constructor. The member object is set to NULL.\n\t\tintrusive_ptr()\n\t\t\t: mpObject(NULL)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\t/// intrusive_ptr\n\t\t/// Provides a constructor which takes ownership of a pointer.\n\t\t/// The incoming pointer is AddRefd.\n\t\t///\n\t\t/// Example usage:\n\t\t///    intrusive_ptr<Widget> pWidget(new Widget);\n\t\tintrusive_ptr(T* p, bool bAddRef = true)\n\t\t\t: mpObject(p) \n\t\t{\n\t\t\tif(mpObject && bAddRef)\n\t\t\t\tintrusive_ptr_add_ref(mpObject);  // Intentionally do not prefix the call with eastl:: but instead allow namespace lookup to resolve the namespace.\n\t\t} \n\n\t\t/// intrusive_ptr\n\t\t/// Construction from self type.\n\t\tintrusive_ptr(const intrusive_ptr& ip) \n\t\t\t: mpObject(ip.mpObject) \n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\tintrusive_ptr_add_ref(mpObject);\n\t\t}\n\n\n\t\t/// intrusive_ptr\n\t\t/// move constructor\n\t\tintrusive_ptr(intrusive_ptr&& ip) \n\t\t\t: mpObject(nullptr)\n\t\t{\n\t\t\tswap(ip);\n\t\t}\n\n\t\t/// intrusive_ptr\n\t\t/// Provides a constructor which copies a pointer from another intrusive_ptr.\n\t\t/// The incoming pointer is AddRefd. The source intrusive_ptr object maintains\n\t\t/// its AddRef on the pointer.\n\t\t///\n\t\t/// Example usage:\n\t\t///    intrusive_ptr<Widget> pWidget1;\n\t\t///    intrusive_ptr<Widget> pWidget2(pWidget1);\n\t\ttemplate <typename U>\n\t\tintrusive_ptr(const intrusive_ptr<U>& ip) \n\t\t\t: mpObject(ip.mpObject) \n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\tintrusive_ptr_add_ref(mpObject);\n\t\t}\n\n\t\t/// intrusive_ptr\n\t\t/// Releases the owned pointer.\n\t\t~intrusive_ptr() \n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\tintrusive_ptr_release(mpObject);\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Assignment to self type.\n\t\tintrusive_ptr& operator=(const intrusive_ptr& ip)\n\t\t{\n\t\t\treturn operator=(ip.mpObject);\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Move assignment operator \n\t\tintrusive_ptr& operator=(intrusive_ptr&& ip)\n\t\t{\n\t\t\tswap(ip);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator =\n\t\t/// Assigns an intrusive_ptr object to this intrusive_ptr object.\n\t\t/// The incoming pointer is AddRefd. The source intrusive_ptr object \n\t\t/// maintains its AddRef on the pointer. If there is an existing member\n\t\t/// pointer, it is Released before the incoming pointer is assigned.\n\t\t/// If the incoming pointer is equal to the existing pointer, no    \n\t\t/// action is taken. The incoming pointer is AddRefd before any \n\t\t/// member pointer is Released.\n\t\ttemplate <typename U>\n\t\tintrusive_ptr& operator=(const intrusive_ptr<U>& ip)       \n\t\t{\n\t\t\treturn operator=(ip.mpObject);\n\t\t}\n\n\t\t/// operator=\n\t\t/// Assigns an intrusive_ptr object to this intrusive_ptr object.\n\t\t/// The incoming pointer is AddRefd. If there is an existing member\n\t\t/// pointer, it is Released before the incoming pointer is assigned.\n\t\t/// If the incoming pointer is equal to the existing pointer, no    \n\t\t/// action is taken. The incoming pointer is AddRefd before any \n\t\t/// member pointer is Released.\n\t\tintrusive_ptr& operator=(T* pObject)\n\t\t{\n\t\t\tif(pObject != mpObject)\n\t\t\t{\n\t\t\t\tT* const pTemp = mpObject; // Create temporary to prevent possible problems with re-entrancy.\n\t\t\t\tif(pObject)\n\t\t\t\t\tintrusive_ptr_add_ref(pObject);\n\t\t\t\tmpObject = pObject;\n\t\t\t\tif(pTemp)\n\t\t\t\t\tintrusive_ptr_release(pTemp);\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\t/// operator *\n\t\t/// Returns a reference to the contained object.\n\t\tT& operator *() const \n\t\t{\n\t\t\treturn *mpObject;\n\t\t}\n\n\t\t/// operator *\n\t\t/// Returns a pointer to the contained object, allowing the \n\t\t/// user to use this container as if it were contained pointer itself. \n\t\tT* operator ->() const\n\t\t{\n\t\t\treturn mpObject;\n\t\t}\n\n\t\t/// get()\n\t\t/// Returns a pointer to the contained object. \n\t\tT* get() const\n\t\t{\n\t\t\treturn mpObject;\n\t\t}\n\n\t\t/// reset\n\t\t/// Releases the owned object and clears our reference to it.\n\t\tvoid reset() \n\t\t{\n\t\t\tT* const pTemp = mpObject;\n\t\t\tmpObject = NULL;\n\t\t\tif(pTemp)\n\t\t\t\tintrusive_ptr_release(pTemp);\n\t\t}\n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer beween two intrusive_ptr objects.\n\t\tvoid swap(this_type& ip)\n\t\t{\n\t\t\tT* const pTemp = mpObject;\n\t\t\tmpObject = ip.mpObject;\n\t\t\tip.mpObject = pTemp;\n\t\t}\n\n\t\t/// attach\n\t\t/// Sets an intrusive_ptr pointer without calling AddRef() on\n\t\t/// the pointed object. The intrusive_ptr thus eventually only does a\n\t\t/// Release() on the object. This is useful for assuming a reference\n\t\t/// that someone else has handed you and making sure it is always\n\t\t/// released, even if you return in the middle of a function or an\n\t\t/// exception is thrown.\n\t\t///\n\t\tvoid attach(T* pObject)\n\t\t{\n\t\t\tT* const pTemp = mpObject;\n\t\t\tmpObject = pObject;\n\t\t\tif(pTemp)\n\t\t\t\tintrusive_ptr_release(pTemp);\n\t\t}\n\n\t\t/// detach\n\t\t/// Surrenders the reference held by an intrusive_ptr pointer -- \n\t\t/// it returns the current reference and nulls the pointer. If the returned\n\t\t/// pointer is non-null it must be released. This is useful in functions\n\t\t/// that must return a reference while possibly being aborted by a return\n\t\t/// or thrown exception:\n\t\t///\n\t\t/// bool GetFoo(T** pp){\n\t\t///    intrusive_ptr<T> p(PrivateGetFoo());\n\t\t///    if(p->Method())\n\t\t///        return false;\n\t\t///    *pp = p.detach();\n\t\t///    return true;\n\t\t/// }\n\t\tT* detach()\n\t\t{\n\t\t\tT* const pTemp = mpObject;\n\t\t\tmpObject = NULL;\n\t\t\treturn pTemp;\n\t\t}\n\n\t\t/// Implicit operator bool\n\t\t/// Allows for using a intrusive_ptr as a boolean. \n\t\t/// Example usage:\n\t\t///    intrusive_ptr<Widget> ptr = new Widget;\n\t\t///    if(ptr)\n\t\t///        ++*ptr;\n\t\t///     \n\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t/// The result is that this: if(intrusivePtr == 1) would yield true (bad).\n\t\ttypedef T* (this_type::*bool_)() const;\n\t\toperator bool_() const\n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\treturn &this_type::get;\n\t\t\treturn NULL;\n\t\t}\n\n\t\t/// operator!\n\t\t/// This returns the opposite of operator bool; it returns true if \n\t\t/// the owned pointer is null. Some compilers require this and some don't.\n\t\t///    intrusive_ptr<Widget> ptr = new Widget;\n\t\t///    if(!ptr)\n\t\t///        assert(false);\n\t\tbool operator!() const\n\t\t{\n\t\t\treturn (mpObject == NULL);\n\t\t}\n\n\t}; // class intrusive_ptr\n\n\n\t/// get_pointer\n\t/// returns intrusive_ptr::get() via the input intrusive_ptr. \n\ttemplate <typename T>\n\tinline T* get_pointer(const intrusive_ptr<T>& intrusivePtr)\n\t{\n\t\treturn intrusivePtr.get();\n\t}\n\n\t/// swap\n\t/// Exchanges the owned pointer beween two intrusive_ptr objects.\n\t/// This non-member version is useful for compatibility of intrusive_ptr\n\t/// objects with the C++ Standard Library and other libraries.\n\ttemplate <typename T>\n\tinline void swap(intrusive_ptr<T>& intrusivePtr1, intrusive_ptr<T>& intrusivePtr2)\n\t{\n\t\tintrusivePtr1.swap(intrusivePtr2);\n\t}\n\n\n\ttemplate <typename T, typename U>\n\tbool operator==(intrusive_ptr<T> const& iPtr1, intrusive_ptr<U> const& iPtr2)\n\t{\n\t\treturn (iPtr1.get() == iPtr2.get());\n\t}\n\n\ttemplate <typename T, typename U>\n\tbool operator!=(intrusive_ptr<T> const& iPtr1, intrusive_ptr<U> const& iPtr2)\n\t{\n\t\treturn (iPtr1.get() != iPtr2.get());\n\t}\n\n\ttemplate <typename T>\n\tbool operator==(intrusive_ptr<T> const& iPtr1, T* p)\n\t{\n\t\treturn (iPtr1.get() == p);\n\t}\n\n\ttemplate <typename T>\n\tbool operator!=(intrusive_ptr<T> const& iPtr1, T* p)\n\t{\n\t\treturn (iPtr1.get() != p);\n\t}\n\n\ttemplate <typename T>\n\tbool operator==(T* p, intrusive_ptr<T> const& iPtr2)\n\t{\n\t\treturn (p == iPtr2.get());\n\t}\n\n\ttemplate <typename T>\n\tbool operator!=(T* p, intrusive_ptr<T> const& iPtr2)\n\t{\n\t\treturn (p != iPtr2.get());\n\t}\n\n\ttemplate <typename T, typename U>\n\tbool operator<(intrusive_ptr<T> const& iPtr1, intrusive_ptr<U> const& iPtr2)\n\t{\n\t\treturn ((uintptr_t)iPtr1.get() < (uintptr_t)iPtr2.get());\n\t}\n\n\n\t/// static_pointer_cast\n\t/// Returns an intrusive_ptr<T> static-casted from a intrusive_ptr<U>.\n\ttemplate <class T, class U>\n\tintrusive_ptr<T> static_pointer_cast(const intrusive_ptr<U>& intrusivePtr)\n\t{\n\t\treturn static_cast<T*>(intrusivePtr.get());\n\t}\n\n\n\t#if EASTL_RTTI_ENABLED\n\n\t/// dynamic_pointer_cast\n\t/// Returns an intrusive_ptr<T> dynamic-casted from a intrusive_ptr<U>.\n\ttemplate <class T, class U>\n\tintrusive_ptr<T> dynamic_pointer_cast(const intrusive_ptr<U>& intrusivePtr)\n\t{\n\t\treturn dynamic_cast<T*>(intrusivePtr.get());\n\t}\n\n\t#endif\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/iterator.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_ITERATOR_H\n#define EASTL_ITERATOR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/internal/type_detected.h>\n#include <EASTL/internal/type_void_t.h>\n#include <EASTL/internal/memory_base.h>\n#include <EASTL/initializer_list.h>\n\nEA_DISABLE_ALL_VC_WARNINGS();\n\n#include <stddef.h>\n\nEA_RESTORE_ALL_VC_WARNINGS();\n\n// If the user has specified that we use std iterator\n// categories instead of EASTL iterator categories,\n// then #include <iterator>.\n#if EASTL_STD_ITERATOR_CATEGORY_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS();\n\n\t#include <iterator>\n\n\tEA_RESTORE_ALL_VC_WARNINGS();\n#endif\n\n\nEA_DISABLE_VC_WARNING(4619); // There is no warning number 'number'.\nEA_DISABLE_VC_WARNING(4217); // Member template functions cannot be used for copy-assignment or copy-construction.\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// iterator_status_flag\n\t///\n\t/// Defines the validity status of an iterator. This is primarily used for\n\t/// iterator validation in debug builds. These are implemented as OR-able\n\t/// flags (as opposed to mutually exclusive values) in order to deal with\n\t/// the nature of iterator status. In particular, an iterator may be valid\n\t/// but not dereferencable, as in the case with an iterator to container end().\n\t/// An iterator may be valid but also dereferencable, as in the case with an\n\t/// iterator to container begin().\n\t///\n\tenum iterator_status_flag\n\t{\n\t\tisf_none            = 0x00, /// This is called none and not called invalid because it is not strictly the opposite of invalid.\n\t\tisf_valid           = 0x01, /// The iterator is valid, which means it is in the range of [begin, end].\n\t\tisf_current         = 0x02, /// The iterator is valid and points to the same element it did when created. For example, if an iterator points to vector::begin() but an element is inserted at the front, the iterator is valid but not current. Modification of elements in place do not make iterators non-current.\n\t\tisf_can_dereference = 0x04  /// The iterator is dereferencable, which means it is in the range of [begin, end). It may or may not be current.\n\t};\n\n\n\n\t// The following declarations are taken directly from the C++ standard document.\n\t//    input_iterator_tag, etc.\n\t//    iterator\n\t//    iterator_traits\n\t//    reverse_iterator\n\n\t// Iterator categories\n\t// Every iterator is defined as belonging to one of the iterator categories that\n\t// we define here. These categories come directly from the C++ standard.\n\t#if !EASTL_STD_ITERATOR_CATEGORY_ENABLED // If we are to use our own iterator category definitions...\n\t\tstruct input_iterator_tag { };\n\t\tstruct output_iterator_tag { };\n\t\tstruct forward_iterator_tag       : public input_iterator_tag { };\n\t\tstruct bidirectional_iterator_tag : public forward_iterator_tag { };\n\t\tstruct random_access_iterator_tag : public bidirectional_iterator_tag { };\n\t\t// Originally an extension to the C++ standard, standardized in C++20.\n\t\t// Contiguous ranges are more than random access, they are physically contiguous.\n\t\t// Note: Pointers are contiguous but the specialization of iterator_traits for pointers defines\n\t\t// iterator_traits<T>::iterator_category as random_access_iterator_tag and thus users must\n\t\t// explicitly check both the iterator_category and the type.\n\t\tstruct contiguous_iterator_tag    : public random_access_iterator_tag { };\n\t#else\n\t\tusing input_iterator_tag = std::input_iterator_tag;\n\t\tusing output_iterator_tag = std::output_iterator_tag;\n\t\tusing forward_iterator_tag = std::forward_iterator_tag;\n\t\tusing bidirectional_iterator_tag = std::bidirectional_iterator_tag;\n\t\tusing random_access_iterator_tag = std::random_access_iterator_tag;\n\t#if defined(EA_COMPILER_CPP20_ENABLED)\n\t\tusing contiguous_iterator_tag = std::contiguous_iterator_tag;\n\t#endif\n\t#endif\n\n\n\t// struct iterator_traits\n\tnamespace internal\n\t{\n\t\t// Helper to make iterator_traits SFINAE friendly as N3844 requires.\n\t\ttemplate <typename Iterator, class = void>\n\t\tstruct default_iterator_traits {};\n\n\t\ttemplate <typename Iterator>\n\t\tstruct default_iterator_traits<\n\t\t\tIterator,\n\t\t\tvoid_t<\n\t\t\t\ttypename Iterator::iterator_category,\n\t\t\t\ttypename Iterator::value_type,\n\t\t\t\ttypename Iterator::difference_type,\n\t\t\t\ttypename Iterator::pointer,\n\t\t\t\ttypename Iterator::reference\n\t\t\t>\n\t\t>\n\t\t{\n\t\t\ttypedef typename Iterator::iterator_category iterator_category;\n\t\t\ttypedef typename Iterator::value_type        value_type;\n\t\t\ttypedef typename Iterator::difference_type   difference_type;\n\t\t\ttypedef typename Iterator::pointer           pointer;\n\t\t\ttypedef typename Iterator::reference         reference;\n\t\t};\n\t}\n\t\n\ttemplate <typename Iterator>\n\tstruct iterator_traits : internal::default_iterator_traits<Iterator> {};\n\t\n\ttemplate <typename T>\n\tstruct iterator_traits<T*>\n\t{\n\t\ttypedef eastl::random_access_iterator_tag iterator_category;     // To consider: Change this to contiguous_iterator_tag for the case that\n\t\ttypedef T                                        value_type;            //              EASTL_ITC_NS is \"eastl\" instead of \"std\".\n\t\ttypedef ptrdiff_t                                difference_type;\n\t\ttypedef T*                                       pointer;\n\t\ttypedef T&                                       reference;\n\t};\n\n\ttemplate <typename T>\n\tstruct iterator_traits<const T*>\n\t{\n\t\ttypedef eastl::random_access_iterator_tag iterator_category;\n\t\ttypedef T                                        value_type;\n\t\ttypedef ptrdiff_t                                difference_type;\n\t\ttypedef const T*                                 pointer;\n\t\ttypedef const T&                                 reference;\n\t};\n\n\n\n\n\t/// is_iterator_wrapper\n\t///\n\t/// Tells if an Iterator type is a wrapper type as opposed to a regular type.\n\t/// Relies on the class declaring a member function called unwrap.\n\t///\n\t/// Examples of wrapping iterators:\n\t///     generic_iterator\n\t///     move_iterator\n\t///     reverse_iterator<T> (if T is a wrapped iterator)\n\t/// Examples of non-wrapping iterators:\n\t///     iterator\n\t///     list::iterator\n\t///     char*\n\t///\n\t/// Example behavior:\n\t///     is_iterator_wrapper(int*)::value\t\t\t\t\t\t\t\t\t\t\t\t=> false\n\t///     is_iterator_wrapper(eastl::array<char>*)::value\t\t\t\t\t\t\t\t\t=> false\n\t///     is_iterator_wrapper(eastl::vector<int>::iterator)::value\t\t\t\t\t\t=> false\n\t///     is_iterator_wrapper(eastl::generic_iterator<int*>)::value\t\t\t\t\t\t=> true\n\t///     is_iterator_wrapper(eastl::move_iterator<eastl::array<int>::iterator>)::value\t=> true\n\t///     is_iterator_wrapper(eastl::reverse_iterator<int*>)::value\t\t\t\t\t\t=> false\n\t///     is_iterator_wrapper(eastl::reverse_iterator<eastl::move_iterator<int*>>)::value\t=> true\n\t///\n\ttemplate<typename Iterator>\n\tclass EASTL_REMOVE_AT_2024_SEPT is_iterator_wrapper\n\t{\n#if defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_CLANG_CL)\n\t\t// Using a default template type parameter trick here because\n\t\t// of a bug in clang that makes the other implementation not\n\t\t// work when unwrap() is private and this is class is a\n\t\t// friend.\n\t\t// See: https://bugs.llvm.org/show_bug.cgi?id=25334\n\t\ttemplate<typename T, typename U = decltype(eastl::declval<T>().unwrap())>\n\t\tusing detect_has_unwrap = U;\n#else\n\t\t// Note: the above implementation does not work on GCC when\n\t\t// unwrap() is private and this class is a friend. So we're\n\t\t// forced to diverge here to support both GCC and clang.\n\t\ttemplate<typename T>\n\t\tusing detect_has_unwrap = decltype(eastl::declval<T>().unwrap());\n#endif\n\tpublic:\n\t\tstatic const bool value = eastl::is_detected<detect_has_unwrap, Iterator>::value;\n\t};\n\n\n\t/// unwrap_iterator\n\t///\n\t/// Takes a wrapper Iterator (e.g. move_iterator, reverse_iterator, generic_iterator) instance\n\t/// and returns the wrapped iterator type. If Iterator is not a wrapper (including being a pointer),\n\t/// or is not an iterator, then this function returns it as-is.\n\t/// unwrap_iterator unwraps only a single layer of iterator at a time. You need to call it twice,\n\t/// for example, to unwrap two layers of iterators.\n\t///\n\t/// Example usage:\n\t///     int* pInt             = unwrap_iterator(&pIntArray[15]);\n\t///     int* pInt             = unwrap_iterator(generic_iterator(&pIntArray[15]));\n\t///     MyVector::iterator it = unwrap_iterator(myVector.begin());\n\t///     MyVector::iterator it = unwrap_iterator(move_iterator(myVector.begin()));\n\t///\n\ttemplate <typename Iterator, bool isWrapper>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_iterator_wrapper_helper\n\t{\n\t\tusing iterator_type = Iterator;\n\n\t\tstatic iterator_type get_unwrapped(Iterator it) { return it; }\n\t};\n\n\n\t// Note: some compilers (notably GCC) trigger deprecation warnings when doing template\n\t// specialization if the main template is derpecated, so turn the warning off here. If this\n\t// specialization is used, the warning will still trigger in the user code, this just\n\t// disables the warning in this declaration.\nEASTL_INTERNAL_DISABLE_DEPRECATED()\n\ttemplate <typename Iterator>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_iterator_wrapper_helper<Iterator, true>\n\t{\n\t\t// get_unwrapped must return by value since we're returning\n\t\t// it.unwrap(), and `it` will be out of scope as soon as\n\t\t// get_unwrapped returns.\n\t\tusing iterator_type =\n\t\t    typename eastl::remove_cvref<decltype(eastl::declval<Iterator>().unwrap())>::type;\n\n\t\tstatic iterator_type get_unwrapped(Iterator it) { return it.unwrap(); }\n\t};\n\n\n\ttemplate <typename Iterator>\n\tEASTL_REMOVE_AT_2024_SEPT inline typename is_iterator_wrapper_helper<Iterator, eastl::is_iterator_wrapper<Iterator>::value>::iterator_type unwrap_iterator(Iterator it)\n\t\t{ return eastl::is_iterator_wrapper_helper<Iterator, eastl::is_iterator_wrapper<Iterator>::value>::get_unwrapped(it); }\nEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\n\t/// reverse_iterator\n\t///\n\t/// From the C++ standard:\n\t/// Bidirectional and random access iterators have corresponding reverse\n\t/// iterator adaptors that iterate through the data structure in the\n\t/// opposite direction. They have the same signatures as the corresponding\n\t/// iterators. The fundamental relation between a reverse iterator and its\n\t/// corresponding iterator i is established by the identity:\n\t///     &*(reverse_iterator(i)) == &*(i - 1).\n\t/// This mapping is dictated by the fact that while there is always a pointer\n\t/// past the end of an array, there might not be a valid pointer before the\n\t/// beginning of an array.\n\t///\n\ttemplate <typename Iterator>\n\tclass reverse_iterator\n\t{\n\tpublic:\n\t\ttypedef Iterator\t\t\t\t\t\t\t\t\t\t\t\t\t\titerator_type;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::iterator_category\titerator_category;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::value_type\t\t\tvalue_type;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::difference_type\t\tdifference_type;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::pointer\t\t\t\tpointer;\n\t\ttypedef typename eastl::iterator_traits<Iterator>::reference\t\t\treference;\n\n\tprotected:\n\t\tIterator mIterator;\n\n\tpublic:\n\t\tEA_CPP14_CONSTEXPR reverse_iterator()      // It's important that we construct mIterator, because if Iterator\n\t\t\t: mIterator() { }\t\t\t\t\t   // is a pointer, there's a difference between doing it and not.\n\n\t\tEA_CPP14_CONSTEXPR explicit reverse_iterator(iterator_type i)\n\t\t\t: mIterator(i) { }\n\n\t\ttemplate <typename U>\n\t\tEA_CPP14_CONSTEXPR reverse_iterator(const reverse_iterator<U>& ri)\n\t\t\t: mIterator(ri.base()) { }\n\n\t\ttemplate <typename U>\n\t\tEA_CPP14_CONSTEXPR reverse_iterator<Iterator>& operator=(const reverse_iterator<U>& ri)\n\t\t\t{ mIterator = ri.base(); return *this; }\n\n\t\tEA_CPP14_CONSTEXPR iterator_type base() const\n\t\t\t{ return mIterator; }\n\n\t\tEA_CPP14_CONSTEXPR reference operator*() const\n\t\t{\n\t\t\titerator_type i(mIterator);\n\t\t\treturn *--i;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR pointer operator->() const\n\t\t\t{ return &(operator*()); }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator& operator++()\n\t\t\t{ --mIterator; return *this; }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator operator++(int)\n\t\t{\n\t\t\treverse_iterator ri(*this);\n\t\t\t--mIterator;\n\t\t\treturn ri;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator& operator--()\n\t\t\t{ ++mIterator; return *this; }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator operator--(int)\n\t\t{\n\t\t\treverse_iterator ri(*this);\n\t\t\t++mIterator;\n\t\t\treturn ri;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator operator+(difference_type n) const\n\t\t\t{ return reverse_iterator(mIterator - n); }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator& operator+=(difference_type n)\n\t\t\t{ mIterator -= n; return *this; }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator operator-(difference_type n) const\n\t\t\t{ return reverse_iterator(mIterator + n); }\n\n\t\tEA_CPP14_CONSTEXPR reverse_iterator& operator-=(difference_type n)\n\t\t\t{ mIterator += n; return *this; }\n\n\t\t// http://cplusplus.github.io/LWG/lwg-defects.html#386,\n\t\t// http://llvm.org/bugs/show_bug.cgi?id=17883\n\t\t// random_access_iterator operator[] is merely required to return something convertible to reference.\n\t\t// reverse_iterator operator[] can't necessarily know what to return as the underlying iterator\n\t\t// operator[] may return something other than reference.\n\t\tEA_CPP14_CONSTEXPR reference operator[](difference_type n) const\n\t\t\t{ return mIterator[-n - 1]; }\n\n\t\t\n    EASTL_INTERNAL_DISABLE_DEPRECATED() // 'is_iterator_wrapper': was declared deprecated\n\tprivate:\n\t\tusing base_wrapped_iterator_type =\n\t\t    typename eastl::is_iterator_wrapper_helper<Iterator,\n\t\t                                               eastl::is_iterator_wrapper<Iterator>::value>::iterator_type;\n\n\t\t// Unwrapping interface, not part of the public API.\n\t\ttemplate <typename U = iterator_type>\n\t\tEASTL_REMOVE_AT_2024_SEPT EA_CPP14_CONSTEXPR typename eastl::enable_if<eastl::is_iterator_wrapper<U>::value, reverse_iterator<base_wrapped_iterator_type>>::type unwrap() const\n\t\t{ return reverse_iterator<base_wrapped_iterator_type>(unwrap_iterator(mIterator)); }\n\n\t\t// The unwrapper helpers need access to unwrap() (when it exists).\n\t\tusing this_type = reverse_iterator<Iterator>;\n\t\tfriend is_iterator_wrapper_helper<this_type, is_iterator_wrapper<iterator_type>::value>;\n\t\tfriend is_iterator_wrapper<this_type>;\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t};\n\n\n\t// The C++ library working group has tentatively approved the usage of two\n\t// template parameters (Iterator1 and Iterator2) in order to allow reverse_iterators\n\t// and const_reverse iterators to be comparable. This is a similar issue to the\n\t// C++ defect report #179 regarding comparison of container iterators and const_iterators.\n\t//\n\t// libstdc++ reports that std::relops breaks the usage of two iterator types and if we\n\t// want to support relops then we need to also make versions of each of below with\n\t// a single template parameter to placate std::relops. But relops is hardly used due to\n\t// the troubles it causes and so we are avoiding support here until somebody complains about it.\n\ttemplate <typename Iterator1, typename Iterator2>\n\tEA_CPP14_CONSTEXPR inline bool\n\toperator==(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)\n\t\t{ return a.base() == b.base(); }\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tEA_CPP14_CONSTEXPR inline bool\n\toperator<(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)\n\t\t{ return a.base() > b.base(); }\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tEA_CPP14_CONSTEXPR inline bool\n\toperator!=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)\n\t\t{ return a.base() != b.base(); }\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tEA_CPP14_CONSTEXPR inline bool\n\toperator>(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)\n\t\t{ return a.base() < b.base(); }\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tEA_CPP14_CONSTEXPR inline bool\n\toperator<=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)\n\t\t{ return a.base() >= b.base(); }\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tEA_CPP14_CONSTEXPR inline bool\n\toperator>=(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)\n\t\t{ return a.base() <= b.base(); }\n\n\n\ttemplate <typename Iterator1, typename Iterator2>\n\tEA_CPP14_CONSTEXPR inline typename reverse_iterator<Iterator1>::difference_type\n\toperator-(const reverse_iterator<Iterator1>& a, const reverse_iterator<Iterator2>& b)\n\t\t{ return b.base() - a.base(); }\n\n\n\ttemplate <typename Iterator>\n\tEA_CPP14_CONSTEXPR inline reverse_iterator<Iterator>\n\toperator+(typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& a)\n\t\t{ return reverse_iterator<Iterator>(a.base() - n); }\n\n\n\t/// is_reverse_iterator\n\t///\n\t/// This is a type traits extension utility.\n\t/// Given an iterator, tells if it's a reverse_iterator vs anything else.\n\t/// If it's a reverse iterator wrapped by another iterator then value is false.\n\t/// To consider: Detect that if it's a move_iterator<reverse_iterator> and unwrap\n\t/// move_iterator so we can detect that underneath it's reverse_iterator.\n\t///\n\ttemplate <typename T>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_reverse_iterator\n\t\t: public eastl::false_type {};\n\n\t// Note: some compilers (notably GCC) trigger deprecation warnings when doing template\n\t// specialization if the main template is derpecated, so turn the warning off here. If this\n\t// specialization is used, the warning will still trigger in the user code, this just\n\t// disables the warning in this declaration.\nEASTL_INTERNAL_DISABLE_DEPRECATED()\n\ttemplate<typename Iterator>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_reverse_iterator<eastl::reverse_iterator<Iterator>>\n\t\t: public eastl::true_type {};\nEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\t/// unwrap_reverse_iterator is not implemented since there's no\n\t/// good use case and there's some abiguitiy. Note that\n\t/// unwrap_iterator(reverse_iterator<T>) returns\n\t/// reverse_iterator<unwrap(T)>. However, given what\n\t/// unwrap_generic_iterator and unwrap_move_iterator do, one might\n\t/// expect unwrap_reverse_iterator(reverse_iterator<T>) to return\n\t/// T, which is not the same. To avoid that confusion, and because\n\t/// there's no current use case for this, we don't provide\n\t/// unwrap_reverse_iterator.\n\n\n\n\t/// move_iterator\n\t///\n\t/// From the C++11 Standard, section 24.5.3.1:\n\t/// Class template move_iterator is an iterator adaptor with the same behavior as the underlying iterator\n\t/// except that its dereference operator implicitly converts the value returned by the underlying iterator's\n\t/// dereference operator to an rvalue reference. Some generic algorithms can be called with move iterators to\n\t/// replace copying with moving.\n\n\ttemplate<typename Iterator>\n\tclass move_iterator\n\t{\n\tprivate:\n\t\tusing WrappedIteratorReference = typename iterator_traits<Iterator>::reference;\n\n\tpublic:\n\t\ttypedef Iterator                                iterator_type;\n\t\ttypedef iterator_traits<Iterator>               traits_type;\n\t\ttypedef typename traits_type::iterator_category iterator_category; // todo: use is_contiguous_iterator<Iterator> to correctly identify pointers as contiguous?\n\t\ttypedef typename traits_type::value_type        value_type;\n\t\ttypedef typename traits_type::difference_type   difference_type;\n\t\ttypedef Iterator                                pointer;\n\t\tusing reference = conditional_t<is_reference<WrappedIteratorReference>::value,\n\t\t\t\t\t\t\t\t\t\tremove_reference_t<WrappedIteratorReference>&&,\n\t\t\t\t\t\t\t\t\t\tWrappedIteratorReference>;\n\n\tprotected:\n\t\titerator_type mIterator;\n\n\tpublic:\n\t\tmove_iterator()\n\t\t  : mIterator()\n\t\t{\n\t\t}\n\n\t\texplicit move_iterator(iterator_type mi)\n\t\t  : mIterator(mi) { }\n\n\t\ttemplate<typename U>\n\t\tmove_iterator(const move_iterator<U>& mi)\n\t\t  : mIterator(mi.base())\n\t\t{\n\t\t}\n\n\t\ttemplate <typename U>\n\t\tmove_iterator& operator=(const move_iterator<U>& mi)\n\t\t{\n\t\t\tmIterator = mi.mIterator;\n\t\t\treturn *this;\n\t\t}\n\n\t\titerator_type base() const\n\t\t\t{ return mIterator; }\n\n\t\treference operator*() const { return static_cast<reference>(*mIterator); }\n\n\t\tpointer operator->() const\n\t\t\t{ return mIterator; }\n\n\t\tmove_iterator& operator++()\n\t\t{\n\t\t\t++mIterator;\n\t\t\treturn *this;\n\t\t}\n\n\t\tmove_iterator operator++(int)\n\t\t{\n\t\t\tmove_iterator tempMoveIterator = *this;\n\t\t\t++mIterator;\n\t\t\treturn tempMoveIterator;\n\t\t}\n\n\t\tmove_iterator& operator--()\n\t\t{\n\t\t\t--mIterator;\n\t\t\treturn *this;\n\t\t}\n\n\t\tmove_iterator operator--(int)\n\t\t{\n\t\t\tmove_iterator tempMoveIterator = *this;\n\t\t\t--mIterator;\n\t\t\treturn tempMoveIterator;\n\t\t}\n\n\t\tmove_iterator operator+(difference_type n) const\n\t\t\t{ return move_iterator(mIterator + n); }\n\n\t\tmove_iterator& operator+=(difference_type n)\n\t\t{\n\t\t\tmIterator += n;\n\t\t\treturn *this;\n\t\t}\n\n\t\tmove_iterator operator-(difference_type n) const\n\t\t\t{ return move_iterator(mIterator - n); }\n\n\t\tmove_iterator& operator-=(difference_type n)\n\t\t{\n\t\t\tmIterator -= n;\n\t\t\treturn *this;\n\t\t}\n\n\t\treference operator[](difference_type n) const\n\t\t\t{ return eastl::move(mIterator[n]); }\n\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // 'is_iterator_wrapper': was declared deprecated\n\tprivate:\n\t\t// Unwrapping interface, not part of the public API.\n\t\tEASTL_REMOVE_AT_2024_SEPT iterator_type unwrap() const\n\t\t\t{ return mIterator; }\n\n\t\t// The unwrapper helpers need access to unwrap().\n\t\tusing this_type = move_iterator<Iterator>;\n\t\tfriend is_iterator_wrapper_helper<this_type, true>;\n\t\tfriend is_iterator_wrapper<this_type>;\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t};\n\n\ttemplate<typename Iterator1, typename Iterator2>\n\tinline bool\n\toperator==(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)\n\t\t{ return a.base() == b.base(); }\n\n\n\ttemplate<typename Iterator1, typename Iterator2>\n\tinline bool\n\toperator!=(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)\n\t\t{ return !(a == b); }\n\n\n\ttemplate<typename Iterator1, typename Iterator2>\n\tinline bool\n\toperator<(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)\n\t\t{ return a.base() < b.base(); }\n\n\n\ttemplate<typename Iterator1, typename Iterator2>\n\tinline bool\n\toperator<=(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)\n\t\t{ return !(b < a); }\n\n\n\ttemplate<typename Iterator1, typename Iterator2>\n\tinline bool\n\toperator>(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)\n\t\t{ return b < a; }\n\n\n\ttemplate<typename Iterator1, typename Iterator2>\n\tinline bool\n\toperator>=(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b)\n\t\t{ return !(a < b); }\n\n\n\ttemplate<typename Iterator1, typename Iterator2>\n\tinline auto\n\toperator-(const move_iterator<Iterator1>& a, const move_iterator<Iterator2>& b) -> decltype(a.base() - b.base())\n\t\t{ return a.base() - b.base(); }\n\n\n\ttemplate<typename Iterator>\n\tinline move_iterator<Iterator>\n\toperator+(typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator>& a)\n\t\t{ return a + n; }\n\n\n\ttemplate<typename Iterator>\n\tinline move_iterator<Iterator> make_move_iterator(Iterator i)\n\t\t{ return move_iterator<Iterator>(i); }\n\n\n\t// make_move_if_noexcept_iterator returns move_iterator<Iterator> if the Iterator is of a noexcept type;\n\t// otherwise returns Iterator as-is. The point of this is to be able to avoid moves that can generate exceptions and instead\n\t// fall back to copies or whatever the default IteratorType::operator* returns for use by copy/move algorithms.\n\t// To consider: merge the conditional expression usage here with the one used by move_if_noexcept, as they are the same condition.\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\ttemplate <typename Iterator, typename IteratorType = typename eastl::conditional<eastl::is_nothrow_move_constructible<typename eastl::iterator_traits<Iterator>::value_type>::value ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t !eastl::is_copy_constructible<typename eastl::iterator_traits<Iterator>::value_type>::value,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::move_iterator<Iterator>, Iterator>::type>\n\t\tinline IteratorType make_move_if_noexcept_iterator(Iterator i)\n\t\t\t{ return IteratorType(i); }\n\t#else\n\t\t// Else there are no exceptions and thus we always return a move_iterator.\n\t\ttemplate <typename Iterator>\n\t\tinline eastl::move_iterator<Iterator> make_move_if_noexcept_iterator(Iterator i)\n\t\t\t{ return eastl::move_iterator<Iterator>(i); }\n\t#endif\n\n\n\n\t/// is_move_iterator\n\t///\n\t/// This is a type traits extension utility.\n\t/// Given an iterator, tells if it's a move iterator vs anything else.\n\t/// Example usage (though somewhat useless):\n\t///     template <typename T>\n\t///     bool IsMoveIterator() { return typename eastl::is_move_iterator<T>::value; }\n\t///\n\ttemplate <typename T>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_move_iterator\n\t\t: public eastl::false_type {};\n\n\t// Note: some compilers (notably GCC) trigger deprecation warnings when doing template\n\t// specialization if the main template is derpecated, so turn the warning off here. If this\n\t// specialization is used, the warning will still trigger in the user code, this just\n\t// disables the warning in this declaration.\nEASTL_INTERNAL_DISABLE_DEPRECATED()\n\ttemplate<typename Iterator>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_move_iterator<eastl::move_iterator<Iterator>>\n\t\t: public eastl::true_type {};\nEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\t/// unwrap_move_iterator\n\t///\n\t/// Returns `it.base()` if it's a move_iterator, else returns `it` as-is.\n\t///\n\t/// Example usage:\n\t///      vector<int> intVector;\n\t///      eastl::move_iterator<vector<int>::iterator> moveIterator(intVector.begin());\n\t///      vector<int>::iterator it = unwrap_move_iterator(moveIterator);\n\t///\nEASTL_INTERNAL_DISABLE_DEPRECATED() // is_iterator_wrapper_helper is deprecated\n\ttemplate <typename Iterator>\n\tEASTL_REMOVE_AT_2024_SEPT inline typename eastl::is_iterator_wrapper_helper<Iterator, eastl::is_move_iterator<Iterator>::value>::iterator_type unwrap_move_iterator(Iterator it)\n\t{\n\t\t// get_unwrapped(it) -> it.unwrap() which is equivalent to `it.base()` for move_iterator and to `it` otherwise.\n\t\treturn eastl::is_iterator_wrapper_helper<Iterator, eastl::is_move_iterator<Iterator>::value>::get_unwrapped(it);\n\t}\nEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\t/// back_insert_iterator\n\t///\n\t/// A back_insert_iterator is simply a class that acts like an iterator but when you\n\t/// assign a value to it, it calls push_back on the container with the value.\n\t///\n\ttemplate <typename Container>\n\tclass back_insert_iterator\n\t{\n\tpublic:\n\t\ttypedef back_insert_iterator<Container>     this_type;\n\t\ttypedef Container                           container_type;\n\t\ttypedef typename Container::const_reference const_reference;\n\t\ttypedef eastl::output_iterator_tag\titerator_category;\n\t\ttypedef void\t\t\t\t\t\t\t\tvalue_type;\n\t\ttypedef void\t\t\t\t\t\t\t\tdifference_type;\n\t\ttypedef void\t\t\t\t\t\t\t\tpointer;\n\t\ttypedef void\t\t\t\t\t\t\t\treference;\n\n\tprotected:\n\t\tContainer* container;\n\n\tpublic:\n\t\texplicit back_insert_iterator(Container& x)\n\t\t\t: container(eastl::addressof(x)) { }\n\n\t\tback_insert_iterator(const back_insert_iterator&) = default;\n\t\tback_insert_iterator& operator=(const back_insert_iterator&) = default;\n\n\t\tback_insert_iterator& operator=(const typename Container::value_type& value)\n\t\t\t{ container->push_back(value); return *this; }\n\n\t\tback_insert_iterator& operator=(typename Container::value_type&& value)\n\t\t\t{ container->push_back(eastl::move(value)); return *this; }\n\n\t\tback_insert_iterator& operator*()\n\t\t\t{ return *this; }\n\n\t\tback_insert_iterator& operator++()\n\t\t\t{ return *this; } // This is by design.\n\n\t\tback_insert_iterator operator++(int)\n\t\t\t{ return *this; } // This is by design.\n\t};\n\n\n\t/// back_inserter\n\t///\n\t/// Creates an instance of a back_insert_iterator.\n\t///\n\ttemplate <typename Container>\n\tinline back_insert_iterator<Container>\n\tback_inserter(Container& x)\n\t\t{ return back_insert_iterator<Container>(x); }\n\n\n\n\n\t/// front_insert_iterator\n\t///\n\t/// A front_insert_iterator is simply a class that acts like an iterator but when you\n\t/// assign a value to it, it calls push_front on the container with the value.\n\t///\n\ttemplate <typename Container>\n\tclass front_insert_iterator\n\t{\n\tpublic:\n\t\ttypedef front_insert_iterator<Container>    this_type;\n\t\ttypedef Container                           container_type;\n\t\ttypedef typename Container::const_reference const_reference;\n\t\ttypedef eastl::output_iterator_tag\titerator_category;\n\t\ttypedef void\t\t\t\t\t\t\t\tvalue_type;\n\t\ttypedef void\t\t\t\t\t\t\t\tdifference_type;\n\t\ttypedef void\t\t\t\t\t\t\t\tpointer;\n\t\ttypedef void\t\t\t\t\t\t\t\treference;\n\n\tprotected:\n\t\tContainer* container;\n\n\tpublic:\n\t\texplicit front_insert_iterator(Container& x) : container(eastl::addressof(x)) {}\n\n\t\tfront_insert_iterator(const front_insert_iterator&) = default;\n\t\tfront_insert_iterator& operator=(const front_insert_iterator&) = default;\n\n\t\tfront_insert_iterator& operator=(const typename Container::value_type& value)\n\t\t\t{ container->push_front(value); return *this; }\n\n\t\tfront_insert_iterator& operator*()\n\t\t\t{ return *this; }\n\n\t\tfront_insert_iterator& operator++()\n\t\t\t{ return *this; } // This is by design.\n\n\t\tfront_insert_iterator operator++(int)\n\t\t\t{ return *this; } // This is by design.\n\t};\n\n\n\t/// front_inserter\n\t///\n\t/// Creates an instance of a front_insert_iterator.\n\t///\n\ttemplate <typename Container>\n\tinline front_insert_iterator<Container>\n\tfront_inserter(Container& x)\n\t\t{ return front_insert_iterator<Container>(x); }\n\n\n\n\n\t/// insert_iterator\n\t///\n\t/// An insert_iterator is like an iterator except that when you assign a value to it,\n\t/// the insert_iterator inserts the value into the container and increments the iterator.\n\t///\n\t/// insert_iterator is an iterator adaptor that functions as an OutputIterator:\n\t/// assignment through an insert_iterator inserts an object into a container.\n\t/// Specifically, if ii is an insert_iterator, then ii keeps track of a container c and\n\t/// an insertion point p; the expression *ii = x performs the insertion container.insert(p, x).\n\t///\n\t/// If you assign through an insert_iterator several times, then you will be inserting\n\t/// several elements into the underlying container. In the case of a sequence, they will\n\t/// appear at a particular location in the underlying sequence, in the order in which\n\t/// they were inserted: one of the arguments to insert_iterator's constructor is an\n\t/// iterator p, and the new range will be inserted immediately before p.\n\t///\n\ttemplate <typename Container>\n\tclass insert_iterator\n\t{\n\tpublic:\n\t\ttypedef Container                           container_type;\n\t\ttypedef typename Container::iterator        iterator_type;\n\t\ttypedef typename Container::const_reference const_reference;\n\t\ttypedef eastl::output_iterator_tag\titerator_category;\n\t\ttypedef void\t\t\t\t\t\t\t\tvalue_type;\n\t\ttypedef void\t\t\t\t\t\t\t\tdifference_type;\n\t\ttypedef void\t\t\t\t\t\t\t\tpointer;\n\t\ttypedef void\t\t\t\t\t\t\t\treference;\n\n\tprotected:\n\t\tContainer*     container;\n\t\titerator_type  it;\n\n\tpublic:\n\t\tinsert_iterator(Container& x, iterator_type itNew)\n\t\t\t: container(eastl::addressof(x)), it(itNew) {}\n\n\t\tinsert_iterator(const insert_iterator&) = default;\n\t\tinsert_iterator& operator=(const insert_iterator&) = default;\n\n\t\tinsert_iterator& operator=(const typename Container::value_type& value)\n\t\t{\n\t\t\tit = container->insert(it, value);\n\t\t\t++it;\n\t\t\treturn *this;\n\t\t}\n\n\t\tinsert_iterator& operator*()\n\t\t\t{ return *this; }\n\n\t\tinsert_iterator& operator++()\n\t\t\t{ return *this; } // This is by design.\n\n\t\tinsert_iterator& operator++(int)\n\t\t\t{ return *this; } // This is by design.\n\n\t}; // insert_iterator\n\n\n\t/// inserter\n\t///\n\t/// Creates an instance of an insert_iterator.\n\t///\n\ttemplate <typename Container, typename Iterator>\n\tinline eastl::insert_iterator<Container>\n\tinserter(Container& x, Iterator i)\n\t{\n\t\ttypedef typename Container::iterator iterator;\n\t\treturn eastl::insert_iterator<Container>(x, iterator(i));\n\t}\n\n\n\t/// is_insert_iterator\n\t///\n\t/// This is a type traits extension utility.\n\t/// Given an iterator, tells if it's an insert_iterator vs anything else.\n\t/// If it's a insert_iterator wrapped by another iterator then value is false.\n\t///\n\ttemplate <typename T>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_insert_iterator\n\t\t: public eastl::false_type {};\n\n\t// Note: some compilers (notably GCC) trigger deprecation warnings when doing template\n\t// specialization if the main template is derpecated, so turn the warning off here. If this\n\t// specialization is used, the warning will still trigger in the user code, this just\n\t// disables the warning in this declaration.\nEASTL_INTERNAL_DISABLE_DEPRECATED()\n\ttemplate<typename Iterator>\n\tstruct EASTL_REMOVE_AT_2024_SEPT is_insert_iterator<eastl::insert_iterator<Iterator>>\n\t\t: public eastl::true_type {};\nEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\n\n\t//////////////////////////////////////////////////////////////////////////////////\n\t/// distance\n\t///\n\t/// Implements the distance() function. There are two versions, one for\n\t/// random access iterators (e.g. with vector) and one for regular input\n\t/// iterators (e.g. with list). The former is more efficient.\n\t///\n\ttemplate <typename InputIterator>\n\tEA_CONSTEXPR\n\tinline typename eastl::iterator_traits<InputIterator>::difference_type\n\tdistance_impl(InputIterator first, InputIterator last, eastl::input_iterator_tag)\n\t{\n\t\ttypename eastl::iterator_traits<InputIterator>::difference_type n = 0;\n\n\t\twhile(first != last)\n\t\t{\n\t\t\t++first;\n\t\t\t++n;\n\t\t}\n\t\treturn n;\n\t}\n\n\ttemplate <typename RandomAccessIterator>\n\tEA_CONSTEXPR\n\tinline typename eastl::iterator_traits<RandomAccessIterator>::difference_type\n\tdistance_impl(RandomAccessIterator first, RandomAccessIterator last, eastl::random_access_iterator_tag)\n\t{\n\t\treturn last - first;\n\t}\n\n\t// Special version defined so that std C++ iterators can be recognized by\n\t// this function. Unfortunately, this function treats all foreign iterators\n\t// as InputIterators and thus can seriously hamper performance in the case\n\t// of large ranges of bidirectional_iterator_tag iterators.\n\t//template <typename InputIterator>\n\t//inline typename eastl::iterator_traits<InputIterator>::difference_type\n\t//distance_impl(InputIterator first, InputIterator last, ...)\n\t//{\n\t//    typename eastl::iterator_traits<InputIterator>::difference_type n = 0;\n\t//\n\t//    while(first != last)\n\t//    {\n\t//        ++first;\n\t//        ++n;\n\t//    }\n\t//    return n;\n\t//}\n\n\ttemplate <typename InputIterator>\n\tEA_CONSTEXPR\n\tinline typename eastl::iterator_traits<InputIterator>::difference_type\n\tdistance(InputIterator first, InputIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\n\t\treturn eastl::distance_impl(first, last, IC());\n\t}\n\n\n\n\n\t//////////////////////////////////////////////////////////////////////////////////\n\t/// advance\n\t///\n\t/// Implements the advance() function. There are three versions, one for\n\t/// random access iterators (e.g. with vector), one for bidirectional\n\t/// iterators (list) and one for regular input iterators (e.g. with slist).\n\t///\n\ttemplate <typename InputIterator, typename Distance>\n\tinline void\n\tadvance_impl(InputIterator& i, Distance n, eastl::input_iterator_tag)\n\t{\n\t\twhile(n--)\n\t\t\t++i;\n\t}\n\n\ttemplate <bool signedDistance>\n\tstruct advance_bi_impl\n\t{\n\t\ttemplate <typename BidirectionalIterator, typename Distance>\n\t\tstatic void advance_impl(BidirectionalIterator& i, Distance n) // Specialization for unsigned distance type.\n\t\t{\n\t\t\twhile(n--)\n\t\t\t\t++i;\n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct advance_bi_impl<true>\n\t{\n\t\ttemplate <typename BidirectionalIterator, typename Distance>\n\t\tstatic void advance_impl(BidirectionalIterator& i, Distance n) // Specialization for signed distance type.\n\t\t{\n\t\t\tif(n > 0)\n\t\t\t{\n\t\t\t\twhile(n--)\n\t\t\t\t\t++i;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\twhile(n++)\n\t\t\t\t\t--i;\n\t\t\t}\n\t\t}\n\t};\n\n\ttemplate <typename BidirectionalIterator, typename Distance>\n\tinline void\n\tadvance_impl(BidirectionalIterator& i, Distance n, eastl::bidirectional_iterator_tag)\n\t{\n\t\tadvance_bi_impl<eastl::is_signed<Distance>::value>::advance_impl(i, n);\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename Distance>\n\tinline void\n\tadvance_impl(RandomAccessIterator& i, Distance n, eastl::random_access_iterator_tag)\n\t{\n\t\ti += n;\n\t}\n\n\t// Special version defined so that std C++ iterators can be recognized by\n\t// this function. Unfortunately, this function treats all foreign iterators\n\t// as InputIterators and thus can seriously hamper performance in the case\n\t// of large ranges of bidirectional_iterator_tag iterators.\n\t//template <typename InputIterator, typename Distance>\n\t//inline void\n\t//advance_impl(InputIterator& i, Distance n, ...)\n\t//{\n\t//    while(n--)\n\t//        ++i;\n\t//}\n\n\ttemplate <typename InputIterator, typename Distance>\n\tinline void\n\tadvance(InputIterator& i, Distance n)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\n\t\teastl::advance_impl(i, n, IC());\n\t}\n\n\n\t// eastl::next / eastl::prev\n\t// Return the nth/-nth successor of iterator it.\n\t//\n\t// http://en.cppreference.com/w/cpp/iterator/next\n\t//\n\ttemplate<typename InputIterator>\n\tinline InputIterator\n\tnext(InputIterator it, typename eastl::iterator_traits<InputIterator>::difference_type n = 1)\n\t{\n\t\teastl::advance(it, n);\n\t\treturn it;\n\t}\n\n\ttemplate<typename InputIterator>\n\tinline InputIterator\n\tprev(InputIterator it, typename eastl::iterator_traits<InputIterator>::difference_type n = 1)\n\t{\n\t\teastl::advance(it, -n);\n\t\treturn it;\n\t}\n\n\n#if defined(EA_COMPILER_CPP11_ENABLED) && EA_COMPILER_CPP11_ENABLED\n\n\t// eastl::data\n\t//\n\t// http://en.cppreference.com/w/cpp/iterator/data\n\t//\n\ttemplate <class Container>\n\tEA_CPP14_CONSTEXPR auto data(Container& c) -> decltype(c.data())\n\t\t{ return c.data(); }\n\n\ttemplate <class Container>\n\tEA_CPP14_CONSTEXPR auto data(const Container& c) -> decltype(c.data())\n\t\t{ return c.data(); }\n\n\ttemplate <class T, size_t N>\n\tEA_CPP14_CONSTEXPR T* data(T(&array)[N]) EA_NOEXCEPT\n\t\t{ return array; }\n\n\ttemplate <class E>\n\tEA_CPP14_CONSTEXPR const E* data(std::initializer_list<E> il) EA_NOEXCEPT\n\t\t{ return il.begin(); }\n\n\n\t// eastl::size\n\t//\n\t// http://en.cppreference.com/w/cpp/iterator/size\n\t//\n\ttemplate <class C>\n\tEA_CPP14_CONSTEXPR auto size(const C& c) -> decltype(c.size())\n\t\t{ return c.size(); }\n\n\ttemplate <class T, size_t N>\n\tEA_CPP14_CONSTEXPR size_t size(const T (&)[N]) EA_NOEXCEPT\n\t\t{ return N; }\n\n\n\t// eastl::ssize\n\t//\n\t// https://en.cppreference.com/w/cpp/iterator/size\n\t//\n\ttemplate <class T, ptrdiff_t N>\n\tEA_CPP14_CONSTEXPR ptrdiff_t ssize(const T(&)[N]) EA_NOEXCEPT\n\t\t{ return N; }\n\n\ttemplate <class C>\n\tEA_CPP14_CONSTEXPR auto ssize(const C& c)\n\t    -> eastl::common_type_t<ptrdiff_t, eastl::make_signed_t<decltype(c.size())>>\n\t{\n\t\tusing R = eastl::common_type_t<ptrdiff_t, eastl::make_signed_t<decltype(c.size())>>;\n\t\treturn static_cast<R>(c.size());\n\t}\n\n\n\t// eastl::empty\n\t//\n\t// http://en.cppreference.com/w/cpp/iterator/empty\n\t//\n\ttemplate <class Container>\n\tEA_CPP14_CONSTEXPR auto empty(const Container& c) -> decltype(c.empty())\n\t\t{ return c.empty(); }\n\n\ttemplate <class T, size_t N>\n\tEA_CPP14_CONSTEXPR bool empty(const T (&)[N]) EA_NOEXCEPT\n\t\t{ return false; }\n\n\ttemplate <class E>\n\tEA_CPP14_CONSTEXPR bool empty(std::initializer_list<E> il) EA_NOEXCEPT\n\t\t{ return il.size() == 0; }\n\n#endif // defined(EA_COMPILER_CPP11_ENABLED) && EA_COMPILER_CPP11_ENABLED\n\n\n\t// eastl::begin / eastl::end\n\t// http://en.cppreference.com/w/cpp/iterator/begin\n\t//\n\t// In order to enable eastl::begin and eastl::end, the compiler needs to have conforming support\n\t// for argument-dependent lookup if it supports C++11 range-based for loops. The reason for this is\n\t// that in C++11 range-based for loops result in usage of std::begin/std::end, but allow that to\n\t// be overridden by argument-dependent lookup:\n\t//     C++11 Standard, section 6.5.4, paragraph 1.\n\t//     \"otherwise, begin-expr and end-expr are begin(__range) and end(__range), respectively,\n\t//      where begin and end are looked up with argument-dependent lookup (3.4.2). For the\n\t//      purposes of this name lookup, namespace std is an associated namespace.\"\n\t// It turns out that one compiler has a problem: GCC 4.6. That version added support for\n\t// range-based for loops but has broken argument-dependent lookup which was fixed in GCC 4.7.\n\t//\n\t#if (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION == 4006))\n\t\t#define EASTL_BEGIN_END_ENABLED 0\n\t#else\n\t\t#define EASTL_BEGIN_END_ENABLED 1\n\t#endif\n\n\t#if EASTL_BEGIN_END_ENABLED\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto begin(Container& container) -> decltype(container.begin())\n\t\t{\n\t\t\treturn container.begin();\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto begin(const Container& container) -> decltype(container.begin())\n\t\t{\n\t\t\treturn container.begin();\n\t\t}\n\n\t\ttemplate<typename T, size_t arraySize>\n\t\tEA_CPP14_CONSTEXPR inline T* begin(T (&arrayObject)[arraySize]) EA_NOEXCEPT\n\t\t{\n\t\t\treturn arrayObject;\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto cbegin(const Container& container) -> decltype(eastl::begin(container))\n\t\t{\n\t\t\treturn eastl::begin(container);\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto end(Container& container) -> decltype(container.end())\n\t\t{\n\t\t\treturn container.end();\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto end(const Container& container) -> decltype(container.end())\n\t\t{\n\t\t\treturn container.end();\n\t\t}\n\n\t\ttemplate<typename T, size_t arraySize>\n\t\tEA_CPP14_CONSTEXPR inline T* end(T (&arrayObject)[arraySize]) EA_NOEXCEPT\n\t\t{\n\t\t\treturn (arrayObject + arraySize);\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto cend(const Container& container) -> decltype(eastl::end(container))\n\t\t{\n\t\t\treturn eastl::end(container);\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto rbegin(Container& container) -> decltype(container.rbegin())\n\t\t{\n\t\t\treturn container.rbegin();\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto rbegin(const Container& container) -> decltype(container.rbegin())\n\t\t{\n\t\t\treturn container.rbegin();\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto rend(Container& container) -> decltype(container.rend())\n\t\t{\n\t\t\treturn container.rend();\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto rend(const Container& container) -> decltype(container.rend())\n\t\t{\n\t\t\treturn container.rend();\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto crbegin(const Container& container) -> decltype(eastl::rbegin(container))\n\t\t{\n\t\t\treturn container.rbegin();\n\t\t}\n\n\t\ttemplate <typename Container>\n\t\tEA_CPP14_CONSTEXPR inline auto crend(const Container& container) -> decltype(eastl::rend(container))\n\t\t{\n\t\t\treturn container.rend();\n\t\t}\n\n\n\t\ttemplate <typename T, size_t arraySize>\n\t\tEA_CPP14_CONSTEXPR inline reverse_iterator<T*> rbegin(T (&arrayObject)[arraySize])\n\t\t{\n\t\t\treturn reverse_iterator<T*>(arrayObject + arraySize);\n\t\t}\n\n\t\ttemplate <typename T, size_t arraySize>\n\t\tEA_CPP14_CONSTEXPR inline reverse_iterator<T*> rend(T (&arrayObject)[arraySize])\n\t\t{\n\t\t\treturn reverse_iterator<T*>(arrayObject);\n\t\t}\n\n\t\ttemplate <typename E>\n\t\tEA_CPP14_CONSTEXPR inline reverse_iterator<const E*> rbegin(std::initializer_list<E> ilist)\n\t\t{\n\t\t\treturn eastl::reverse_iterator<const E*>(ilist.end());\n\t\t}\n\n\t\ttemplate <typename E>\n\t\tEA_CPP14_CONSTEXPR inline reverse_iterator<const E*> rend(std::initializer_list<E> ilist)\n\t\t{\n\t\t\treturn eastl::reverse_iterator<const E*>(ilist.begin());\n\t\t}\n\n\t\ttemplate <typename Iterator>\n\t\tEA_CPP14_CONSTEXPR reverse_iterator<Iterator> make_reverse_iterator(Iterator i)\n\t\t\t{ return reverse_iterator<Iterator>(i); }\n\n\t#endif // EASTL_BEGIN_END_ENABLED\n\n} // namespace eastl\n\n\n\n// Some compilers (e.g. GCC 4.6) support range-based for loops, but have a bug with\n// respect to argument-dependent lookup which results on them unilaterally using std::begin/end\n// with range-based for loops. To work around this we #include <iterator> for this case in\n// order to make std::begin/end visible to users of <EASTL/iterator.h>, for portability.\n#if !EASTL_BEGIN_END_ENABLED && !defined(EA_COMPILER_NO_RANGE_BASED_FOR_LOOP)\n\t#include <iterator>\n#endif\n\n\n\nEA_RESTORE_VC_WARNING();\nEA_RESTORE_VC_WARNING();\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/linked_array.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This class implements a linked_array template, which is an array version\n// of linked_ptr. See linked_ptr for detailed documentation.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_LINKED_ARRAY_H\n#define EASTL_LINKED_ARRAY_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/smart_ptr.h>   // Defines smart_array_deleter\n#include <EASTL/linked_ptr.h>           // Defines linked_ptr_base \n#include <stddef.h>                     // Definition of ptrdiff_t\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// class linked_array\n\t///\n\t/// This class implements a linked_array template, which is an array version\n\t/// of linked_ptr. See linked_ptr for detailed documentation.\n\t///\n\ttemplate <typename T, typename Deleter = smart_array_deleter<T> >\n\tclass linked_array\n\t{\n\t\n\tprotected:\n\t\n\t\t/// this_type\n\t\t/// This is an alias for linked_array<T>, this class.\n\t\ttypedef linked_array<T> this_type;\n\n\t\t/// deleter_type\n\t\ttypedef Deleter deleter_type;\n\n\t\tT* mpArray;\n\t\tmutable const this_type* mpPrev;\n\t\tmutable const this_type* mpNext;\n\n\t\tvoid link(const linked_array& linkedArray)\n\t\t{   // This code can only be called when we are in a reset state.\n\t\t\t// assert(!mpArray && (mpNext == mpPrev));\n\t\t\tmpNext             = linkedArray.mpNext;\n\t\t\tmpNext->mpPrev     = this;\n\t\t\tmpPrev             = &linkedArray;\n\t\t\tlinkedArray.mpNext = this;\n\t\t}\n\n\tpublic:\n\t\t/// element_type\n\t\t/// Synonym for type T, useful for external code to reference the \n\t\t/// type in a generic way.\n\t\ttypedef T element_type;\n\n\n\t\t/// linked_array\n\t\t/// Takes ownership of the pointer. It is OK if the input pointer is null.\n\t\texplicit linked_array(T* pArray = NULL) \n\t\t\t: mpArray(pArray)\n\t\t{\n\t\t\tmpPrev = mpNext = this;\n\t\t}\n\n\n\t\t/// linked_array\n\t\t/// Shares ownership of a pointer with another instance of linked_array.\n\t\tlinked_array(const linked_array& linkedArray)\n\t\t\t: mpArray(linkedArray.mpArray)\n\t\t{\n\t\t\tif(mpArray)\n\t\t\t\tlink(linkedArray);\n\t\t\telse\n\t\t\t\tmpPrev = mpNext = this;\n\t\t}\n\n\n\t\t/// ~linked_array\n\t\t/// Removes this object from the of objects using the shared pointer.\n\t\t/// If this object is the last owner of the shared pointer, the shared \n\t\t/// pointer is deleted.\n\t\t~linked_array() \n\t\t{\n\t\t\treset();\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Copies another linked_array to this object. Note that this object\n\t\t/// may already own a shared pointer with another different pointer\n\t\t/// (but still of the same type) before this call. In that case,\n\t\t/// this function removes ownership of the old pointer and takes shared \n\t\t/// ownership of the new pointer and increments its reference count.\n\t\tlinked_array& operator=(const linked_array& linkedArray)\n\t\t{\n\t\t\tif(linkedArray.mpArray != mpArray)\n\t\t\t{\n\t\t\t\treset(linkedArray.mpArray);\n\t\t\t\tif(linkedArray.mpArray)\n\t\t\t\t\tlink(linkedArray);\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Assigns a new pointer. If the new pointer is equivalent\n\t\t/// to the current pointer, nothing is done. Otherwise the \n\t\t/// current pointer is unlinked and possibly destroyed.\n\t\t/// The new pointer can be NULL.\n\t\tlinked_array& operator=(T* pArray)\n\t\t{\n\t\t\treset(pArray);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Releases the owned pointer and takes ownership of the \n\t\t/// passed in pointer. If the passed in pointer is the same\n\t\t/// as the owned pointer, nothing is done. The passed in pointer\n\t\t/// can be null, in which case the use count is set to 1.\n\t\tvoid reset(T* pArray = NULL)\n\t\t{\n\t\t\tif(pArray != mpArray)\n\t\t\t{\n\t\t\t\tif(unique())\n\t\t\t\t{\n\t\t\t\t\tdeleter_type del;\n\t\t\t\t\tdel(mpArray);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tmpPrev->mpNext  = mpNext;\n\t\t\t\t\tmpNext->mpPrev  = mpPrev;\n\t\t\t\t\tmpPrev = mpNext = this;\n\t\t\t\t}\n\t\t\t\tmpArray = pArray;\n\t\t\t}\n\t\t}\n\n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer beween two linkedArray objects.\n\t\t///\n\t\t/// This function is disabled as it is currently deemed unsafe.\n\t\t/// The problem is that the only way to implement this function\n\t\t/// is to transfer pointers between the objects; you cannot \n\t\t/// transfer the linked list membership between the objects. \n\t\t/// Thus unless both linked_array objects were 'unique()', the \n\t\t/// shared pointers would be duplicated amongst containers, \n\t\t/// resulting in a crash.\n\t\t//void swap(linked_array& linkedArray)\n\t\t//{\n\t\t//    if(linkedArray.mpArray != mpArray)\n\t\t//    {   // This is only safe if both linked_arrays are unique().\n\t\t//        linkedArray::element_type* const pArrayTemp = linkedArray.mpArray;\n\t\t//        linkedArray.reset(mpArray);\n\t\t//        reset(pArrayTemp);\n\t\t//    }\n\t\t//}\n\n\n\t\t/// operator[]\n\t\t/// Returns a reference to the specified item in the owned pointer array. \n\t\tT& operator[](ptrdiff_t i) const\n\t\t{\n\t\t\t// assert(mpArray && (i >= 0));\n\t\t\treturn mpArray[i];\n\t\t}\n\n\n\t\t/// operator*\n\t\t/// Returns the owner pointer dereferenced.\n\t\tT& operator*() const\n\t\t{\n\t\t\treturn *mpArray;\n\t\t}\n\n\n\t\t/// operator->\n\t\t/// Allows access to the owned pointer via operator->()\n\t\tT* operator->() const\n\t\t{\n\t\t\treturn mpArray;\n\t\t}\n\n\n\t\t/// get\n\t\t/// Returns the owned pointer. Note that this class does \n\t\t/// not provide an operator T() function. This is because such\n\t\t/// a thing (automatic conversion) is deemed unsafe.\n\t\tT* get() const\n\t\t{\n\t\t\treturn mpArray;\n\t\t}\n\n\n\t\t/// use_count\n\t\t/// Returns the use count of the shared pointer.\n\t\t/// The return value is one if the owned pointer is null.\n\t\t/// This function is provided for compatibility with the \n\t\t/// proposed C++ standard and for debugging purposes. It is not\n\t\t/// intended for runtime use given that its execution time is\n\t\t/// not constant.\n\t\tint use_count() const\n\t\t{\n\t\t\tint useCount(1);\n\t\t\t\n\t\t\tfor(const linked_ptr_base* pCurrent = this; pCurrent->mpNext != this; pCurrent = pCurrent->mpNext)\n\t\t\t\t++useCount;\n\n\t\t\treturn useCount;\n\t\t}\n\n\n\t\t/// unique\n\t\t/// Returns true if the use count of the owned pointer is one.\n\t\t/// The return value is true if the owned pointer is null.\n\t\tbool unique() const\n\t\t{\n\t\t\treturn (mpNext == this);\n\t\t}\n\n\n\t\t/// Implicit operator bool\n\t\t/// Allows for using a linked_array as a boolean. \n\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t/// The result is that this: if(linkedArray == 1) would yield true (bad).\n\t\ttypedef T* (this_type::*bool_)() const;\n\t\toperator bool_() const\n\t\t{\n\t\t\tif(mpArray)\n\t\t\t\treturn &this_type::get;\n\t\t\treturn NULL;\n\t\t}\n\n\n\t\t/// operator!\n\t\t/// This returns the opposite of operator bool; it returns true if \n\t\t/// the owned pointer is null. Some compilers require this and some don't.\n\t\tbool operator!()\n\t\t{\n\t\t\treturn (mpArray == NULL);\n\t\t}\n\n\n\t\t/// force_delete\n\t\t/// Forces deletion of the shared pointer. Fixes all references to the \n\t\t/// pointer by any other owners to be NULL.\n\t\tvoid force_delete()\n\t\t{\n\t\t\tT* const pArray = mpArray;\n\n\t\t\tthis_type* p = this;\n\t\t\tdo\n\t\t\t{\n\t\t\t\tthis_type* const pNext = const_cast<this_type*>(p->mpNext);\n\t\t\t\tp->mpArray = NULL;\n\t\t\t\tp->mpNext  = p->mpPrev = p;\n\t\t\t\tp = pNext;\n\t\t\t}\n\t\t\twhile(p != this);\n\n\t\t\tdeleter_type del;\n\t\t\tdel(pArray);\n\t\t}\n\n\t}; // class linked_array\n\n\n\n\t/// get_pointer\n\t/// Returns linked_array::get() via the input linked_array. Provided for compatibility\n\t/// with certain well-known libraries that use this functionality.\n\ttemplate <typename T>\n\tinline T* get_pointer(const linked_array<T>& linkedArray)\n\t{\n\t\treturn linkedArray.get();\n\t}\n\n\n\t/// operator==\n\t/// Compares two linked_array objects for equality. Equality is defined as \n\t/// being true when the pointer shared between two linked_array objects is equal.\n\ttemplate <typename T, typename TD, typename U, typename UD>\n\tinline bool operator==(const linked_array<T, TD>& linkedArray1, const linked_array<U, UD>& linkedArray2)\n\t{\n\t\treturn (linkedArray1.get() == linkedArray2.get());\n\t}\n\n\n\t/// operator!=\n\t/// Compares two linked_array objects for inequality. Equality is defined as \n\t/// being true when the pointer shared between two linked_array objects is equal.\n\ttemplate <typename T, typename TD, typename U, typename UD>\n\tinline bool operator!=(const linked_array<T, TD>& linkedArray1, const linked_array<U, UD>& linkedArray2)\n\t{\n\t\treturn (linkedArray1.get() != linkedArray2.get());\n\t}\n\n\n\t/// operator<\n\t/// Returns which linked_array is 'less' than the other. Useful when storing\n\t/// sorted containers of linked_array objects.\n\ttemplate <typename T, typename TD, typename U, typename UD>\n\tinline bool operator<(const linked_array<T, TD>& linkedArray1, const linked_array<U, UD>& linkedArray2)\n\t{\n\t\treturn (linkedArray1.get() < linkedArray2.get());\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/linked_ptr.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_LINKED_PTR_H\n#define EASTL_LINKED_PTR_H\n\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/smart_ptr.h>   // Defines smart_ptr_deleter\n#include <EASTL/allocator.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// linked_ptr_base\n\t///\n\t/// This class allows linked_ptr<T> and linked_ptr<U> to share the same \n\t/// base nodes and thus be in the same linked list.\n\t///\n\tstruct linked_ptr_base\n\t{\n\t\tmutable linked_ptr_base* mpPrev;\n\t\tmutable linked_ptr_base* mpNext;\n\t};\n\n\n\t/// linked_ptr\n\t///\n\t/// This class implements a linked_ptr template. A linked_ptr is like the C++\n\t/// Standard Library auto_ptr except that it allows sharing of pointers between\n\t/// instances of auto_ptr via reference counting. linked_ptr objects can safely\n\t/// be copied and can safely be used in C++ Standard Library containers such\n\t/// as std::vector or std::list. This implementation, however, is not thread-safe.\n\t/// you would need to use a separate linked_ptr_mt (multi-threaded) to get \n\t/// thread safety.\n\t///\n\t/// linked_ptr is a variation of shared_ptr (a.k.a. counted_ptr) which differs \n\t/// in that instead of being implemented by a shared integer stored on the heap, \n\t/// it is implemented by linked list stored within the linked_ptr object itself.\n\t/// The result is that no memory is explicitly allocated from the heap, though\n\t/// the cost of each linked_ptr object is 12 bytes of memory (32 bit machine)\n\t/// instead of 4 bytes for the case of shared_ptr (depending on the heap).\n\t///\n\ttemplate <typename T, typename Deleter = smart_ptr_deleter<T> >\n\tclass linked_ptr : public linked_ptr_base\n\t{\n\tprotected:\n\t\ttemplate <typename U, typename D> friend class linked_ptr;\n\n\t\t/// this_type\n\t\t/// This is an alias for linked_ptr<T>, this class.\n\t\ttypedef linked_ptr<T> this_type;\n\n\t\t/// deleter_type\n\t\ttypedef Deleter deleter_type;\n\n\t\tT* mpValue; /// The owned pointer.\n\n\t\ttemplate <typename U, typename D>\n\t\tvoid link(const linked_ptr<U, D>& linkedPtr)\n\t\t{   // This code can only be called when we are in a reset state.\n\t\t\t// assert(!mpValue && (mpNext == mpPrev));\n\t\t\tmpNext           = linkedPtr.mpNext;\n\t\t\tmpNext->mpPrev   = this;\n\t\t\tmpPrev           = const_cast<linked_ptr<U, D>*>(&linkedPtr);\n\t\t\tlinkedPtr.mpNext = this;\n\t\t}\n\n\tpublic:\n\t\t/// element_type\n\t\t/// Synonym for type T, useful for external code to reference the \n\t\t/// type in a generic way.\n\t\ttypedef T element_type;\n\n\n\t\t/// linked_ptr\n\t\t/// Default constructor.\n\t\tlinked_ptr() \n\t\t\t: mpValue(NULL)\n\t\t{\n\t\t\tmpPrev = mpNext = this;\n\t\t}\n\n\n\t\t/// linked_ptr\n\t\t/// Takes ownership of the pointer. It is OK if the input pointer is null.\n\t\ttemplate <typename U>\n\t\texplicit linked_ptr(U* pValue) \n\t\t\t: mpValue(pValue)\n\t\t{\n\t\t\tmpPrev = mpNext = this;\n\t\t}\n\n\n\t\t/// linked_ptr\n\t\t/// Construction with self type.\n\t\t/// If we want a shared_ptr constructor that is templated on linked_ptr<U>,\n\t\t/// then we need to make it in addition to this function, as otherwise \n\t\t/// the compiler will generate this function and things will go wrong.\n\t\tlinked_ptr(const linked_ptr& linkedPtr)\n\t\t\t: mpValue(linkedPtr.mpValue)\n\t\t{\n\t\t\tif(mpValue)\n\t\t\t\tlink(linkedPtr);\n\t\t\telse\n\t\t\t\tmpPrev = mpNext = this;\n\t\t}\n\n\n\t\t/// linked_ptr\n\t\t/// Shares ownership of a pointer with another instance of linked_ptr.\n\t\ttemplate <typename U, typename D>\n\t\tlinked_ptr(const linked_ptr<U, D>& linkedPtr)\n\t\t\t: mpValue(linkedPtr.mpValue)\n\t\t{\n\t\t\tif(mpValue)\n\t\t\t\tlink(linkedPtr);\n\t\t\telse\n\t\t\t\tmpPrev = mpNext = this;\n\t\t}\n\n\n\t\t/// ~linked_ptr\n\t\t/// Removes this object from the of objects using the shared pointer.\n\t\t/// If this object is the last owner of the shared pointer, the shared \n\t\t/// pointer is deleted.\n\t\t~linked_ptr() \n\t\t{\n\t\t\treset();\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// If we want a shared_ptr operator= that is templated on linked_ptr<U>,\n\t\t/// then we need to make it in addition to this function, as otherwise \n\t\t/// the compiler will generate this function and things will go wrong.\n\t\tlinked_ptr& operator=(const linked_ptr& linkedPtr)\n\t\t{\n\t\t\tif(linkedPtr.mpValue != mpValue)\n\t\t\t{\n\t\t\t\treset(linkedPtr.mpValue);\n\t\t\t\tif(linkedPtr.mpValue)\n\t\t\t\t\tlink(linkedPtr);\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Copies another linked_ptr to this object. Note that this object\n\t\t/// may already own a shared pointer with another different pointer\n\t\t/// (but still of the same type) before this call. In that case,\n\t\t/// this function removes ownership of the old pointer and takes shared \n\t\t/// ownership of the new pointer and increments its reference count.\n\t\ttemplate <typename U, typename D>\n\t\tlinked_ptr& operator=(const linked_ptr<U, D>& linkedPtr)\n\t\t{\n\t\t\tif(linkedPtr.mpValue != mpValue)\n\t\t\t{\n\t\t\t\treset(linkedPtr.mpValue);\n\t\t\t\tif(linkedPtr.mpValue)\n\t\t\t\t\tlink(linkedPtr);\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Assigns a new pointer. If the new pointer is equivalent\n\t\t/// to the current pointer, nothing is done. Otherwise the \n\t\t/// current pointer is unlinked and possibly destroyed.\n\t\t/// The new pointer can be NULL.\n\t\ttemplate <typename U>\n\t\tlinked_ptr& operator=(U* pValue)\n\t\t{\n\t\t\treset(pValue);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Releases the owned pointer and takes ownership of the \n\t\t/// passed in pointer. If the passed in pointer is the same\n\t\t/// as the owned pointer, nothing is done. The passed in pointer\n\t\t/// can be NULL, in which case the use count is set to 1.\n\t\ttemplate <typename U>\n\t\tvoid reset(U* pValue)\n\t\t{\n\t\t\tif(pValue != mpValue)\n\t\t\t{\n\t\t\t\tif(unique())\n\t\t\t\t{\n\t\t\t\t\tdeleter_type del;\n\t\t\t\t\tdel(mpValue);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tmpPrev->mpNext  = mpNext;\n\t\t\t\t\tmpNext->mpPrev  = mpPrev;\n\t\t\t\t\tmpPrev = mpNext = this;\n\t\t\t\t}\n\t\t\t\tmpValue = pValue;\n\t\t\t}\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Resets the container with NULL. If the current pointer\n\t\t/// is non-NULL, it is unlinked and possibly destroyed.\n\t\tvoid reset()\n\t\t{\n\t\t\treset((T*)NULL);\n\t\t}\n\n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer beween two linkedPtr objects.\n\t\t///\n\t\t/// This function is disabled as it is currently deemed unsafe.\n\t\t/// The problem is that the only way to implement this function\n\t\t/// is to transfer pointers between the objects; you cannot \n\t\t/// transfer the linked list membership between the objects. \n\t\t/// Thus unless both linked_ptr objects were 'unique()', the \n\t\t/// shared pointers would be duplicated amongst containers, \n\t\t/// resulting in a crash.\n\t\t//template <typename U, typename D>\n\t\t//void swap(linked_ptr<U, D>& linkedPtr)\n\t\t//{\n\t\t//    if(linkedPtr.mpValue != mpValue)\n\t\t//    {   // This is only safe if both linked_ptrs are unique().\n\t\t//        linkedPtr::element_type* const pValueTemp = linkedPtr.mpValue;\n\t\t//        linkedPtr.reset(mpValue);\n\t\t//        reset(pValueTemp);\n\t\t//    }\n\t\t//}\n\n\n\t\t/// operator*\n\t\t/// Returns the owner pointer dereferenced.\n\t\tT& operator*() const\n\t\t{\n\t\t\treturn *mpValue;\n\t\t}\n\n\n\t\t/// operator->\n\t\t/// Allows access to the owned pointer via operator->()\n\t\tT* operator->() const\n\t\t{\n\t\t\treturn mpValue;\n\t\t}\n\n\n\t\t/// get\n\t\t/// Returns the owned pointer. Note that this class does \n\t\t/// not provide an operator T() function. This is because such\n\t\t/// a thing (automatic conversion) is deemed unsafe.\n\t\tT* get() const\n\t\t{\n\t\t\treturn mpValue;\n\t\t}\n\n\n\t\t/// use_count\n\t\t/// Returns the use count of the shared pointer.\n\t\t/// The return value is one if the owned pointer is null.\n\t\t/// This function is provided for compatibility with the \n\t\t/// proposed C++ standard and for debugging purposes. It is not\n\t\t/// intended for runtime use given that its execution time is\n\t\t/// not constant.\n\t\tint use_count() const\n\t\t{\n\t\t\tint useCount(1);\n\t\t\t\n\t\t\tfor(const linked_ptr_base* pCurrent = static_cast<const linked_ptr_base*>(this); \n\t\t\t\t\tpCurrent->mpNext != static_cast<const linked_ptr_base*>(this); pCurrent = pCurrent->mpNext)\n\t\t\t\t++useCount;\n\n\t\t\treturn useCount;\n\t\t}\n\n\n\t\t/// unique\n\t\t/// Returns true if the use count of the owned pointer is one.\n\t\t/// The return value is true if the owned pointer is null.\n\t\tbool unique() const\n\t\t{\n\t\t\treturn (mpNext == static_cast<const linked_ptr_base*>(this));\n\t\t}\n\n\n\t\t/// Implicit operator bool\n\t\t/// Allows for using a linked_ptr as a boolean. \n\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t/// The result is that this: if(linkedPtr == 1) would yield true (bad).\n\t\ttypedef T* (this_type::*bool_)() const;\n\t\toperator bool_() const\n\t\t{\n\t\t\tif(mpValue)\n\t\t\t\treturn &this_type::get;\n\t\t\treturn NULL;\n\t\t}\n\n\n\t\t/// operator!\n\t\t/// This returns the opposite of operator bool; it returns true if \n\t\t/// the owned pointer is null. Some compilers require this and some don't.\n\t\tbool operator!()\n\t\t{\n\t\t\treturn (mpValue == NULL);\n\t\t}\n\n\n\t\t/// detach\n\t\t/// Returns ownership of the pointer to the caller.  Fixes all\n\t\t/// references to the pointer by any other owners to be NULL.\n\t\t/// This function can work properly only if all entries in the list \n\t\t/// refer to type T and none refer to any other type (e.g. U).\n\t\tT* detach()\n\t\t{\n\t\t\tT* const pValue = mpValue;\n\n\t\t\tlinked_ptr_base* p = this;\n\t\t\tdo\n\t\t\t{\n\t\t\t\tlinked_ptr_base* const pNext = p->mpNext;\n\t\t\t\tstatic_cast<this_type*>(p)->mpValue = NULL;\n\t\t\t\tp->mpNext = p->mpPrev = p;\n\t\t\t\tp = pNext;\n\t\t\t}\n\t\t\twhile(p != this);\n\n\t\t\treturn pValue;\n\t\t}\n\n\t\t/// force_delete\n\t\t/// Forces deletion of the shared pointer. Fixes all references to the \n\t\t/// pointer by any other owners to be NULL.\n\t\t/// This function can work properly only if all entries in the list \n\t\t/// refer to type T and none refer to any other type (e.g. U).\n\t\tvoid force_delete()\n\t\t{\n\t\t\tT* const pValue = detach();\n\t\t\tDeleter del;\n\t\t\tdel(pValue);\n\t\t}\n\n\t}; // class linked_ptr\n\n\n\n\t/// get_pointer\n\t/// Returns linked_ptr::get() via the input linked_ptr. Provided for compatibility\n\t/// with certain well-known libraries that use this functionality.\n\ttemplate <typename T, typename D>\n\tinline T* get_pointer(const linked_ptr<T, D>& linkedPtr)\n\t{\n\t\treturn linkedPtr.get();\n\t}\n\n\n\t/// operator==\n\t/// Compares two linked_ptr objects for equality. Equality is defined as \n\t/// being true when the pointer shared between two linked_ptr objects is equal.\n\ttemplate <typename T, typename TD, typename U, typename UD>\n\tinline bool operator==(const linked_ptr<T, TD>& linkedPtr1, const linked_ptr<U, UD>& linkedPtr2)\n\t{\n\t\treturn (linkedPtr1.get() == linkedPtr2.get());\n\t}\n\n\n\t/// operator!=\n\t/// Compares two linked_ptr objects for inequality. Equality is defined as \n\t/// being true when the pointer shared between two linked_ptr objects is equal.\n\ttemplate <typename T, typename TD, typename U, typename UD>\n\tinline bool operator!=(const linked_ptr<T, TD>& linkedPtr1, const linked_ptr<U, UD>& linkedPtr2)\n\t{\n\t\treturn (linkedPtr1.get() != linkedPtr2.get());\n\t}\n\n\n\t/// operator<\n\t/// Returns which linked_ptr is 'less' than the other. Useful when storing\n\t/// sorted containers of linked_ptr objects.\n\ttemplate <typename T, typename TD, typename U, typename UD>\n\tinline bool operator<(const linked_ptr<T, TD>& linkedPtr1, const linked_ptr<U, UD>& linkedPtr2)\n\t{\n\t\treturn (linkedPtr1.get() < linkedPtr2.get());\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/list.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a doubly-linked list, much like the C++ std::list class.\n// The primary distinctions between this list and std::list are:\n//    - list doesn't implement some of the less-frequently used functions \n//      of std::list. Any required functions can be added at a later time.\n//    - list has a couple extension functions that increase performance.\n//    - list can contain objects with alignment requirements. std::list cannot\n//      do so without a bit of tedious non-portable effort.\n//    - list has optimizations that don't exist in the STL implementations \n//      supplied by library vendors for our targeted platforms.\n//    - list supports debug memory naming natively.\n//    - list::size() by default is not a constant time function, like the list::size \n//      in some std implementations such as STLPort and SGI STL but unlike the \n//      list in Dinkumware and Metrowerks. The EASTL_LIST_SIZE_CACHE option can change this.\n//    - list provides a guaranteed portable node definition that allows users\n//      to write custom fixed size node allocators that are portable.\n//    - list is easier to read, debug, and visualize.\n//    - list is savvy to an environment that doesn't have exception handling,\n//      as is sometimes the case with console or embedded environments.\n//    - list has less deeply nested function calls and allows the user to \n//      enable forced inlining in debug builds in order to reduce bloat.\n//    - list doesn't keep a member size variable. This means that list is \n//      smaller than std::list (depends on std::list) and that for most operations\n//      it is faster than std::list. However, the list::size function is slower.\n//    - list::size_type is defined as eastl_size_t instead of size_t in order to \n//      save memory and run faster on 64 bit systems.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_LIST_H\n#define EASTL_LIST_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/memory.h>\n#include <EASTL/bonus/compressed_pair.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <new>\n#include <stddef.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4345 - Behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\n// 4623 - default constructor was implicitly defined as deleted\nEA_DISABLE_VC_WARNING(4530 4345 4571 4623);\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_LIST_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_LIST_DEFAULT_NAME\n\t\t#define EASTL_LIST_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" list\" // Unless the user overrides something, this is \"EASTL list\".\n\t#endif\n\n\n\t/// EASTL_LIST_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_LIST_DEFAULT_ALLOCATOR\n\t\t#define EASTL_LIST_DEFAULT_ALLOCATOR allocator_type(EASTL_LIST_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// ListNodeBase\n\t///\n\t/// We define a ListNodeBase separately from ListNode (below), because it allows\n\t/// us to have non-templated operations such as insert, remove (below), and it \n\t/// makes it so that the list anchor node doesn't carry a T with it, which would\n\t/// waste space and possibly lead to surprising the user due to extra Ts existing\n\t/// that the user didn't explicitly create. The downside to all of this is that \n\t/// it makes debug viewing of a list harder, given that the node pointers are of \n\t/// type ListNodeBase and not ListNode. However, see ListNodeBaseProxy below.\n\t///\n\tstruct ListNodeBase\n\t{\n\t\tListNodeBase* mpNext;\n\t\tListNodeBase* mpPrev;\n\n\t\tvoid        insert(ListNodeBase* pNext) EA_NOEXCEPT;                                // Inserts this standalone node before the node pNext in pNext's list. \n\t\tvoid        remove() EA_NOEXCEPT;                                                   // Removes this node from the list it's in. Leaves this node's mpNext/mpPrev invalid.\n\t\tvoid        splice(ListNodeBase* pFirst, ListNodeBase* pLast) EA_NOEXCEPT;          // Removes [pFirst,pLast) from the list it's in and inserts it before this in this node's list.\n\t\tvoid        reverse() EA_NOEXCEPT;                                                  // Reverses the order of nodes in the circular list this node is a part of.\n\t\tstatic void swap(ListNodeBase& a, ListNodeBase& b) EA_NOEXCEPT;                     // Swaps the nodes a and b in the lists to which they belong.\n\n\t\tvoid        insert_range(ListNodeBase* pFirst, ListNodeBase* pFinal) EA_NOEXCEPT;   // Differs from splice in that first/final aren't in another list.\n\t\tstatic void remove_range(ListNodeBase* pFirst, ListNodeBase* pFinal) EA_NOEXCEPT;   // \n\t};\n\n\tEA_DISABLE_VC_WARNING(4625 4626)\n\ttemplate <typename T>\n\tstruct ListNode : public ListNodeBase\n\t{\n\t\t\tT mValue;\n\t\t};\n\tEA_RESTORE_VC_WARNING()\n\n\t/// ListIterator\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tstruct ListIterator\n\t{\n\t\ttypedef ListIterator<T, Pointer, Reference>         this_type;\n\t\ttypedef ListIterator<T, T*, T&>                     iterator;\n\t\ttypedef ListIterator<T, const T*, const T&>         const_iterator;\n\t\ttypedef eastl_size_t                                size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                   difference_type;\n\t\ttypedef T                                           value_type;\n\t\ttypedef ListNodeBase                                base_node_type;\n\t\ttypedef ListNode<T>                                 node_type;\n\t\ttypedef Pointer                                     pointer;\n\t\ttypedef Reference                                   reference;\n\t\ttypedef eastl::bidirectional_iterator_tag    iterator_category;\n\n\tpublic:\n\t\tbase_node_type* mpNode;\n\n\tpublic:\n\t\tListIterator() EA_NOEXCEPT;\n\t\tListIterator(const ListNodeBase* pNode) EA_NOEXCEPT;\n\n\t\ttemplate <typename This = this_type, enable_if_t<!is_same_v<This, iterator>, bool> = true>\n\t\tinline ListIterator(const iterator& x) EA_NOEXCEPT\n\t\t\t: mpNode(x.mpNode)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\tthis_type next() const EA_NOEXCEPT;\n\t\tthis_type prev() const EA_NOEXCEPT;\n\n\t\treference operator*() const EA_NOEXCEPT;\n\t\tpointer   operator->() const EA_NOEXCEPT;\n\n\t\tthis_type& operator++() EA_NOEXCEPT;\n\t\tthis_type  operator++(int) EA_NOEXCEPT;\n\n\t\tthis_type& operator--() EA_NOEXCEPT;\n\t\tthis_type  operator--(int) EA_NOEXCEPT;\n\n\t}; // ListIterator\n\n\n\n\n\t/// ListBase\n\t///\n\t/// See VectorBase (class vector) for an explanation of why we \n\t/// create this separate base class.\n\t///\n\ttemplate <typename T, typename Allocator>\n\tclass ListBase\n\t{\n\tpublic:\n\t\ttypedef T                                    value_type;\n\t\ttypedef Allocator                            allocator_type;\n\t\ttypedef ListNode<T>                          node_type;\n\t\ttypedef eastl_size_t                         size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                            difference_type;\n\t\ttypedef ListNodeBase                         base_node_type; // We use ListNodeBase instead of ListNode<T> because we don't want to create a T.\n\n\tprotected:\n\t\teastl::compressed_pair<base_node_type, allocator_type>  mNodeAllocator;\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\tsize_type  mSize;\n\t\t#endif\n\n\t\tbase_node_type& internalNode() EA_NOEXCEPT { return mNodeAllocator.first(); }\n\t\tbase_node_type const& internalNode() const EA_NOEXCEPT { return mNodeAllocator.first(); }\n\t\tallocator_type& internalAllocator() EA_NOEXCEPT { return mNodeAllocator.second(); }\n\t\tconst allocator_type& internalAllocator() const EA_NOEXCEPT { return mNodeAllocator.second(); }\n\n\tpublic:\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT;\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT;\n\t\tvoid                  set_allocator(const allocator_type& allocator);\n\n\tprotected:\n\t\tListBase();\n\t\tListBase(const allocator_type& a);\n\t   ~ListBase();\n\n\t\tnode_type* DoAllocateNode();\n\t\tvoid       DoFreeNode(node_type* pNode);\n\n\t\tvoid DoInit() EA_NOEXCEPT;\n\t\tvoid DoClear();\n\n\t}; // ListBase\n\n\n\n\n\t/// list\n\t///\n\t/// -- size() is O(n) --\n\t/// Note that as of this writing, list::size() is an O(n) operation when EASTL_LIST_SIZE_CACHE is disabled. \n\t/// That is, getting the size of the list is not a fast operation, as it requires traversing the list and \n\t/// counting the nodes. We could make list::size() be fast by having a member mSize variable. There are reasons \n\t/// for having such functionality and reasons for not having such functionality. We currently choose\n\t/// to not have a member mSize variable as it would add four bytes to the class, add a tiny amount\n\t/// of processing to functions such as insert and erase, and would only serve to improve the size\n\t/// function, but no others. The alternative argument is that the C++ standard states that std::list\n\t/// should be an O(1) operation (i.e. have a member size variable), most C++ standard library list\n\t/// implementations do so, the size is but an integer which is quick to update, and many users \n\t/// expect to have a fast size function. The EASTL_LIST_SIZE_CACHE option changes this.\n\t/// To consider: Make size caching an optional template parameter.\n\t///\n\t/// Pool allocation\n\t/// If you want to make a custom memory pool for a list container, your pool \n\t/// needs to contain items of type list::node_type. So if you have a memory\n\t/// pool that has a constructor that takes the size of pool items and the\n\t/// count of pool items, you would do this (assuming that MemoryPool implements\n\t/// the Allocator interface):\n\t///     typedef list<Widget, MemoryPool> WidgetList;           // Delare your WidgetList type.\n\t///     MemoryPool myPool(sizeof(WidgetList::node_type), 100); // Make a pool of 100 Widget nodes.\n\t///     WidgetList myList(&myPool);                            // Create a list that uses the pool.\n\t///\n\ttemplate <typename T, typename Allocator = EASTLAllocatorType>\n\tclass list : public ListBase<T, Allocator>\n\t{\n\t\ttypedef ListBase<T, Allocator>                  base_type;\n\t\ttypedef list<T, Allocator>                      this_type;\n\n\tprotected:\n\t\tusing base_type::mNodeAllocator;\n\t\tusing base_type::DoAllocateNode;\n\t\tusing base_type::DoFreeNode;\n\t\tusing base_type::DoClear;\n\t\tusing base_type::DoInit;\n#if EASTL_LIST_SIZE_CACHE\n\t\tusing base_type::mSize;\n#endif\n\t\tusing base_type::internalNode;\n\t\tusing base_type::internalAllocator;\n\n\tpublic:\n\t\ttypedef T                                       value_type;\n\t\ttypedef T*                                      pointer;\n\t\ttypedef const T*                                const_pointer;\n\t\ttypedef T&                                      reference;\n\t\ttypedef const T&                                const_reference;\n\t\ttypedef ListIterator<T, T*, T&>                 iterator;\n\t\ttypedef ListIterator<T, const T*, const T&>     const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>       reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator> const_reverse_iterator;\n\t\ttypedef typename base_type::size_type           size_type;\n\t\ttypedef typename base_type::difference_type     difference_type;\n\t\ttypedef typename base_type::allocator_type      allocator_type;\n\t\ttypedef typename base_type::node_type           node_type;\n\t\ttypedef typename base_type::base_node_type      base_node_type;\n\n\t\tusing base_type::get_allocator;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"vector<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"vector<T> value_type must be non-volatile.\");\n\n\tpublic:\n\t\tlist();\n\t\tlist(const allocator_type& allocator);\n\t\texplicit list(size_type n, const allocator_type& allocator = EASTL_LIST_DEFAULT_ALLOCATOR);\n\t\tlist(size_type n, const value_type& value, const allocator_type& allocator = EASTL_LIST_DEFAULT_ALLOCATOR);\n\t\tlist(const this_type& x);\n\t\tlist(const this_type& x, const allocator_type& allocator);\n\t\tlist(this_type&& x);\n\t\tlist(this_type&&, const allocator_type&);\n\t\tlist(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_LIST_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tlist(InputIterator first, InputIterator last); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\t// In the case that the two containers' allocators are unequal, swap copies elements instead\n\t\t// of replacing them in place. In this case swap is an O(n) operation instead of O(1).\n\t\tvoid swap(this_type& x);\n\n\t\tvoid assign(size_type n, const value_type& value);\n\n\t\ttemplate <typename InputIterator>                       // It turns out that the C++ std::list specifies a two argument\n\t\tvoid assign(InputIterator first, InputIterator last);   // version of assign that takes (int size, int value). These are not \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// iterators, so we need to do a template compiler trick to do the right thing.\n\t\tvoid assign(std::initializer_list<value_type> ilist);\n\n\t\titerator       begin() EA_NOEXCEPT;\n\t\tconst_iterator begin() const EA_NOEXCEPT;\n\t\tconst_iterator cbegin() const EA_NOEXCEPT;\n\n\t\titerator       end() EA_NOEXCEPT;\n\t\tconst_iterator end() const EA_NOEXCEPT;\n\t\tconst_iterator cend() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rbegin() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crbegin() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rend() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rend() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crend() const EA_NOEXCEPT;\n\n\t\tbool      empty() const EA_NOEXCEPT;\n\t\tsize_type size() const EA_NOEXCEPT;\n\n\t\tvoid resize(size_type n, const value_type& value);\n\t\tvoid resize(size_type n);\n\n\t\treference       front();\n\t\tconst_reference front() const;\n\n\t\treference       back();\n\t\tconst_reference back() const;\n\n\t\ttemplate <typename... Args>\n\t\treference emplace_front(Args&&... args);\n\n\t\ttemplate <typename... Args>\n\t\treference emplace_back(Args&&... args);\n\n\t\tvoid      push_front(const value_type& value);\n\t\tvoid      push_front(value_type&& x);\n\t\treference push_front();\n\t\tvoid*     push_front_uninitialized();\n\n\t\tvoid      push_back(const value_type& value);\n\t\tvoid      push_back(value_type&& x);\n\t\treference push_back();\n\t\tvoid*     push_back_uninitialized();\n\n\t\tvoid pop_front();\n\t\tvoid pop_back();\n\n\t\ttemplate <typename... Args>\n\t\titerator emplace(const_iterator position, Args&&... args);\n\n\t\titerator insert(const_iterator position);\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\titerator insert(const_iterator position, value_type&& x);\n\t\titerator insert(const_iterator position, std::initializer_list<value_type> ilist);\n\t\titerator insert(const_iterator position, size_type n, const value_type& value);\n\n\t\ttemplate <typename InputIterator>\n\t\titerator insert(const_iterator position, InputIterator first, InputIterator last);\n\n\t\titerator erase(const_iterator position);\n\t\titerator erase(const_iterator first, const_iterator last);\n\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\tvoid clear() EA_NOEXCEPT;\n\t\tvoid reset_lose_memory() EA_NOEXCEPT;    // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type remove(const T& x);\n\n\t\ttemplate <typename Predicate>\n\t\tsize_type remove_if(Predicate);\n\n\t\tvoid reverse() EA_NOEXCEPT;\n\n\t\t// splice inserts elements in the range [first,last) before position and removes the elements from x.\n\t\t// In the case that the two containers' allocators are unequal, splice copies elements \n\t\t// instead of splicing them. In this case elements are not removed from x, and iterators \n\t\t// into the spliced elements from x continue to point to the original values in x.\n\t\tvoid splice(const_iterator position, this_type& x);\n\t\tvoid splice(const_iterator position, this_type& x, const_iterator i);\n\t\tvoid splice(const_iterator position, this_type& x, const_iterator first, const_iterator last);\n\t\tvoid splice(const_iterator position, this_type&& x);\n\t\tvoid splice(const_iterator position, this_type&& x, const_iterator i);\n\t\tvoid splice(const_iterator position, this_type&& x, const_iterator first, const_iterator last);\n\n\tpublic:\n\t\t// For merge, see notes for splice regarding the handling of unequal allocators.\n\t\tvoid merge(this_type& x);\n\t\tvoid merge(this_type&& x);\n\n\t\ttemplate <typename Compare>\n\t\tvoid merge(this_type& x, Compare compare);\n\n\t\ttemplate <typename Compare>\n\t\tvoid merge(this_type&& x, Compare compare);\n\n\t\tsize_type unique();\n\n\t\ttemplate <typename BinaryPredicate>\n\t\tsize_type unique(BinaryPredicate);\n\n\t\t// Sorting functionality\n\t\t// This is independent of the global sort algorithms, as lists are \n\t\t// linked nodes and can be sorted more efficiently by moving nodes\n\t\t// around in ways that global sort algorithms aren't privy to.\n\t\tvoid sort();\n\n\t\ttemplate<typename Compare>\n\t\tvoid sort(Compare compare);\n\n\tpublic:\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\tprotected:\n\t\tnode_type* DoCreateNode();\n\n\t\ttemplate<typename... Args>\n\t\tnode_type* DoCreateNode(Args&&... args);\n\n\t\ttemplate <typename Integer>\n\t\tvoid DoAssign(Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoAssign(InputIterator first, InputIterator last, false_type);\n\n\t\tvoid DoAssignValues(size_type n, const value_type& value);\n\n\t\ttemplate <typename Integer>\n\t\tvoid DoInsert(ListNodeBase* pNode, Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoInsert(ListNodeBase* pNode, InputIterator first, InputIterator last, false_type);\n\n\t\tvoid DoInsertValues(ListNodeBase* pNode, size_type n, const value_type& value);\n\t   \n\t\ttemplate<typename... Args>\n\t\tvoid DoInsertValue(ListNodeBase* pNode, Args&&... args);\n\n\t\tvoid DoErase(ListNodeBase* pNode);\n\n\t\tvoid DoSwap(this_type& x);\n\n\t\ttemplate <typename Compare>\n\t\titerator DoSort(iterator i1, iterator end2, size_type n, Compare& compare);\n\n\t}; // class list\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// ListNodeBase\n\t///////////////////////////////////////////////////////////////////////\n\n\t// Swaps the nodes a and b in the lists to which they belong. This is similar to \n\t// splicing a into b's list and b into a's list at the same time.\n\t// Works by swapping the members of a and b, and fixes up the lists that a and b \n\t// were part of to point to the new members.\n\tinline void ListNodeBase::swap(ListNodeBase& a, ListNodeBase& b) EA_NOEXCEPT\n\t{\n\t\tconst ListNodeBase temp(a);\n\t\ta = b;\n\t\tb = temp;\n\n\t\tif(a.mpNext == &b)\n\t\t\ta.mpNext = a.mpPrev = &a;\n\t\telse\n\t\t\ta.mpNext->mpPrev = a.mpPrev->mpNext = &a;\n\n\t\tif(b.mpNext == &a)\n\t\t\tb.mpNext = b.mpPrev = &b;\n\t\telse\n\t\t\tb.mpNext->mpPrev = b.mpPrev->mpNext = &b;\n\t}\n\n\n\t// splices the [first,last) range from its current list into our list before this node.\n\tinline void ListNodeBase::splice(ListNodeBase* first, ListNodeBase* last) EA_NOEXCEPT\n\t{\n\t\t// We assume that [first, last] are not within our list.\n\t\tlast->mpPrev->mpNext  = this;\n\t\tfirst->mpPrev->mpNext = last;\n\t\tthis->mpPrev->mpNext  = first;\n\n\t\tListNodeBase* const pTemp = this->mpPrev;\n\t\tthis->mpPrev  = last->mpPrev;\n\t\tlast->mpPrev  = first->mpPrev;\n\t\tfirst->mpPrev = pTemp;\n\t}\n\n\n\tinline void ListNodeBase::reverse() EA_NOEXCEPT\n\t{\n\t\tListNodeBase* pNode = this;\n\t\tdo\n\t\t{\n\t\t\tEA_ANALYSIS_ASSUME(pNode != NULL);\n\t\t\tListNodeBase* const pTemp = pNode->mpNext;\n\t\t\tpNode->mpNext = pNode->mpPrev;\n\t\t\tpNode->mpPrev = pTemp;\n\t\t\tpNode         = pNode->mpPrev;\n\t\t} \n\t\twhile(pNode != this);\n\t}\n\n\n\tinline void ListNodeBase::insert(ListNodeBase* pNext) EA_NOEXCEPT\n\t{\n\t\tmpNext = pNext;\n\t\tmpPrev = pNext->mpPrev;\n\t\tpNext->mpPrev->mpNext = this;\n\t\tpNext->mpPrev = this;\n\t}\n\n\n\t// Removes this node from the list that it's in. Assumes that the \n\t// node is within a list and thus that its prev/next pointers are valid.\n\tinline void ListNodeBase::remove() EA_NOEXCEPT\n\t{\n\t\tmpNext->mpPrev = mpPrev;\n\t\tmpPrev->mpNext = mpNext;\n\t}\n\n\n\t// Inserts the standalone range [pFirst, pFinal] before pPosition. Assumes that the\n\t// range is not within a list and thus that it's prev/next pointers are not valid.\n\t// Assumes that this node is within a list and thus that its prev/next pointers are valid.\n\tinline void ListNodeBase::insert_range(ListNodeBase* pFirst, ListNodeBase* pFinal) EA_NOEXCEPT\n\t{\n\t\tmpPrev->mpNext = pFirst;\n\t\tpFirst->mpPrev = mpPrev;\n\t\tmpPrev         = pFinal;\n\t\tpFinal->mpNext = this;\n\t}\n\n\n\t// Removes the range [pFirst, pFinal] from the list that it's in. Assumes that the \n\t// range is within a list and thus that its prev/next pointers are valid.\n\tinline void ListNodeBase::remove_range(ListNodeBase* pFirst, ListNodeBase* pFinal) EA_NOEXCEPT\n\t{\n\t\tpFinal->mpNext->mpPrev = pFirst->mpPrev;\n\t\tpFirst->mpPrev->mpNext = pFinal->mpNext;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// ListIterator\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline ListIterator<T, Pointer, Reference>::ListIterator() EA_NOEXCEPT\n\t\t: mpNode() // To consider: Do we really need to intialize mpNode?\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline ListIterator<T, Pointer, Reference>::ListIterator(const ListNodeBase* pNode) EA_NOEXCEPT\n\t\t: mpNode(const_cast<base_node_type*>(pNode))\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::this_type\n\tListIterator<T, Pointer, Reference>::next() const EA_NOEXCEPT\n\t{\n\t\treturn ListIterator(mpNode->mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::this_type\n\tListIterator<T, Pointer, Reference>::prev() const EA_NOEXCEPT\n\t{\n\t\treturn ListIterator(mpNode->mpPrev);\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::reference\n\tListIterator<T, Pointer, Reference>::operator*() const EA_NOEXCEPT\n\t{\n\t\treturn static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::pointer\n\tListIterator<T, Pointer, Reference>::operator->() const EA_NOEXCEPT\n\t{\n\t\treturn &static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::this_type&\n\tListIterator<T, Pointer, Reference>::operator++() EA_NOEXCEPT\n\t{\n\t\tmpNode = mpNode->mpNext;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::this_type\n\tListIterator<T, Pointer, Reference>::operator++(int) EA_NOEXCEPT\n\t{\n\t\tthis_type temp(*this);\n\t\tmpNode = mpNode->mpNext;\n\t\treturn temp;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::this_type&\n\tListIterator<T, Pointer, Reference>::operator--() EA_NOEXCEPT\n\t{\n\t\tmpNode = mpNode->mpPrev;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename ListIterator<T, Pointer, Reference>::this_type \n\tListIterator<T, Pointer, Reference>::operator--(int) EA_NOEXCEPT\n\t{\n\t\tthis_type temp(*this);\n\t\tmpNode = mpNode->mpPrev;\n\t\treturn temp;\n\t}\n\n\n\t// The C++ defect report #179 requires that we support comparisons between const and non-const iterators.\n\t// Thus we provide additional template paremeters here to support this. The defect report does not\n\t// require us to support comparisons between reverse_iterators and const_reverse_iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator==(const ListIterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const ListIterator<T, PointerB, ReferenceB>& b) EA_NOEXCEPT\n\t{\n\t\treturn a.mpNode == b.mpNode;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator!=(const ListIterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const ListIterator<T, PointerB, ReferenceB>& b) EA_NOEXCEPT\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\t// We provide a version of operator!= for the case where the iterators are of the \n\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline bool operator!=(const ListIterator<T, Pointer, Reference>& a, \n\t\t\t\t\t\t   const ListIterator<T, Pointer, Reference>& b) EA_NOEXCEPT\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// ListBase\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline ListBase<T, Allocator>::ListBase()\n\t\t: mNodeAllocator(base_node_type(), allocator_type(EASTL_LIST_DEFAULT_NAME))\n\t\t  #if EASTL_LIST_SIZE_CACHE\n\t\t  , mSize(0)\n\t\t  #endif\n\t{\n\t\tDoInit();\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline ListBase<T, Allocator>::ListBase(const allocator_type& allocator)\n\t\t: mNodeAllocator(base_node_type(), allocator)\n\t\t  #if EASTL_LIST_SIZE_CACHE\n\t\t  , mSize(0)\n\t\t  #endif\n\t{\n\t\tDoInit();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline ListBase<T, Allocator>::~ListBase()\n\t{\n\t\tDoClear();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tconst typename ListBase<T, Allocator>::allocator_type&\n\tListBase<T, Allocator>::get_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename ListBase<T, Allocator>::allocator_type&\n\tListBase<T, Allocator>::get_allocator() EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void ListBase<T, Allocator>::set_allocator(const allocator_type& allocator)\n\t{\n\t\tif((internalAllocator() != allocator) && (static_cast<node_type*>(internalNode().mpNext) != &internalNode()))\n\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"list::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\tinternalAllocator() = allocator;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename ListBase<T, Allocator>::node_type*\n\tListBase<T, Allocator>::DoAllocateNode()\n\t{\n\t\tnode_type* pNode = (node_type*)allocate_memory(internalAllocator(), sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t\tEASTL_ASSERT(pNode != nullptr);\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void ListBase<T, Allocator>::DoFreeNode(node_type* p)\n\t{\n\t\tEASTLFree(internalAllocator(), p, sizeof(node_type));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void ListBase<T, Allocator>::DoInit() EA_NOEXCEPT\n\t{\n\t\tinternalNode().mpNext = &internalNode();\n\t\tinternalNode().mpPrev = &internalNode();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void ListBase<T, Allocator>::DoClear()\n\t{\n\t\tbase_node_type* p = internalNode().mpNext;\n\n\t\twhile(p != &internalNode())\n\t\t{\n\t\t\tnode_type* const pTemp = static_cast<node_type*>(p);\n\t\t\tp = p->mpNext;\n\t\t\tpTemp->~node_type();\n\t\t\tEASTLFree(internalAllocator(), pTemp, sizeof(node_type));\n\t\t}\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// list\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list()\n\t\t: base_type()\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(size_type n, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInsertValues(&internalNode(), n, value_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(size_type n, const value_type& value, const allocator_type& allocator)\n\t\t: base_type(allocator) \n\t{\n\t\tDoInsertValues(&internalNode(), n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(const this_type& x)\n\t\t: base_type(x.internalAllocator())\n\t{\n\t\tDoInsert(&internalNode(), const_iterator(x.internalNode().mpNext), const_iterator(&x.internalNode()), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(const this_type& x, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInsert(&internalNode(), const_iterator(x.internalNode().mpNext), const_iterator(&x.internalNode()), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(this_type&& x)\n\t\t: base_type(eastl::move(x.internalAllocator()))\n\t{\n\t\tswap(x);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tswap(x); // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline list<T, Allocator>::list(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInsert(&internalNode(), ilist.begin(), ilist.end(), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tlist<T, Allocator>::list(InputIterator first, InputIterator last)\n\t\t: base_type(EASTL_LIST_DEFAULT_ALLOCATOR)\n\t{\n\t\t//insert(const_iterator(&internalNode()), first, last);\n\t\tDoInsert(&internalNode(), first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::iterator\n\tinline list<T, Allocator>::begin() EA_NOEXCEPT\n\t{\n\t\treturn iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_iterator\n\tlist<T, Allocator>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_iterator\n\tlist<T, Allocator>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::end() EA_NOEXCEPT\n\t{\n\t\treturn iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_iterator\n\tlist<T, Allocator>::end() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_iterator\n\tlist<T, Allocator>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::reverse_iterator\n\tlist<T, Allocator>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_reverse_iterator\n\tlist<T, Allocator>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_reverse_iterator\n\tlist<T, Allocator>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::reverse_iterator\n\tlist<T, Allocator>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_reverse_iterator\n\tlist<T, Allocator>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_reverse_iterator\n\tlist<T, Allocator>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::reference\n\tlist<T, Allocator>::front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<node_type*>(internalNode().mpNext) == &internalNode()))\n\t\t\t\tEASTL_FAIL_MSG(\"list::front -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<node_type*>(internalNode().mpNext)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_reference\n\tlist<T, Allocator>::front() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<node_type*>(internalNode().mpNext) == &internalNode()))\n\t\t\t\tEASTL_FAIL_MSG(\"list::front -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<node_type*>(internalNode().mpNext)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::reference\n\tlist<T, Allocator>::back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<node_type*>(internalNode().mpNext) == &internalNode()))\n\t\t\t\tEASTL_FAIL_MSG(\"list::back -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<node_type*>(internalNode().mpPrev)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::const_reference\n\tlist<T, Allocator>::back() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(static_cast<node_type*>(internalNode().mpNext) == &internalNode()))\n\t\t\t\tEASTL_FAIL_MSG(\"list::back -- empty container\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn static_cast<node_type*>(internalNode().mpPrev)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool list<T, Allocator>::empty() const EA_NOEXCEPT\n\t{\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\treturn (mSize == 0);\n\t\t#else\n\t\t\treturn static_cast<node_type*>(internalNode().mpNext) == &internalNode();\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::size_type\n\tlist<T, Allocator>::size() const EA_NOEXCEPT\n\t{\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\treturn mSize;\n\t\t#else\n\t\t\t#if EASTL_DEBUG\n\t\t\t\tconst ListNodeBase* p = internalNode().mpNext;\n\t\t\t\tsize_type n = 0;\n\t\t\t\twhile(p != &internalNode())\n\t\t\t\t{\n\t\t\t\t\t++n;\n\t\t\t\t\tp = p->mpNext;\n\t\t\t\t}\n\t\t\t\treturn n;\n\t\t\t#else\n\t\t\t\t// The following optimizes to slightly better code than the code above.\n\t\t\t\treturn (size_type)eastl::distance(const_iterator(internalNode().mpNext), const_iterator(&internalNode()));\n\t\t\t#endif\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::this_type&\n\tlist<T, Allocator>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x) // If not assigning to self...\n\t\t{\n\t\t\t// If (EASTL_ALLOCATOR_COPY_ENABLED == 1) and the current contents are allocated by an \n\t\t\t// allocator that's unequal to x's allocator, we need to reallocate our elements with \n\t\t\t// our current allocator and reallocate it with x's allocator. If the allocators are \n\t\t\t// equal then we can use a more optimal algorithm that doesn't reallocate our elements\n\t\t\t// but instead can copy them in place.\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tbool bSlowerPathwayRequired = (internalAllocator() != x.internalAllocator());\n\t\t\t#else\n\t\t\t\tbool bSlowerPathwayRequired = false;\n\t\t\t#endif\n\n\t\t\tif(bSlowerPathwayRequired)\n\t\t\t{\n\t\t\t\tclear();\n\n\t\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\t\tinternalAllocator() = x.internalAllocator();\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tDoAssign(x.begin(), x.end(), eastl::false_type());\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::this_type&\n\tlist<T, Allocator>::operator=(this_type&& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();        // To consider: Are we really required to clear here? x is going away soon and will clear itself in its dtor.\n\t\t\tswap(x);        // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::this_type&\n\tlist<T, Allocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tDoAssign(ilist.begin(), ilist.end(), false_type());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::assign(size_type n, const value_type& value)\n\t{\n\t\tDoAssignValues(n, value);\n\t}\n\n\n\t// It turns out that the C++ std::list specifies a two argument\n\t// version of assign that takes (int size, int value). These are not \n\t// iterators, so we need to do a template compiler trick to do the right thing.\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline void list<T, Allocator>::assign(InputIterator first, InputIterator last)\n\t{\n\t\tDoAssign(first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::assign(std::initializer_list<value_type> ilist)\n\t{\n\t\tDoAssign(ilist.begin(), ilist.end(), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::clear() EA_NOEXCEPT\n\t{\n\t\tDoClear();\n\t\tDoInit();\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\tmSize = 0;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::reset_lose_memory() EA_NOEXCEPT\n\t{\n\t\t// The reset_lose_memory function is a special extension function which unilaterally \n\t\t// resets the container to an empty state without freeing the memory of \n\t\t// the contained objects. This is useful for very quickly tearing down a \n\t\t// container built into scratch memory.\n\t\tDoInit();\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\tmSize = 0;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid list<T, Allocator>::resize(size_type n, const value_type& value)\n\t{\n\t\titerator current(internalNode().mpNext);\n\t\tsize_type i = 0;\n\n\t\twhile((current.mpNode != &internalNode()) && (i < n))\n\t\t{\n\t\t\t++current;  \n\t\t\t++i;\n\t\t}\n\t\tif(i == n)\n\t\t\terase(current, &internalNode());\n\t\telse\n\t\t\tinsert(&internalNode(), n - i, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::resize(size_type n)\n\t{\n\t\tresize(n, value_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename... Args>\n\ttypename list<T, Allocator>::reference list<T, Allocator>::emplace_front(Args&&... args)\n\t{\n\t\tDoInsertValue(internalNode().mpNext, eastl::forward<Args>(args)...);\n\t\treturn static_cast<node_type*>(internalNode().mpNext)->mValue; // Same as return front();\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename... Args>\n\ttypename list<T, Allocator>::reference list<T, Allocator>::emplace_back(Args&&... args)\n\t{\n\t\tDoInsertValue(&internalNode(), eastl::forward<Args>(args)...);\n\t\treturn static_cast<node_type*>(internalNode().mpPrev)->mValue; // Same as return back();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::push_front(const value_type& value)\n\t{\n\t\tDoInsertValue(internalNode().mpNext, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::push_front(value_type&& value)\n\t{\n\t\templace(begin(), eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::reference\n\tlist<T, Allocator>::push_front()\n\t{\n\t\tnode_type* const pNode = DoCreateNode();\n\t\tpNode->insert(internalNode().mpNext);\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize;\n\t\t#endif\n\t\treturn static_cast<node_type*>(internalNode().mpNext)->mValue; // Same as return front();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void* list<T, Allocator>::push_front_uninitialized()\n\t{\n\t\tnode_type* const pNode = DoAllocateNode();\n\t\tpNode->insert(internalNode().mpNext);\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize;\n\t\t#endif\n\t\treturn &pNode->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::pop_front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(static_cast<node_type*>(internalNode().mpNext) == &internalNode()))\n\t\t\t\tEASTL_FAIL_MSG(\"list::pop_front -- empty container\");\n\t\t#endif\n\n\t\tDoErase(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::push_back(const value_type& value)\n\t{\n\t\tDoInsertValue(&internalNode(), value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::push_back(value_type&& value)\n\t{\n\t\templace(end(), eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::reference\n\tlist<T, Allocator>::push_back()\n\t{\n\t\tnode_type* const pNode = DoCreateNode();\n\t\tpNode->insert(&internalNode());\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize;\n\t\t#endif\n\t\treturn static_cast<node_type*>(internalNode().mpPrev)->mValue;  // Same as return back();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void* list<T, Allocator>::push_back_uninitialized()\n\t{\n\t\tnode_type* const pNode = DoAllocateNode();\n\t\tpNode->insert(&internalNode());\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize;\n\t\t#endif\n\t\treturn &pNode->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::pop_back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(static_cast<node_type*>(internalNode().mpNext) == &internalNode()))\n\t\t\t\tEASTL_FAIL_MSG(\"list::pop_back -- empty container\");\n\t\t#endif\n\n\t\tDoErase(internalNode().mpPrev);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename... Args>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::emplace(const_iterator position, Args&&... args)\n\t{\n\t\tDoInsertValue(position.mpNode, eastl::forward<Args>(args)...);\n\t\treturn iterator(position.mpNode->mpPrev);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::insert(const_iterator position)\n\t{\n\t\tListNodeBase* const pNode = DoCreateNode(value_type());\n\t\tpNode->insert(position.mpNode);\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize;\n\t\t#endif\n\t\treturn pNode;\n\t}\n\n\t\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::insert(const_iterator position, const value_type& value)\n\t{\n\t\tListNodeBase* const pNode = DoCreateNode(value);\n\t\tpNode->insert(position.mpNode);\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize;\n\t\t#endif\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::insert(const_iterator position, value_type&& value)\n\t{\n\t\treturn emplace(position, eastl::move(value));\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::insert(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\titerator itPrev(position.mpNode);\n\t\t--itPrev;\n\t\tDoInsertValues(position.mpNode, n, value);\n\t\treturn ++itPrev; // Inserts in front of position, returns iterator to new elements. \n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::insert(const_iterator position, InputIterator first, InputIterator last)\n\t{\n\t\titerator itPrev(position.mpNode);\n\t\t--itPrev;\n\t\tDoInsert(position.mpNode, first, last, is_integral<InputIterator>());\n\t\treturn ++itPrev; // Inserts in front of position, returns iterator to new elements. \n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::iterator \n\tlist<T, Allocator>::insert(const_iterator position, std::initializer_list<value_type> ilist)\n\t{\n\t\titerator itPrev(position.mpNode);\n\t\t--itPrev;\n\t\tDoInsert(position.mpNode, ilist.begin(), ilist.end(), false_type());\n\t\treturn ++itPrev; // Inserts in front of position, returns iterator to new elements. \n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::iterator\n\tlist<T, Allocator>::erase(const_iterator position)\n\t{\n\t\t++position;\n\t\tDoErase(position.mpNode->mpPrev);\n\t\treturn iterator(position.mpNode);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::iterator\n\tlist<T, Allocator>::erase(const_iterator first, const_iterator last)\n\t{\n\t\twhile(first != last)\n\t\t\tfirst = erase(first);\n\t\treturn iterator(last.mpNode);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::reverse_iterator\n\tlist<T, Allocator>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::reverse_iterator\n\tlist<T, Allocator>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\tconst_iterator itLastBase((++last).base());\n\t\tconst_iterator itFirstBase((++first).base());\n\n\t\treturn reverse_iterator(erase(itLastBase, itFirstBase));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::size_type list<T, Allocator>::remove(const value_type& value)\n\t{\n\t\titerator current(internalNode().mpNext);\n\t\tsize_type numRemoved = 0;\n\n\t\twhile(current.mpNode != &internalNode())\n\t\t{\n\t\t\tif(EASTL_LIKELY(!(*current == value)))\n\t\t\t\t++current; // We have duplicate '++current' statements here and below, but the logic here forces this.\n\t\t\telse\n\t\t\t{\n\t\t\t\t++current;\n\t\t\t\tDoErase(current.mpNode->mpPrev);\n\t\t\t\t++numRemoved;\n\t\t\t}\n\t\t}\n\t\treturn numRemoved;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Predicate>\n\tinline typename list<T, Allocator>::size_type list<T, Allocator>::remove_if(Predicate predicate)\n\t{\n\t\tsize_type numRemoved = 0;\n\t\tfor(iterator first(internalNode().mpNext), last(&internalNode()); first != last; )\n\t\t{\n\t\t\titerator temp(first);\n\t\t\t++temp;\n\t\t\tif(predicate(static_cast<node_type*>(first.mpNode)->mValue))\n\t\t\t{\n\t\t\t\tDoErase(first.mpNode);\n\t\t\t\t++numRemoved;\n\t\t\t}\n\t\t\tfirst = temp;\n\t\t}\n\t\treturn numRemoved;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::reverse() EA_NOEXCEPT\n\t{\n\t\t((ListNodeBase&)internalNode()).reverse();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::splice(const_iterator position, this_type& x)\n\t{\n\t\t// Splicing operations cannot succeed if the two containers use unequal allocators.\n\t\t// This issue is not addressed in the C++ 1998 standard but is discussed in the \n\t\t// LWG defect reports, such as #431. There is no simple solution to this problem.\n\t\t// One option is to throw an exception. Another option which probably captures the\n\t\t// user intent most of the time is to copy the range from the source to the dest and \n\t\t// remove it from the source. \n\n\t\tif(internalAllocator() == x.internalAllocator())\n\t\t{\n\t\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t\tif(x.mSize)\n\t\t\t\t{\n\t\t\t\t\t(position.mpNode)->splice(x.internalNode().mpNext, &x.internalNode());\n\t\t\t\t\tmSize += x.mSize;\n\t\t\t\t\tx.mSize = 0;\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tif(!x.empty())\n\t\t\t\t\t(position.mpNode)->splice(x.internalNode().mpNext, &x.internalNode());\n\t\t\t#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinsert(position, x.begin(), x.end());\n\t\t\tx.clear();\n\t\t}\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::splice(const_iterator position, this_type&& x)\n\t{\n\t\treturn splice(position, x); // This will call splice(const_iterator, const this_type&);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::splice(const_iterator position, list& x, const_iterator i)\n\t{\n\t\tif(internalAllocator() == x.internalAllocator())\n\t\t{\n\t\t\titerator i2(i.mpNode);\n\t\t\t++i2;\n\t\t\tif((position != i) && (position != i2))\n\t\t\t{\n\t\t\t\t(position.mpNode)->splice(i.mpNode, i2.mpNode);\n\n\t\t\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t\t\t++mSize;\n\t\t\t\t\t--x.mSize;\n\t\t\t\t#endif\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinsert(position, *i);\n\t\t\tx.erase(i);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::splice(const_iterator position, list<T,Allocator>&& x, const_iterator i)\n\t{\n\t\treturn splice(position, x, i); // This will call splice(const_iterator, const this_type&, const_iterator);\n\t}\n\t\t\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::splice(const_iterator position, this_type& x, const_iterator first, const_iterator last)\n\t{\n\t\tif(internalAllocator() == x.internalAllocator())\n\t\t{\n\t\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t\tconst size_type n = (size_type)eastl::distance(first, last);\n\n\t\t\t\tif(n)\n\t\t\t\t{\n\t\t\t\t\t(position.mpNode)->splice(first.mpNode, last.mpNode);\n\t\t\t\t\tmSize += n;\n\t\t\t\t\tx.mSize -= n;\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tif(first != last)\n\t\t\t\t\t(position.mpNode)->splice(first.mpNode, last.mpNode);\n\t\t\t#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinsert(position, first, last);\n\t\t\tx.erase(first, last);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::splice(const_iterator position, list<T,Allocator>&& x, const_iterator first, const_iterator last)\n\t{\n\t\treturn splice(position, x, first, last); // This will call splice(const_iterator, const this_type&, const_iterator, const_iterator);\n\t}\n\n\n\t// does not propagate allocators on swap.\n\t// in addition, requires T be copy constructible and copy assignable, which isn't required by the standard.\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::swap(this_type& x)\n\t{\n\t\tif(internalAllocator() == x.internalAllocator()) // If allocators are equivalent...\n\t\t\tDoSwap(x);\n\t\telse // else swap the contents.\n\t\t{\n\t\t\tconst this_type temp(*this); // Can't call eastl::swap because that would\n\t\t\t*this = x;                   // itself call this member swap function.\n\t\t\tx     = temp;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid list<T, Allocator>::merge(this_type& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\titerator       first(begin());\n\t\t\titerator       firstX(x.begin());\n\t\t\tconst iterator last(end());\n\t\t\tconst iterator lastX(x.end());\n\n\t\t\twhile((first != last) && (firstX != lastX))\n\t\t\t{\n\t\t\t\tif(*firstX < *first)\n\t\t\t\t{\n\t\t\t\t\titerator next(firstX);\n\n\t\t\t\t\tsplice(first, x, firstX, ++next);\n\t\t\t\t\tfirstX = next;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++first;\n\t\t\t}\n\n\t\t\tif(firstX != lastX)\n\t\t\t\tsplice(last, x, firstX, lastX);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid list<T, Allocator>::merge(this_type&& x)\n\t{\n\t\treturn merge(x); // This will call merge(this_type&)\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Compare>\n\tvoid list<T, Allocator>::merge(this_type& x, Compare compare)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\titerator       first(begin());\n\t\t\titerator       firstX(x.begin());\n\t\t\tconst iterator last(end());\n\t\t\tconst iterator lastX(x.end());\n\n\t\t\twhile((first != last) && (firstX != lastX))\n\t\t\t{\n\t\t\t\tif(compare(*firstX, *first))\n\t\t\t\t{\n\t\t\t\t\titerator next(firstX);\n\n\t\t\t\t\tsplice(first, x, firstX, ++next);\n\t\t\t\t\tfirstX = next;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++first;\n\t\t\t}\n\n\t\t\tif(firstX != lastX)\n\t\t\t\tsplice(last, x, firstX, lastX);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Compare>\n\tvoid list<T, Allocator>::merge(this_type&& x, Compare compare)\n\t{\n\t\treturn merge(x, compare); // This will call merge(this_type&, Compare)\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename list<T, Allocator>::size_type list<T, Allocator>::unique()\n\t{\n\t\tsize_type      numRemoved = 0;\n\t\titerator       first(begin());\n\t\tconst iterator last(end());\n\n\t\tif(first != last)\n\t\t{\n\t\t\titerator next(first);\n\n\t\t\twhile(++next != last)\n\t\t\t{\n\t\t\t\tif (*first == *next)\n\t\t\t\t{\n\t\t\t\t\tDoErase(next.mpNode);\n\t\t\t\t\t++numRemoved;\n\t\t\t\t\tnext = first;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfirst = next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn numRemoved;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename BinaryPredicate>\n\ttypename list<T, Allocator>::size_type list<T, Allocator>::unique(BinaryPredicate predicate)\n\t{\n\t\tsize_type      numRemoved = 0;\n\t\titerator       first(begin());\n\t\tconst iterator last(end());\n\n\t\tif(first != last)\n\t\t{\n\t\t\titerator next(first);\n\n\t\t\twhile(++next != last)\n\t\t\t{\n\t\t\t\tif (predicate(*first, *next))\n\t\t\t\t{\n\t\t\t\t\tDoErase(next.mpNode);\n\t\t\t\t\t++numRemoved;\n\t\t\t\t\tnext = first;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfirst = next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn numRemoved;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid list<T, Allocator>::sort()\n\t{\n\t\teastl::less<value_type> compare;\n\t\tDoSort(begin(), end(), size(), compare);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Compare>\n\tvoid list<T, Allocator>::sort(Compare compare)\n\t{\n\t\tDoSort(begin(), end(), size(), compare);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Compare>\n\ttypename list<T, Allocator>::iterator\n\tlist<T, Allocator>::DoSort(iterator i1, iterator end2, size_type n, Compare& compare)\n\t{\n\t\t// A previous version of this function did this by creating temporary lists, \n\t\t// but that was incompatible with fixed_list because the sizes could be too big.\n\t\t// We sort subsegments by recursive descent. Then merge as we ascend.\n\t\t// Return an iterator to the beginning of the sorted subsegment.\n\t\t// Start with a special case for small node counts.\n\t\tswitch (n)\n\t\t{\n\t\t\tcase 0:\n\t\t\tcase 1:\n\t\t\t\treturn i1;\n\n\t\t\tcase 2:\n\t\t\t\t// Potentialy swap these two nodes and return the resulting first of them.\n\t\t\t\tif(compare(*--end2, *i1))\n\t\t\t\t{\n\t\t\t\t\tend2.mpNode->remove();\n\t\t\t\t\tend2.mpNode->insert(i1.mpNode);\n\t\t\t\t\treturn end2;\n\t\t\t\t}\n\t\t\t\treturn i1;\n\n\t\t\tcase 3:\n\t\t\t{\n\t\t\t\t// We do a list insertion sort. Measurements showed this improved performance 3-12%.\n\t\t\t\titerator lowest = i1;\n\n\t\t\t\tfor(iterator current = i1.next(); current != end2; ++current)\n\t\t\t\t{\n\t\t\t\t\tif(compare(*current, *lowest))\n\t\t\t\t\t\tlowest = current;\n\t\t\t\t}\n\n\t\t\t\tif(lowest == i1)\n\t\t\t\t\t++i1;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlowest.mpNode->remove();\n\t\t\t\t\tlowest.mpNode->insert(i1.mpNode);\n\t\t\t\t}\n\n\t\t\t\tif(compare(*--end2, *i1)) // At this point, i1 refers to the second element in this three element segment.\n\t\t\t\t{\n\t\t\t\t\tend2.mpNode->remove();\n\t\t\t\t\tend2.mpNode->insert(i1.mpNode);\n\t\t\t\t}\n\n\t\t\t\treturn lowest;\n\t\t\t}\n\t\t }\n\n\t\t// Divide the range into two parts are recursively sort each part. Upon return we will have\n\t\t// two halves that are each sorted but we'll need to merge the two together before returning.\n\t\titerator  result;\n\t\tsize_type nMid = (n / 2);\n\t\titerator  end1 = eastl::next(i1, (difference_type)nMid);\n\t\t\t\t  i1   = DoSort(i1, end1, nMid, compare);        // Return the new beginning of the first sorted sub-range.\n\t\titerator  i2   = DoSort(end1, end2, n - nMid, compare);  // Return the new beginning of the second sorted sub-range.\n\n\t\t// If the start of the second list is before the start of the first list, insert the first list \n\t\t// into the second at an appropriate starting place. \n\t\tif(compare(*i2, *i1))\n\t\t{\n\t\t\t// Find the position to insert the first list into the second list. \n\t\t\titerator ix = i2.next();\n\t\t\twhile((ix != end2) && compare(*ix, *i1))\n\t\t\t\t++ix;\n\n\t\t\t// Cut out the initial segment of the second list and move it to be in front of the first list. \n\t\t\tListNodeBase* i2Cut     = i2.mpNode;\n\t\t\tListNodeBase* i2CutLast = ix.mpNode->mpPrev;\n\t\t\tresult = i2;\n\t\t\tend1   = i2 = ix;\n\t\t\tListNodeBase::remove_range(i2Cut, i2CutLast);\n\t\t\ti1.mpNode->insert_range(i2Cut, i2CutLast);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tresult = i1;\n\t\t\tend1   = i2;\n\t\t}\n\n\t\t// Merge the two segments. We do this by merging the second sub-segment into the first, by walking forward in each of the two sub-segments.\n\t\tfor(++i1; (i1 != end1) && (i2 != end2); ++i1) // while still working on either segment...\n\t\t{\n\t\t\tif(compare(*i2, *i1)) // If i2 is less than i1 and it needs to be merged in front of i1...\n\t\t\t{\n\t\t\t\t// Find the position to insert the i2 list into the i1 list. \n\t\t\t\titerator ix = i2.next();\n\t\t\t\twhile((ix != end2) && compare(*ix, *i1))\n\t\t\t\t\t++ix;\n\n\t\t\t\t// Cut this section of the i2 sub-segment out and merge into the appropriate place in the i1 list.\n\t\t\t\tListNodeBase* i2Cut     = i2.mpNode;\n\t\t\t\tListNodeBase* i2CutLast = ix.mpNode->mpPrev;\n\t\t\t\tif(end1 == i2)\n\t\t\t\t\tend1 = ix;\n\t\t\t\ti2 = ix;\n\t\t\t\tListNodeBase::remove_range(i2Cut, i2CutLast);\n\t\t\t\ti1.mpNode->insert_range(i2Cut, i2CutLast);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate<typename... Args>\n\tinline typename list<T, Allocator>::node_type*\n\tlist<T, Allocator>::DoCreateNode(Args&&... args)\n\t{\n\t\tnode_type* const pNode = DoAllocateNode();  // pNode is of type node_type, but it's uninitialized memory.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue, eastl::forward<Args>(args)...);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue, eastl::forward<Args>(args)...);\n\t\t#endif\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename list<T, Allocator>::node_type*\n\tlist<T, Allocator>::DoCreateNode()\n\t{\n\t\tnode_type* const pNode = DoAllocateNode();\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT)\n\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue);\n#else\n\t\t\t// deprecated: this is default initialization, but should be value initialization.\n\t\t\t::new((void*)&pNode->mValue) value_type;\n#endif\n\t\t#endif\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Integer>\n\tinline void list<T, Allocator>::DoAssign(Integer n, Integer value, true_type)\n\t{\n\t\tDoAssignValues(static_cast<size_type>(n), static_cast<value_type>(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tvoid list<T, Allocator>::DoAssign(InputIterator first, InputIterator last, false_type)\n\t{\n\t\tnode_type* pNode = static_cast<node_type*>(internalNode().mpNext);\n\n\t\tfor(; (pNode != &internalNode()) && (first != last); ++first)\n\t\t{\n\t\t\tpNode->mValue = *first;\n\t\t\tpNode         = static_cast<node_type*>(pNode->mpNext);\n\t\t}\n\n\t\tif(first == last)\n\t\t\terase(const_iterator(pNode), &internalNode());\n\t\telse\n\t\t\tDoInsert(&internalNode(), first, last, false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid list<T, Allocator>::DoAssignValues(size_type n, const value_type& value)\n\t{\n\t\tnode_type* pNode  = static_cast<node_type*>(internalNode().mpNext);\n\n\t\tfor(; (pNode != &internalNode()) && (n > 0); --n)\n\t\t{\n\t\t\tpNode->mValue = value;\n\t\t\tpNode         = static_cast<node_type*>(pNode->mpNext);\n\t\t}\n\n\t\tif(n)\n\t\t\tDoInsertValues(&internalNode(), n, value);\n\t\telse\n\t\t\terase(const_iterator(pNode), &internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Integer>\n\tinline void list<T, Allocator>::DoInsert(ListNodeBase* pNode, Integer n, Integer value, true_type)\n\t{\n\t\tDoInsertValues(pNode, static_cast<size_type>(n), static_cast<value_type>(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline void list<T, Allocator>::DoInsert(ListNodeBase* pNode, InputIterator first, InputIterator last, false_type)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t\tDoInsertValue(pNode, *first);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::DoInsertValues(ListNodeBase* pNode, size_type n, const value_type& value)\n\t{\n\t\tfor(; n > 0; --n)\n\t\t\tDoInsertValue(pNode, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate<typename... Args>\n\tinline void list<T, Allocator>::DoInsertValue(ListNodeBase* pNode, Args&&... args)\n\t{\n\t\tnode_type* const pNodeNew = DoCreateNode(eastl::forward<Args>(args)...);\n\t\tpNodeNew->insert(pNode);\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::DoErase(ListNodeBase* pNode)\n\t{\n\t\tpNode->remove();\n\t\t((node_type*)pNode)->~node_type();\n\t\tDoFreeNode(((node_type*)pNode));\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t--mSize;\n\t\t#endif\n\n\t\t/* Test version that uses union intermediates\n\t\tunion\n\t\t{\n\t\t\tListNodeBase* mpBase;\n\t\t\tnode_type*    mpNode;\n\t\t} node = { pNode };\n\n\t\tnode.mpNode->~node_type();\n\t\tnode.mpBase->remove();\n\t\tDoFreeNode(node.mpNode);\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t--mSize;\n\t\t#endif\n\t\t*/\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void list<T, Allocator>::DoSwap(this_type& x)\n\t{\n\t\tListNodeBase::swap((ListNodeBase&)internalNode(), (ListNodeBase&)x.internalNode()); // We need to implement a special swap because we can't do a shallow swap.\n\t\teastl::swap(internalAllocator(), x.internalAllocator()); // We do this even if EASTL_ALLOCATOR_COPY_ENABLED is 0.\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\teastl::swap(mSize, x.mSize);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool list<T, Allocator>::validate() const\n\t{\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\tsize_type n = 0;\n\n\t\t\tfor(const_iterator i(begin()), iEnd(end()); i != iEnd; ++i)\n\t\t\t\t++n;\n\n\t\t\tif(n != mSize)\n\t\t\t\treturn false;\n\t\t#endif\n\n\t\t// To do: More validation.\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int list<T, Allocator>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Come up with a more efficient mechanism of doing this.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tbool operator==(const list<T, Allocator>& a, const list<T, Allocator>& b)\n\t{\n\t\ttypename list<T, Allocator>::const_iterator ia   = a.begin();\n\t\ttypename list<T, Allocator>::const_iterator ib   = b.begin();\n\t\ttypename list<T, Allocator>::const_iterator enda = a.end();\n\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\tif(a.size() == b.size())\n\t\t\t{\n\t\t\t\twhile((ia != enda) && (*ia == *ib))\n\t\t\t\t{\n\t\t\t\t\t++ia;\n\t\t\t\t\t++ib;\n\t\t\t\t}\n\t\t\t\treturn (ia == enda);\n\t\t\t}\n\t\t\treturn false;\n\t\t#else\n\t\t\ttypename list<T, Allocator>::const_iterator endb = b.end();\n\n\t\t\twhile((ia != enda) && (ib != endb) && (*ia == *ib))\n\t\t\t{\n\t\t\t\t++ia;\n\t\t\t\t++ib;\n\t\t\t}\n\t\t\treturn (ia == enda) && (ib == endb);\n\t\t#endif\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Allocator>\n\tinline synth_three_way_result<T> operator<=>(const list<T, Allocator>& a, const list<T, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#else\n\ttemplate <typename T, typename Allocator>\n\tbool operator<(const list<T, Allocator>& a, const list<T, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbool operator!=(const list<T, Allocator>& a, const list<T, Allocator>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbool operator>(const list<T, Allocator>& a, const list<T, Allocator>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbool operator<=(const list<T, Allocator>& a, const list<T, Allocator>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbool operator>=(const list<T, Allocator>& a, const list<T, Allocator>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n#endif\n\ttemplate <typename T, typename Allocator>\n\tvoid swap(list<T, Allocator>& a, list<T, Allocator>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase / erase_if\n\t//\n\t// https://en.cppreference.com/w/cpp/container/list/erase2\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class T, class Allocator, class U>\n\ttypename list<T, Allocator>::size_type erase(list<T, Allocator>& c, const U& value)\n\t{\n\t\t// Erases all elements that compare equal to value from the container.\n\t\treturn c.remove(value);\n\t}\n\n\ttemplate <class T, class Allocator, class Predicate>\n\ttypename list<T, Allocator>::size_type erase_if(list<T, Allocator>& c, Predicate predicate)\n\t{\n\t\t// Erases all elements that satisfy the predicate pred from the container.\n\t\treturn c.remove_if(predicate);\n\t}\n\n\n} // namespace eastl\n\n\nEA_RESTORE_SN_WARNING()\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/map.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_MAP_H\n#define EASTL_MAP_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/red_black_tree.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_MAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_MAP_DEFAULT_NAME\n\t\t#define EASTL_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" map\" // Unless the user overrides something, this is \"EASTL map\".\n\t#endif\n\n\n\t/// EASTL_MULTIMAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_MULTIMAP_DEFAULT_NAME\n\t\t#define EASTL_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" multimap\" // Unless the user overrides something, this is \"EASTL multimap\".\n\t#endif\n\n\n\t/// EASTL_MAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_MAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_MAP_DEFAULT_ALLOCATOR allocator_type(EASTL_MAP_DEFAULT_NAME)\n\t#endif\n\n\t/// EASTL_MULTIMAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_MULTIMAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_MULTIMAP_DEFAULT_ALLOCATOR allocator_type(EASTL_MULTIMAP_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// map\n\t///\n\t/// Implements a canonical map. \n\t///\n\t/// The large majority of the implementation of this class is found in the rbtree\n\t/// base class. We control the behaviour of rbtree via template parameters.\n\t///\n\t/// Pool allocation\n\t/// If you want to make a custom memory pool for a map container, your pool \n\t/// needs to contain items of type map::node_type. So if you have a memory\n\t/// pool that has a constructor that takes the size of pool items and the\n\t/// count of pool items, you would do this (assuming that MemoryPool implements\n\t/// the Allocator interface):\n\t///     typedef map<Widget, int, less<Widget>, MemoryPool> WidgetMap;  // Delare your WidgetMap type.\n\t///     MemoryPool myPool(sizeof(WidgetMap::node_type), 100);          // Make a pool of 100 Widget nodes.\n\t///     WidgetMap myMap(&myPool);                                      // Create a map that uses the pool.\n\t///\n\ttemplate <typename Key, typename T, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>\n\tclass map\n\t\t: public rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator, eastl::use_first<eastl::pair<const Key, T> >, true, true>\n\t{\n\tpublic:\n\t\ttypedef rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator,\n\t\t\t\t\t\teastl::use_first<eastl::pair<const Key, T> >, true, true>   base_type;\n\t\ttypedef map<Key, T, Compare, Allocator>                                     this_type;\n\t\ttypedef typename base_type::size_type                                       size_type;\n\t\ttypedef typename base_type::key_type                                        key_type;\n\t\ttypedef T                                                                   mapped_type;\n\t\ttypedef typename base_type::value_type                                      value_type;\n\t\ttypedef typename base_type::node_type                                       node_type;\n\t\ttypedef typename base_type::iterator                                        iterator;\n\t\ttypedef typename base_type::const_iterator                                  const_iterator;\n\t\ttypedef typename base_type::allocator_type                                  allocator_type;\n\t\ttypedef typename base_type::insert_return_type                              insert_return_type;\n\t\ttypedef typename base_type::extract_key                                     extract_key;\n\t\t// Other types are inherited from the base class.\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::find;\n\t\tusing base_type::lower_bound;\n\t\tusing base_type::upper_bound;\n\t\tusing base_type::insert;\n\t\tusing base_type::erase;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"map<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"map<T> value_type must be non-volatile.\");\n\n\tprotected:\n\t\tusing base_type::compare;\n\t\tusing base_type::get_compare;\n\n\tpublic:\n\t\tclass value_compare \n\t\t{\n\t\tprotected:\n\t\t\tfriend class map;\n\t\t\tCompare compare;\n\t\t\tvalue_compare(Compare c) : compare(c) {}\n\n\t\tpublic:\n\t\t\tbool operator()(const value_type& x, const value_type& y) const \n\t\t\t\t{ return compare(x.first, y.first); }\n\t\t};\n\n\tpublic:\n\t\tmap(const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);\n\t\tmap(const Compare& compare, const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);\n\t\tmap(const this_type& x);\n\t\tmap(this_type&& x);\n\t\tmap(this_type&& x, const allocator_type& allocator);\n\t\tmap(std::initializer_list<value_type> ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);\n\t\tmap(std::initializer_list<value_type> ilist, const allocator_type& allocator);\n\n\t\ttemplate <typename Iterator>\n\t\tmap(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To consider: Make a second version of this function without a default arg.\n\n\t\t// missing constructors, to implement:\n\t\t// \n\t\t// map(const this_type& x, const allocator_type& allocator);\n\t\t// \n\t\t// template <typename InputIterator>\n\t\t// map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());\n\t\t//\n\t\t// template <typename InputIterator>\n\t\t// map(InputIterator first, InputIterator last, const Allocator& alloc);\n\n\t\tthis_type& operator=(const this_type& x) { return (this_type&)base_type::operator=(x); }\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist) { return (this_type&)base_type::operator=(ilist); }\n\t\tthis_type& operator=(this_type&& x) { return (this_type&)base_type::operator=(eastl::move(x)); }\n\n\tpublic:\n\t\t/// This is an extension to the C++ standard. We insert a default-constructed \n\t\t/// element with the given key. The reason for this is that we can avoid the \n\t\t/// potentially expensive operation of creating and/or copying a mapped_type\n\t\t/// object on the stack. Note that C++11 move insertions and variadic emplace\n\t\t/// support make this extension mostly no longer necessary.\n\t\tinsert_return_type insert(const Key& key);\n\n\t\t// Standard conversion overload to avoid the overhead of mismatched 'pair<const Key, Value>' types.\n\t\ttemplate <typename P, eastl::enable_if_t<eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tinsert_return_type insert(P&& otherValue) { return base_type::emplace(eastl::forward<P>(otherValue)); }\n\n\t\tvalue_compare value_comp() const;\n\n\t\tsize_type erase(const Key& key) { return DoErase(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, iterator> && !eastl::is_convertible_v<KX&&, const_iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type erase(KX&& key) { return DoErase(eastl::forward<KX>(key)); }\n\n\t\tsize_type count(const Key& key) const;\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& key) const { return (find(key) != end()) ? 1 : 0; }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const Key& key) { return DoEqualRange(key); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return DoEqualRange(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& key) { return DoEqualRange(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& key) const { return DoEqualRange(key); }\n\n\t\tT& operator[](const Key& key); // Of map, multimap, set, and multimap, only map has operator[].\n\t\tT& operator[](Key&& key);\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tT& operator[](KX&& key) { return try_emplace(eastl::forward<KX>(key)).first->second; }\n\n\t\tT& at(const Key& key) { return DoAt(key); }\n\t\tconst T& at(const Key& key) const { return DoAt(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tT& at(const KX& key) { return DoAt(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst T& at(const KX& key) const { return DoAt(key); }\n\n\t\ttemplate <class... Args> eastl::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);\n\t\ttemplate <class... Args> eastl::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);\n\t\ttemplate <class KX, class... Args, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, const_iterator> && !eastl::is_convertible_v<KX&&, iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, bool> try_emplace(KX&& k, Args&&... args) { return try_emplace_forward(eastl::forward<KX>(k), eastl::forward<Args>(args)...); }\n\t\ttemplate <class... Args> iterator                    try_emplace(const_iterator position, const key_type& k, Args&&... args);\n\t\ttemplate <class... Args> iterator                    try_emplace(const_iterator position, key_type&& k, Args&&... args);\n\t\ttemplate <class KX, class... Args, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator                    try_emplace(const_iterator hint, KX&& k, Args&&... args) { return try_emplace_forward(hint, eastl::forward<KX>(k), eastl::forward<Args>(args)...); }\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tsize_type DoErase(KX&& key);\n\n\t\ttemplate <class KFwd, class... Args>\n\t\teastl::pair<iterator, bool> try_emplace_forward(KFwd&& k, Args&&... args);\n\n\t\ttemplate <class KFwd, class... Args>\n\t\titerator try_emplace_forward(const_iterator hint, KFwd&& key, Args&&... args);\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\tT& DoAt(const KX& key);\n\t\ttemplate<typename KX>\n\t\tconst T& DoAt(const KX& key) const;\n\t}; // map\n\n\n\n\n\n\n\t/// multimap\n\t///\n\t/// Implements a canonical multimap.\n\t///\n\t/// The large majority of the implementation of this class is found in the rbtree\n\t/// base class. We control the behaviour of rbtree via template parameters.\n\t///\n\t/// Pool allocation\n\t/// If you want to make a custom memory pool for a multimap container, your pool \n\t/// needs to contain items of type multimap::node_type. So if you have a memory\n\t/// pool that has a constructor that takes the size of pool items and the\n\t/// count of pool items, you would do this (assuming that MemoryPool implements\n\t/// the Allocator interface):\n\t///     typedef multimap<Widget, int, less<Widget>, MemoryPool> WidgetMap;  // Delare your WidgetMap type.\n\t///     MemoryPool myPool(sizeof(WidgetMap::node_type), 100);               // Make a pool of 100 Widget nodes.\n\t///     WidgetMap myMap(&myPool);                                           // Create a map that uses the pool.\n\t///\n\ttemplate <typename Key, typename T, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>\n\tclass multimap\n\t\t: public rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator, eastl::use_first<eastl::pair<const Key, T> >, true, false>\n\t{\n\tpublic:\n\t\ttypedef rbtree<Key, eastl::pair<const Key, T>, Compare, Allocator, \n\t\t\t\t\t\teastl::use_first<eastl::pair<const Key, T> >, true, false>  base_type;\n\t\ttypedef multimap<Key, T, Compare, Allocator>                                this_type;\n\t\ttypedef typename base_type::size_type                                       size_type;\n\t\ttypedef typename base_type::key_type                                        key_type;\n\t\ttypedef T                                                                   mapped_type;\n\t\ttypedef typename base_type::value_type                                      value_type;\n\t\ttypedef typename base_type::node_type                                       node_type;\n\t\ttypedef typename base_type::iterator                                        iterator;\n\t\ttypedef typename base_type::const_iterator                                  const_iterator;\n\t\ttypedef typename base_type::allocator_type                                  allocator_type;\n\t\ttypedef typename base_type::insert_return_type                              insert_return_type;\n\t\ttypedef typename base_type::extract_key                                     extract_key;\n\t\t// Other types are inherited from the base class.\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::find;\n\t\tusing base_type::lower_bound;\n\t\tusing base_type::upper_bound;\n\t\tusing base_type::insert;\n\t\tusing base_type::erase;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"multimap<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"multimap<T> value_type must be non-volatile.\");\n\n\tprotected:\n\t\tusing base_type::compare;\n\t\tusing base_type::get_compare;\n\n\tpublic:\n\t\tclass value_compare \n\t\t{\n\t\tprotected:\n\t\t\tfriend class multimap;\n\t\t\tCompare compare;\n\t\t\tvalue_compare(Compare c) : compare(c) {}\n\n\t\tpublic:\n\t\t\tbool operator()(const value_type& x, const value_type& y) const \n\t\t\t\t{ return compare(x.first, y.first); }\n\t\t};\n\n\tpublic:\n\t\tmultimap(const allocator_type& allocator = EASTL_MULTIMAP_DEFAULT_ALLOCATOR);\n\t\tmultimap(const Compare& compare, const allocator_type& allocator = EASTL_MULTIMAP_DEFAULT_ALLOCATOR);\n\t\tmultimap(const this_type& x);\n\t\tmultimap(this_type&& x);\n\t\tmultimap(this_type&& x, const allocator_type& allocator);\n\t\tmultimap(std::initializer_list<value_type> ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_MULTIMAP_DEFAULT_ALLOCATOR);\n\t\tmultimap(std::initializer_list<value_type> ilist, const allocator_type& allocator);\n\n\t\ttemplate <typename Iterator>\n\t\tmultimap(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To consider: Make a second version of this function without a default arg.\n\n\t\t// missing constructors, to implement:\n\t\t// \n\t\t// multimap(const this_type& x, const allocator_type& allocator);\n\t\t// \n\t\t// template <typename InputIterator>\n\t\t// multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());\n\t\t//\n\t\t// template <typename InputIterator>\n\t\t// multimap(InputIterator first, InputIterator last, const Allocator& alloc);\n\n\t\tthis_type& operator=(const this_type& x) { return (this_type&)base_type::operator=(x); }\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist) { return (this_type&)base_type::operator=(ilist); }\n\t\tthis_type& operator=(this_type&& x) { return (this_type&)base_type::operator=(eastl::move(x)); }\n\n\tpublic:\n\t\t/// This is an extension to the C++ standard. We insert a default-constructed \n\t\t/// element with the given key. The reason for this is that we can avoid the \n\t\t/// potentially expensive operation of creating and/or copying a mapped_type\n\t\t/// object on the stack. Note that C++11 move insertions and variadic emplace\n\t\t/// support make this extension mostly no longer necessary.\n\t\tinsert_return_type insert(const Key& key);\n\n\t\t// Standard conversion overload to avoid the overhead of mismatched 'pair<const Key, Value>' types.\n\t\ttemplate <typename P, eastl::enable_if_t<eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tinsert_return_type insert(P&& otherValue) { return base_type::emplace(eastl::forward<P>(otherValue)); }\n\n\t\tvalue_compare value_comp() const;\n\n\t\tsize_type erase(const Key& key) { return DoErase(key); }\n\t\t\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, iterator> && !eastl::is_convertible_v<KX&&, const_iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type erase(KX&& key) { return DoErase(eastl::forward<KX>(key)); }\n\n\t\tsize_type count(const Key& key) const { return DoCount(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& key) const { return DoCount(key); }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const Key& key) { return DoEqualRange(key); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return DoEqualRange(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& key) { return DoEqualRange(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& key) const { return DoEqualRange(key); }\n\n\t\t/// equal_range_small\n\t\t/// This is a special version of equal_range which is optimized for the \n\t\t/// case of there being few or no duplicated keys in the tree.\n\t\teastl::pair<iterator, iterator>             equal_range_small(const Key& key) { return DoEqualRangeSmall(key); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const Key& key) const { return DoEqualRangeSmall(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range_small(const KX& key) { return DoEqualRangeSmall(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const KX& key) const { return DoEqualRangeSmall(key); }\n\n\tprivate:\n\t\t// these base member functions are not included in multimaps\n\t\tusing base_type::insert_or_assign;\n\n\t\ttemplate<typename KX>\n\t\tsize_type DoErase(KX&& key);\n\n\t\ttemplate<typename KX>\n\t\tsize_type DoCount(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRangeSmall(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRangeSmall(const KX& key) const;\n\t}; // multimap\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// map\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline map<Key, T, Compare, Allocator>::map(const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline map<Key, T, Compare, Allocator>::map(const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline map<Key, T, Compare, Allocator>::map(const this_type& x)\n\t\t: base_type(x)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline map<Key, T, Compare, Allocator>::map(this_type&& x)\n\t\t: base_type(eastl::move(x))\n\t{\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline map<Key, T, Compare, Allocator>::map(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(eastl::move(x), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline map<Key, T, Compare, Allocator>::map(std::initializer_list<value_type> ilist, const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline map<Key, T, Compare, Allocator>::map(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), Compare(), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename Iterator>\n\tinline map<Key, T, Compare, Allocator>::map(Iterator itBegin, Iterator itEnd)\n\t\t: base_type(itBegin, itEnd, Compare(), EASTL_MAP_DEFAULT_ALLOCATOR)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename map<Key, T, Compare, Allocator>::insert_return_type\n\tmap<Key, T, Compare, Allocator>::insert(const Key& key)\n\t{\n\t\treturn base_type::DoInsertKey(true_type(), key);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename map<Key, T, Compare, Allocator>::value_compare \n\tmap<Key, T, Compare, Allocator>::value_comp() const\n\t{\n\t\treturn value_compare(get_compare());\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline typename map<Key, T, Compare, Allocator>::size_type\n\tmap<Key, T, Compare, Allocator>::DoErase(KX&& key)\n\t{\n\t\tconst iterator it(find(key));\n\n\t\tif(it != end()) // If it exists...\n\t\t{\n\t\t\tbase_type::erase(it);\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename map<Key, T, Compare, Allocator>::size_type\n\tmap<Key, T, Compare, Allocator>::count(const Key& key) const\n\t{\n\t\tconst const_iterator it(find(key));\n\t\treturn (it != end()) ? 1 : 0;\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename map<Key, T, Compare, Allocator>::iterator,\n\t\t\t\t\t   typename map<Key, T, Compare, Allocator>::iterator>\n\tmap<Key, T, Compare, Allocator>::DoEqualRange(const KX& key)\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst iterator itLower(lower_bound(key));\n\n\t\tif((itLower == end()) || compare(key, itLower->first)) // If at the end or if (key is < itLower)...\n\t\t\treturn eastl::pair<iterator, iterator>(itLower, itLower);\n\n\t\titerator itUpper(itLower);\n\t\treturn eastl::pair<iterator, iterator>(itLower, ++itUpper);\n\t}\n\t\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename map<Key, T, Compare, Allocator>::const_iterator, \n\t\t\t\t\t   typename map<Key, T, Compare, Allocator>::const_iterator>\n\tmap<Key, T, Compare, Allocator>::DoEqualRange(const KX& key) const\n\t{\n\t\t// See DoEqualRange above for comments.\n\t\tconst const_iterator itLower(lower_bound(key));\n\n\t\tif((itLower == end()) || compare(key, itLower->first)) // If at the end or if (key is < itLower)...\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itLower);\n\n\t\tconst_iterator itUpper(itLower);\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline T& map<Key, T, Compare, Allocator>::operator[](const Key& key)\n\t{\n\t\titerator itLower(lower_bound(key)); // itLower->first is >= key.\n\n\t\tif((itLower == end()) || compare(key, (*itLower).first))\n\t\t{\n\t\t\titLower = base_type::DoInsertKey(true_type(), itLower, key);\n\t\t}\n\n\t\treturn (*itLower).second;\n\n\t\t// Reference implementation of this function, which may not be as fast:\n\t\t//iterator it(base_type::insert(eastl::pair<iterator, iterator>(key, T())).first);\n\t\t//return it->second;\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline T& map<Key, T, Compare, Allocator>::operator[](Key&& key)\n\t{\n\t\titerator itLower(lower_bound(key)); // itLower->first is >= key.\n\n\t\tif((itLower == end()) || compare(key, (*itLower).first))\n\t\t{\n\t\t\titLower = base_type::DoInsertKey(true_type(), itLower, eastl::move(key));\n\t\t}\n\n\t\treturn (*itLower).second;\n\n\t\t// Reference implementation of this function, which may not be as fast:\n\t\t//iterator it(base_type::insert(eastl::pair<iterator, iterator>(key, T())).first);\n\t\t//return it->second;\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline synth_three_way_result<eastl::pair<const Key, T>> operator<=>(const map<Key, T, Compare, Allocator>& a, \n\t\t\tconst map<Key, T, Compare, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#endif\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline T& map<Key, T, Compare, Allocator>::DoAt(const KX& key)\n\t{\n\t\t// use the use const version of ::DoAt to remove duplication\n\t\treturn const_cast<T&>(const_cast<map<Key, T, Compare, Allocator> const*>(this)->DoAt(key));\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline const T& map<Key, T, Compare, Allocator>::DoAt(const KX& key) const\n\t{\n\t\tconst_iterator candidate = this->find(key);\n\n\t\tif (candidate == end())\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow std::out_of_range(\"map::at key does not exist\");\n\t\t\t#else\n\t\t\t\tEASTL_FAIL_MSG(\"map::at key does not exist\");\n\t\t\t#endif\n\t\t}\n\n\t\treturn candidate->second;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_if\n\t//\n\t// https://en.cppreference.com/w/cpp/container/map/erase_if\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class Key, class T, class Compare, class Allocator, class Predicate>\n\ttypename map<Key, T, Compare, Allocator>::size_type erase_if(map<Key, T, Compare, Allocator>& c, Predicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n\n\ttemplate <class Key, class T, class Compare, class Allocator>\n\ttemplate <class... Args>\n\tinline eastl::pair<typename map<Key, T, Compare, Allocator>::iterator, bool>\n\tmap<Key, T, Compare, Allocator>::try_emplace(const key_type& key, Args&&... args)\n\t{\n\t\treturn try_emplace_forward(key, eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <class Key, class T, class Compare, class Allocator>\n\ttemplate <class... Args>\n\tinline eastl::pair<typename map<Key, T, Compare, Allocator>::iterator, bool>\n\tmap<Key, T, Compare, Allocator>::try_emplace(key_type&& key, Args&&... args)\n\t{\n\t\treturn try_emplace_forward(eastl::move(key), eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <class Key, class T, class Compare, class Allocator>\n\ttemplate <class KFwd, class... Args>\n\tinline eastl::pair<typename map<Key, T, Compare, Allocator>::iterator, bool>\n\tmap<Key, T, Compare, Allocator>::try_emplace_forward(KFwd&& key, Args&&... args)\n\t{\n\t\tbool canInsert;\n\t\trbtree_node_base* const pPosition = base_type::DoGetKeyInsertionPositionUniqueKeys(canInsert, key);\n\t\tif (!canInsert)\n\t\t{\n\t\t\treturn pair<iterator, bool>(iterator(pPosition), false);\n\t\t}\n\t\tnode_type* const pNodeNew =\n\t\t    base_type::DoCreateNode(piecewise_construct, eastl::forward_as_tuple(eastl::forward<KFwd>(key)),\n\t\t                            eastl::forward_as_tuple(eastl::forward<Args>(args)...));\n\t\t// the key might be moved above, so we can't re-use it,\n\t\t// we need to get it back from the node's value.\n\t\tconst auto& k = extract_key{}(pNodeNew->mValue);\n\t\tconst iterator itResult(base_type::DoInsertValueImpl(pPosition, false, k, pNodeNew));\n\t\treturn pair<iterator, bool>(itResult, true);\n\t}\n\n\ttemplate <class Key, class T, class Compare, class Allocator>\n\ttemplate <class... Args>\n\tinline typename map<Key, T, Compare, Allocator>::iterator\n\tmap<Key, T, Compare, Allocator>::try_emplace(const_iterator hint, const key_type& key, Args&&... args)\n\t{\n\t\treturn try_emplace_forward(hint, key, eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <class Key, class T, class Compare, class Allocator>\n\ttemplate <class... Args>\n\tinline typename map<Key, T, Compare, Allocator>::iterator\n\tmap<Key, T, Compare, Allocator>::try_emplace(const_iterator hint, key_type&& key, Args&&... args)\n\t{\n\t\treturn try_emplace_forward(hint, eastl::move(key), eastl::forward<Args>(args)...);\n\t}\n\n\ttemplate <class Key, class T, class Compare, class Allocator>\n\ttemplate <class KFwd, class... Args>\n\tinline typename map<Key, T, Compare, Allocator>::iterator\n\tmap<Key, T, Compare, Allocator>::try_emplace_forward(const_iterator hint, KFwd&& key, Args&&... args)\n\t{\n\t\tbool bForceToLeft;\n\t\trbtree_node_base* const pPosition = base_type::DoGetKeyInsertionPositionUniqueKeysHint(hint, bForceToLeft, key);\n\n\t\tif (!pPosition)\n\t\t{\n\t\t\t// the hint didn't help, we need to do a normal insert.\n\t\t\treturn try_emplace_forward(eastl::forward<KFwd>(key), eastl::forward<Args>(args)...).first;\n\t\t}\n\n\t\tnode_type* const pNodeNew =\n\t\t    base_type::DoCreateNode(piecewise_construct, eastl::forward_as_tuple(eastl::forward<KFwd>(key)),\n\t\t                            eastl::forward_as_tuple(eastl::forward<Args>(args)...));\n\t\t// the key might be moved above, so we can't re-use it,\n\t\t// we need to get it back from the node's value.\n\t\treturn base_type::DoInsertValueImpl(pPosition, bForceToLeft, extract_key{}(pNodeNew->mValue), pNodeNew);\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// multimap\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(const this_type& x)\n\t\t: base_type(x)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(this_type&& x)\n\t\t: base_type(eastl::move(x))\n\t{\n\t}\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(eastl::move(x), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(std::initializer_list<value_type> ilist, const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), Compare(), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename Iterator>\n\tinline multimap<Key, T, Compare, Allocator>::multimap(Iterator itBegin, Iterator itEnd)\n\t\t: base_type(itBegin, itEnd, Compare(), EASTL_MULTIMAP_DEFAULT_ALLOCATOR)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename multimap<Key, T, Compare, Allocator>::insert_return_type\n\tmultimap<Key, T, Compare, Allocator>::insert(const Key& key)\n\t{\n\t\treturn base_type::DoInsertKey(false_type(), key);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline typename multimap<Key, T, Compare, Allocator>::value_compare \n\tmultimap<Key, T, Compare, Allocator>::value_comp() const\n\t{\n\t\treturn value_compare(get_compare());\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline typename multimap<Key, T, Compare, Allocator>::size_type\n\tmultimap<Key, T, Compare, Allocator>::DoErase(KX&& key)\n\t{\n\t\tconst eastl::pair<iterator, iterator> range(equal_range(key));\n\t\tconst size_type n = (size_type)eastl::distance(range.first, range.second);\n\t\tbase_type::erase(range.first, range.second);\n\t\treturn n;\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline typename multimap<Key, T, Compare, Allocator>::size_type\n\tmultimap<Key, T, Compare, Allocator>::DoCount(const KX& key) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> range(equal_range(key));\n\t\treturn (size_type)eastl::distance(range.first, range.second);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multimap<Key, T, Compare, Allocator>::iterator,\n\t\t\t\t\t   typename multimap<Key, T, Compare, Allocator>::iterator>\n\tmultimap<Key, T, Compare, Allocator>::DoEqualRange(const KX& key)\n\t{\n\t\t// There are multiple ways to implement equal_range. The implementation mentioned\n\t\t// in the C++ standard and which is used by most (all?) commercial STL implementations\n\t\t// is this:\n\t\t//    return eastl::pair<iterator, iterator>(lower_bound(key), upper_bound(key));\n\t\t//\n\t\t// This does two tree searches -- one for the lower bound and one for the \n\t\t// upper bound. This works well for the case whereby you have a large container\n\t\t// and there are lots of duplicated values. We provide an alternative version\n\t\t// of equal_range called equal_range_small for cases where the user is confident\n\t\t// that the number of duplicated items is only a few.\n\n\t\treturn eastl::pair<iterator, iterator>(lower_bound(key), upper_bound(key));\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multimap<Key, T, Compare, Allocator>::const_iterator,\n\t\t\t\t\t   typename multimap<Key, T, Compare, Allocator>::const_iterator>\n\tmultimap<Key, T, Compare, Allocator>::DoEqualRange(const KX& key) const\n\t{\n\t\t// See comments above in the non-const version of equal_range.\n\t\treturn eastl::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multimap<Key, T, Compare, Allocator>::iterator,\n\t\t\t\t\t   typename multimap<Key, T, Compare, Allocator>::iterator>\n\tmultimap<Key, T, Compare, Allocator>::DoEqualRangeSmall(const KX& key)\n\t{\n\t\t// We provide alternative version of equal_range here which works faster\n\t\t// for the case where there are at most small number of potential duplicated keys.\n\t\tconst iterator itLower(lower_bound(key));\n\t\titerator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !compare(key, itUpper->first))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<iterator, iterator>(itLower, itUpper);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multimap<Key, T, Compare, Allocator>::const_iterator,\n\t\t\t\t\t   typename multimap<Key, T, Compare, Allocator>::const_iterator>\n\tmultimap<Key, T, Compare, Allocator>::DoEqualRangeSmall(const KX& key) const\n\t{\n\t\t// We provide alternative version of equal_range here which works faster\n\t\t// for the case where there are at most small number of potential duplicated keys.\n\t\tconst const_iterator itLower(lower_bound(key));\n\t\tconst_iterator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !compare(key, itUpper->first))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itUpper);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_if\n\t//\n\t// https://en.cppreference.com/w/cpp/container/multimap/erase_if\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class Key, class T, class Compare, class Allocator, class Predicate>\n\ttypename multimap<Key, T, Compare, Allocator>::size_type erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\t// Erases all elements that satisfy the predicate pred from the container.\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator>\n\tinline synth_three_way_result<eastl::pair<const Key, T>> operator<=>(const multimap<Key, T, Compare, Allocator>& a, \n\t\t\tconst multimap<Key, T, Compare, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#endif\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/memory.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the following functions from the C++ standard that\n// are found in the <memory> header:\n//\n// Utility:\n//    late_constructed                  - Extention to standard functionality.\n//\n// Uninitialized operations:\n//    These are the same as the copy, fill, and fill_n algorithms, except that\n//    they *construct* the destination with the source values rather than assign\n//    the destination with the source values.\n//\n//    uninitialized_copy\n//    uninitialized_copy_n\n//    uninitialized_default_construct\n//    uninitialized_default_construct_n\n//    uninitialized_move\n//    uninitialized_move_if_noexcept    - Extention to standard functionality.\n//    uninitialized_move_n\n//    uninitialized_fill\n//    uninitialized_fill_n\n//    uninitialized_value_construct\n//    uninitialized_value_construct_n\n//    uninitialized_copy_fill           - Extention to standard functionality.\n//    uninitialized_fill_copy           - Extention to standard functionality.\n//    uninitialized_copy_copy           - Extention to standard functionality.\n//\n// In-place destructor helpers:\n//    destruct(T*)                      - Non-standard extension. Equivalent to destroy_at(T*)\n//    destruct(first, last)             - Non-standard extension. Equivalent to destroy(first, last)\n//    destroy_at(T*)\n//    destroy(first, last)\n//    destroy_n(first, n)\n//\n// Alignment\n//    align\n//    align_advance                     - Extention to standard functionality.\n//\n// Allocator-related\n//    uses_allocator\n//    allocator_arg_t\n//    allocator_arg\n//\n// Pointers\n//    pointer_traits\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_MEMORY_H\n#define EASTL_MEMORY_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/memory_base.h>\n#include <EASTL/internal/memory_uses_allocator.h>\n#include <EASTL/internal/pair_fwd_decls.h>\n#include <EASTL/internal/functional_base.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/utility.h>\n#include <EASTL/numeric_limits.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdlib.h>\n#include <new>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4146 - unary minus operator applied to unsigned type, result still unsigned\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\nEA_DISABLE_VC_WARNING(4530 4146 4571);\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\nnamespace eastl\n{\n\n\t/// EASTL_TEMP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_TEMP_DEFAULT_NAME\n\t\t#define EASTL_TEMP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" temp\" // Unless the user overrides something, this is \"EASTL temp\".\n\t#endif\n\n\n\t/// late_constructed\n\t///\n\t/// Implements a smart pointer type which separates the memory allocation of an object from\n\t/// the object's construction. The primary use case is to declare a global variable of the\n\t/// late_construction type, which allows the memory to be global but the constructor executes\n\t/// at some point after main() begins as opposed to before main, which is often dangerous\n\t/// for non-trivial types.\n\t///\n\t/// The autoConstruct template parameter controls whether the object is automatically default\n\t/// constructed upon first reference or must be manually constructed upon the first use of\n\t/// operator * or ->. autoConstruct is convenient but it causes * and -> to be slightly slower\n\t/// and may result in construction at an inconvenient time.\n\t///\n\t/// The autoDestruct template parameter controls whether the object, if constructed, is automatically\n\t/// destructed when ~late_constructed() is called or must be manually destructed via a call to\n\t/// destruct().\n\t///\n\t/// While construction can be automatic or manual, automatic destruction support is always present.\n\t/// Thus you aren't required in any case to manually call destruct. However, you may safely manually\n\t/// destruct the object at any time before the late_constructed destructor is executed.\n\t///\n\t/// You may still use late_constructed after calling destruct(), including calling construct()\n\t/// again to reconstruct the instance. destruct returns the late_constructed instance to a\n\t/// state equivalent to before construct was called.\n\t///\n\t/// Caveat: While late_constructed instances can be declared in global scope and initialize\n\t/// prior to main() executing, you cannot otherwise use such globally declared instances prior\n\t/// to main with guaranteed behavior unless you can ensure that the late_constructed instance\n\t/// is itself constructed prior to your use of it.\n\t///\n\t/// Example usage (demonstrating manual-construction):\n\t///     late_constructed<Widget, false> gWidget;\n\t///\n\t///     void main(){\n\t///         gWidget.construct(kScrollbarType, kVertical, \"MyScrollbar\");\n\t///         gWidget->SetValue(15);\n\t///         gWidget.destruct();\n\t///     }\n\t///\n\t/// Example usage (demonstrating auto-construction):\n\t///     late_constructed<Widget, true> gWidget;\n\t///\n\t///     void main(){\n\t///         gWidget->SetValue(15);\n\t///         // You may want to call destruct here, but aren't required to do so unless the Widget type requires it.\n\t///     }\n\t///\n\ttemplate <typename T, bool autoConstruct = true, bool autoDestruct = true>\n\tclass late_constructed\n\t{\n\tpublic:\n\t\tusing this_type    = late_constructed<T, autoConstruct, autoDestruct>;\n\t\tusing value_type   = T;\n\t\tusing storage_type = eastl::aligned_storage_t<sizeof(value_type), eastl::alignment_of_v<value_type>>;\n\n\t\tconstexpr late_constructed() noexcept  // In the case of the late_constructed instance being at global scope, we rely on the\n\t\t  : mStorage(), mpValue(nullptr) {}    // compiler executing this constructor or placing the instance in auto-zeroed-at-startup memory.\n\n\t\t~late_constructed()\n\t\t{\n\t\t\tif (autoDestruct && mpValue)\n\t\t\t\t(*mpValue).~value_type();\n\t\t}\n\n\t\ttemplate <typename... Args>\n\t\tvoid construct(Args&&... args)\n\t\t{\n\t\t\tif(!mpValue)\n\t\t\t\tmpValue = new (&mStorage) value_type(eastl::forward<Args>(args)...);\n\t\t}\n\n\t\tbool is_constructed() const noexcept\n\t\t\t{ return mpValue != nullptr; }\n\n\t\tvoid destruct()\n\t\t{\n\t\t\tif(mpValue)\n\t\t\t{\n\t\t\t\t(*mpValue).~value_type();\n\t\t\t\tmpValue = nullptr;\n\t\t\t}\n\t\t}\n\n\t\tvalue_type& operator*() noexcept\n\t\t{\n\t\t\tif(!mpValue)\n\t\t\t\tconstruct();\n\n\t\t\tEA_ANALYSIS_ASSUME(mpValue);\n\t\t\treturn *mpValue;\n\t\t}\n\n\t\tconst value_type& operator*() const noexcept\n\t\t{\n\t\t\tif(!mpValue)\n\t\t\t\tconstruct();\n\n\t\t\tEA_ANALYSIS_ASSUME(mpValue);\n\t\t\treturn *mpValue;\n\t\t}\n\n\t\tvalue_type* operator->() noexcept\n\t\t{\n\t\t\tif(!mpValue)\n\t\t\t\tconstruct();\n\t\t\treturn mpValue;\n\t\t}\n\n\t\tconst value_type* operator->() const noexcept\n\t\t{\n\t\t\tif(!mpValue)\n\t\t\t\tconstruct();\n\t\t\treturn mpValue;\n\t\t}\n\n\t\tvalue_type* get() noexcept\n\t\t{\n\t\t\tif(!mpValue)\n\t\t\t\tconstruct();\n\t\t\treturn mpValue;\n\t\t}\n\n\t\tconst value_type* get() const noexcept\n\t\t{\n\t\t\tif(!mpValue)\n\t\t\t\tconstruct();\n\t\t\treturn mpValue;\n\t\t}\n\n\tprotected:\n\t\tstorage_type mStorage; // Declared first because it may have aligment requirements, and it would be more space-efficient if it was first.\n\t\tvalue_type*  mpValue;\n\t};\n\n\n\t// Specialization that doesn't auto-construct on demand.\n\ttemplate <typename T, bool autoDestruct>\n\tclass late_constructed<T, false, autoDestruct> : public late_constructed<T, true, autoDestruct>\n\t{\n\tpublic:\n\t\ttypedef late_constructed<T, true, autoDestruct> base_type;\n\n\t\ttypename base_type::value_type& operator*() noexcept\n\t\t\t{ EASTL_ASSERT(base_type::mpValue); return *base_type::mpValue; }\n\n\t\tconst typename base_type::value_type& operator*() const noexcept\n\t\t\t{ EASTL_ASSERT(base_type::mpValue); return *base_type::mpValue; }\n\n\t\ttypename base_type::value_type* operator->() noexcept\n\t\t\t{ EASTL_ASSERT(base_type::mpValue); return base_type::mpValue; }\n\n\t\tconst typename base_type::value_type* operator->() const noexcept\n\t\t\t{ EASTL_ASSERT(base_type::mpValue); return base_type::mpValue; }\n\n\t\ttypename base_type::value_type* get() noexcept\n\t\t\t{ return base_type::mpValue; }\n\n\t\tconst typename base_type::value_type* get() const noexcept\n\t\t\t{ return base_type::mpValue; }\n\t};\n\n\n\t// uninitialized_copy\n\t//\n\tnamespace Internal\n\t{\n\t\ttemplate<bool isTriviallyCopyable, bool isInputIteratorReferenceAddressable, bool areIteratorsContiguous>\n\t\tstruct uninitialized_copy_impl\n\t\t{\n\t\t\ttemplate <typename InputIterator, typename ForwardIterator>\n\t\t\tstatic ForwardIterator impl(InputIterator first, InputIterator last, ForwardIterator dest)\n\t\t\t{\n\t\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\t\tForwardIterator currentDest(dest);\n\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n#endif\n\t\t\t\t\tfor (; first != last; ++first, ++currentDest)\n\t\t\t\t\t\t::new(static_cast<void*>(eastl::addressof(*currentDest))) value_type(*first);\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch (...)\n\t\t\t\t{\n\t\t\t\t\tfor (; dest < currentDest; ++dest)\n\t\t\t\t\t\t(*dest).~value_type();\n\t\t\t\t\tthrow;\n\t\t\t\t}\n#endif\n\n\t\t\t\treturn currentDest;\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct uninitialized_copy_impl<true, true, false>\n\t\t{\n\t\t\ttemplate <typename InputIterator, typename ForwardIterator>\n\t\t\tstatic ForwardIterator impl(InputIterator first, InputIterator last, ForwardIterator dest)\n\t\t\t{\n\t\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\n\t\t\t\tfor (; first != last; ++first, ++dest)\n\t\t\t\t\tmemmove(eastl::addressof(*dest), eastl::addressof(*first), sizeof(value_type));\n\n\t\t\t\treturn dest;\n\t\t\t}\n\t\t};\n\n\t\ttemplate<>\n\t\tstruct uninitialized_copy_impl<true, true, true>\n\t\t{\n\t\t\ttemplate <typename InputIterator, typename ForwardIterator>\n\t\t\tstatic ForwardIterator impl(InputIterator first, InputIterator last, ForwardIterator dest)\n\t\t\t{\n\t\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\n\t\t\t\tif (EASTL_UNLIKELY(first == last))\n\t\t\t\t\treturn dest;\n\n\t\t\t\tauto count = (last - first);\n\t\t\t\tmemmove(eastl::addressof(*dest), eastl::addressof(*first), sizeof(value_type) * count);\n\t\t\t\treturn dest + count;\n\t\t\t}\n\t\t};\n\t}\n\n\t/// uninitialized_copy\n\t///\n\t/// Copies a source range to a destination, copy-constructing the destination with\n\t/// the source values (and not *assigning* the destination with the source values).\n\t/// Returns the end of the destination range (i.e. dest + (last - first)).\n\t///\n\t/// Declaration:\n\t///    template <typename InputIterator, typename ForwardIterator>\n\t///    ForwardIterator uninitialized_copy(InputIterator sourceFirst, InputIterator sourceLast, ForwardIterator destination);\n\t///\n\t/// Example usage:\n\t///    SomeClass* pArray = malloc(10 * sizeof(SomeClass));\n\t///    uninitialized_copy(pSourceDataBegin, pSourceDataBegin + 10, pArray);\n\t///\n\ttemplate <typename InputIterator, typename ForwardIterator>\n\tinline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category  IIC;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::iterator_category OIC;\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::value_type         value_type_input;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type        value_type_output;\n\n\t\t// isTriviallyCopyable identifies if (non-overlapping) objects may be safely copied by means of memcpy/memmove.\n\t\tconst bool isTriviallyCopyable = eastl::is_same<value_type_input, value_type_output>::value && eastl::is_trivially_copyable<value_type_output>::value;\n\t\t// ie. is eastl::addressof(*first) valid? ie. invalid for iterators that return value_type&&.\n\t\tconst bool isInputIteratorReferenceAddressable = eastl::is_convertible<typename eastl::add_lvalue_reference<value_type_input>::type, typename eastl::iterator_traits<InputIterator>::reference>::value;\n\t\t// can memcpy/memmove a contiguous block, not just the individual elements?\n\t\tconst bool areIteratorsContiguous = (eastl::is_pointer<InputIterator>::value || internal::is_contiguous_iterator<IIC>::value) &&\n\t\t\t\t\t\t\t\t\t\t\t(eastl::is_pointer<ForwardIterator>::value || internal::is_contiguous_iterator<OIC>::value);\n\n\t\treturn Internal::uninitialized_copy_impl<isTriviallyCopyable, isInputIteratorReferenceAddressable, areIteratorsContiguous>::impl(first, last, result);\n\t}\n\n\n\t/// uninitialized_copy_n\n\t///\n\t/// Copies count elements from a range beginning at first to an uninitialized memory area\n\t/// beginning at dest. The elements in the uninitialized area are constructed using copy constructor.\n\t/// If an exception is thrown during the initialization, the function has no final effects.\n\t///\n\t/// first:        Beginning of the range of the elements to copy.\n\t/// dest:         Beginning of the destination range.\n\t/// return value: Iterator of dest type to the element past the last element copied.\n\t///\n\tnamespace Internal\n\t{\n\t\ttemplate <typename InputIterator, typename Count, typename ForwardIterator, typename IteratorTag>\n\t\tstruct uninitialized_copy_n_impl\n\t\t{\n\t\t\tstatic ForwardIterator impl(InputIterator first, Count n, ForwardIterator dest)\n\t\t\t{\n\t\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\t\tForwardIterator currentDest(dest);\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t#endif\n\t\t\t\t\t\tfor(; n > 0; --n, ++first, ++currentDest)\n\t\t\t\t\t\t\t::new((void*)(eastl::addressof(*currentDest))) value_type(*first);\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor(; dest < currentDest; ++dest)\n\t\t\t\t\t\t\t(*dest).~value_type();\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\treturn currentDest;\n\t\t\t}\n\t\t};\n\n\t\ttemplate <typename InputIterator, typename Count, typename ForwardIterator>\n\t\tstruct uninitialized_copy_n_impl<InputIterator, Count, ForwardIterator, eastl::random_access_iterator_tag>\n\t\t{\n\t\t\tstatic inline ForwardIterator impl(InputIterator first, Count n, ForwardIterator dest)\n\t\t\t{\n\t\t\t\treturn eastl::uninitialized_copy(first, first + n, dest);\n\t\t\t}\n\t\t};\n\t}\n\n\ttemplate<typename InputIterator, typename Count, typename ForwardIterator>\n\tinline ForwardIterator uninitialized_copy_n(InputIterator first, Count n, ForwardIterator dest)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\treturn Internal::uninitialized_copy_n_impl<InputIterator, Count, ForwardIterator, IC>::impl(first, n, dest);\n\t}\n\n\n\n\t/// uninitialized_copy_ptr\n\t///\n\t/// This is a specialization of uninitialized_copy for iterators that are pointers. We use it because\n\t/// internally it uses generic_iterator to make pointers act like regular eastl::iterator.\n\t///\n\ttemplate <typename First, typename Last, typename Result>\n\tEASTL_REMOVE_AT_2024_SEPT inline Result uninitialized_copy_ptr(First first, Last last, Result result)\n\t{\n\t\treturn eastl::uninitialized_copy(first, last, result);\n\t}\n\n\n\n\t/// uninitialized_move_ptr\n\t///\n\t/// This is a specialization of uninitialized_move for iterators that are pointers. We use it because\n\t/// internally it uses generic_iterator to make pointers act like regular eastl::iterator.\n\t///\n\ttemplate <typename First, typename Last, typename Result>\n\tEASTL_REMOVE_AT_2024_SEPT inline Result uninitialized_move_ptr(First first, Last last, Result dest)\n\t{\n\t\treturn uninitialized_move(first, last, dest);\n\t}\n\n\n\n\n\t/// uninitialized_move\n\t///\n\t/// Moves a source range to a destination, move-constructing the destination with\n\t/// the source values (and not *assigning* the destination with the source values).\n\t/// Returns the end of the destination range (i.e. dest + (last - first)).\n\t///\n\t/// Example usage:\n\t///    SomeClass* pArray = malloc(10 * sizeof(SomeClass));\n\t///    uninitialized_move(pSourceDataBegin, pSourceDataBegin + 10, pArray);\n\t///\n\ttemplate <typename InputIterator, typename ForwardIterator>\n\tinline ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator dest)\n\t{\n\t\treturn eastl::uninitialized_copy(eastl::make_move_iterator(first), eastl::make_move_iterator(last), dest);\n\t}\n\n\n\t/// uninitialized_move_if_noexcept\n\t///\n\t/// If the iterated type can be moved without exceptions, move construct the dest with the input. Else copy-construct\n\t/// the dest witih the input. If move isn't supported by the compiler, do regular copy.\n\t///\n\ttemplate <typename InputIterator, typename ForwardIterator>\n\tinline ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest)\n\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\treturn eastl::uninitialized_copy(eastl::make_move_if_noexcept_iterator(first), eastl::make_move_if_noexcept_iterator(last), dest);\n#else\n\t\treturn eastl::uninitialized_move(first, last, dest);\n#endif\n\t}\n\n\n\t/// uninitialized_move_ptr_if_noexcept\n\t///\n\ttemplate <typename First, typename Last, typename Result>\n\tEASTL_REMOVE_AT_2024_SEPT inline Result uninitialized_move_ptr_if_noexcept(First first, Last last, Result dest)\n\t{\n\t\treturn eastl::uninitialized_move_if_noexcept(first, last, dest);\n\t}\n\n\n\t/// uninitialized_move_n\n\t///\n\t/// Moves count elements from a range beginning at first to an uninitialized memory area\n\t/// beginning at dest. The elements in the uninitialized area are constructed using copy constructor.\n\t/// If an exception is thrown during the initialization, the function has no final effects.\n\t///\n\t/// first:        Beginning of the range of the elements to move.\n\t/// dest:         Beginning of the destination range.\n\t/// return value: Iterator of dest type to the element past the last element moved.\n\t///\n\ttemplate<typename InputIterator, typename Count, typename ForwardIterator>\n\tinline ForwardIterator uninitialized_move_n(InputIterator first, Count n, ForwardIterator dest)\n\t{\n\t\treturn eastl::uninitialized_copy_n(eastl::make_move_iterator(first), n, dest);\n\t}\n\n\t/// uninitialized_default_construct\n\t///\n\t/// Constructs objects in the uninitialized storage designated by the range [first, last) by default-initialization.\n\t///\n\t/// Default-initialization:\n\t///  If T is a class, the default constructor is called; otherwise, no initialization is done, resulting in\n\t///  indeterminate values.\n\t///\n\t/// http://en.cppreference.com/w/cpp/memory/uninitialized_default_construct\n\t///\n\ttemplate <typename ForwardIterator>\n\tinline void uninitialized_default_construct(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\tForwardIterator currentDest(first);\n\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\ttry\n\t\t{\n\t#endif\n\t\t\tfor (; currentDest != last; ++currentDest)\n\t\t\t\t::new (eastl::addressof(*currentDest)) value_type;\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\tfor (; first < currentDest; ++first)\n\t\t\t\t(*first).~value_type();\n\t\t\tthrow;\n\t\t}\n\t#endif\n\t}\n\n\t/// uninitialized_default_construct_n\n\t///\n\t/// Constructs n objects in the uninitialized storage starting at first by default-initialization.\n\t///\n\t/// http://en.cppreference.com/w/cpp/memory/uninitialized_default_construct_n\n\t///\n\ttemplate <typename ForwardIterator, typename Count>\n\tinline ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Count n)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\tForwardIterator currentDest(first);\n\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\ttry\n\t\t{\n\t#endif\n\t\t\tfor (; n > 0; --n, ++currentDest)\n\t\t\t\t::new (eastl::addressof(*currentDest)) value_type;\n\t\t\treturn currentDest;\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\tfor (; first < currentDest; ++first)\n\t\t\t\t(*first).~value_type();\n\t\t\tthrow;\n\t\t}\n\t#endif\n\t}\n\n\t/// uninitialized_fill\n\t///\n\t/// Copy-constructs the elements in the destination range with the given input value.\n\t/// Returns void. It wouldn't be useful to return the end of the destination range,\n\t/// as that is the same as the 'last' input parameter.\n\t///\n\t/// Declaration:\n\t///    template <typename ForwardIterator, typename T>\n\t///    void uninitialized_fill(ForwardIterator destinationFirst, ForwardIterator destinationLast, const T& value);\n\t///\n\tnamespace Internal\n\t{\n\t\ttemplate <typename ForwardIterator, typename T>\n\t\tinline void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, true_type)\n\t\t{\n\t\t\teastl::fill(first, last, value);\n\t\t}\n\n\t\ttemplate <typename ForwardIterator, typename T>\n\t\tvoid uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, false_type)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\tForwardIterator currentDest(first);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\tfor(; currentDest != last; ++currentDest)\n\t\t\t\t\t\t::new((void*)eastl::addressof(*currentDest)) value_type(value);\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tfor(; first < currentDest; ++first)\n\t\t\t\t\t\t(*first).~value_type();\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\t}\n\n\ttemplate <typename ForwardIterator, typename T>\n\tinline void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\tInternal::uninitialized_fill_impl(first, last, value, eastl::is_trivially_copy_assignable<value_type>());\n\t}\n\n\t/// uninitialized_value_construct\n\t///\n\t/// Constructs objects in the uninitialized storage range [first, last) by value-initialization.\n\t///\n\t/// Value-Initialization:\n\t/// If T is a class, the object is default-initialized (after being zero-initialized if T's default\n\t/// constructor is not user-provided/deleted); otherwise, the object is zero-initialized.\n\t///\n\t/// http://en.cppreference.com/w/cpp/memory/uninitialized_value_construct\n\t///\n\ttemplate <class ForwardIterator>\n\tvoid uninitialized_value_construct(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\tForwardIterator currentDest(first);\n\n    #if EASTL_EXCEPTIONS_ENABLED\n\t\ttry\n\t\t{\n\t#endif\n\t\t\tfor (; currentDest != last; ++currentDest)\n\t\t\t\t::new (eastl::addressof(*currentDest)) value_type();\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\tfor (; first < currentDest; ++first)\n\t\t\t\t(*first).~value_type();\n\t\t\tthrow;\n\t\t}\n\t#endif\n\t}\n\n\t/// uninitialized_value_construct_n\n\t///\n\t/// Constructs n objects in the uninitialized storage starting at first by value-initialization.\n\t///\n\t/// Value-Initialization:\n\t/// If T is a class, the object is default-initialized (after being zero-initialized if T's default\n\t/// constructor is not user-provided/deleted); otherwise, the object is zero-initialized.\n\t///\n\t/// http://en.cppreference.com/w/cpp/memory/uninitialized_value_construct_n\n\t///\n\ttemplate <class ForwardIterator, class Count>\n\tForwardIterator uninitialized_value_construct_n(ForwardIterator first, Count n)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\tForwardIterator currentDest(first);\n\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\ttry\n\t\t{\n\t#endif\n\t\t\tfor (; n > 0; --n, ++currentDest)\n\t\t\t\t::new (eastl::addressof(*currentDest)) value_type();\n\t\t\treturn currentDest;\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\tfor (; first < currentDest; ++first)\n\t\t\t\t(*first).~value_type();\n\t\t\tthrow;\n\t\t}\n\t#endif\n\t}\n\n\t/// uninitialized_fill_ptr\n\t///\n\t/// This is a specialization of uninitialized_fill for iterators that are pointers.\n\t/// It exists so that we can declare a value_type for the iterator, which you\n\t/// can't do with a pointer by itself.\n\t///\n\ttemplate <typename T>\n\tEASTL_REMOVE_AT_2024_SEPT inline void uninitialized_fill_ptr(T* first, T* last, const T& value)\n\t{\n\t\tuninitialized_fill(first, last, value);\n\t}\n\n\t/// uninitialized_fill_n\n\t///\n\t/// Copy-constructs the range of [first, first + n) with the given input value.\n\t/// Returns void as per the C++ standard, though returning the end input iterator\n\t/// value may be of use.\n\t///\n\t/// Declaration:\n\t///    template <typename ForwardIterator, typename Count, typename T>\n\t///    void uninitialized_fill_n(ForwardIterator destination, Count n, const T& value);\n\t///\n\tnamespace Internal\n\t{\n\t\ttemplate <typename ForwardIterator, typename Count, typename T>\n\t\tinline void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, true_type /* is_trivially_copy_assignable */)\n\t\t{\n\t\t\t// todo: implementation uses operator = but should instead be using the copy constructor, as documented.\n\t\t\teastl::fill_n(first, n, value);\n\t\t}\n\n\t\ttemplate <typename ForwardIterator, typename Count, typename T>\n\t\tvoid uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, false_type /* is_trivially_copy_assignable */)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\tForwardIterator currentDest(first);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t#endif\n\t\t\t\t\tfor(; n > 0; --n, ++currentDest)\n\t\t\t\t\t\t::new((void*)eastl::addressof(*currentDest)) value_type(value);\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tfor(; first < currentDest; ++first)\n\t\t\t\t\t\t(*first).~value_type();\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\t}\n\n\ttemplate <typename ForwardIterator, typename Count, typename T>\n\tinline void uninitialized_fill_n(ForwardIterator first, Count n, const T& value)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\tInternal::uninitialized_fill_n_impl(first, n, value, eastl::is_trivially_copy_assignable<value_type>());\n\t}\n\n\n\n\t/// uninitialized_fill_n_ptr\n\t///\n\t/// This is a specialization of uninitialized_fill_n for iterators that are pointers.\n\t/// It exists so that we can declare a value_type for the iterator, which you\n\t/// can't do with a pointer by itself.\n\t///\n\ttemplate <typename T, typename Count>\n\tEASTL_REMOVE_AT_2024_SEPT inline void uninitialized_fill_n_ptr(T* first, Count n, const T& value)\n\t{\n\t\tuninitialized_fill_n(first, n, value);\n\t}\n\n\n\n\n\t/// uninitialized_copy_fill\n\t///\n\t/// Copies [first1, last1) into [first2, first2 + (last1 - first1)) then\n\t/// fills [first2 + (last1 - first1), last2) with value.\n\t///\n\ttemplate <typename InputIterator, typename ForwardIterator, typename T>\n\tinline void uninitialized_copy_fill(InputIterator first1, InputIterator last1,\n\t\t\t\t\t\t\t\t\t\tForwardIterator first2, ForwardIterator last2, const T& value)\n\t{\n\t\tconst ForwardIterator mid(eastl::uninitialized_copy(first1, last1, first2));\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\teastl::uninitialized_fill(mid, last2, value);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tfor(; first2 < mid; ++first2)\n\t\t\t\t\t(*first2).~value_type();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\t/// uninitialized_move_fill\n\t///\n\t/// Moves [first1, last1) into [first2, first2 + (last1 - first1)) then\n\t/// fills [first2 + (last1 - first1), last2) with value.\n\t///\n\ttemplate <typename InputIterator, typename ForwardIterator, typename T>\n\tinline void uninitialized_move_fill(InputIterator first1, InputIterator last1,\n\t\t\t\t\t\t\t\t\t\tForwardIterator first2, ForwardIterator last2, const T& value)\n\t{\n\t\tconst ForwardIterator mid(eastl::uninitialized_move(first1, last1, first2));\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\teastl::uninitialized_fill(mid, last2, value);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tfor(; first2 < mid; ++first2)\n\t\t\t\t\t(*first2).~value_type();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\n\n\n\t/// uninitialized_fill_copy\n\t///\n\t/// Fills [result, mid) with value then copies [first, last) into [mid, mid + (last - first)).\n\t///\n\ttemplate <typename ForwardIterator, typename T, typename InputIterator>\n\tinline ForwardIterator\n\tuninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)\n\t{\n\t\teastl::uninitialized_fill(result, mid, value);\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\treturn eastl::uninitialized_copy(first, last, mid);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tfor(; result < mid; ++result)\n\t\t\t\t\t(*result).~value_type();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\t/// uninitialized_fill_move\n\t///\n\t/// Fills [result, mid) with value then copies [first, last) into [mid, mid + (last - first)).\n\t///\n\ttemplate <typename ForwardIterator, typename T, typename InputIterator>\n\tinline ForwardIterator\n\tuninitialized_fill_move(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)\n\t{\n\t\teastl::uninitialized_fill(result, mid, value);\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\treturn eastl::uninitialized_move(first, last, mid);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tfor(; result < mid; ++result)\n\t\t\t\t\t(*result).~value_type();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\n\t/// uninitialized_copy_copy\n\t///\n\t/// Copies [first1, last1) into [result, result + (last1 - first1)) then\n\t/// copies [first2, last2) into [result, result + (last1 - first1) + (last2 - first2)).\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename ForwardIterator>\n\tinline ForwardIterator\n\tuninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,\n\t\t\t\t\t\t\tInputIterator2 first2, InputIterator2 last2,\n\t\t\t\t\t\t\tForwardIterator result)\n\t{\n\t\tconst ForwardIterator mid(eastl::uninitialized_copy(first1, last1, result));\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\t\ttry\n\t\t\t{\n\t\t#endif\n\t\t\t\treturn eastl::uninitialized_copy(first2, last2, mid);\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tfor(; result < mid; ++result)\n\t\t\t\t\t(*result).~value_type();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#endif\n\t}\n\n\n\n\t/// destruct\n\t///\n\t/// Calls the destructor of a given object.\n\t///\n\t/// Note that we don't have a specialized version of this for objects\n\t/// with trivial destructors, such as integers. This is because the\n\t/// compiler can already see in our version here that the destructor\n\t/// is a no-op.\n\t///\n\ttemplate <typename T>\n\tinline void destruct(T* p)\n\t{\n\t\t// https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(C4100)&rd=true\n\t\t// \"C4100 can also be issued when code calls a destructor on a otherwise unreferenced parameter\n\t\t//  of primitive type. This is a limitation of the Visual C++ compiler.\"\n\t\tEA_UNUSED(p);\n\t\tp->~T();\n\t}\n\n\n\n\t// destruct(first, last)\n\t//\n\ttemplate <typename ForwardIterator>\n\tinline void destruct_impl(ForwardIterator /*first*/, ForwardIterator /*last*/, true_type) // true means the type has a trivial destructor.\n\t{\n\t\t// Empty. The type has a trivial destructor.\n\t}\n\n\ttemplate <typename ForwardIterator>\n\tinline void destruct_impl(ForwardIterator first, ForwardIterator last, false_type) // false means the type has a significant destructor.\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\n\t\tfor(; first != last; ++first)\n\t\t\t(*first).~value_type();\n\t}\n\n\t/// destruct\n\t///\n\t/// Calls the destructor on a range of objects.\n\t///\n\t/// We have a specialization for objects with trivial destructors, such as\n\t/// PODs. In this specialization the destruction of the range is a no-op.\n\t///\n\ttemplate <typename ForwardIterator>\n\tinline void destruct(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;\n\t\tdestruct_impl(first, last, eastl::is_trivially_destructible<value_type>());\n\t}\n\n\n\t/// destroy_at\n\t///\n\t/// Calls the destructor of a given object.\n\t///\n\t/// Note that we don't have a specialized version of this for objects\n\t/// with trivial destructors, such as integers. This is because the\n\t/// compiler can already see in our version here that the destructor\n\t/// is a no-op.\n\t///\n\t/// This is the same as eastl::destruct but we included for C++17 compliance.\n\t///\n\t/// http://en.cppreference.com/w/cpp/memory/destroy_at\n\t///\n\ttemplate <typename T>\n\tinline void destroy_at(T* p)\n\t{\n\t\tEA_UNUSED(p);\n\t\tp->~T();\n\t}\n\n\n\t/// destroy\n\t///\n\t/// Calls the destructor on a range of objects.\n\t///\n\t/// http://en.cppreference.com/w/cpp/memory/destroy\n\t///\n\ttemplate <typename ForwardIterator>\n\tinline void destroy(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tfor (; first != last; ++first)\n\t\t\teastl::destroy_at(eastl::addressof(*first));\n\t}\n\n\n\t/// destroy_n\n\t///\n\t/// Calls the destructor on the n objects in the range.\n\t///\n\t/// http://en.cppreference.com/w/cpp/memory/destroy_n\n\t///\n\ttemplate <typename ForwardIterator, typename Size>\n\tForwardIterator destroy_n(ForwardIterator first, Size n)\n\t{\n\t\tfor (; n > 0; ++first, --n)\n\t\t\teastl::destroy_at(eastl::addressof(*first));\n\n\t\treturn first;\n\t}\n\n\n\t/// align\n\t///\n\t/// Same as C++11 std::align. http://en.cppreference.com/w/cpp/memory/align\n\t/// If it is possible to fit size bytes of storage aligned by alignment into the buffer pointed to by\n\t/// ptr with length space, the function updates ptr to point to the first possible address of such storage,\n\t/// decreases space by the number of bytes used for alignment, and returns the new ptr value. Otherwise,\n\t/// the function returns NULL and leaves ptr and space unmodified.\n\t///\n\t/// Example usage:\n\t///     char   buffer[512];\n\t///     size_t space = sizeof(buffer);\n\t///     void*  p  = buffer;\n\t///     void*  p1 = eastl::align(16,  3, p, space); p = (char*)p +  3; space -=  3;\n\t///     void*  p2 = eastl::align(32, 78, p, space); p = (char*)p + 78; space -= 78;\n\t///     void*  p3 = eastl::align(64,  9, p, space); p = (char*)p +  9; space -=  9;\n\n\tinline void* align(size_t alignment, size_t size, void*& ptr, size_t& space)\n\t{\n\t\tif(space >= size)\n\t\t{\n\t\t\tchar*  ptrAligned = (char*)(((size_t)ptr + (alignment - 1)) & -alignment);\n\t\t\tsize_t offset     = (size_t)(ptrAligned - (char*)ptr);\n\n\t\t\tif((space - size) >= offset) // Have to implement this in terms of subtraction instead of addition in order to handle possible overflow.\n\t\t\t{\n\t\t\t\tptr    = ptrAligned;\n\t\t\t\tspace -= offset;\n\n\t\t\t\treturn ptrAligned;\n\t\t\t}\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\n\t/// align_advance\n\t///\n\t/// Same as align except ptr and space can be adjusted to reflect remaining space.\n\t/// Not present in the C++ Standard.\n\t/// Note that the example code here is similar to align but simpler.\n\t///\n\t/// Example usage:\n\t///     char   buffer[512];\n\t///     size_t space = sizeof(buffer);\n\t///     void*  p  = buffer;\n\t///     void*  p1 = eastl::align_advance(16,  3, p, space, &p, &space); // p is advanced and space reduced accordingly.\n\t///     void*  p2 = eastl::align_advance(32, 78, p, space, &p, &space);\n\t///     void*  p3 = eastl::align_advance(64,  9, p, space, &p, &space);\n\t///     void*  p4 = eastl::align_advance(16, 33, p, space);\n\n\tinline void* align_advance(size_t alignment, size_t size, void* ptr, size_t space, void** ptrAdvanced = NULL, size_t* spaceReduced = NULL)\n\t{\n\t\tif(space >= size)\n\t\t{\n\t\t\tchar*  ptrAligned = (char*)(((size_t)ptr + (alignment - 1)) & -alignment);\n\t\t\tsize_t offset     = (size_t)(ptrAligned - (char*)ptr);\n\n\t\t\tif((space - size) >= offset) // Have to implement this in terms of subtraction instead of addition in order to handle possible overflow.\n\t\t\t{\n\t\t\t\tif(ptrAdvanced)\n\t\t\t\t\t*ptrAdvanced = (ptrAligned + size);\n\t\t\t\tif(spaceReduced)\n\t\t\t\t\t*spaceReduced = (space - (offset + size));\n\n\t\t\t\treturn ptrAligned;\n\t\t\t}\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// pointer_traits\n\t//\n\t// C++11 Standard section 20.6.3\n\t// Provides information about a pointer type, mostly for the purpose\n\t// of handling the case where the pointer type isn't a built-in T* but\n\t// rather is a class that acts like a pointer.\n\t//\n\t// A user-defined Pointer has the following properties, by example:\n\t//     template <class T, class... MoreArgs>\n\t//     struct Pointer\n\t//     {\n\t//         typedef Pointer pointer;                         // required for use by pointer_traits.\n\t//         typedef T1      element_type;                    // optional for use by pointer_traits.\n\t//         typedef T2      difference_type;                 // optional for use by pointer_traits.\n\t//\n\t//         template <class Other>\n\t//         using rebind = typename Ptr<Other, MoreArgs...>; // optional for use by pointer_traits.\n\t//\n\t//         static pointer pointer_to(element_type& obj);    // required for use by pointer_traits.\n\t//     };\n\t//\n\t//\n\t// Example usage:\n\t//     template <typename Pointer>\n\t//     typename pointer_traits::element_type& GetElementPointedTo(Pointer p)\n\t//      { return *p; }\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\tnamespace Internal\n\t{\n\t\t// pointer_element_type\n\t\ttemplate <typename Pointer>\n\t\tstruct has_element_type // has_element_type<T>::value is true if T has an element_type member typedef.\n\t\t{\n\t\tprivate:\n\t\t\ttemplate <typename U> static eastl::no_type  test(...);\n\t\t\ttemplate <typename U> static eastl::yes_type test(typename U::element_type* = 0);\n\t\tpublic:\n\t\t\tstatic const bool value = sizeof(test<Pointer>(0)) == sizeof(eastl::yes_type);\n\t\t};\n\n\t\ttemplate <typename Pointer, bool = has_element_type<Pointer>::value>\n\t\tstruct pointer_element_type\n\t\t{\n\t\t\tusing type = Pointer;\n\t\t};\n\n\t\ttemplate <typename Pointer>\n\t\tstruct pointer_element_type<Pointer, true>\n\t\t\t{ typedef typename Pointer::element_type type; };\n\n\t\ttemplate <template <typename, typename...> class Pointer, typename T, typename... Args>\n\t\tstruct pointer_element_type<Pointer<T, Args...>, false>\n\t\t\t{ typedef T type; };\n\n\n\t\t// pointer_difference_type\n\t\ttemplate <typename Pointer>\n\t\tstruct has_difference_type // has_difference_type<T>::value is true if T has an difference_type member typedef.\n\t\t{\n\t\tprivate:\n\t\t\ttemplate <typename U> static eastl::no_type  test(...);\n\t\t\ttemplate <typename U> static eastl::yes_type test(typename U::difference_type* = 0);\n\t\tpublic:\n\t\t\tstatic const bool value = sizeof((test<Pointer>(0))) == sizeof(eastl::yes_type);\n\t\t};\n\n\t\ttemplate <typename Pointer, bool = has_difference_type<Pointer>::value>\n\t\tstruct pointer_difference_type\n\t\t\t{ typedef typename Pointer::difference_type type; };\n\n\t\ttemplate <typename Pointer>\n\t\tstruct pointer_difference_type<Pointer, false>\n\t\t\t{ typedef ptrdiff_t type; };\n\n\n\t\t// pointer_rebind\n\t\t// The following isn't correct, as it is unilaterally requiring that Pointer typedef its\n\t\t// own rebind. We can fix this if needed to make it optional (in which case it would return\n\t\t// its own type), but we don't currently use rebind in EASTL (as we have a different allocator\n\t\t// system than the C++ Standard Library has) and this is currently moot.\n\t\ttemplate <typename Pointer, typename U>\n\t\tstruct pointer_rebind\n\t\t{\n\t\t\ttypedef typename Pointer::template rebind<U> type;\n\t\t};\n\n\n\t} // namespace Internal\n\n\n\ttemplate <typename Pointer>\n\tstruct pointer_traits\n\t{\n\t\ttypedef Pointer                                                   pointer;\n\t\ttypedef typename Internal::pointer_element_type<pointer>::type    element_type;\n\t\ttypedef typename Internal::pointer_difference_type<pointer>::type difference_type;\n\n\t\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t\ttemplate <typename U>\n\t\t\tstruct rebind { typedef typename Internal::pointer_rebind<pointer, U>::type other; };\n\t\t#else\n\t\t\ttemplate <typename U>\n\t\t\tusing rebind = typename Internal::pointer_rebind<pointer, U>::type;\n\t\t#endif\n\n\tpublic:\n\t\tstatic pointer pointer_to(typename eastl::conditional<eastl::is_void<element_type>::value, void, element_type>::type& r) // 20.6.3.2: if element_type is (possibly cv-qualified) void, the type of r is unspecified; otherwise, it is T&.\n\t\t\t{ return pointer::pointer_to(r); } // The C++11 Standard requires that Pointer provides a static pointer_to function.\n\t};\n\n\n\ttemplate <typename T>\n\tstruct pointer_traits<T*>\n\t{\n\t\ttypedef T*        pointer;\n\t\ttypedef T         element_type;\n\t\ttypedef ptrdiff_t difference_type;\n\n\t\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t\ttemplate <typename U>\n\t\t\tstruct rebind { typedef U* other; };\n\t\t#else\n\t\t\ttemplate <typename U>\n\t\t\tusing rebind = U*;\n\t\t#endif\n\n\tpublic:\n\t\tstatic pointer pointer_to(typename eastl::conditional<eastl::is_void<element_type>::value, void, element_type>::type& r) EA_NOEXCEPT\n\t\t\t{ return eastl::addressof(r); } // 20.6.3.2: if element_type is (possibly cv-qualified) void, the type of r is unspecified; otherwise, it is T&.\n\t};\n\n\t///////////////////////////////////////////////////////////////////////\n\t// to_address\n\t//\n\t// Helper that call the customization point in pointer_traits<T>::to_address for retrieving the address of a pointer.\n\t// This is useful if you are using fancy-pointers.\n\t///////////////////////////////////////////////////////////////////////\n\n\tnamespace Internal\n\t{\n\t\ttemplate <class T>\n\t\tusing detect_pointer_traits_to_address = decltype(eastl::pointer_traits<T>::to_address(eastl::declval<const T&>()));\n\n\t\ttemplate <class T>\n\t\tusing result_detect_pointer_traits_to_address = eastl::is_detected<detect_pointer_traits_to_address, T>;\n\t}\n\n\ttemplate<class T>\n\tEA_CPP14_CONSTEXPR T* to_address(T* p) noexcept\n\t{\n\t\tstatic_assert(!eastl::is_function<T>::value, \"Cannot call to_address with a function pointer. C++20 20.2.4.1 - Pointer conversion.\");\n\t\treturn p;\n\t}\n\n\ttemplate <class Ptr, typename eastl::enable_if<Internal::result_detect_pointer_traits_to_address<Ptr>::value, int>::type = 0>\n\tEA_CPP14_CONSTEXPR auto to_address(const Ptr& ptr) noexcept -> decltype(eastl::pointer_traits<Ptr>::to_address(ptr))\n\t{\n\t\treturn eastl::pointer_traits<Ptr>::to_address(ptr);\n\t}\n\n\ttemplate <class Ptr, typename eastl::enable_if<!Internal::result_detect_pointer_traits_to_address<Ptr>::value, int>::type = 0>\n\tEA_CPP14_CONSTEXPR auto to_address(const Ptr& ptr) noexcept -> decltype(to_address(ptr.operator->()))\n\t{\n\t\treturn to_address(ptr.operator->());\n\t}\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/meta.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_META_H\n#define EASTL_META_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/internal/integer_sequence.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n////////////////////////////////////////////////////////////////////////////////////////////\n// This file contains meta programming utilities that are internal to EASTL. We reserve\n// the right to change this file at any time as it is only intended to be used internally.\n////////////////////////////////////////////////////////////////////////////////////////////\n\nnamespace eastl\n{\n\tnamespace meta\n\t{\n\t\t////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// get_type_index_v\n\t\t//\n\t\t// Linearly searches a typelist using compile-time recursion to inspect each T in\n\t\t// the typelist and returns its index, if the type is found.  If the T isn't found\n\t\t// in the typelist -1 is returned.\n\t\t//\n\t\tnamespace Internal\n\t\t{\n\t\t\ttemplate <int I, typename T, typename... Types>\n\t\t\tstruct get_type_index;\n\n\t\t\ttemplate <int I, typename T, typename Head, typename... Types>\n\t\t\tstruct get_type_index<I, T, Head, Types...>\n\t\t\t{\n\t\t\t\tstatic EA_CONSTEXPR_OR_CONST int value = is_same_v<T, Head> ? I : get_type_index<I + 1, T, Types...>::value;\n\t\t\t};\n\n\t\t\ttemplate <int I, typename T>\n\t\t\tstruct get_type_index<I, T>\n\t\t\t{\n\t\t\t\tstatic EA_CONSTEXPR_OR_CONST int value = -1;\n\t\t\t};\n\t\t}\n\n\t\ttemplate<typename T, typename... Types>\n\t\tstruct get_type_index\n\t\t{\n\t\t\tstatic EA_CONSTEXPR_OR_CONST int value = Internal::get_type_index<0, T, Types...>::value;\n\t\t};\n\n\t\ttemplate <typename T, typename... Ts>\n\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR int get_type_index_v = get_type_index<T, Ts...>::value;\n\n\n\t\t////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// get_type_at\n\t\t//\n\t\t// This traverses the variadic type list and retrieves the type at the user provided index.\n\t\t//\n\t\ttemplate <size_t I, typename... Ts>\n\t\t\tstruct get_type_at_helper;\n\n\t\ttemplate <size_t I, typename Head, typename... Tail>\n\t\t\tstruct get_type_at_helper<I, Head, Tail...>\n\t\t\t{ typedef typename get_type_at_helper<I - 1, Tail...>::type type; };\n\n\t\ttemplate <typename Head, typename... Tail>\n\t\t\tstruct get_type_at_helper<0, Head, Tail...>\n\t\t\t{ typedef Head type; };\n\n\t\ttemplate <int I, typename... Ts>\n\t\tusing get_type_at_t = typename get_type_at_helper<I, Ts...>::type;\n\n\n\t\t////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// type_count_v\n\t\t//\n\t\t// Returns the number of occurrences of type T in a typelist.\n\t\t//\n\t\ttemplate <typename T, typename... Types>\n\t\tstruct type_count;\n\n\t\ttemplate <typename T, typename H, typename... Types>\n\t\tstruct type_count<T, H, Types...>\n\t\t{\n\t\t\tstatic EA_CONSTEXPR_OR_CONST int value = (is_same_v<T, H> ? 1 : 0) + type_count<T, Types...>::value;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct type_count<T>\n\t\t{\n\t\t\tstatic EA_CONSTEXPR_OR_CONST int value = 0;\n\t\t};\n\n\t\ttemplate <typename T, typename... Ts>\n\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR int type_count_v = type_count<T, Ts...>::value;\n\n\n\n\t\t////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// duplicate_type_check_v\n\t\t//\n\t\t// Checks if a type T occurs in a typelist more than once.\n\t\t//\n\t\ttemplate <typename T, typename... Types>\n\t\tstruct duplicate_type_check\n\t\t{\n\t\t\tstatic EA_CONSTEXPR_OR_CONST bool value = (type_count<T, Types...>::value == 1);\n\t\t};\n\n\t\ttemplate <typename... Ts>\n\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool duplicate_type_check_v = duplicate_type_check<Ts...>::value;\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////\n\t\t// type_list\n\t\t//\n\t\t// type_list is a simple struct that allows us to pass template parameter packs\n\t\t// around in a single struct, and deduce parameter packs from function arguments\n\t\t// like so:\n\t\t//\n\t\t//     template <typename... Ts> void foo(type_list<Ts...>);\n\t\t//     foo(type_list<A, B, C>); // deduces Ts... as A, B, C\n\t\t//\n\t\ttemplate <typename...> struct type_list {};\n\n\n\t\t//////////////////////////////////////////////////////////////////////////////////\n\t\t// unique_type_list\n\t\t//\n\t\t// unique_type_list is a meta-function which takes a parameter pack as its\n\t\t// argument, and returns a type_list with duplicate types removed, like so:\n\t\t//\n\t\t//    unique_type_list<int, int, string>::type;    // type = type_list<int, string>\n\t\t//    unique_type_list<int, string, string>::type; // type = type_list<int, string>\n\t\t//\n\t\t// To use unique_type_list, specialize a variadic class template for a single\n\t\t// type parameter, which is type_list<Ts...>:\n\t\t//\n\t\t//    template <typename... Ts> struct foo {};\n\t\t//    template <typename... Ts> struct foo<type_list<Ts...>> {};\n\t\t//\n\t\t// Then instantiate the template with unique_type_list_t<Ts...> as its parameter:\n\t\t//\n\t\t//    template <typename... Ts> struct bar : public foo<unique_type_list_t<Ts...>> {}\n\t\t//\n\t\t// See overload_set below for examples.\n\t\ttemplate <typename T, typename... Ts>\n\t\tstruct unique_type_list : public unique_type_list<Ts...>\n\t\t{\n\t\t\ttemplate <typename... Args>\n\t\t\tstatic enable_if_t<!disjunction_v<is_same<T, Args>...>, type_list<T, Args...>>\n\t\t\ttypes(type_list<Args...>);\n\n\t\t\ttemplate <typename... Args>\n\t\t\tstatic enable_if_t<disjunction_v<is_same<T, Args>...>, type_list<Args...>>\n\t\t\ttypes(type_list<Args...>);\n\n\t\t\ttypedef decltype(types(declval<typename unique_type_list<Ts...>::type>())) type;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct unique_type_list<T>\n\t\t{\n\t\t\tusing type = type_list<T>;\n\t\t};\n\n\t\ttemplate <typename... Ts>\n\t\tusing unique_type_list_t = typename unique_type_list<Ts...>::type;\n\n\n\t\t////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// overload_resolution_t\n\t\t//\n\t\t// Given an input type and a typelist (which is a stand-in for alternative\n\t\t// function overloads) this traits will return the same type chosen as if\n\t\t// overload_resolution has selected a function to run.\n\t\t//\n\n\t\t// a single overload of an individual type\n\t\ttemplate <typename T>\n\t\tstruct overload\n\t\t{\n\t\t\t// Overload is implicitly convertible to the surrogated function\n\t\t\t// call for pointer to member functions (pmf). This gets around\n\t\t\t// variadic pack expansion in a class using statement being a C++17\n\t\t\t// language feature. It is the core mechanism of aggregating all the\n\t\t\t// individual overloads into the overload_set structure.\n\t\t\tusing F = T (*)(T);\n\t\t\toperator F() const { return nullptr; }\n\t\t};\n\n\t\ttemplate <typename...> struct overload_set_impl;\n\n\t\ttemplate <typename... Ts>\n\t\tstruct overload_set_impl<type_list<Ts...>> : public overload<Ts>... {};\n\n\t\ttemplate <typename... Ts>\n\t\tstruct overload_set : public overload_set_impl<unique_type_list_t<Ts...>>\n\t\t{\n\t\t\t// encapsulates the overloads matching the types of the variadic pack\n\t\t};\n\n\t\tEA_DISABLE_VC_WARNING(4242 4244) // conversion from 'T' to 'U', possible loss of data.\n\t\ttemplate <typename T, typename OverloadSet, typename ResultT = decltype(declval<OverloadSet>()(declval<T>()))>\n\t\tstruct overload_resolution\n\t\t{\n\t\t\t// capture the return type of the function the compiler selected by\n\t\t\t// performing overload resolution on the overload set parameter\n\t\t\tusing type = ResultT;\n\t\t};\n\n\t\tEA_RESTORE_VC_WARNING()\n\n\t\ttemplate <typename T, typename OverloadSet>\n\t\tusing overload_resolution_t = typename overload_resolution<decay_t<T>, OverloadSet>::type;\n\n\n\t\t////////////////////////////////////////////////////////////////////////////////////////////\n\t\t// double_pack_expansion\n\t\t//\n\t\t// MSVC 2017 has a hard time expanding two packs of different lengths.\n\t\t// This is a helper meant to coerce MSVC 2017 into doing the expansion by adding another level\n\t\t// of indirection.\n\t\t//\n\n\t\ttemplate <typename T, size_t I>\n\t\tstruct double_pack_expansion;\n\n\t\ttemplate <size_t... Is, size_t I>\n\t\tstruct double_pack_expansion<index_sequence<Is...>, I>\n\t\t{\n\t\t\tusing type = index_sequence<Is..., I>;\n\t\t};\n\n\t\ttemplate <typename IndexSequence, size_t I>\n\t\tusing double_pack_expansion_t = typename double_pack_expansion<IndexSequence, I>::type;\n\n\n\t} // namespace meta\n} // namespace eastl\n\n#endif // EASTL_META_H\n"
  },
  {
    "path": "include/EASTL/numeric.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file defines numeric algorithms just like the std C++ <numeric> \n// algorithm header does. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_NUMERIC_H\n#define EASTL_NUMERIC_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// accumulate\n\t///\n\t/// Accumulates the values in the range [first, last) using operator+.  \n\t/// The initial value is init. The values are processed in order.\n\t///\n\ttemplate <typename InputIterator, typename T>\n\tT accumulate(InputIterator first, InputIterator last, T init)\n\t{\n\t\t// The C++ standard specifies that we use (init = init + first).\n\t\t// However, for non-built-in types, this is less efficent than \n\t\t// operator +=, as no temporary is created. Until a serious problem \n\t\t// is found with using operator +=, we'll use it.\n\n\t\tfor(; first != last; ++first)\n\t\t\tinit += *first;\n\t\treturn init;\n\t}\n\n\n\t/// accumulate\n\t///\n\t/// Accumulates the values in the range [first, last) using binary_op.  \n\t/// The initial value is init. The values are processed in order.\n\t///\n\ttemplate <typename InputIterator, typename T, typename BinaryOperation>\n\tT accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t\tinit = binary_op(init, *first);\n\t\treturn init;\n\t}\n\n\n\n\t/// iota\n\t///\n\t/// Requires: T shall be convertible to ForwardIterator's value type. The expression ++val, \n\t/// where val has type T, shall be well formed.\n\t/// Effects: For each element referred to by the iterator i in the range [first, last), \n\t/// assigns *i = value and increments value as if by ++value.\n\t/// Complexity: Exactly last - first increments and assignments.\n\t/// Example usage: seeding a deck of cards with values 0-51.\n\t///\n\ttemplate <typename ForwardIterator, typename T>\n\tvoid iota(ForwardIterator first, ForwardIterator last, T value)\n\t{\n\t\twhile(first != last)\n\t\t{\n\t\t\t*first++ = value;\n\t\t\t++value;\n\t\t}\n\t}\n\n\n\t/// inner_product\n\t///\n\t/// Starting with an initial value of init, multiplies successive\n\t/// elements from the two ranges and adds each product into the accumulated\n\t/// value using operator+. The values in the ranges are processed in order.\n\t/// \n\ttemplate <typename InputIterator1, typename InputIterator2, typename T>\n\tT inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init)\n\t{\n\t\t// The C++ standard specifies that we use (init = init + (*first1 * *first2)).\n\t\t// However, for non-built-in types, this is less efficent than \n\t\t// operator +=, as no temporary is created. Until a serious problem \n\t\t// is found with using operator +=, we'll use it.\n\n\t\tfor(; first1 != last1; ++first1, ++first2)\n\t\t\tinit += (*first1 * *first2);\n\t\treturn init;\n\t}\n\n\n\t/// inner_product\n\t///\n\t/// Starting with an initial value of init, applies binary_op2 to\n\t/// successive elements from the two ranges and accumulates each result \n\t/// into the accumulated value using binary_op1. The values in the \n\t/// ranges are processed in order.\n\t/// \n\ttemplate <typename InputIterator1, typename InputIterator2, typename T, typename BinaryOperation1, typename BinaryOperation2>\n\tT inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, \n\t\t\t\t\tBinaryOperation1 binary_op1, BinaryOperation2 binary_op2)\n\t{\n\t\tfor(; first1 != last1; ++first1, ++first2)\n\t\t\tinit = binary_op1(init, binary_op2(*first1, *first2));\n\t\treturn init;\n\t}\n\n\n\n\n\n\t/// partial_sum\n\t///\n\t/// Accumulates the values in the range [first, last) using operator+.\n\t/// As each successive input value is added into the total, that partial \n\t/// sum is written to result. Therefore, the first value in result is the\n\t/// first value of the input, the second value in result is the sum of the\n\t/// first and second input values, and so on.\n\t/// \n\ttemplate <typename InputIterator, typename OutputIterator>\n\tOutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result)\n\t{\n\t\ttypedef typename iterator_traits<InputIterator>::value_type value_type;\n\n\t\tif(first != last)\n\t\t{\n\t\t\tvalue_type value(*first);\n\t\t\t\n\t\t\tfor(*result = value; ++first != last; *++result = value)\n\t\t\t\tvalue += *first; // See discussions above on the decision use += instead of +.\n\n\t\t\t++result;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\t/// partial_sum\n\t///\n\t/// Accumulates the values in the range [first,last) using binary_op.\n\t/// As each successive input value is added into the total, that partial \n\t/// sum is written to result. Therefore, the first value in result is the\n\t/// first value of the input, the second value in result is the sum of the\n\t/// first and second input values, and so on.\n\n\ttemplate <typename InputIterator, typename OutputIterator, typename BinaryOperation>\n\tOutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op)\n\t{\n\t\ttypedef typename iterator_traits<InputIterator>::value_type value_type;\n\n\t\tif(first != last)\n\t\t{\n\t\t\tvalue_type value(*first);\n\n\t\t\tfor(*result = value; ++first != last; *++result = value)\n\t\t\t\tvalue = binary_op(value, *first);\n\n\t\t\t++result;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\n\n\n\t/// adjacent_difference\n\t///\n\t/// Computes the difference between adjacent values in the range\n\t/// [first, last) using operator- and writes the result to result.\n\t/// \n\ttemplate <typename InputIterator, typename OutputIterator>\n\tOutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result)\n\t{\n\t\ttypedef typename iterator_traits<InputIterator>::value_type value_type;\n\n\t\tif(first != last)\n\t\t{\n\t\t\tvalue_type value(*first);\n\n\t\t\tfor(*result = value; ++first != last; )\n\t\t\t{\n\t\t\t\tconst value_type temp(*first);\n\n\t\t\t\t*++result = temp - value;\n\t\t\t\tvalue = temp;\n\t\t\t}\n\n\t\t\t++result;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\t/// adjacent_difference\n\t///\n\t/// Computes the difference between adjacent values in the range\n\t/// [first, last) using binary_op and writes the result to result.\n\t/// \n\ttemplate <typename InputIterator, typename OutputIterator, typename BinaryOperation>\n\tOutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op)\n\t{\n\t\ttypedef typename iterator_traits<InputIterator>::value_type value_type;\n\n\t\tif(first != last)\n\t\t{\n\t\t\tvalue_type value(*first);\n\t\t\t\n\t\t\tfor(*result = value; ++first != last; )\n\t\t\t{\n\t\t\t\tconst value_type temp(*first);\n\n\t\t\t\t*++result = binary_op(temp, value);\n\t\t\t\tvalue = temp;\n\t\t\t}\n\n\t\t\t++result;\n\t\t}\n\n\t\treturn result;\n\t}\n\n}\n\n\n///\n/// is_constant_evaluated\n///\n/// Detects whether the function call occurs within a constant-evaluated context.\n///\n/// See: https://en.cppreference.com/w/cpp/types/is_constant_evaluated\n/// \n#if defined(EA_COMPILER_CPP20_ENABLED)\nnamespace eastl\n{\n\t[[nodiscard]] constexpr bool is_constant_evaluated() noexcept\n\t{\n\t\t// MSVC, Clang, and GCC all use the same builtin name\n\t\treturn __builtin_is_constant_evaluated();\n\t}\n}\n#endif\n\n///\n/// isnan\n///\n/// Returns true if the argument is a NaN floating-point value.\n///\nnamespace eastl\n{\n\t[[nodiscard]] constexpr bool isnan(float f)\n\t{\n\t\treturn f != f;\n\t}\n\n\t[[nodiscard]] constexpr bool isnan(double d)\n\t{\n\t\treturn d != d;\n\t}\n\n\t[[nodiscard]] constexpr bool isnan(long double d)\n\t{\n\t\treturn d != d;\n\t}\n}\n\n\n///\n/// midpoint\n///\n/// Computes the midpoint of integers, floating-points, or pointers @lhs and @rhs\n/// \n/// If the operands are of integer type and the sum is odd, the result will be rounded closer to @lhs\n/// If the operands are floating points, then at most one inexact operation occurs.\n///\n#if defined(EA_COMPILER_CPP20_ENABLED)\nnamespace eastl\n{\n\ttemplate <typename T, enable_if_t<is_arithmetic_v<T> && !is_same_v<remove_cv_t<T>, bool>, int> = 0>\n\tconstexpr T midpoint(T lhs, T rhs) noexcept\n\t{\n\t\t// If T is an integral type\n\t\tif constexpr(eastl::is_integral_v<T>)\n\t\t{\n\t\t\tusing U = eastl::make_unsigned_t<T>;\n\n\t\t\tbool const lgtr = lhs > rhs;\n\t\t\tint const sign = lgtr ? -1 : 1;\n\t\t\tU const a = lgtr ? lhs : rhs;\n\t\t\tU const b = lgtr ? rhs : lhs;\n\n\t\t\treturn lhs + static_cast<T>(sign * static_cast<T>(static_cast<U>(a - b) / 2));\n\t\t}\n\t\t// otherwise if T is a floating point\n\t\telse\n\t\t{\n\t\t\tif (eastl::is_constant_evaluated())\n\t\t\t{\n\t\t\t\t// almost any operation, including addition, on floating-point\n\t\t\t\t// values that include a signalling-NaN will throw a floating-\n\t\t\t\t// point exception. this is UB when it occurs in constexpr\n\t\t\t\t// expression evaluation. to circumvent this we will simply\n\t\t\t\t// return the NaN value outright.\n\n\t\t\t\tif (isnan(lhs))\n\t\t\t\t{\n\t\t\t\t\treturn lhs;\n\t\t\t\t}\n\n\t\t\t\tif (isnan(rhs))\n\t\t\t\t{\n\t\t\t\t\treturn rhs;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (isnan(lhs) || isnan(rhs))\n\t\t\t{\n\t\t\t\t// when we encounter a NaN at runtime, we will propagate the\n\t\t\t\t// NaNiness immediately and raise FE_INVALID\n\n\t\t\t\treturn lhs + rhs;\n\t\t\t}\n\n\t\t\tauto lhs_abs = (lhs < 0) ? -lhs : lhs;\n\t\t\tauto rhs_abs = (rhs < 0) ? -rhs : rhs;\n\n\t\t\tconstexpr T hi = eastl::numeric_limits<T>::max() / 2;\n\t\t\tif (lhs_abs <= hi && rhs_abs <= hi)\n\t\t\t{\n\t\t\t\t// lhs and rhs are small enough that this will not overflow\n\t\t\t\treturn (lhs + rhs) / 2;\n\t\t\t}\n\n\t\t\t// either lhs or rhs has a very small magnitude. we divide the\n\t\t\t// larger of the two (an inexact operation), and add the small\n\t\t\t// value to it. because the small value is so very small (smaller\n\t\t\t// than one ULP) we can simply add it directly.\n\t\t\tconstexpr T lo = eastl::numeric_limits<T>::min() * 2;\n\t\t\tif (lhs_abs < lo)\n\t\t\t{\n\t\t\t\treturn lhs + rhs / 2;\n\t\t\t}\n\t\t\telse if (rhs_abs < lo)\n\t\t\t{\n\t\t\t\treturn lhs / 2 + rhs;\n\t\t\t}\n\n\t\t\t// neither lhs nor rhs are small enough to allow for the above\n\t\t\t// magic, and they are too large to first add and then perform a\n\t\t\t// single division, so we perform the slowest but correct\n\t\t\t// operation by dividing both in half first before summing.\n\t\t\treturn lhs / 2 + rhs / 2;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, enable_if_t<is_object_v<T>, int> = 0>\n\t[[nodiscard]] constexpr T* midpoint(T* lhs, T* rhs) noexcept\n\t{\n\t\tif (lhs > rhs)\n\t\t{\n\t\t\treturn lhs - ((lhs - rhs) >> 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn lhs + ((rhs - lhs) >> 1);\n\t\t}\n\t}\n}\n#endif\n\n\n\n\n\nnamespace eastl\n{\nnamespace internal\n{\n\ttemplate <class T>\n\tconstexpr T shared_lerp(const T a, const T b, const T t) EA_NOEXCEPT\n\t{\n\t\tif ((a <= 0 && b >= 0) || (a >= 0 && b <= 0))\n\t\t{\n\t\t\treturn t * b + (1 - t) * a;\n\t\t}\n\n\t\tif (t == 1)\n\t\t{\n\t\t\treturn b;\n\t\t}\n\n\t\tconst T X = a + t * (b - a);\n\n\t\tif ((t > 1) == (b > a))\n\t\t{\n\t\t\treturn (b > X) ? b : X;\n\t\t}\n\t\treturn (b < X) ? b : X;\n\t}\n} // namespace internal\n\n\t/// lerp\n\t///\n\t/// Calculates the linear interpolation of two points A and B expressed A + T * (B - A)\n\t/// where T is some value in range [0, 1]. If T is outside this range, the linear extrapolation will be computed.\n\t///\n\t/// https://en.cppreference.com/w/cpp/numeric/lerp\n\t///\n\t/// C++ proposal paper:\n\t/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0811r3.html\n\t///\n\tconstexpr float lerp(float a, float b, float t) EA_NOEXCEPT { return internal::shared_lerp(a, b, t); }\n\tconstexpr double lerp(double a, double b, double t) EA_NOEXCEPT { return internal::shared_lerp(a, b, t); }\n\tconstexpr long double lerp(long double a, long double b, long double t) EA_NOEXCEPT { return internal::shared_lerp(a, b, t); }\n} // namespace eastl\n\n\n\n#endif // Header include guard\n\n"
  },
  {
    "path": "include/EASTL/numeric_limits.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// We support eastl::numeric_limits for the following types. Sized types such\n// as int32_t are covered by these basic types, with the exception of int128_t.\n//\n//     bool\n//     char                 (distinct from signed and unsigned char)\n//     unsigned char,\n//     signed char, \n//     wchar_t\n//     char16_t             (when char16_t is a distict type)\n//     char32_t             (when char32_t is a distinct type)\n//     unsigned short,\n//     signed short\n//     unsigned int\n//     signed int\n//     unsigned long\n//     signed long\n//     signed long long\n//     unsigned long long\n//     uint128_t            (when supported natively by the compiler)\n//     int128_t             (when supported natively by the compiler)\n//     float\n//     double\n//     long double\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_NUMERIC_LIMITS_H\n#define EASTL_NUMERIC_LIMITS_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <limits.h>                 // C limits.h header\n#include <float.h>\n#if defined(_CPPLIB_VER)            // Dinkumware.\n\t#include <ymath.h>\n#endif\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n// Disable Warnings:\n//   4310 - cast truncates constant value\n//   4296 - expression is always false\nEA_DISABLE_VC_WARNING(4310 4296)\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// min/max workaround\n//\n// MSVC++ has #defines for min/max which collide with the min/max algorithm\n// declarations. The following may still not completely resolve some kinds of\n// problems with MSVC++ #defines, though it deals with most cases in production\n// game code.\n//\n#if EASTL_NOMINMAX\n\t#ifdef min\n\t\t#undef min\n\t#endif\n\t#ifdef max\n\t\t#undef max\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_LIMITS macros\n// These apply to integral types only.\n///////////////////////////////////////////////////////////////////////////////\n\n// true or false.\n#define EASTL_LIMITS_IS_SIGNED(T)    ((T)(-1) < 0)\n\n// The min possible value of T. \n#define EASTL_LIMITS_MIN_S(T) ((T)((T)1 << EASTL_LIMITS_DIGITS_S(T)))\n#define EASTL_LIMITS_MIN_U(T) ((T)0)\n#define EASTL_LIMITS_MIN(T)   ((EASTL_LIMITS_IS_SIGNED(T) ? EASTL_LIMITS_MIN_S(T) : EASTL_LIMITS_MIN_U(T)))\n\n// The max possible value of T. \n#define EASTL_LIMITS_MAX_S(T) ((T)(((((T)1 << (EASTL_LIMITS_DIGITS(T) - 1)) - 1) << 1) + 1))\n#define EASTL_LIMITS_MAX_U(T) ((T)~(T)0)\n#define EASTL_LIMITS_MAX(T)   ((EASTL_LIMITS_IS_SIGNED(T) ? EASTL_LIMITS_MAX_S(T) : EASTL_LIMITS_MAX_U(T)))\n\n// The number of bits in the representation of T.\n#define EASTL_LIMITS_DIGITS_S(T) ((sizeof(T) * CHAR_BIT) - 1)\n#define EASTL_LIMITS_DIGITS_U(T) ((sizeof(T) * CHAR_BIT))\n#define EASTL_LIMITS_DIGITS(T)   ((EASTL_LIMITS_IS_SIGNED(T) ? EASTL_LIMITS_DIGITS_S(T) : EASTL_LIMITS_DIGITS_U(T)))\n\n// The number of decimal digits that can be represented by T.\n#define EASTL_LIMITS_DIGITS10_S(T) ((EASTL_LIMITS_DIGITS_S(T) * 643L) / 2136) // (643 / 2136) ~= log10(2).\n#define EASTL_LIMITS_DIGITS10_U(T) ((EASTL_LIMITS_DIGITS_U(T) * 643L) / 2136)\n#define EASTL_LIMITS_DIGITS10(T)   ((EASTL_LIMITS_IS_SIGNED(T) ? EASTL_LIMITS_DIGITS10_S(T) : EASTL_LIMITS_DIGITS10_U(T)))\n\n\n\n\n\n\nnamespace eastl\n{\n\t// See C++11 18.3.2.5\n\tenum float_round_style\n\t{\n\t\tround_indeterminate       = -1,    /// Intermediate.\n\t\tround_toward_zero         =  0,    /// To zero.\n\t\tround_to_nearest          =  1,    /// To the nearest representable value.\n\t\tround_toward_infinity     =  2,    /// To infinity.\n\t\tround_toward_neg_infinity =  3     /// To negative infinity.\n\t};\n\n\t// See C++11 18.3.2.6\n\tenum float_denorm_style\n\t{\n\t\tdenorm_indeterminate = -1,          /// It cannot be determined whether or not the type allows denormalized values.\n\t\tdenorm_absent        =  0,          /// The type does not allow denormalized values.\n\t\tdenorm_present       =  1           /// The type allows denormalized values.\n\t};\n\n\n\t// Default numeric_limits.\n\t// See C++11 18.3.2.3\n\ttemplate<typename T>\n\tclass numeric_limits;\n\n\n\t// Const/volatile variations of numeric_limits.\n\ttemplate<typename T>\n\tclass numeric_limits<const T>\n\t\t: public numeric_limits<T>\n\t{};\n\n\ttemplate<typename T>\n\tclass numeric_limits<volatile T>\n\t\t: public numeric_limits<T>\n\t{};\n\n\ttemplate<typename T>\n\tclass numeric_limits<const volatile T>\n\t\t: public numeric_limits<T>\n\t{};\n\n\n\n\t// numeric_limits<bool>\n\ttemplate<>\n\tclass numeric_limits<bool>\n\t{\n\tpublic:\n\t\ttypedef bool value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = 1;      // In practice bool is stores as a byte, or sometimes an int.\n\t\tstatic constexpr int                digits10          = 0;\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = false;  // In practice bool may be implemented as signed char.\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = false;\n\t\tstatic constexpr bool               traps             = true;   // Should this be true or false? Given that it's implemented in hardware as an integer type, we use true.\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return false; }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return true; }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return false; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return false; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return false; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return value_type(); }\n\t};\n\n\n\t// numeric_limits<char>\n\ttemplate<>\n\tclass numeric_limits<char>\n\t{\n\tpublic:\n\t\ttypedef char value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = EASTL_LIMITS_IS_SIGNED(value_type);\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }    // Question: Should we return 0 here or value_type()?\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return (value_type)0; }\n\t};\n\n\n\t// numeric_limits<unsigned char>\n\ttemplate<>\n\tclass numeric_limits<unsigned char>\n\t{\n\tpublic:\n\t\ttypedef unsigned char value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_U(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_U(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = false;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_U(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return (value_type)0; }\n\t};\n\n\n\t// numeric_limits<signed char>\n\ttemplate<>\n\tclass numeric_limits<signed char>\n\t{\n\tpublic:\n\t\ttypedef signed char value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_S(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_S(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_S(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return (value_type)0; }\n\t};\n\n\n\t// numeric_limits<wchar_t>\n\t// VC++ has the option of making wchar_t simply be unsigned short. If that's enabled then  \n\t// the code below could possibly cause compile failures due to redundancy. The best resolution \n\t// may be to use __wchar_t here for VC++ instead of wchar_t, as __wchar_t is always a true \n\t// unique type under VC++. http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/9059330a-7cce-4d0d-a8e0-e1dcb63322bd/\n\ttemplate<>\n\tclass numeric_limits<wchar_t>\n\t{\n\tpublic:\n\t\ttypedef wchar_t value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = EASTL_LIMITS_IS_SIGNED(value_type);\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return (value_type)0; }\n\t};\n\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\ttemplate<>\n\tclass numeric_limits<char8_t>\n\t{\n\tpublic:\n\t\ttypedef char8_t value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = EASTL_LIMITS_IS_SIGNED(value_type);\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n \t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min()\n\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX(value_type); }\n\n\t\tstatic constexpr value_type lowest()\n\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\tstatic constexpr value_type epsilon()\n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error()\n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity()\n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type quiet_NaN()\n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type denorm_min()\n\t\t\t{ return (value_type)0; }\n\t};\n\t#endif\n\n\t#if EA_CHAR16_NATIVE // If char16_t is a true unique type (as called for by the C++11 Standard)...\n\n\t\t// numeric_limits<char16_t>\n\t\ttemplate<>\n\t\tclass numeric_limits<char16_t>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef char16_t value_type;\n\n\t\t\tstatic constexpr bool               is_specialized    = true;\n\t\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS(value_type);\n\t\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10(value_type);\n\t\t\tstatic constexpr int                max_digits10      = 0;\n\t\t\tstatic constexpr bool               is_signed         = EASTL_LIMITS_IS_SIGNED(value_type);\n\t\t\tstatic constexpr bool               is_integer        = true;\n\t\t\tstatic constexpr bool               is_exact          = true;\n\t\t\tstatic constexpr int                radix             = 2;\n\t\t\tstatic constexpr int                min_exponent      = 0;\n\t\t\tstatic constexpr int                min_exponent10    = 0;\n\t\t\tstatic constexpr int                max_exponent      = 0;\n\t\t\tstatic constexpr int                max_exponent10    = 0;\n\t\t\tstatic constexpr bool               is_bounded        = true;\n\t\t\tstatic constexpr bool               is_modulo         = true;\n\t\t\tstatic constexpr bool               traps             = true;\n\t\t\tstatic constexpr bool               tinyness_before   = false;\n\t\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\t\tstatic constexpr bool               has_infinity      = false;\n\t\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\t\tstatic constexpr value_type min() \n\t\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return EASTL_LIMITS_MAX(value_type); }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t{ return (value_type)0; }\n\t\t};\n\n\t#endif\n\n\n\t#if EA_CHAR32_NATIVE // If char32_t is a true unique type (as called for by the C++11 Standard)...\n\n\t\t// numeric_limits<char32_t>\n\t\ttemplate<>\n\t\tclass numeric_limits<char32_t>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef char32_t value_type;\n\n\t\t\tstatic constexpr bool               is_specialized    = true;\n\t\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS(value_type);\n\t\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10(value_type);\n\t\t\tstatic constexpr int                max_digits10      = 0;\n\t\t\tstatic constexpr bool               is_signed         = EASTL_LIMITS_IS_SIGNED(value_type);\n\t\t\tstatic constexpr bool               is_integer        = true;\n\t\t\tstatic constexpr bool               is_exact          = true;\n\t\t\tstatic constexpr int                radix             = 2;\n\t\t\tstatic constexpr int                min_exponent      = 0;\n\t\t\tstatic constexpr int                min_exponent10    = 0;\n\t\t\tstatic constexpr int                max_exponent      = 0;\n\t\t\tstatic constexpr int                max_exponent10    = 0;\n\t\t\tstatic constexpr bool               is_bounded        = true;\n\t\t\tstatic constexpr bool               is_modulo         = true;\n\t\t\tstatic constexpr bool               traps             = true;\n\t\t\tstatic constexpr bool               tinyness_before   = false;\n\t\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\t\tstatic constexpr bool               has_infinity      = false;\n\t\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\t\tstatic constexpr value_type min() \n\t\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return EASTL_LIMITS_MAX(value_type); }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return EASTL_LIMITS_MIN(value_type); }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t{ return (value_type)0; }\n\t\t};\n\n\t#endif\n\n\n\t// numeric_limits<unsigned short>\n\ttemplate<>\n\tclass numeric_limits<unsigned short>\n\t{\n\tpublic:\n\t\ttypedef unsigned short value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_U(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_U(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = false;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_U(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\t// numeric_limits<signed short>\n\ttemplate<>\n\tclass numeric_limits<signed short>\n\t{\n\tpublic:\n\t\ttypedef signed short value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_S(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_S(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_S(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\n\t// numeric_limits<unsigned int>\n\ttemplate<>\n\tclass numeric_limits<unsigned int>\n\t{\n\tpublic:\n\t\ttypedef unsigned int value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_U(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_U(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = false;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_U(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\t// numeric_limits<signed int>\n\ttemplate<>\n\tclass numeric_limits<signed int>\n\t{\n\tpublic:\n\t\ttypedef signed int value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_S(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_S(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return INT_MIN; } // It's hard to get EASTL_LIMITS_MIN_S to work with all compilers here.\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_S(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return INT_MIN; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\t// numeric_limits<unsigned long>\n\ttemplate<>\n\tclass numeric_limits<unsigned long>\n\t{\n\tpublic:\n\t\ttypedef unsigned long value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_U(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_U(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = false;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_U(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\t// numeric_limits<signed long>\n\ttemplate<>\n\tclass numeric_limits<signed long>\n\t{\n\tpublic:\n\t\ttypedef signed long value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_S(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_S(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return LONG_MIN; }  // It's hard to get EASTL_LIMITS_MIN_S to work with all compilers here.\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_S(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return LONG_MIN; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\t// numeric_limits<unsigned long long>\n\ttemplate<>\n\tclass numeric_limits<unsigned long long>\n\t{\n\tpublic:\n\t\ttypedef unsigned long long value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_U(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_U(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = false;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_U(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\t// numeric_limits<signed long long>\n\ttemplate<>\n\tclass numeric_limits<signed long long>\n\t{\n\tpublic:\n\t\ttypedef signed long long value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_S(value_type);\n\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_S(value_type);\n\t\tstatic constexpr int                max_digits10      = 0;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = true;\n\t\tstatic constexpr bool               is_exact          = true;\n\t\tstatic constexpr int                radix             = 2;\n\t\tstatic constexpr int                min_exponent      = 0;\n\t\tstatic constexpr int                min_exponent10    = 0;\n\t\tstatic constexpr int                max_exponent      = 0;\n\t\tstatic constexpr int                max_exponent10    = 0;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = true;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\tstatic constexpr bool               has_infinity      = false;\n\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\tstatic constexpr value_type min() \n\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\tstatic constexpr value_type max()\n\t\t\t{ return EASTL_LIMITS_MAX_S(value_type); }\n\n\t\tstatic constexpr value_type lowest() \n\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\tstatic constexpr value_type epsilon() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type round_error() \n\t\t\t{ return 0; }\n\n\t\tstatic constexpr value_type infinity() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t{ return value_type(); }\n\n\t\tstatic constexpr value_type denorm_min() \n\t\t\t{ return static_cast<value_type>(0); }\n\t};\n\n\n\t#if (EA_COMPILER_INTMAX_SIZE >= 16) && (defined(EA_COMPILER_GNUC) || defined(__clang__)) // If __int128_t/__uint128_t is supported...\n\t\t// numeric_limits<__uint128_t>\n\t\ttemplate<>\n\t\tclass numeric_limits<__uint128_t>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef __uint128_t value_type;\n\n\t\t\tstatic constexpr bool               is_specialized    = true;\n\t\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_U(value_type);\n\t\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_U(value_type);\n\t\t\tstatic constexpr int                max_digits10      = 0;\n\t\t\tstatic constexpr bool               is_signed         = false;\n\t\t\tstatic constexpr bool               is_integer        = true;\n\t\t\tstatic constexpr bool               is_exact          = true;\n\t\t\tstatic constexpr int                radix             = 2;\n\t\t\tstatic constexpr int                min_exponent      = 0;\n\t\t\tstatic constexpr int                min_exponent10    = 0;\n\t\t\tstatic constexpr int                max_exponent      = 0;\n\t\t\tstatic constexpr int                max_exponent10    = 0;\n\t\t\tstatic constexpr bool               is_bounded        = true;\n\t\t\tstatic constexpr bool               is_modulo         = true;\n\t\t\tstatic constexpr bool               traps             = true;\n\t\t\tstatic constexpr bool               tinyness_before   = false;\n\t\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\t\tstatic constexpr bool               has_infinity      = false;\n\t\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\t\tstatic constexpr value_type min() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return EASTL_LIMITS_MAX_U(value_type); }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t{ return static_cast<value_type>(0); }\n\t\t};\n\n\n\t\t// numeric_limits<__int128_t>\n\t\ttemplate<>\n\t\tclass numeric_limits<__int128_t>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef __int128_t value_type;\n\n\t\t\tstatic constexpr bool               is_specialized    = true;\n\t\t\tstatic constexpr int                digits            = EASTL_LIMITS_DIGITS_S(value_type);\n\t\t\tstatic constexpr int                digits10          = EASTL_LIMITS_DIGITS10_S(value_type);\n\t\t\tstatic constexpr int                max_digits10      = 0;\n\t\t\tstatic constexpr bool               is_signed         = true;\n\t\t\tstatic constexpr bool               is_integer        = true;\n\t\t\tstatic constexpr bool               is_exact          = true;\n\t\t\tstatic constexpr int                radix             = 2;\n\t\t\tstatic constexpr int                min_exponent      = 0;\n\t\t\tstatic constexpr int                min_exponent10    = 0;\n\t\t\tstatic constexpr int                max_exponent      = 0;\n\t\t\tstatic constexpr int                max_exponent10    = 0;\n\t\t\tstatic constexpr bool               is_bounded        = true;\n\t\t\tstatic constexpr bool               is_modulo         = true;\n\t\t\tstatic constexpr bool               traps             = true;\n\t\t\tstatic constexpr bool               tinyness_before   = false;\n\t\t\tstatic constexpr float_round_style  round_style       = round_toward_zero;\n\t\t\tstatic constexpr bool               has_infinity      = false;\n\t\t\tstatic constexpr bool               has_quiet_NaN     = false;\n\t\t\tstatic constexpr bool               has_signaling_NaN = false;\n\t\t\tstatic constexpr float_denorm_style has_denorm        = denorm_absent;\n\t\t\tstatic constexpr bool               has_denorm_loss   = false;\n\t\t\tstatic constexpr bool               is_iec559         = false;\n\n\t\t\tstatic constexpr value_type min() \n\t\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return EASTL_LIMITS_MAX_S(value_type); }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return EASTL_LIMITS_MIN_S(value_type); }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0; }\n\n\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t{ return value_type(); }\n\n\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t{ return static_cast<value_type>(0); }\n\t\t};\n\t#endif\n\n\n\t// numeric_limits<float>\n\ttemplate<>\n\tclass numeric_limits<float>\n\t{\n\tpublic:\n\t\ttypedef float value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = FLT_MANT_DIG;\n\t\tstatic constexpr int                digits10          = FLT_DIG;\n\t\tstatic constexpr int                max_digits10      = FLT_MANT_DIG;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = false;\n\t\tstatic constexpr bool               is_exact          = false;\n\t\tstatic constexpr int                radix             = FLT_RADIX;\n\t\tstatic constexpr int                min_exponent      = FLT_MIN_EXP;\n\t\tstatic constexpr int                min_exponent10    = FLT_MIN_10_EXP;\n\t\tstatic constexpr int                max_exponent      = FLT_MAX_EXP;\n\t\tstatic constexpr int                max_exponent10    = FLT_MAX_10_EXP;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = false;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_to_nearest;\n\t\tstatic constexpr bool               has_infinity      = true;\n\t\tstatic constexpr bool               has_quiet_NaN     = true;                   // This may be wrong for some platforms.\n\t\tstatic constexpr bool               has_signaling_NaN = true;                   // This may be wrong for some platforms.\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_present;         // This may be wrong for some platforms.\n\t\tstatic constexpr bool               has_denorm_loss   = false;                  // This may be wrong for some platforms.\n\t\tstatic constexpr bool               is_iec559         = has_infinity && has_quiet_NaN && (has_denorm == denorm_present);\n\n\t\t#if (defined(EA_COMPILER_GNUC) || defined(__clang__)) && defined(__FLT_MIN__)\n\t\t\tstatic constexpr value_type min()\n\t\t\t\t{ return __FLT_MIN__; }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return __FLT_MAX__; }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return -__FLT_MAX__; }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return __FLT_EPSILON__; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0.5f; }\n\n\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t{ return __builtin_huge_valf(); }\n\n\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t{ return __builtin_nanf(\"\"); }\n\n\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t{ return __builtin_nansf(\"\"); }\n\n\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t{ return __FLT_DENORM_MIN__; }\n\n\t\t#elif defined(_CPPLIB_VER) // If using the Dinkumware Standard library...\n\t\t\tstatic constexpr value_type min()\n\t\t\t\t{ return FLT_MIN; }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return FLT_MAX; }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return -FLT_MAX; }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return FLT_EPSILON; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0.5f; }\n\n\t\t\t#if defined(_MSVC_STL_UPDATE) && _MSVC_STL_UPDATE >= 202206L // If using a recent version of MSVC's STL...\n\t\t\t\tstatic constexpr value_type infinity()\n\t\t\t\t\t{ return __builtin_huge_valf(); }\n\n\t\t\t\tstatic constexpr value_type quiet_NaN()\n\t\t\t\t\t{ return __builtin_nanf(\"0\"); }\n\n\t\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t\t{ return __builtin_nansf(\"1\"); }\n\n\t\t\t\tstatic constexpr value_type denorm_min()\n\t\t\t\t\t{ return FLT_TRUE_MIN; }\n\t\t\t#else\n\t\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t\t{ return _CSTD _FInf._Float; }\n\n\t\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t\t{ return _CSTD _FNan._Float; }\n\n\t\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t\t{ return _CSTD _FSnan._Float; } \n\n\t\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t\t{ return _CSTD _FDenorm._Float; }\n\t\t\t#endif\n\t\t#endif\n\t};\n\n\n\t// numeric_limits<double>\n\ttemplate<>\n\tclass numeric_limits<double>\n\t{\n\tpublic:\n\t\ttypedef double value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = DBL_MANT_DIG;\n\t\tstatic constexpr int                digits10          = DBL_DIG;\n\t\tstatic constexpr int                max_digits10      = DBL_MANT_DIG;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = false;\n\t\tstatic constexpr bool               is_exact          = false;\n\t\tstatic constexpr int                radix             = FLT_RADIX;              // FLT_RADIX applies to all floating point types.\n\t\tstatic constexpr int                min_exponent      = DBL_MIN_EXP;\n\t\tstatic constexpr int                min_exponent10    = DBL_MIN_10_EXP;\n\t\tstatic constexpr int                max_exponent      = DBL_MAX_EXP;\n\t\tstatic constexpr int                max_exponent10    = DBL_MAX_10_EXP;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = false;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_to_nearest;\n\t\tstatic constexpr bool               has_infinity      = true;\n\t\tstatic constexpr bool               has_quiet_NaN     = true;                   // This may be wrong for some platforms.\n\t\tstatic constexpr bool               has_signaling_NaN = true;                   // This may be wrong for some platforms.\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_present;         // This may be wrong for some platforms.\n\t\tstatic constexpr bool               has_denorm_loss   = false;                  // This may be wrong for some platforms.\n\t\tstatic constexpr bool               is_iec559         = has_infinity && has_quiet_NaN && (has_denorm == denorm_present);\n\n\t\t#if (defined(EA_COMPILER_GNUC) || defined(__clang__)) && defined(__DBL_MIN__)\n\t\t\tstatic constexpr value_type min()\n\t\t\t\t{ return __DBL_MIN__; }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return __DBL_MAX__; }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return -__DBL_MAX__; }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return __DBL_EPSILON__; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0.5f; }\n\n\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t{ return __builtin_huge_val(); }\n\n\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t{ return __builtin_nan(\"\"); }\n\n\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t{ return __builtin_nans(\"\"); }\n\n\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t{ return __DBL_DENORM_MIN__; }\n\n\t\t#elif defined(_CPPLIB_VER) // If using the Dinkumware Standard library...\n\t\t\tstatic constexpr value_type min()\n\t\t\t\t{ return DBL_MIN; }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return DBL_MAX; }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return -DBL_MAX; }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return DBL_EPSILON; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0.5f; }\n\n\t\t\t#if defined(_MSVC_STL_UPDATE) && _MSVC_STL_UPDATE >= 202206L // If using a recent version of MSVC's STL...\n\t\t\t\tstatic constexpr value_type infinity()\n\t\t\t\t\t{ return __builtin_huge_val(); }\n\n\t\t\t\tstatic constexpr value_type quiet_NaN()\n\t\t\t\t\t{ return __builtin_nan(\"0\"); }\n\n\t\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t\t{ return __builtin_nans(\"1\"); }\n\n\t\t\t\tstatic constexpr value_type denorm_min()\n\t\t\t\t\t{ return DBL_TRUE_MIN; }\n\t\t\t#else\n\t\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t\t{ return _CSTD _Inf._Double; }\n\n\t\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t\t{ return _CSTD _Nan._Double; }\n\n\t\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t\t{ return _CSTD _Snan._Double; } \n\n\t\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t\t{ return _CSTD _Denorm._Double; }\n\t\t\t#endif\n\t\t#endif\n\t};\n\n\n\t// numeric_limits<long double>\n\ttemplate<>\n\tclass numeric_limits<long double>\n\t{\n\tpublic:\n\t\ttypedef long double value_type;\n\n\t\tstatic constexpr bool               is_specialized    = true;\n\t\tstatic constexpr int                digits            = LDBL_MANT_DIG;\n\t\tstatic constexpr int                digits10          = LDBL_DIG;\n\t\tstatic constexpr int                max_digits10      = LDBL_MANT_DIG;\n\t\tstatic constexpr bool               is_signed         = true;\n\t\tstatic constexpr bool               is_integer        = false;\n\t\tstatic constexpr bool               is_exact          = false;\n\t\tstatic constexpr int                radix             = FLT_RADIX;              // FLT_RADIX applies to all floating point types.\n\t\tstatic constexpr int                min_exponent      = LDBL_MIN_EXP;\n\t\tstatic constexpr int                min_exponent10    = LDBL_MIN_10_EXP;\n\t\tstatic constexpr int                max_exponent      = LDBL_MAX_EXP;\n\t\tstatic constexpr int                max_exponent10    = LDBL_MAX_10_EXP;\n\t\tstatic constexpr bool               is_bounded        = true;\n\t\tstatic constexpr bool               is_modulo         = false;\n\t\tstatic constexpr bool               traps             = true;\n\t\tstatic constexpr bool               tinyness_before   = false;\n\t\tstatic constexpr float_round_style  round_style       = round_to_nearest;\n\t\tstatic constexpr bool               has_infinity      = true;\n\t\tstatic constexpr bool               has_quiet_NaN     = true;                   // This may be wrong for some platforms.\n\t\tstatic constexpr bool               has_signaling_NaN = true;                   // This may be wrong for some platforms.\n\t\tstatic constexpr float_denorm_style has_denorm        = denorm_present;         // This may be wrong for some platforms.\n\t\tstatic constexpr bool               has_denorm_loss   = false;                  // This may be wrong for some platforms.\n\t\tstatic constexpr bool               is_iec559         = has_infinity && has_quiet_NaN && (has_denorm == denorm_present);\n\n\t\t#if (defined(EA_COMPILER_GNUC) || defined(__clang__)) && defined(__LDBL_MIN__)\n\t\t\tstatic constexpr value_type min()\n\t\t\t\t{ return __LDBL_MIN__; }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return __LDBL_MAX__; }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return -__LDBL_MAX__; }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return __LDBL_EPSILON__; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0.5f; }\n\n\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t{ return __builtin_huge_val(); }\n\n\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t{ return __builtin_nan(\"\"); }\n\n\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t{ return __builtin_nans(\"\"); }\n\n\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t{ return __LDBL_DENORM_MIN__; }\n\n\t\t#elif defined(_CPPLIB_VER) // If using the Dinkumware Standard library...\n\t\t\tstatic constexpr value_type min()\n\t\t\t\t{ return LDBL_MIN; }\n\n\t\t\tstatic constexpr value_type max()\n\t\t\t\t{ return LDBL_MAX; }\n\n\t\t\tstatic constexpr value_type lowest() \n\t\t\t\t{ return -LDBL_MAX; }\n\n\t\t\tstatic constexpr value_type epsilon() \n\t\t\t\t{ return LDBL_EPSILON; }\n\n\t\t\tstatic constexpr value_type round_error() \n\t\t\t\t{ return 0.5f; }\n\n\t\t\t#if defined(_MSVC_STL_UPDATE) && _MSVC_STL_UPDATE >= 202206L // If using a recent version of MSVC's STL...\n\t\t\t\tstatic constexpr value_type infinity()\n\t\t\t\t\t{ return __builtin_huge_val(); }\n\n\t\t\t\tstatic constexpr value_type quiet_NaN()\n\t\t\t\t\t{ return __builtin_nan(\"0\"); }\n\n\t\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t\t{ return __builtin_nans(\"1\"); }\n\n\t\t\t\tstatic constexpr value_type denorm_min()\n\t\t\t\t\t{ return LDBL_TRUE_MIN; }\n\t\t\t#else\n\t\t\t\tstatic constexpr value_type infinity() \n\t\t\t\t\t{ return _CSTD _LInf._Long_double; }\n\n\t\t\t\tstatic constexpr value_type quiet_NaN() \n\t\t\t\t\t{ return _CSTD _LNan._Long_double; }\n\n\t\t\t\tstatic constexpr value_type signaling_NaN()\n\t\t\t\t\t{ return _CSTD _LSnan._Long_double; } \n\n\t\t\t\tstatic constexpr value_type denorm_min() \n\t\t\t\t\t{ return _CSTD _LDenorm._Long_double; }\n\t\t\t#endif\n\t\t#endif\n\t};\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING()\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/optional.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the class template optional that represents optional objects.\n//\n// An optional object is an object that contains the storage for another object and\n// manages the lifetime of this contained object, if any. The contained object may be\n// initialized after the optional object has been initialized, and may be destroyed before\n// the optional object has been destroyed.\n//\n// Any instance of optional<T> at any given time either contains a value or does not\n// contain a value. When an instance of optional<T> contains a value, it means that an\n// object of type T, referred to as the optional object's contained value, is allocated\n// within the storage of the optional object. Implementations are not permitted to use\n// additional storage, such as dynamic memory, to allocate its contained value.\n//\n// The contained value is allocated in the optional<T> storage suitably\n// aligned for the type T. When an object of type optional<T> is contextually converted to\n// bool, the conversion returns true if the object contains a value; otherwise the\n// conversion returns false.\n//\n// T shall be an object type and satisfy the requirements of Destructible.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_OPTIONAL_H\n#define EASTL_OPTIONAL_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/memory.h> // eastl::addressof\n#include <EASTL/internal/concepts.h>\n#include <EASTL/internal/in_place_t.h> // eastl::in_place_t\n#include <EASTL/internal/special_member_functions_variant_optional.h>\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <stdexcept> // std::logic_error.\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\n#if defined(EASTL_OPTIONAL_ENABLED) && EASTL_OPTIONAL_ENABLED\n\nEA_DISABLE_VC_WARNING(4582 4583) // constructor/destructor is not implicitly called\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////////\n\t/// nullopt_t\n\t///\n\t/// nullopt_t is class type used to indicate eastl::optional type with uninitialized state.\n\t///\n\tstruct nullopt_tag_t {};\n\n\tstruct nullopt_t\n\t{\n\t\tEA_CONSTEXPR nullopt_t(nullopt_tag_t) {}\n\t};\n\n\tEA_CONSTEXPR nullopt_t nullopt{nullopt_tag_t{}};\n\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t/// bad_optional_access\n\t///\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\tstruct bad_optional_access : public std::logic_error\n\t\t{\n\t\t\tbad_optional_access() : std::logic_error(\"eastl::bad_optional_access exception\") {}\n\t\t\tvirtual ~bad_optional_access() EA_NOEXCEPT {}\n\t\t};\n\t#endif\n\n\ttemplate <typename T>\n\tclass optional; // Forward declaration for Internal::is_optional.\n\t\t\n\tnamespace Internal\n\t{\n\t\ttemplate <typename T>\n\t\tstruct is_optional : false_type {};\n\n\t\ttemplate <typename T>\n\t\tstruct is_optional<optional<T>> : true_type {};\n\n\t\ttemplate <typename T>\n\t\tconstexpr bool is_optional_v = is_optional<T>::value;\n\t\t\n\t\ttemplate <typename T>\n\t\tconstexpr bool is_specialization_of_optional_v = false;\n\n\t\ttemplate <typename T>\n\t\tconstexpr bool is_specialization_of_optional_v<optional<T>> = true;\n\n\t\ttemplate<typename T, typename W>\n\t\tconstexpr bool converts_from_any_cvref_v =\n\t\t\tis_constructible_v<T, W&> || is_convertible_v<W&, T> ||\n\t\t\tis_constructible_v<T, W> || is_convertible_v<W, T> ||\n\t\t\tis_constructible_v<T, const W&> || is_convertible_v<const W&, T> ||\n\t\t\tis_constructible_v<T, const W> || is_convertible_v<const W, T>;\n\n\t\t///////////////////////////////////////////////////////////////////////////////\n\t\t/// optional_storage\n\t\t///\n\t\ttemplate<typename T, bool IsTriviallyDestructible = eastl::is_trivially_destructible_v<T>>\n\t\tstruct optional_storage\n\t\t{\n\t\t\tusing value_type = T; // non-const, non-volatile\n\n\t\t\tinline ~optional_storage()\n\t\t\t{\n\t\t\t\tif (engaged)\n\t\t\t\t\tdestruct_value();\n\t\t\t}\n\n\t\t\tinline EA_CPP20_CONSTEXPR void destruct_value() { (*reinterpret_cast<value_type*>(eastl::addressof(val))).~value_type(); }\n\n\t\t\teastl::aligned_storage_t<sizeof(value_type), eastl::alignment_of_v<value_type>> val;\n\t\t\tbool engaged = false;\n\t\t};\n\n\n\t\t/// optional_storage<T, true>\n\t\t///\n\t\t/// Template specialization for trivial types to satisfy the requirement that optional<T> is trivially\n\t\t/// destructible when T is trivially destructible.\n\t\t///\n\t\ttemplate<typename T>\n\t\tstruct optional_storage<T, true>\n\t\t{\n\t\t\tusing value_type = T; // non-const, non-volatile\n\n\t\t\t// Removed to make optional<T> trivially destructible when T is trivially destructible.\n\t\t\t~optional_storage() EA_NOEXCEPT = default;\n\n\t\t\tinline EA_CPP20_CONSTEXPR void destruct_value() {} // no implementation necessary since T is trivially destructible.\n\n\t\t\teastl::aligned_storage_t<sizeof(value_type), eastl::alignment_of_v<value_type>> val;\n\t\t\tbool engaged = false;\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tclass optional_base : private Internal::optional_storage<remove_cv_t<T>>\n\t\t{\n\t\t\tusing base_type = Internal::optional_storage<remove_cv_t<T>>;\n\n\t\tpublic:\n\t\t\tusing base_type::destruct_value;\n\t\t\tusing base_type::val;\n\t\t\tusing base_type::engaged;\n\n\t\t\tusing value_type = T;\n\n#if !EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\toptional_base() = default;\n#endif\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\tvoid ConstructFrom(const optional_base& other)\n#else\n\t\t\toptional_base(const optional_base& other)\n#endif\n\t\t\t{\n\t\t\t\tengaged = other.engaged;\n\n\t\t\t\tif (engaged)\n\t\t\t\t{\n\t\t\t\t\tconstruct_value(*other.get_value_address());\n\t\t\t\t}\n\t\t\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\tvoid ConstructFrom(optional_base&& other)\n\t\t\t\tEA_NOEXCEPT_IF(eastl::is_nothrow_move_constructible<value_type>::value)\n#else\n\t\t\toptional_base(optional_base&& other)\n#endif\n\t\t\t{\n\t\t\t\tengaged = other.engaged;\n\n\t\t\t\tif (engaged)\n\t\t\t\t{\n\t\t\t\t\tconstruct_value(eastl::move(*other.get_value_address()));\n\t\t\t\t}\n\t\t\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\tvoid AssignFrom(const optional_base& other)\n#else\n\t\t\toptional_base& operator=(const optional_base& other)\n#endif\n\t\t\t{\n\t\t\t\tif (engaged && !other.engaged)\n\t\t\t\t{\n\t\t\t\t\tdestruct_value();\n\t\t\t\t\tengaged = false;\n\t\t\t\t}\n\t\t\t\telse if (engaged && other.engaged)\n\t\t\t\t{\n\t\t\t\t\t*get_value_address() = *other.get_value_address();\n\t\t\t\t}\n\t\t\t\telse if (!engaged && other.engaged)\n\t\t\t\t{\n\t\t\t\t\tconstruct_value(*other.get_value_address());\n\t\t\t\t\tengaged = true;\n\t\t\t\t}\n\t\t\t\t// else if (!engaged && !other.engaged)\n\t\t\t\t//\tno op\n\n#if !EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\t\treturn *this;\n#endif\n\t\t\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\tvoid AssignFrom(optional_base&& other)\n\t\t\t\tEA_NOEXCEPT_IF(eastl::is_nothrow_move_assignable<value_type>::value&&\n\t\t\t\t\teastl::is_nothrow_move_constructible<value_type>::value)\n#else\n\t\t\toptional_base& operator=(optional_base&& other)\n#endif\n\t\t\t{\n\t\t\t\tif (engaged && !other.engaged)\n\t\t\t\t{\n\t\t\t\t\tdestruct_value();\n\t\t\t\t\tengaged = false;\n\t\t\t\t}\n\t\t\t\telse if (engaged && other.engaged)\n\t\t\t\t{\n\t\t\t\t\t*get_value_address() = eastl::move(*other.get_value_address());\n\t\t\t\t\t// note, standard specifies: other.has_value() is unchanged.\n\t\t\t\t}\n\t\t\t\telse if (!engaged && other.engaged)\n\t\t\t\t{\n\t\t\t\t\tconstruct_value(eastl::move(*other.get_value_address()));\n\t\t\t\t\tengaged = true;\n\t\t\t\t}\n\t\t\t\t// else if (!engaged && !other.engaged)\n\t\t\t\t//\tno op\n\n#if !EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\t\treturn *this;\n#endif\n\t\t\t}\n\n\t\t\ttemplate <class... Args>\n\t\t\tinline void construct_value(Args&&... args)\n\t\t\t{\n\t\t\t\t::new (eastl::addressof(val)) value_type(eastl::forward<Args>(args)...);\n\t\t\t}\n\n\t\t\tinline EA_CONSTEXPR T* get_value_address() EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn reinterpret_cast<T*>(eastl::addressof(val));\n\t\t\t}\n\n\t\t\tinline EA_CONSTEXPR const T* get_value_address() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn reinterpret_cast<const T*>(eastl::addressof(val));\n\t\t\t}\n\n\t\t};\n\n\t} // namespace Internal\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t/// optional\n\t///\n    template <typename T>\n\tclass optional\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t: private internal::EnableVariantOptionalSpecialMemberFunctions<Internal::optional_base<T>, T>\n\t{\n\t\tusing base_type = internal::EnableVariantOptionalSpecialMemberFunctions<Internal::optional_base<T>, T>;\n#else\n\t\t: private Internal::optional_base<T>\n\t{\n\t\tusing base_type = Internal::optional_base<T>;\n#endif\n\n\t\tusing base_type::destruct_value;\n\t\tusing base_type::val;\n\t\tusing base_type::engaged;\n\t\tusing base_type::construct_value;\n\t\tusing base_type::get_value_address;\n\n\tpublic:\n\t\tusing value_type = T;\n\t\tusing value_result_type = remove_volatile_t<value_type>;\n\n\t\t// https://eel.is/c++draft/optional#optional.general-3\n\t\t// https://eel.is/c++draft/utility.arg.requirements#:Cpp17Destructible\n\t\tstatic_assert(eastl::is_destructible_v<value_type>, \"value type must be destructible\");\n\t\tstatic_assert(eastl::is_object_v<value_type>, \"value type must be destructible (non-object type is ill-formed)\");\n\t\tstatic_assert(!eastl::is_array_v<value_type>, \"value type must be destructible (array type is ill-formed)\");\n\t\tstatic_assert(!eastl::is_same<remove_cv_t<value_type>, in_place_t>::value, \"eastl::optional of a in_place_t type is ill-formed\");\n\t\tstatic_assert(!eastl::is_same<remove_cv_t<value_type>, nullopt_t>::value, \"eastl::optional of a nullopt_t type is ill-formed\");\n\n\t\tinline EA_CONSTEXPR optional() EA_NOEXCEPT {}\n\t\tinline EA_CONSTEXPR optional(nullopt_t) EA_NOEXCEPT {}\n\n#if !EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tinline EA_CONSTEXPR optional(const value_type& value)\n\t\t{\n\t\t\tconstruct_value(value);\n\t\t\tengaged = true;\n\t\t}\n\n\t\tinline EA_CONSTEXPR optional(value_type&& value) EA_NOEXCEPT_IF(eastl::is_nothrow_move_constructible_v<T>)\n\t\t{\n\t\t\tconstruct_value(eastl::move(value));\n\t\t\tengaged = true;\n\t\t}\n#endif\n\n\t\t// implemented by EnableVariantOptionalSpecialMemberFunctions<...>\n\t\toptional(const optional&) = default;\n\t\toptional(optional&&) = default;\n\n\t\t// converting copy constructor, explicit version\n\t\ttemplate<typename U,\n\t\t\teastl::enable_if_t<is_constructible_v<T, const U&> && (is_same_v<eastl::remove_cv_t<T>, bool> || !Internal::converts_from_any_cvref_v<T, optional<U>>) &&\n\t\t\t!is_convertible_v<const U&, T>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR explicit optional(const optional<U>& other)\n\t\t{\n\t\t\tif (other)\n\t\t\t{\n\t\t\t\tconstruct_value(*other);\n\t\t\t\tengaged = true;\n\t\t\t}\n\t\t}\n\n\t\t// converting copy constructor, non-explicit version\n\t\ttemplate<typename U,\n\t\t\teastl::enable_if_t<is_constructible_v<T, const U&> && (is_same_v<eastl::remove_cv_t<T>, bool> || !Internal::converts_from_any_cvref_v<T, optional<U>>) &&\n\t\t\tis_convertible_v<const U&, T>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR optional(const optional<U>& other)\n\t\t{\n\t\t\tif (other)\n\t\t\t{\n\t\t\t\tconstruct_value(*other);\n\t\t\t\tengaged = true;\n\t\t\t}\n\t\t}\n\n\t\t// converting move constructor, explicit version\n\t\ttemplate<typename U,\n\t\t\teastl::enable_if_t<is_constructible_v<T, U> && (is_same_v<eastl::remove_cv_t<T>, bool> || !Internal::converts_from_any_cvref_v<T, optional<U>>) &&\n\t\t\t!is_convertible_v<U, T>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR explicit optional(optional<U>&& other)\n\t\t{\n\t\t\tif (other)\n\t\t\t{\n\t\t\t\tconstruct_value(eastl::move(*other));\n\t\t\t\tengaged = true;\n\t\t\t\t// note, standard specifies: other.has_value() is unchanged.\n\t\t\t}\n\t\t}\n\n\t\t// converting move constructor, non-explicit version\n\t\ttemplate<typename U,\n\t\t\teastl::enable_if_t<is_constructible_v<T, U> && (is_same_v<eastl::remove_cv_t<T>, bool> || !Internal::converts_from_any_cvref_v<T, optional<U>>) &&\n\t\t\tis_convertible_v<U, T>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR explicit optional(optional<U>&& other)\n\t\t{\n\t\t\tif (other)\n\t\t\t{\n\t\t\t\tconstruct_value(eastl::move(*other));\n\t\t\t\tengaged = true;\n\t\t\t\t// note, standard specifies: other.has_value() is unchanged.\n\t\t\t}\n\t\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\ttemplate <typename... Args,\n\t\t\teastl::enable_if_t<eastl::is_constructible_v<T, Args...>, bool> = true>\n#else\n\t\ttemplate <typename... Args>\n#endif\n\t\tinline EA_CONSTEXPR explicit optional(in_place_t, Args&&... args)\n\t\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\tconstruct_value(eastl::forward<Args>(args)...);\n#else\n\t\t\t// value_type{ ... } is direct-list-initialization, which permits aggregate initialization.\n\t\t\t// that's not allowed by the standard; it's meant to be direct-non-list-initialization (which is what construct_value() implements).\n\t\t\t// this block (and omitting the is_constructible_v requirement) is to deprecate incorrect usage.\n\t\t\t::new (eastl::addressof(val)) value_type{ eastl::forward<Args>(args)... };\n#endif\n\t\t\tengaged = true;\n\t\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\ttemplate <typename U, typename... Args,\n\t\t\teastl::enable_if_t<eastl::is_constructible_v<T, std::initializer_list<U>&, Args...>, bool> = true>\n#else\n\t\ttemplate <typename U, typename... Args>\n#endif\n\t\tinline EA_CONSTEXPR explicit optional(in_place_t, std::initializer_list<U> ilist, Args&&... args)\n\t\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\tconstruct_value(ilist, eastl::forward<Args>(args)...);\n#else\n\t\t\t// value_type{ ... } is direct-list-initialization, which permits aggregate initialization.\n\t\t\t// that's not allowed by the standard; it's meant to be direct-non-list-initialization (which is what construct_value() implements).\n\t\t\t// this block (and omitting the is_constructible_v requirement) is to deprecate incorrect usage.\n\t\t\t::new (eastl::addressof(val)) value_type{ ilist, eastl::forward<Args>(args)... };\n#endif\n\t\t\tengaged = true;\n\t\t}\n\n\t\t// constructs an optional that contains a value, explicit version\n\t\ttemplate <typename U = T,\n\t\t\teastl::enable_if_t<eastl::is_constructible_v<T, U&&> &&\n\t\t\t!eastl::is_same_v<eastl::remove_cvref_t<U>, eastl::in_place_t> &&\n\t\t\t!eastl::is_same_v<eastl::remove_cvref_t<U>, optional<T>> &&\n\t\t\t(!eastl::is_same_v<eastl::remove_cv_t<T>, bool> || !Internal::is_specialization_of_optional_v<eastl::remove_cvref_t<U>>) &&\n\t\t\t!eastl::is_convertible_v<U&&, T>,\n\t\t\tbool> = true>\n\t\tinline explicit EA_CONSTEXPR optional(U&& value)\n\t\t{\n\t\t\tconstruct_value(eastl::forward<U>(value));\n\t\t\tengaged = true;\n\t\t}\n\n\t\t// constructs an optional that contains a value, non-explicit version\n\t\ttemplate <typename U = T,\n\t\t\teastl::enable_if_t<eastl::is_constructible_v<T, U&&> &&\n\t\t\t!eastl::is_same_v<eastl::remove_cvref_t<U>, eastl::in_place_t> &&\n\t\t\t!eastl::is_same_v<eastl::remove_cvref_t<U>, optional<T>> &&\n\t\t\t(!eastl::is_same_v<eastl::remove_cv_t<T>, bool> || !Internal::is_specialization_of_optional_v<eastl::remove_cvref_t<U>>) &&\n\t\t\teastl::is_convertible_v<U&&, T>,\n\t\t\tbool> = true>\n\t\tinline EA_CONSTEXPR optional(U&& value)\n\t\t{\n\t\t\tconstruct_value(eastl::forward<U>(value));\n\t\t\tengaged = true;\n\t\t}\n\n\t\tinline EA_CPP20_CONSTEXPR optional& operator=(nullopt_t) EA_NOEXCEPT\n\t\t{\n\t\t\treset();\n\t\t\treturn *this;\n\t\t}\n\n\t\t// implemented by EnableVariantOptionalSpecialMemberFunctions<...>\n\t\toptional& operator=(const optional&) = default;\n\t\toptional& operator=(optional&&) = default;\n\n\t\t// converting copy assignment\n\t\ttemplate<typename U,\n\t\t\teastl::enable_if_t<is_constructible_v<T, const U&> && is_assignable_v<T&, const U&> && !Internal::converts_from_any_cvref_v<T, optional<U>> &&\n\t\t\t!is_assignable_v<T&, optional<U>&> && !is_assignable_v<T&, optional<U>&&> && !is_assignable_v<T&, const optional<U>&> && !is_assignable_v<T&, const optional<U>&&>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR optional& operator=(const optional<U>& other)\n\t\t{\n\t\t\tif (engaged && other.engaged)\n\t\t\t{\n\t\t\t\t*get_value_address() = *other;\n\t\t\t}\n\t\t\telse if (engaged && !other.engaged)\n\t\t\t{\n\t\t\t\tdestruct_value();\n\t\t\t\tengaged = false;\n\t\t\t}\n\t\t\telse if (!engaged && other.engaged)\n\t\t\t{\n\t\t\t\tconstruct_value(*other);\n\t\t\t\tengaged = true;\n\t\t\t}\n\t\t\t// else if (!engaged && !other.engaged)\n\t\t\t//\tno op\n\n\t\t\treturn *this;\n\t\t}\n\n\t\t// converting move assignment\n\t\ttemplate<typename U,\n\t\t\teastl::enable_if_t<is_constructible_v<T, U> && is_assignable_v<T&, U> && !Internal::converts_from_any_cvref_v<T, optional<U>> &&\n\t\t\t!is_assignable_v<T&, optional<U>&> && !is_assignable_v<T&, optional<U>&&> && !is_assignable_v<T&, const optional<U>&> && !is_assignable_v<T&, const optional<U>&&>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR optional& operator=(optional<U>&& other)\n\t\t{\n\t\t\tif (engaged && other.engaged)\n\t\t\t{\n\t\t\t\t*get_value_address() = eastl::move(*other);\n\t\t\t\t// note, standard specifies: other.has_value() is unchanged.\n\t\t\t}\n\t\t\telse if (engaged && !other.engaged)\n\t\t\t{\n\t\t\t\tdestruct_value();\n\t\t\t\tengaged = false;\n\t\t\t}\n\t\t\telse if (!engaged && other.engaged)\n\t\t\t{\n\t\t\t\tconstruct_value(eastl::move(*other));\n\t\t\t\tengaged = true;\n\t\t\t}\n\t\t\t//else if (!engaged && !other.engaged)\n\t\t\t//\tno op\n\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <class U = T, typename eastl::enable_if_t<\n\t\t\t!eastl::is_same_v<eastl::remove_cvref_t<U>, optional<T>>&&\n\t\t\teastl::is_constructible_v<T, U>&&\n\t\t\teastl::is_assignable_v<T&, U> && (!eastl::is_scalar_v<T> || !eastl::is_same_v<eastl::decay_t<U>, T>), bool> = true>\n\t\tinline EA_CPP20_CONSTEXPR optional& operator=(U&& u)\n\t\t{\n\t\t\tif (engaged)\n\t\t\t{\n\t\t\t\t*get_value_address() = eastl::forward<U>(u);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconstruct_value(eastl::forward<U>(u));\n\t\t\t\tengaged = true;\n\t\t\t}\n\n\t\t\treturn *this;\n\t\t}\n\n\t    EA_CONSTEXPR inline explicit operator bool() const EA_NOEXCEPT { return engaged; }\n\n\t\tEA_CONSTEXPR inline bool has_value() const EA_NOEXCEPT { return engaged; }\n\n\t    template <class U>\n\t    inline EA_CONSTEXPR value_result_type value_or(U&& default_value) const&\n\t\t\t{ return engaged ? value() : static_cast<value_type>(eastl::forward<U>(default_value)); }\n\n\t    template <class U>\n\t    inline EA_CONSTEXPR value_result_type value_or(U&& default_value) &&\n\t\t\t{ return engaged ? eastl::move(value()) : static_cast<value_type>(eastl::forward<U>(default_value)); }\n\n\t\tinline EA_CONSTEXPR T& value()&\n\t\t{\n\t\t\tif (!engaged)\n\t\t\t\tEASTL_THROW_OR_ASSERT(bad_optional_access, \"no value to retrieve\");\n\t\t\treturn *get_value_address();\n\t\t}\n\n\t\tinline EA_CONSTEXPR const T& value() const&\n\t\t{\n\t\t\tif (!engaged)\n\t\t\t\tEASTL_THROW_OR_ASSERT(bad_optional_access, \"no value to retrieve\");\n\t\t\treturn *get_value_address();\n\t\t}\n\n\t\tinline EA_CONSTEXPR T&& value()&&\n\t\t{\n\t\t\tif (!engaged)\n\t\t\t\tEASTL_THROW_OR_ASSERT(bad_optional_access, \"no value to retrieve\");\n\t\t\treturn eastl::move(*get_value_address());\n\t\t}\n\n\t\tinline EA_CONSTEXPR const T&& value() const&&\n\t\t{\n\t\t\tif (!engaged)\n\t\t\t\tEASTL_THROW_OR_ASSERT(bad_optional_access, \"no value to retrieve\");\n\t\t\treturn eastl::move(*get_value_address());\n\t\t}\n\n\t\t// These all assume has_value() is true. Otherwise, calling them is UB (as per the\n\t\t// standard).  When asserts are enabled, we've decided to assert the precondition\n\t\t// similar to what would be done in a hardened library implementation.\n\t\tinline EA_CONSTEXPR T* operator->() EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(), \"Pre-condition failed! Accessing an optional without a value.\");\n\t\t\treturn get_value_address();\n\t\t}\n\t\tinline EA_CONSTEXPR const T* operator->() const EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(), \"Pre-condition failed! Accessing an optional without a value.\");\n\t\t\treturn get_value_address();\n\t\t}\n\t\tinline EA_CONSTEXPR T& operator*() & EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(), \"Pre-condition failed! Accessing an optional without a value.\");\n\t\t\treturn *get_value_address();\n\t\t}\n\t\tinline EA_CONSTEXPR T&& operator*() && EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(), \"Pre-condition failed! Accessing an optional without a value.\");\n\t\t\treturn eastl::move(*get_value_address());\n\t\t}\n\t\tinline EA_CONSTEXPR const T& operator*() const& EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(), \"Pre-condition failed! Accessing an optional without a value.\");\n\t\t\treturn *get_value_address();\n\t\t}\n\t\tinline EA_CONSTEXPR const T&& operator*() const&& EA_NOEXCEPT\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(has_value(), \"Pre-condition failed! Accessing an optional without a value.\");\n\t\t\treturn eastl::move(*get_value_address());\n\t\t}\n\n\t\t// Monadic operations\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto and_then(F&& f) &\n\t\t{\n\t\t\tusing U = eastl::invoke_result_t<F, decltype(value())>;\n\t\t\tstatic_assert(Internal::is_optional_v<eastl::remove_cvref_t<U>>,\n\t\t\t\t\t\t  \"The supplied callable isn't returning an optional.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), value());\n\t\t\t}\n\n\t\t\treturn eastl::remove_cvref_t<U>();\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto and_then(F&& f) const&\n\t\t{\n\t\t\tusing U = eastl::invoke_result_t<F, decltype(value())>;\n\t\t\tstatic_assert(Internal::is_optional_v<eastl::remove_cvref_t<U>>,\n\t\t\t\t\t\t  \"The supplied callable isn't returning an optional.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), value());\n\t\t\t}\n\n\t\t\treturn eastl::remove_cvref_t<U>();\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto and_then(F&& f) &&\n\t\t{\n\t\t\tusing U = eastl::invoke_result_t<F, decltype(eastl::move(value()))>;\n\t\t\tstatic_assert(Internal::is_optional_v<eastl::remove_cvref_t<U>>,\n\t\t\t\t\t\t  \"The supplied callable isn't returning an optional.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(value()));\n\t\t\t}\n\n\t\t\treturn eastl::remove_cvref_t<U>();\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto and_then(F&& f) const&&\n\t\t{\n\t\t\tusing U = eastl::invoke_result_t<F, decltype(eastl::move(value()))>;\n\t\t\tstatic_assert(Internal::is_optional_v<eastl::remove_cvref_t<U>>,\n\t\t\t\t\t\t  \"The supplied callable isn't returning an optional.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<F>(f), eastl::move(value()));\n\t\t\t}\n\n\t\t\treturn eastl::remove_cvref_t<U>();\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto transform(F&& f) &\n\t\t{\n\t\t\tusing U = eastl::remove_cvref_t<eastl::invoke_result_t<F, decltype(value())>>;\n\n\t\t\tstatic_assert(!eastl::is_same_v<U, in_place_t>, \"The supplied callable cannot return in_place_t.\");\n\t\t\tstatic_assert(!eastl::is_same_v<U, nullopt_t>, \"The supplied callable cannot return nullopt_t.\");\n\t\t\tstatic_assert(eastl::is_object_v<U>, \"The supplied callable must return an object type.\");\n\t\t\tstatic_assert(!eastl::is_array_v<U>, \"The supplied callable cannot return an array type.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::optional<U>(eastl::invoke(eastl::forward<F>(f), value()));\n\t\t\t}\n\n\t\t\treturn eastl::optional<U>();\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto transform(F&& f) const&\n\t\t{\n\t\t\tusing U = eastl::remove_cvref_t<eastl::invoke_result_t<F, decltype(value())>>;\n\n\t\t\tstatic_assert(!eastl::is_same_v<U, in_place_t>, \"The supplied callable cannot return in_place_t.\");\n\t\t\tstatic_assert(!eastl::is_same_v<U, nullopt_t>, \"The supplied callable cannot return nullopt_t.\");\n\t\t\tstatic_assert(eastl::is_object_v<U>, \"The supplied callable must return an object type.\");\n\t\t\tstatic_assert(!eastl::is_array_v<U>, \"The supplied callable cannot return an array type.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::optional<U>(eastl::invoke(eastl::forward<F>(f), value()));\n\t\t\t}\n\n\t\t\treturn eastl::optional<U>();\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto transform(F&& f) &&\n\t\t{\n\t\t\tusing U = eastl::remove_cvref_t<eastl::invoke_result_t<F, decltype(eastl::move(value()))>>;\n\n\t\t\tstatic_assert(!eastl::is_same_v<U, in_place_t>, \"The supplied callable cannot return in_place_t.\");\n\t\t\tstatic_assert(!eastl::is_same_v<U, nullopt_t>, \"The supplied callable cannot return nullopt_t.\");\n\t\t\tstatic_assert(eastl::is_object_v<U>, \"The supplied callable must return an object type.\");\n\t\t\tstatic_assert(!eastl::is_array_v<U>, \"The supplied callable cannot return an array type.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::optional<U>(eastl::invoke(eastl::forward<F>(f), eastl::move(value())));\n\t\t\t}\n\n\t\t\treturn eastl::optional<U>();\n\t\t}\n\n\t\ttemplate <typename F>\n\t\tconstexpr inline auto transform(F&& f) const&&\n\t\t{\n\t\t\tusing U = eastl::remove_cvref_t<eastl::invoke_result_t<F, decltype(eastl::move(value()))>>;\n\n\t\t\tstatic_assert(!eastl::is_same_v<U, in_place_t>, \"The supplied callable cannot return in_place_t.\");\n\t\t\tstatic_assert(!eastl::is_same_v<U, nullopt_t>, \"The supplied callable cannot return nullopt_t.\");\n\t\t\tstatic_assert(eastl::is_object_v<U>, \"The supplied callable must return an object type.\");\n\t\t\tstatic_assert(!eastl::is_array_v<U>, \"The supplied callable cannot return an array type.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::optional<U>(eastl::invoke(eastl::forward<F>(f), eastl::move(value())));\n\t\t\t}\n\n\t\t\treturn eastl::optional<U>();\n\t\t}\n\n\t\ttemplate <typename F, enable_if_t<is_invocable_v<F> && internal::concepts::copy_constructible<T>, int> = 0>\n\t\tconstexpr inline optional or_else(F&& f) const&\n\t\t{\n\t\t\tstatic_assert(eastl::is_same_v<eastl::remove_cvref_t<eastl::invoke_result_t<F>>, optional>,\n\t\t\t\t\t\t  \"The supplied callable must return an optional of the same type.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn *this;\n\t\t\t}\n\n\t\t\treturn eastl::forward<F>(f)();\n\t\t}\n\n\t\ttemplate <typename F, enable_if_t<is_invocable_v<F> && internal::concepts::move_constructible<T>, int> = 0>\n\t\tconstexpr inline optional or_else(F&& f) &&\n\t\t{\n\t\t\tstatic_assert(eastl::is_same_v<eastl::remove_cvref_t<eastl::invoke_result_t<F>>, optional>,\n\t\t\t\t\t\t  \"The supplied callable must return an optional of the same type.\");\n\n\t\t\tif (has_value())\n\t\t\t{\n\t\t\t\treturn eastl::move(*this);\n\t\t\t}\n\n\t\t\treturn eastl::forward<F>(f)();\n\t\t}\n\n\t\ttemplate <class... Args>\n\t\tEA_CPP20_CONSTEXPR T& emplace(Args&&... args)\n\t\t{\n\t\t\tif (engaged)\n\t\t\t{\n\t\t\t\tdestruct_value();\n\t\t\t\tengaged = false;\n\t\t\t}\n\t\t\tconstruct_value(eastl::forward<Args>(args)...);\n\t\t\tengaged = true;\n\t\t\treturn *get_value_address();\n\t\t}\n\n\t\ttemplate <class U, class... Args>\n\t\tEA_CPP20_CONSTEXPR T& emplace(std::initializer_list<U> ilist, Args&&... args)\n\t\t{\n\t\t\tif (engaged)\n\t\t\t{\n\t\t\t\tdestruct_value();\n\t\t\t\tengaged = false;\n\t\t\t}\n\t\t\tconstruct_value(ilist, eastl::forward<Args>(args)...);\n\t\t\tengaged = true;\n\t\t\treturn *get_value_address();\n\t\t}\n\n\t    inline EA_CPP20_CONSTEXPR void swap(optional& other)\n\t        EA_NOEXCEPT_IF(eastl::is_nothrow_move_constructible<T>::value && eastl::is_nothrow_swappable<T>::value)\n\t    {\n\t\t\tif (!engaged && other.engaged)\n\t\t\t{\n\t\t\t\tconstruct_value(eastl::move(*other.get_value_address()));\n\t\t\t\tother.destruct_value();\n\t\t\t\tengaged = true;\n\t\t\t\tother.engaged = false;\n\t\t\t}\n\t\t\telse if (engaged && !other.engaged)\n\t\t\t{\n\t\t\t\tother.construct_value(eastl::move(*get_value_address()));\n\t\t\t\tdestruct_value();\n\t\t\t\tengaged = false;\n\t\t\t\tother.engaged = true;\n\t\t\t}\n\t\t\telse if (engaged && other.engaged)\n\t\t\t{\n\t\t\t\tusing eastl::swap;\n\t\t\t\tswap(**this, *other);\n\t\t\t}\n\t\t\t//else if (!engaged && !other.engaged)\n\t\t\t//\tno op\n\t    }\n\n\t\tinline EA_CPP20_CONSTEXPR void reset() EA_NOEXCEPT\n\t\t{\n\t\t\tif (engaged)\n\t\t\t{\n\t\t\t\tdestruct_value();\n\t\t\t\tengaged = false;\n\t\t\t}\n\t\t}\n\n    }; // class optional\n\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t/// global swap\n\t///\n    template <class T>\n    void swap(optional<T>& lhs, optional<T>& rhs) EA_NOEXCEPT_IF(EA_NOEXCEPT(lhs.swap(rhs)))\n\t\t{ lhs.swap(rhs); }\n\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t/// global comparisions\n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/optional/operator_cmp\n\t///\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t// Compare two optional objects\n\t//\n\ttemplate <class T>\n\tinline EA_CONSTEXPR bool operator==(const optional<T>& lhs, const optional<T>& rhs)\n\t{\n\t\treturn (bool(lhs) != bool(rhs)) ? false : (bool(lhs) == false) ? true : *lhs == *rhs;\n\t}\n\n\ttemplate <class T>\n\tinline EA_CONSTEXPR bool operator<(const optional<T>& lhs, const optional<T>& rhs)\n\t{\n\t    return (!bool(rhs)) ? false : (!bool(lhs)) ? true : *lhs < *rhs;\n    }\n\n    template <class T>\n\tinline EA_CONSTEXPR bool operator!=(const optional<T>& lhs, const optional<T>& rhs)\n\t\t{ return !(lhs == rhs); }\n\n\ttemplate <class T>\n\tinline EA_CONSTEXPR bool operator<=(const optional<T>& lhs, const optional<T>& rhs)\n\t\t{ return !(rhs < lhs); }\n\n\ttemplate <class T>\n\tinline EA_CONSTEXPR bool operator>(const optional<T>& lhs, const optional<T>& rhs)\n\t\t{ return rhs < lhs; }\n\n\ttemplate <class T>\n\tinline EA_CONSTEXPR bool operator>=(const optional<T>& lhs, const optional<T>& rhs)\n\t\t{ return !(lhs < rhs);\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <class T, class U=T> requires std::three_way_comparable_with<T, U>\n\tinline EA_CONSTEXPR std::compare_three_way_result_t<T, U> operator<=>(const optional<T>& lhs, const optional<U>& rhs)\n\t\t{\n\t\t    if (lhs && rhs)\n\t\t    {\n\t\t        return *lhs <=> *rhs;\n\t\t    }\n\t\t    return lhs.has_value() <=> rhs.has_value();\n\t\t}\n#endif\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t// Compare an optional object with a nullopt\n\t//\n    template <class T>\n    inline EA_CONSTEXPR bool operator==(const optional<T>& opt, eastl::nullopt_t) EA_NOEXCEPT\n\t\t{ return !opt; }\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n    template <class T>\n    inline EA_CONSTEXPR std::strong_ordering operator<=>(const optional<T>& opt, eastl::nullopt_t) EA_NOEXCEPT\n\t\t{ return opt.has_value() <=> false; }\n#else\n    template <class T>\n    inline EA_CONSTEXPR bool operator==(eastl::nullopt_t, const optional<T>& opt) EA_NOEXCEPT\n\t\t{ return !opt; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator!=(const optional<T>& opt, eastl::nullopt_t) EA_NOEXCEPT\n\t\t{ return bool(opt); }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator!=(eastl::nullopt_t, const optional<T>& opt) EA_NOEXCEPT\n\t\t{ return bool(opt); }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<(const optional<T>&, eastl::nullopt_t) EA_NOEXCEPT\n\t\t{ return false; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<(eastl::nullopt_t, const optional<T>& opt) EA_NOEXCEPT\n\t\t{ return bool(opt); }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<=(const optional<T>& opt, eastl::nullopt_t) EA_NOEXCEPT\n\t\t{ return !opt; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<=(eastl::nullopt_t, const optional<T>&) EA_NOEXCEPT\n\t\t{ return true; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>(const optional<T>& opt, eastl::nullopt_t) EA_NOEXCEPT\n\t\t{ return bool(opt); }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>(eastl::nullopt_t, const optional<T>&) EA_NOEXCEPT\n\t\t{ return false; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>=(const optional<T>&, eastl::nullopt_t) EA_NOEXCEPT\n\t\t{ return true; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>=(eastl::nullopt_t, const optional<T>& opt) EA_NOEXCEPT\n\t\t{ return !opt; }\n#endif\n\n    ///////////////////////////////////////////////////////////////////////////////\n    // Compare an optional object with a T\n\t//\n    template <class T>\n    inline EA_CONSTEXPR bool operator==(const optional<T>& opt, const T& value)\n\t\t{ return bool(opt) ? *opt == value : false; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator==(const T& value, const optional<T>& opt)\n\t\t{ return bool(opt) ? value == *opt : false; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator!=(const optional<T>& opt, const T& value)\n\t\t{ return bool(opt) ? !(*opt == value) : true; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator!=(const T& value, const optional<T>& opt)\n\t\t{ return bool(opt) ? !(value == *opt) : true; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<(const optional<T>& opt, const T& value)\n\t\t{ return bool(opt) ? *opt < value  : true; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<(const T& value, const optional<T>& opt)\n\t\t{ return bool(opt) ? value < *opt  : false;  }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<=(const optional<T>& opt, const T& value)\n\t\t{ return !(opt > value); }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator<=(const T& value, const optional<T>& opt)\n\t\t{ return !(value > opt); }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>(const optional<T>& opt, const T& value)\n\t\t{ return bool(opt) ? value < *opt  : false; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>(const T& value, const optional<T>& opt)\n\t\t{ return bool(opt) ? *opt < value  : true; }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>=(const optional<T>& opt, const T& value)\n\t\t{ return !(opt < value); }\n\n    template <class T>\n    inline EA_CONSTEXPR bool operator>=(const T& value, const optional<T>& opt)\n\t\t{ return !(value < opt);  }\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n    template <class T, class U=T> requires std::three_way_comparable_with<T, U>\n    inline EA_CONSTEXPR std::compare_three_way_result_t<T, U> operator<=>(const optional<T>& opt, const U& value)\n\t\t{ return (opt.has_value()) ? *opt <=> value : std::strong_ordering::less; }\n#endif\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t/// hash\n\t///\n\ttemplate <typename T>\n\tstruct hash<eastl::optional<T>>\n\t{\n\t\tsize_t operator()(const eastl::optional<T>& opt) const EA_NOEXCEPT\n\t    {\n\t\t    if (opt)\n\t\t\t    return eastl::hash<T>()(*opt);\n\t\t    else\n\t\t\t    return 0;  // no value to generate a hash from\n\t    }\n    };\n\n\n    ///////////////////////////////////////////////////////////////////////////////\n\t/// make_optional\n\t///\n\ttemplate <class T>\n\tinline EA_CONSTEXPR optional<decay_t<T>> make_optional(T&& value)\n\t{\n\t\treturn optional<decay_t<T>>(eastl::forward<T>(value));\n\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\ttemplate <class T, class... Args, enable_if_t<is_constructible_v<T, Args...>, bool> = true>\n#else\n\ttemplate <class T, class... Args>\n#endif\n\tinline EA_CONSTEXPR optional<T> make_optional(Args&&... args)\n\t{\n\t\treturn optional<T>(eastl::in_place, eastl::forward<Args>(args)...);\n\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\ttemplate <class T, class U, class... Args, enable_if_t<is_constructible_v<T, std::initializer_list<U>&, Args...>, bool> = true>\n#else\n\ttemplate <class T, class U, class... Args>\n#endif\n\tinline EA_CONSTEXPR optional<T> make_optional(std::initializer_list<U> il, Args&&... args)\n\t{\n\t\treturn eastl::optional<T>(eastl::in_place, il, eastl::forward<Args>(args)...);\n\t}\n\n#ifdef __cpp_deduction_guides\n\ttemplate<typename T>\n\toptional(T) -> optional<T>;\n#endif\n\n}  // namespace eastl\n\nEA_RESTORE_VC_WARNING()\n\n#endif  // EASTL_OPTIONAL_ENABLED\n#endif  // EASTL_OPTIONAL_H\n"
  },
  {
    "path": "include/EASTL/priority_queue.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a priority_queue that is just like the C++ \n// std::priority_queue adapter class, except it has a couple extension functions.\n// The primary distinctions between this priority_queue and std::priority_queue are:\n//    - priority_queue has a couple extension functions that allow you to \n//      use a priority queue in extra ways. See the code for documentation.\n//    - priority_queue can contain objects with alignment requirements. \n//      std::priority_queue cannot do so without a bit of tedious non-portable effort.\n//    - priority_queue supports debug memory naming natively.\n//    - priority_queue is easier to read, debug, and visualize.\n//    - priority_queue is savvy to an environment that doesn't have exception handling,\n//      as is sometimes the case with console or embedded environments.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_PRIORITY_QUEUE_H\n#define EASTL_PRIORITY_QUEUE_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/vector.h>\n#include <EASTL/heap.h>\n#include <EASTL/functional.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\nEA_DISABLE_VC_WARNING(4530 4571);\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_PRIORITY_QUEUE_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_PRIORITY_QUEUE_DEFAULT_NAME\n\t\t#define EASTL_PRIORITY_QUEUE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" priority_queue\" // Unless the user overrides something, this is \"EASTL priority_queue\".\n\t#endif\n\n\t/// EASTL_PRIORITY_QUEUE_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_PRIORITY_QUEUE_DEFAULT_ALLOCATOR\n\t\t#define EASTL_PRIORITY_QUEUE_DEFAULT_ALLOCATOR allocator_type(EASTL_PRIORITY_QUEUE_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// priority_queue\n\t///\n\t/// The behaviour of this class is just like the std::priority_queue\n\t/// class and you can refer to std documentation on it.\n\t///\n\t/// A priority_queue is an adapter container which implements a\n\t/// queue-like container whereby pop() returns the item of highest\n\t/// priority. The entire queue isn't necessarily sorted; merely the \n\t/// first item in the queue happens to be of higher priority than \n\t/// other items. You can read about priority_queues in many books\n\t/// on algorithms, such as \"Algorithms\" by Robert Sedgewick.\n\t///\n\t/// The Container type is a container which is random access and \n\t/// supports empty(), size(), clear(), insert(), front(), \n\t/// push_back(), and pop_back(). You would typically use vector\n\t/// or deque.\n\t/// \n\t/// Note that we don't provide functions in the priority_queue \n\t/// interface for working with allocators or names. The reason for \n\t/// this is that priority_queue is an adapter class which can work\n\t/// with any standard sequence and not necessarily just a sequence \n\t/// provided by this library. So what we do is provide a member \n\t/// accessor function get_container() which allows the user to \n\t/// manipulate the sequence as needed. The user needs to be careful\n\t/// not to change the container's contents, however.\n\t///\n\t/// Classic heaps allow for the concept of removing arbitrary items\n\t/// and changing the priority of arbitrary items, though the C++\n\t/// std heap (and thus priority_queue) functions don't support \n\t/// these operations. We have extended the heap algorithms and the \n\t/// priority_queue implementation to support these operations.\n\t///\n\t///////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container = eastl::vector<T>, typename Compare = eastl::less<typename Container::value_type> >\n\tclass priority_queue\n\t{\n\tpublic:\n\t\ttypedef priority_queue<T, Container, Compare>        this_type;\n\t\ttypedef Container                                    container_type;\n\t\ttypedef Compare                                      compare_type;\n\t  //typedef typename Container::allocator_type           allocator_type;  // We can't currently declare this because the container may be a type that doesn't have an allocator. \n\t\ttypedef typename Container::value_type               value_type;\n\t\ttypedef typename Container::reference                reference;\n\t\ttypedef typename Container::const_reference          const_reference;\n\t\ttypedef typename Container::size_type                size_type;\n\t\ttypedef typename Container::difference_type          difference_type;\n\n\tpublic:                   // We declare public so that global comparison operators can be implemented without adding an inline level and without tripping up GCC 2.x friend declaration failures. GCC (through at least v4.0) is poor at inlining and performance wins over correctness.\n\t\tcontainer_type  c;    // The C++ standard specifies that you declare a protected member variable of type Container called 'c'.\n\t\tcompare_type    comp; // The C++ standard specifies that you declare a protected member variable of type Compare called 'comp'.\n\n\tpublic:\n\t\tpriority_queue();\n\n\t\t// Allocator is templated here because we aren't allowed to infer the allocator_type from the Container, as some containers (e.g. array) don't \n\t\t// have allocators. For containers that don't have allocator types, you could use void or char as the Allocator template type.\n\n\t\ttemplate <class Allocator>                      \n\t\texplicit priority_queue(const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t   : c(allocator), comp()\n\t\t{\n\t\t}    \n\n\t\ttemplate <class Allocator>\n\t\tpriority_queue(const this_type& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t\t: c(x.c, allocator), comp(x.comp)\n\t\t{\n\t\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t\t}\n\n\t\ttemplate <class Allocator>\n\t\tpriority_queue(this_type&& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t\t: c(eastl::move(x.c), allocator), comp(x.comp)\n\t\t{\n\t\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t\t}\n\n\t\texplicit priority_queue(const compare_type& compare);\n\t\texplicit priority_queue(const compare_type& compare, container_type&& x);\n\n\t\tpriority_queue(const compare_type& compare, const container_type& x);\n\t\tpriority_queue(std::initializer_list<value_type> ilist, const compare_type& compare = compare_type()); // C++11 doesn't specify that std::priority_queue has initializer list support.\n\n\t\ttemplate <typename InputIterator>\n\t\tpriority_queue(InputIterator first, InputIterator last);\n\n\t\ttemplate <typename InputIterator>\n\t\tpriority_queue(InputIterator first, InputIterator last, const compare_type& compare);\n\n\t\ttemplate <typename InputIterator>\n\t\tpriority_queue(InputIterator first, InputIterator last, const compare_type& compare, const container_type& x);\n\n\t\ttemplate <class InputIterator>\n\t\tpriority_queue(InputIterator first, InputIterator last, const compare_type& compare, container_type&& x);\n\n\t\t// Additional C++11 support to consider:\n\t\t//\n\t\t// template <class Allocator>\n\t\t// priority_queue(const Compare&, const Allocator&);\n\t\t//\n\t\t// template <class Allocator>\n\t\t// priority_queue(const Compare&, const container_type&, const Allocator&);\n\t\t//\n\t\t// template <class Allocator>\n\t\t// priority_queue(const Compare&, container_type&&, const Allocator&);\n\t\t//\n\t\t// template <typename InputIterator, class Allocator>\n\t\t// priority_queue(InputIterator first, InputIterator last, const Allocator& allocator);\n\t\t//\n\t\t// template <typename InputIterator, class Allocator>\n\t\t// priority_queue(InputIterator first, InputIterator last, const compare_type& compare, const Allocator& allocator);\n\t\t//\n\t\t// template <typename InputIterator, class Allocator>\n\t\t// priority_queue(InputIterator first, InputIterator last, const compare_type& compare, const container_type& x, const Allocator& allocator);\n\t\t//\n\t\t// template <typename InputIterator, class Allocator>\n\t\t// priority_queue(InputIterator first, InputIterator last, const compare_type& compare, container_type&& x, const Allocator& allocator);\n\n\t\tbool      empty() const;\n\t\tsize_type size() const;\n\n\t\tconst_reference top() const;\n\n\t\tvoid push(const value_type& value);\n\n\t\tvoid push(value_type&& x);\n\n\t\ttemplate <class... Args>\n\t\tvoid emplace(Args&&... args);\n\n\t\tvoid pop();\n\n\t\tvoid pop(value_type& value);    // Extension to the C++11 Standard that allows popping a move-only type (e.g. unique_ptr).\n\n\t\tvoid change(size_type n);   /// Extension to the C++ Standard. Moves the item at the given array index to a new location based on its current priority.\n\t\tvoid remove(size_type n);   /// Extension to the C++ Standard. Removes the item at the given array index.\n\n\t\tcontainer_type&       get_container();\n\t\tconst container_type& get_container() const;\n\n\t\tvoid swap(this_type& x) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable<this_type::container_type>::value && eastl::is_nothrow_swappable<this_type::compare_type>::value));\n\t\t\n\t\tbool validate() const;\n\n\t}; // class priority_queue\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// priority_queue\n\t///////////////////////////////////////////////////////////////////////\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline priority_queue<T, Container, Compare>::priority_queue()\n\t\t: c(),  // To consider: use c(EASTL_PRIORITY_QUEUE_DEFAULT_ALLOCATOR) here, though that would add the requirement that the user supplied container support this.\n\t\t  comp()\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline priority_queue<T, Container, Compare>::priority_queue(const compare_type& compare)\n\t\t: c(),  // To consider: use c(EASTL_PRIORITY_QUEUE_DEFAULT_ALLOCATOR) here, though that would add the requirement that the user supplied container support this.\n\t\t  comp(compare)\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline priority_queue<T, Container, Compare>::priority_queue(const compare_type& compare, const container_type& x)\n\t\t: c(x), comp(compare)\n\t{\n\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline priority_queue<T, Container, Compare>::priority_queue(const compare_type& compare, container_type&& x)\n\t  : c(eastl::move(x)), comp(compare)\n\t{\n\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline priority_queue<T, Container, Compare>::priority_queue(std::initializer_list<value_type> ilist, const compare_type& compare)\n\t\t: c(), comp(compare)\n\t{\n\t\tc.insert(c.end(), ilist.begin(), ilist.end());\n\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\ttemplate <typename InputIterator>\n\tinline priority_queue<T, Container, Compare>::priority_queue(InputIterator first, InputIterator last)\n\t\t: c(first, last), comp()\n\t{\n\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\ttemplate <typename InputIterator>\n\tinline priority_queue<T, Container, Compare>::priority_queue(InputIterator first, InputIterator last, const compare_type& compare)\n\t\t: c(first, last), comp(compare)\n\t{\n\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\ttemplate <typename InputIterator>\n\tinline priority_queue<T, Container, Compare>::priority_queue(InputIterator first, InputIterator last, const compare_type& compare, const container_type& x)\n\t\t: c(x), comp(compare)\n\t{\n\t\tc.insert(c.end(), first, last);\n\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\ttemplate <typename InputIterator>\n\tinline priority_queue<T, Container, Compare>::priority_queue(InputIterator first, InputIterator last, const compare_type& compare, container_type&& x)\n\t\t: c(eastl::move(x)), comp(compare)\n\t{\n\t\tc.insert(c.end(), first, last);\n\t\teastl::make_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline bool priority_queue<T, Container, Compare>::empty() const\n\t{\n\t\treturn c.empty();\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline typename priority_queue<T, Container, Compare>::size_type\n\tpriority_queue<T, Container, Compare>::size() const\n\t{\n\t\treturn c.size();\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline typename priority_queue<T, Container, Compare>::const_reference\n\tpriority_queue<T, Container, Compare>::top() const\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"priority_queue::top -- empty container\");\n#endif\n\n\t\treturn c.front();\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline void priority_queue<T, Container, Compare>::push(const value_type& value)\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\tc.push_back(value);\n\t\t\t\teastl::push_heap(c.begin(), c.end(), comp);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tc.clear();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n\t\t\tc.push_back(value);\n\t\t\teastl::push_heap(c.begin(), c.end(), comp);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline void priority_queue<T, Container, Compare>::push(value_type&& value)\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\tc.push_back(eastl::move(value));\n\t\t\t\teastl::push_heap(c.begin(), c.end(), comp);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tc.clear();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n\t\t\tc.push_back(eastl::move(value));\n\t\t\teastl::push_heap(c.begin(), c.end(), comp);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\ttemplate <class... Args>\n\tinline void priority_queue<T, Container, Compare>::emplace(Args&&... args)\n\t{\n\t\tpush(value_type(eastl::forward<Args>(args)...)); // The C++11 Standard 23.6.4/1 states that c.emplace is used, but also declares that c doesn't need to have an emplace function.\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline void priority_queue<T, Container, Compare>::pop()\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"priority_queue::pop -- empty container\");\n#endif\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\teastl::pop_heap(c.begin(), c.end(), comp);\n\t\t\t\tc.pop_back();\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tc.clear();\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n\t\t\teastl::pop_heap(c.begin(), c.end(), comp);\n\t\t\tc.pop_back();\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline void priority_queue<T, Container, Compare>::pop(value_type& value)\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"priority_queue::pop -- empty container\");\n#endif\n\n\t\tvalue = eastl::move(c.front());  // To consider: value = move_if_noexcept_assignable(c.front());\n\t\tpop();\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline void priority_queue<T, Container, Compare>::change(size_type n) // This function is not in the STL std::priority_queue.\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(n >= c.size()))\n\t\t\tEASTL_FAIL_MSG(\"priority_queue::change -- out of range\");\n#endif\n\n\t\teastl::change_heap(c.begin(), c.size(), n, comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline void priority_queue<T, Container, Compare>::remove(size_type n) // This function is not in the STL std::priority_queue.\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(n >= c.size()))\n\t\t\tEASTL_FAIL_MSG(\"priority_queue::remove -- out of range\");\n#endif\n\n\t\teastl::remove_heap(c.begin(), c.size(), n, comp);\n\t\tc.pop_back();\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline typename priority_queue<T, Container, Compare>::container_type&\n\tpriority_queue<T, Container, Compare>::get_container()\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline const typename priority_queue<T, Container, Compare>::container_type&\n\tpriority_queue<T, Container, Compare>::get_container() const\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline void priority_queue<T, Container, Compare>::swap(this_type& x) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable<this_type::container_type>::value && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  eastl::is_nothrow_swappable<this_type::compare_type>::value))\n\t{\n\t\tusing eastl::swap;\n\t\tswap(c, x.c);\n\t\tswap(comp, x.comp);\n\t}\n\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline bool\n\tpriority_queue<T, Container, Compare>::validate() const\n\t{\n\t\treturn c.validate() && eastl::is_heap(c.begin(), c.end(), comp);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tbool operator==(const priority_queue<T, Container, Compare>& a, const priority_queue<T, Container, Compare>& b)\n\t{\n\t\treturn (a.c == b.c);\n\t}\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tbool operator<(const priority_queue<T, Container, Compare>& a, const priority_queue<T, Container, Compare>& b)\n\t{\n\t\treturn (a.c < b.c);\n\t}\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline bool operator!=(const priority_queue<T, Container, Compare>& a, const priority_queue<T, Container, Compare>& b)\n\t{\n\t\treturn !(a.c == b.c);\n\t}\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline bool operator>(const priority_queue<T, Container, Compare>& a, const priority_queue<T, Container, Compare>& b)\n\t{\n\t\treturn (b.c < a.c);\n\t}\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline bool operator<=(const priority_queue<T, Container, Compare>& a, const priority_queue<T, Container, Compare>& b)\n\t{\n\t\treturn !(b.c < a.c);\n\t}\n\n\ttemplate <typename T, typename Container, typename Compare>\n\tinline bool operator>=(const priority_queue<T, Container, Compare>& a, const priority_queue<T, Container, Compare>& b)\n\t{\n\t\treturn !(a.c < b.c);\n\t}\n\n\n\ttemplate <class T, class Container, class Compare>\n\tinline void swap(priority_queue<T, Container, Compare>& a,  priority_queue<T, Container, Compare>& b) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable<typename priority_queue<T, Container, Compare>::container_type>::value && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  eastl::is_nothrow_swappable<typename priority_queue<T, Container, Compare>::compare_type>::value)) // EDG has a bug and won't let us use Container in this noexcept statement\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/queue.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a queue that is just like the C++ std::queue adapter class.\n// There are no significant differences between EASTL/queue and std::queue.\n// We provide this class for completeness and where std STL may not be available.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_QUEUE_H\n#define EASTL_QUEUE_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/deque.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_QUEUE_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_QUEUE_DEFAULT_NAME\n\t\t#define EASTL_QUEUE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" queue\" // Unless the user overrides something, this is \"EASTL queue\".\n\t#endif\n\n\t/// EASTL_QUEUE_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_QUEUE_DEFAULT_ALLOCATOR\n\t\t#define EASTL_QUEUE_DEFAULT_ALLOCATOR allocator_type(EASTL_QUEUE_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// queue\n\t///\n\t/// queue is an adapter class provides a FIFO (first-in, first-out) interface\n\t/// via wrapping a sequence container (https://en.cppreference.com/w/cpp/named_req/SequenceContainer)\n\t/// that additionally provides:\n\t///     push_back\n\t///     pop_front\n\t///     front\n\t///     back\n\t///\n\t/// In practice this means deque, list, intrusive_list. vector and (the pseudo-container) string  \n\t/// cannot be used because they don't provide pop_front. This is reasonable because\n\t/// a vector or string pop_front would be inefficient as such an operation would have linear complexity\n\t/// (to move elements after removing the front element, maintaining ordering).\n\t///\n\ttemplate <typename T, typename Container = eastl::deque<T, EASTLAllocatorType, DEQUE_DEFAULT_SUBARRAY_SIZE(T)> >\n\tclass queue\n\t{\n\tpublic:\n\t\ttypedef queue<T, Container>                  this_type;\n\t\ttypedef          Container                   container_type;\n\t  //typedef typename Container::allocator_type   allocator_type;  // We can't currently declare this because the container may be a type that doesn't have an allocator. \n\t\ttypedef typename Container::value_type       value_type;\n\t\ttypedef typename Container::reference        reference;\n\t\ttypedef typename Container::const_reference  const_reference;\n\t\ttypedef typename Container::size_type        size_type;\n\n\tpublic:               // We declare public so that global comparison operators can be implemented without adding an inline level and without tripping up GCC 2.x friend declaration failures. GCC (through at least v4.0) is poor at inlining and performance wins over correctness.\n\t\tcontainer_type c; // The C++ standard specifies that you declare a protected member variable of type Container called 'c'.\n\n\tpublic:\n\t\tqueue();\n\n\t\t// Allocator is templated here because we aren't allowed to infer the allocator_type from the Container, as some containers (e.g. array) don't \n\t\t// have allocators. For containers that don't have allocator types, you could use void or char as the Allocator template type.\n\n\t\ttemplate <class Allocator>                      \n\t\texplicit queue(const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t  : c(allocator)\n\t\t{\n\t\t}    \n\n\t\ttemplate <class Allocator>\n\t\tqueue(const this_type& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t  : c(x.c, allocator)\n\t\t{\n\t\t}\n\n\t\ttemplate <class Allocator>\n\t\tqueue(this_type&& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t  : c(eastl::move(x.c), allocator)\n\t\t{\n\t\t}\n\n\t\texplicit queue(const container_type& x);\n\t\texplicit queue(container_type&& x);\n\n\t\t// Additional C++11 support to consider:\n\t\t//\n\t\t// template <class Allocator>\n\t\t// queue(const container_type& x, const Allocator& allocator);\n\t\t//\n\t\t// template <class Allocator>\n\t\t// queue(container_type&& x, const Allocator& allocator);\n\t\t//\n\t\t// template <class InputIt>\n\t\t// queue(InputIt first, InputIt last);\n\t\t//\n\t\t// template <class InputIt, class Allocator>\n\t\t// queue(InputIt first, InputIt last, const Allocator& allocator);\n\n\t\tqueue(std::initializer_list<value_type> ilist); // C++11 doesn't specify that std::queue has initializer list support.\n\n\t\tbool      empty() const;\n\t\tsize_type size() const;\n\n\t\treference       front();\n\t\tconst_reference front() const;\n\n\t\treference       back();\n\t\tconst_reference back() const;\n\n\t\tvoid push(const value_type& value);\n\t\tvoid push(value_type&& x);\n\n\t\ttemplate <class... Args>\n\t\tdecltype(auto) emplace(Args&&... args);\n\n\t\tvoid pop();\n\n\t\tcontainer_type&       get_container();\n\t\tconst container_type& get_container() const;\n\n\t\tvoid swap(this_type& x) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable<this_type::container_type>::value));\n\n\t\tbool validate() const;\n\n\t}; // class queue\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// queue\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container>\n\tinline queue<T, Container>::queue()\n\t\t: c() // To consider: use c(EASTL_QUEUE_DEFAULT_ALLOCATOR) here, though that would add the requirement that the user supplied container support this.\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline queue<T, Container>::queue(const Container& x)\n\t\t: c(x)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline queue<T, Container>::queue(Container&& x)\n\t\t: c(eastl::move(x))\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline queue<T, Container>::queue(std::initializer_list<value_type> ilist)\n\t\t: c() // We could alternatively use c(ilist) here, but that would require c to have an ilist constructor.\n\t{\n\t\t// Better solution but requires an insert function.\n\t\t// c.insert(ilist.begin(), ilist.end());\n\n\t\t// Possibly slower solution but doesn't require an insert function.\n\t\tfor(typename std::initializer_list<value_type>::iterator it = ilist.begin(); it != ilist.end(); ++it)\n\t\t{\n\t\t\tconst value_type& value = *it;\n\t\t\tc.push_back(value);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline bool queue<T, Container>::empty() const\n\t{\n\t\treturn c.empty();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename queue<T, Container>::size_type\n\tqueue<T, Container>::size() const\n\t{\n\t\treturn c.size();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename queue<T, Container>::reference\n\tqueue<T, Container>::front()\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"queue::front -- empty container\");\n#endif\n\n\t\treturn c.front();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename queue<T, Container>::const_reference\n\tqueue<T, Container>::front() const\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"queue::front -- empty container\");\n#endif\n\n\t\treturn c.front();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename queue<T, Container>::reference\n\tqueue<T, Container>::back()\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"queue::back -- empty container\");\n#endif\n\n\t\treturn c.back();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename queue<T, Container>::const_reference\n\tqueue<T, Container>::back() const\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"queue::back -- empty container\");\n#endif\n\n\t\treturn c.back();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline void queue<T, Container>::push(const value_type& value)\n\t{\n\t\tc.push_back(const_cast<value_type&>(value)); // const_cast so that intrusive_list can work. We may revisit this.\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline void queue<T, Container>::push(value_type&& x) \n\t{\n\t\tc.push_back(eastl::move(x));\n\t}\n\n\ttemplate <typename T, typename Container>\n\ttemplate <class... Args> \n\tinline decltype(auto) queue<T, Container>::emplace(Args&&... args)\n\t{\n\t\treturn c.emplace_back(eastl::forward<Args>(args)...);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline void queue<T, Container>::pop()\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"queue::pop -- empty container\");\n#endif\n\n\t\tc.pop_front();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename queue<T, Container>::container_type&\n\tqueue<T, Container>::get_container()\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline const typename queue<T, Container>::container_type&\n\tqueue<T, Container>::get_container() const\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tvoid queue<T, Container>::swap(this_type& x) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable<this_type::container_type>::value))\n\t{\n\t\tusing eastl::swap;\n\t\tswap(c, x.c);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tbool queue<T, Container>::validate() const\n\t{\n\t\treturn c.validate();\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator==(const queue<T, Container>& a, const queue<T, Container>& b)\n\t{\n\t\treturn (a.c == b.c);\n\t}\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Container> requires std::three_way_comparable<Container>\n\t\n\tinline synth_three_way_result<T> operator<=>(const queue<T, Container>& a, const queue<T, Container>& b)\n\t{\n\t\treturn a.c <=> b.c;\n\t}\n#endif\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator!=(const queue<T, Container>& a, const queue<T, Container>& b)\n\t{\n\t\treturn !(a.c == b.c);\n\t}\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator<(const queue<T, Container>& a, const queue<T, Container>& b)\n\t{\n\t\treturn (a.c < b.c);\n\t}\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator>(const queue<T, Container>& a, const queue<T, Container>& b)\n\t{\n\t\treturn (b.c < a.c);\n\t}\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator<=(const queue<T, Container>& a, const queue<T, Container>& b)\n\t{\n\t\treturn !(b.c < a.c);\n\t}\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator>=(const queue<T, Container>& a, const queue<T, Container>& b)\n\t{\n\t\treturn !(a.c < b.c);\n\t}\n\n\ttemplate <typename T, typename Container>\n\tinline void swap(queue<T, Container>& a, queue<T, Container>& b) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable<typename queue<T, Container>::container_type>::value)) // EDG has a bug and won't let us use Container in this noexcept statement\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/random.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file defines random number generation like the std C++ <random> header. \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_RANDOM_H\n#define EASTL_RANDOM_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/numeric_limits.h>\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// min/max workaround\n//\n// MSVC++ has #defines for min/max which collide with the min/max algorithm\n// declarations. The following may still not completely resolve some kinds of\n// problems with MSVC++ #defines, though it deals with most cases in production\n// game code.\n//\n#if EASTL_NOMINMAX\n\t#ifdef min\n\t\t#undef min\n\t#endif\n\t#ifdef max\n\t\t#undef max\n\t#endif\n#endif\n\n\nnamespace eastl\n{\n\n\t// Implements a uniform distribution of values generated by a Generator, \n\t// where Generator is typically a random or pseudo-random number generator.\n\t// Note that the min/max range for this class is inclusive, so if you want \n\t// random integers 0, 1, 2, and 3, then you need to init this class with (0, 3)\n\t// and not (0, 4).\n\t// See the C++11 Standard, section 26.5.1.6\n\ttemplate<class IntType = int>\n\tclass uniform_int_distribution\n\t{\n\t\tstatic_assert(eastl::is_integral<IntType>::value, \"uniform_int_distribution: IntType must be integral.\");\n\n\tpublic:\n\t\ttypedef IntType result_type;\n\n\t\t// For uniform_int_distribution, param_type defines simply the min and max values of\n\t\t// the range returned by operator(). It may mean something else for other distribution types.\n\t\tstruct param_type\n\t\t{\n\t\t\texplicit param_type(IntType a = 0, IntType b = eastl::numeric_limits<IntType>::max());\n\n\t\t\tresult_type a() const;\n\t\t\tresult_type b() const;\n\n\t\t\tbool operator==(const param_type& x) const { return (x.mA == mA) && (x.mB == mB); }\n\t\t\tbool operator!=(const param_type& x) const { return (x.mA != mA) || (x.mB != mB); }\n\n\t\tprotected:\n\t\t\tIntType mA;\n\t\t\tIntType mB;\n\t\t};\n\n\t\tuniform_int_distribution(IntType a = 0, IntType b = eastl::numeric_limits<IntType>::max());\n\t\tuniform_int_distribution(const param_type& params);\n\n\t\tvoid reset();\n\n\t\ttemplate<class Generator>\n\t\tresult_type operator()(Generator& g);\n\n\t\ttemplate<class Generator>\n\t\tresult_type operator()(Generator& g, const param_type& params);\n\n\t\tresult_type a() const;\n\t\tresult_type b() const;\n\n\t\tparam_type param() const;\n\t\tvoid param(const param_type& params);\n\n\t\tresult_type min() const;\n\t\tresult_type max() const;\n\n\t\tprotected:\n\t\t\tparam_type mParam;\n\t};\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// uniform_int_distribution\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate<class IntType>\n\tinline uniform_int_distribution<IntType>::param_type::param_type(IntType aValue, IntType bValue)\n\t  : mA(aValue), mB(bValue)\n\t{\n\t\tEASTL_ASSERT(aValue <= bValue);\n\t}\n\n\ttemplate<class IntType>\n\tinline typename uniform_int_distribution<IntType>::result_type \n\tuniform_int_distribution<IntType>::param_type::a() const\n\t{\n\t\treturn mA;\n\t}\n\n\ttemplate<class IntType>\n\tinline typename uniform_int_distribution<IntType>::result_type \n\tuniform_int_distribution<IntType>::param_type::b() const\n\t{\n\t\treturn mB;\n\t}\n\n\n\n\ttemplate<class IntType>\n\tinline uniform_int_distribution<IntType>::uniform_int_distribution(IntType aValue, IntType bValue) \n\t  : mParam(aValue, bValue)\n\t{\n\t\t// Nothing more to do.\n\t}\n\n\ttemplate<class IntType>\n\tinline uniform_int_distribution<IntType>::uniform_int_distribution(const param_type& params) \n\t  : mParam(params)\n\t{\n\t\t// Nothing more to do.\n\t}\n\n\ttemplate<class IntType>\n\tvoid uniform_int_distribution<IntType>::reset()\n\t{\n\t\t// Nothing to do.\n\t}\n\n\ttemplate<class IntType>\n\ttemplate<class Generator>\n\tinline typename uniform_int_distribution<IntType>::result_type \n\tuniform_int_distribution<IntType>::operator()(Generator& g)\n\t{\n\t\treturn operator()(g, mParam);\n\t}\n\n\ttemplate<class IntType>\n\ttemplate<class Generator>\n\tinline typename uniform_int_distribution<IntType>::result_type \n\tuniform_int_distribution<IntType>::operator()(Generator& g, const param_type& params)\n\t{\n\t\t// This is a tricky function to implement in a generic way for all integral types.\n\t\t// The solution will involve handling the case of signed types and 64 bit types,\n\t\t// probably in a way that uses template metaprogramming to deal with signed ranges.\n\n\t\t// Temporary solution while we research a full solution. It supports only uint8_t,\n\t\t// uint16_t, and uint32_t uniform_int_distribution types.\n\t\tstatic_assert(eastl::is_unsigned<result_type>::value && (sizeof(result_type) <= 4), \"uniform_int_distribution currently supports only uint8_t, uint16_t, uint32_t.\");\n\n\t\tresult_type v = g();    // Generates a value in the range of (numeric_limits<result_type>::min(), numeric_limits<result_type>::max()).\n\t\tresult_type r = (result_type)((v * (uint64_t)((params.b() - params.a()) + 1)) >> (sizeof(result_type) * 8)); // +1 because ranges are inclusive.\n\t\treturn params.a() + r;\n\t}\n\n\ttemplate<class IntType>\n\tinline typename uniform_int_distribution<IntType>::result_type\n\tuniform_int_distribution<IntType>::a() const\n\t{\n\t\treturn mParam.mA;\n\t}\n\n\ttemplate<class IntType>\n\tinline typename uniform_int_distribution<IntType>::result_type\n\tuniform_int_distribution<IntType>::b() const\n\t{\n\t\treturn mParam.mB;\n\t}\n\n\n\ttemplate<class IntType>\n\tinline typename uniform_int_distribution<IntType>::param_type\n\tuniform_int_distribution<IntType>::param() const\n\t{\n\t\treturn mParam;\n\t}\n\n\ttemplate<class IntType>\n\tinline void\n\tuniform_int_distribution<IntType>::param(const param_type& params)\n\t{\n\t\tmParam = params;\n\t}\n\n\ttemplate<class IntType>\n\tinline typename uniform_int_distribution<IntType>::result_type\n\tuniform_int_distribution<IntType>::min() const\n\t{\n\t\treturn mParam.mA;\n\t}\n\n\ttemplate<class IntType>\n\tinline typename uniform_int_distribution<IntType>::result_type\n\tuniform_int_distribution<IntType>::max() const\n\t{\n\t\treturn mParam.mB;\n\t}\n\n\n\n\ttemplate<class ResultType>\n\tinline bool operator==(const uniform_int_distribution<ResultType>& lhs,\n\t\t\t\t\t\t   const uniform_int_distribution<ResultType>& rhs)\n\t{\n\t\treturn (lhs.param() == rhs.param());\n\t}\n\n\ttemplate<class ResultType>\n\tinline bool operator!=(const uniform_int_distribution<ResultType>& lhs,\n\t\t\t\t\t\t   const uniform_int_distribution<ResultType>& rhs)\n\t{\n\t\treturn (lhs.param() != rhs.param());\n\t}\n\n\n\t// EASTL doesn't currently implement IO stream-related functionality.\n\t// It may be useful to forward declare these templates and let the user implement them in the meantime.\n\t//\n\t// template<class CharT, class Traits, class ResultType>\n\t// eastl::basic_ostream<CharT, Traits>& operator<<(eastl::basic_ostream<CharT, Traits>& os, const uniform_int_distribution& uid);\n\t//\n\t// template<class CharT, class Traits, class ResultType>\n\t// eastl::basic_istream<CharT, Traits>& operator>>(eastl::basic_istream<CharT, Traits>& is, uniform_int_distribution& uid);\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/ratio.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Implements the class template eastl::ratio that provides compile-time\n// rational arithmetic support. Each instantiation of this template exactly\n// represents any finite rational number as long as its numerator Num and\n// denominator Denom are representable as compile-time constants of type\n// intmax_t. In addition, Denom may not be zero and may not be equal to the most\n// negative value. Both numerator and denominator are automatically reduced to\n// the lowest terms.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_RATIO_H\n#define EASTL_RATIO_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once \n#endif\n\n#include <EABase/eabase.h>\n\n\n//////////////////////////////////////////////////////////////////////////////\n// namespace eastl \n// {\n// \ttemplate <intmax_t N, intmax_t D = 1>\n// \tclass ratio\n// \t{\n// \tpublic:\n// \t\tstatic constexpr intmax_t num;\n// \t\tstatic constexpr intmax_t den;\n// \t\ttypedef ratio<num, den> type;\n// \t};\n// \n// \t// ratio arithmetic\n// \ttemplate <class R1, class R2> using ratio_add      = ...;\n// \ttemplate <class R1, class R2> using ratio_subtract = ...;\n// \ttemplate <class R1, class R2> using ratio_multiply = ...;\n// \ttemplate <class R1, class R2> using ratio_divide   = ...;\n// \n// \t// ratio comparison\n// \ttemplate <class R1, class R2> struct ratio_equal;\n// \ttemplate <class R1, class R2> struct ratio_not_equal;\n// \ttemplate <class R1, class R2> struct ratio_less;\n// \ttemplate <class R1, class R2> struct ratio_less_equal;\n// \ttemplate <class R1, class R2> struct ratio_greater;\n// \ttemplate <class R1, class R2> struct ratio_greater_equal;\n// \n// \t// convenience SI typedefs\n// \ttypedef ratio<1, 1000000000000000000000000> yocto;  // not supported\n// \ttypedef ratio<1,    1000000000000000000000> zepto;  // not supported\n// \ttypedef ratio<1,       1000000000000000000> atto;\n// \ttypedef ratio<1,          1000000000000000> femto;\n// \ttypedef ratio<1,             1000000000000> pico;\n// \ttypedef ratio<1,                1000000000> nano;\n// \ttypedef ratio<1,                   1000000> micro;\n// \ttypedef ratio<1,                      1000> milli;\n// \ttypedef ratio<1,                       100> centi;\n// \ttypedef ratio<1,                        10> deci;\n// \ttypedef ratio<                       10, 1> deca;\n// \ttypedef ratio<                      100, 1> hecto;\n// \ttypedef ratio<                     1000, 1> kilo;\n// \ttypedef ratio<                  1000000, 1> mega;\n// \ttypedef ratio<               1000000000, 1> giga;\n// \ttypedef ratio<            1000000000000, 1> tera;\n// \ttypedef ratio<         1000000000000000, 1> peta;\n// \ttypedef ratio<      1000000000000000000, 1> exa;\n// \ttypedef ratio<   1000000000000000000000, 1> zetta;  // not supported\n// \ttypedef ratio<1000000000000000000000000, 1> yotta;  // not supported\n// }\n//////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n\n\nnamespace eastl \n{ \n\t///////////////////////////////////////////////////////////////////////\n\t// compile-time overflow helpers\n\t///////////////////////////////////////////////////////////////////////\n\t#define EASTL_RATIO_ABS(x)\t        \t\t((x) < 0 ? -(x) : (x))\n\n\ttemplate <intmax_t X, intmax_t Y>\n\tstruct AdditionOverFlow\n\t{\n\t\tstatic const bool c1 = (X <= 0 && 0 <= Y) || (Y < 0 && 0 < X);   // True if digits do not have the same sign. \n\t\tstatic const bool c2 = EASTL_RATIO_ABS(Y) <= INTMAX_MAX - EASTL_RATIO_ABS(X);\n\t\tstatic const bool value = c1 || c2;\n\t};\n\n    template <intmax_t X, intmax_t Y>\n    struct MultiplyOverFlow\n    {\n\t    static const bool value = (EASTL_RATIO_ABS(X) <= (INTMAX_MAX / EASTL_RATIO_ABS(Y)));\n    };\n\n\n    ///////////////////////////////////////////////////////////////////////\n\t// ratio (C++ Standard: 20.11.3)\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <intmax_t N = 0, intmax_t D = 1>\n\tclass ratio \n\t{\n\tpublic:\n\t\tstatic EA_CONSTEXPR_OR_CONST intmax_t num = N;\n\t\tstatic EA_CONSTEXPR_OR_CONST intmax_t den = D;\n\t\ttypedef ratio<num, den> type;\n\t};\n\n\tnamespace Internal\n\t{\n\t\t// gcd -- implementation based on euclid's algorithm\n\t\ttemplate <intmax_t X, intmax_t Y> struct gcd { static const intmax_t value = gcd<Y, X % Y>::value; };\n\t\ttemplate <intmax_t X> struct gcd<X, 0>       { static const intmax_t value = X; };\n\t\ttemplate <> struct gcd<0, 0>                 { static const intmax_t value = 1; };\n\n\t\t// lcm\n\t\ttemplate<intmax_t X, intmax_t Y>\n\t\tstruct lcm { static const intmax_t value = (X * (Y / gcd<X,Y>::value)); };\n\n\t\t// ct_add\n\t\ttemplate <intmax_t X, intmax_t Y>\n\t\tstruct ct_add \n\t\t{ \n\t\t\tstatic_assert(AdditionOverFlow<X,Y>::value, \"compile-time addition overflow\"); \n\t\t\tstatic const intmax_t value = X + Y; \n\t\t};\n\n\t\t// ct_sub\n        template <intmax_t X, intmax_t Y>\n        struct ct_sub\n        {\n\t\t\tstatic_assert(AdditionOverFlow<X,-Y>::value, \"compile-time addition overflow\"); \n\t        static const intmax_t value = X - Y;\n        };\n\n        // ct_multi\n        template <intmax_t X, intmax_t Y>\n        struct ct_multi\n        {\n\t\t\tstatic_assert(MultiplyOverFlow<X,Y>::value, \"compile-time multiply overflow\"); \n\t        static const intmax_t value = X * Y;\n        };\n\n        // ct_simplify\n\t\ttemplate <class R1>\n\t\tstruct ct_simplify\n\t\t{ \n\t\t\tstatic const intmax_t divisor = Internal::gcd<R1::num, R1::den>::value; \n\t\t\tstatic const intmax_t num = R1::num / divisor;\n\t\t\tstatic const intmax_t den = R1::den / divisor; \n\n\t\t\ttypedef ratio<num, den> ratio_type;\n\t\t\ttypedef ct_simplify<R1> this_type;\n\t\t};\n\n\t\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\t\ttemplate <intmax_t N1, intmax_t N2> intmax_t ct_add_v   = ct_add<N1, N2>::value;\n\t\t\ttemplate <intmax_t N1, intmax_t N2> intmax_t ct_multi_v = ct_multi<N1, N2>::value;\n\t\t\ttemplate <class R1, class R2> R2 ct_simplify_t          = ct_simplify<R1>::ratio_type;\n\t\t#else\n\t\t\ttemplate <intmax_t N1, intmax_t N2> struct ct_add_v   : public ct_add<N1, N2>::value {};\n\t\t\ttemplate <intmax_t N1, intmax_t N2> struct ct_multi_v : public ct_multi<N1, N2>::value {};\n\t\t\ttemplate <class R1> struct ct_simplify_t \t\t\t  : public ct_simplify<R1>::ratio_type {};\n\t\t#endif\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// ratio_add\n\t\t///////////////////////////////////////////////////////////////////////\n\t\ttemplate <class R1, class R2>\n\t\tstruct ratio_add\n\t\t{\n\t\t\ttypedef typename ct_simplify\n\t\t\t<\n\t\t\t\ttypename ratio\n\t\t\t\t<\n\t\t\t\t\tct_add\n\t\t\t\t\t<\n\t\t\t\t\t\tct_multi<R1::num, R2::den>::value, \n\t\t\t\t\t\tct_multi<R2::num, R1::den>::value\n\t\t\t\t\t>::value,\t\t\t\t\t\t\t\n\t\t\t\t\tct_multi<R1::den, R2::den>::value  \n\t\t\t\t>::type\n\t\t\t>::ratio_type type;\n\t\t};\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// ratio_subtract\n\t\t///////////////////////////////////////////////////////////////////////\n\t\ttemplate <class R1, class R2>\n\t\tstruct ratio_subtract\n\t\t{\n\t\t\ttypedef typename ct_simplify\n\t\t\t<\n\t\t\t\ttypename ratio\n\t\t\t\t<\n\t\t\t\t\tct_sub\n\t\t\t\t\t<\n\t\t\t\t\t\tct_multi<R1::num, R2::den>::value, \n\t\t\t\t\t\tct_multi<R2::num, R1::den>::value\n\t\t\t\t\t>::value,\t\t\t\t\t\t\t\n\t\t\t\t\tct_multi<R1::den, R2::den>::value  \n\t\t\t\t>::type\n\t\t\t>::ratio_type type;\n\t\t};\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// ratio_multiply\n\t\t///////////////////////////////////////////////////////////////////////\n\t\ttemplate <class R1, class R2>\n\t\tstruct ratio_multiply\n\t\t{\n\t\t\ttypedef typename ct_simplify\n\t\t\t<\n\t\t\t\ttypename ratio\n\t\t\t\t<\n\t\t\t\t\tct_multi<R1::num, R2::num>::value, \n\t\t\t\t\tct_multi<R1::den, R2::den>::value  \n\t\t\t\t>::type\n\t\t\t>::ratio_type type;\n\t\t};\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// ratio_divide\n\t\t///////////////////////////////////////////////////////////////////////\n\t\ttemplate <class R1, class R2>\n\t\tstruct ratio_divide\n\t\t{\n\t\t\ttypedef typename ct_simplify\n\t\t\t<\n\t\t\t\ttypename ratio\n\t\t\t\t<\n\t\t\t\t\tct_multi<R1::num, R2::den>::value, \n\t\t\t\t\tct_multi<R1::den, R2::num>::value  \n\t\t\t\t>::type\n\t\t\t>::ratio_type type;\n\t\t};\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// ratio_equal\n\t\t///////////////////////////////////////////////////////////////////////\n\t\ttemplate <class R1, class R2>\n\t\tstruct ratio_equal\n\t\t{\n\t\t\ttypedef ct_simplify<R1> sr1_t;\n\t\t\ttypedef ct_simplify<R2> sr2_t;\n\n\t        static const bool value = (sr1_t::num == sr2_t::num) && (sr1_t::den == sr2_t::den);\n        };\n\n\t\t///////////////////////////////////////////////////////////////////////\n\t\t// ratio_less\n\t\t///////////////////////////////////////////////////////////////////////\n\t\ttemplate <class R1, class R2>\n\t\tstruct ratio_less\n\t\t{\n\t        static const bool value = (R1::num * R2::den) < (R2::num * R1::den); \n        };\n\t} // namespace Internal\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// ratio arithmetic (C++ Standard: 20.11.4)\n\t///////////////////////////////////////////////////////////////////////\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES) || (defined(_MSC_VER) && (_MSC_VER < 1900))  // prior to VS2015\n\t\ttemplate <class R1, class R2> struct ratio_add      : public Internal::ratio_add<R1, R2>::type {};\n\t\ttemplate <class R1, class R2> struct ratio_subtract : public Internal::ratio_subtract<R1, R2>::type {};\n\t\ttemplate <class R1, class R2> struct ratio_multiply : public Internal::ratio_multiply<R1, R2>::type {};\n\t\ttemplate <class R1, class R2> struct ratio_divide   : public Internal::ratio_divide<R1, R2>::type {};\n\t#else\n\t\ttemplate <class R1, class R2> using ratio_add      = typename Internal::ratio_add<R1, R2>::type;\n\t\ttemplate <class R1, class R2> using ratio_subtract = typename Internal::ratio_subtract<R1, R2>::type;\n\t\ttemplate <class R1, class R2> using ratio_multiply = typename Internal::ratio_multiply<R1, R2>::type;\n\t\ttemplate <class R1, class R2> using ratio_divide   = typename Internal::ratio_divide<R1, R2>::type;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// ratio comparison (C++ Standard: 20.11.5)\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class R1, class R2> struct ratio_equal         : public integral_constant<bool, Internal::ratio_equal<R1, R2>::value> {};\n\ttemplate <class R1, class R2> struct ratio_not_equal     : public integral_constant<bool, !ratio_equal<R1, R2>::value> {};\n\ttemplate <class R1, class R2> struct ratio_less          : public integral_constant<bool, Internal::ratio_less<R1, R2>::value> {};\n\ttemplate <class R1, class R2> struct ratio_less_equal    : public integral_constant<bool, !ratio_less<R2, R1>::value> {};\n\ttemplate <class R1, class R2> struct ratio_greater       : public integral_constant<bool, ratio_less<R2, R1>::value> {};\n\ttemplate <class R1, class R2> struct ratio_greater_equal : public integral_constant<bool, !ratio_less<R1, R2>::value> {};\n\n\n    ///////////////////////////////////////////////////////////////////////\n    // convenience SI typedefs (C++ Standard: 20.11.6)\n\t///////////////////////////////////////////////////////////////////////\n\t// typedef ratio<1, 1000000000000000000000000> yocto;  // not supported, too big for intmax_t\n\t// typedef ratio<1, 1000000000000000000000   > zepto;  // not supported, too big for intmax_t\n\ttypedef ratio<1, 1000000000000000000      > atto;\n\ttypedef ratio<1, 1000000000000000         > femto;\n\ttypedef ratio<1, 1000000000000            > pico;\n\ttypedef ratio<1, 1000000000               > nano;\n\ttypedef ratio<1, 1000000                  > micro;\n\ttypedef ratio<1, 1000                     > milli;\n\ttypedef ratio<1, 100                      > centi;\n\ttypedef ratio<1, 10                       > deci;\n\ttypedef ratio<10, 1                       > deca;\n\ttypedef ratio<100, 1                      > hecto;\n\ttypedef ratio<1000, 1                     > kilo;\n\ttypedef ratio<1000000, 1                  > mega;\n\ttypedef ratio<1000000000, 1               > giga;\n\ttypedef ratio<1000000000000, 1            > tera;\n\ttypedef ratio<1000000000000000, 1         > peta;\n\ttypedef ratio<1000000000000000000, 1      > exa;\n\t// typedef ratio<1000000000000000000000, 1   > zetta;  // not supported, too big for intmax_t\n\t// typedef ratio<1000000000000000000000000, 1> yotta;  // not supported, too big for intmax_t\n}\n\n#endif // EASTL_RATIO_H\n"
  },
  {
    "path": "include/EASTL/safe_ptr.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SAFEPTR_H\n#define EASTL_SAFEPTR_H\n\n\n#include <EASTL/internal/config.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\tclass safe_ptr_base;\n\n\n\t/// safe_object\n\t///\n\t/// In order for a class to be the template argument for safe_ptr, \n\t/// it must derive from safe_object.\n\t///\n\t/// Example usage:\n\t///     class RandomLifetimeObject : public safe_object\n\t///     {\n\t///     public:\n\t///         RandomLifetimeObject();\n\t///         Method();\n\t///         ...\n\t///     };\n\t///\n\tclass safe_object\n\t{\n\tpublic:\n\t\tbool is_unreferenced() const;                 /// Returns true if there are zero references (by a smart_ptr) to this object (mpSafePtrList is NULL).\n\t\tbool has_unique_reference() const;            /// Returns true if there is at most one reference (by a smart_ptr) to us.\n\n\tprotected:\n\t\tsafe_object();\n\t   ~safe_object();\n\n\t\tvoid clear_references();                      /// Forcibly removes any references (by smart_ptrs) to this object. All safe_ptr mpObject values are set to NULL. \n\n\tprivate:\n\t\tfriend class safe_ptr_base;\n\n\t\tvoid add(safe_ptr_base* pBase) const;         /// Link pBase into my list of safe pointers.\n\t\tvoid remove(safe_ptr_base* pBase) const;      /// Unlink pBase from my list of safe pointers.\n\n\t\tmutable safe_ptr_base* mpSafePtrList;\n\t};\n\n\n\n\t/// safe_ptr_base\n\t///\n\t/// This is a non-templated base class for safe_ptr<T>, not for direct use by the user.\n\t///\n\tclass safe_ptr_base\n\t{\n\tpublic:\n\t\tbool unique() const;                    /// Returns true if there are no other smart pointers pointing to our object except us. True if mpObject is NUll\n\t\tbool empty() const;                     /// Returns true if mpObject is NULL.\n\t\tvoid reset(const safe_object* pObject); /// Make this point to pObject and enlist.\n\t\tvoid reset();                           /// Make this point to NULL and delist.\n\n\tprotected:\n\t\t// The following are protected and must be overridden in the safe_ptr<T> subclass.\n\t\tsafe_ptr_base();\n\t\tsafe_ptr_base(const safe_object* pObject);\n\t\tsafe_ptr_base(const safe_ptr_base& safePtrBase);\n\t   ~safe_ptr_base();\n\n\tprotected:\n\t\tconst safe_object* mpObject;\n\n\tprivate:\n\t\tfriend class safe_object;\n\n\t\tsafe_ptr_base& operator=(const safe_ptr_base& safePtrBase);\n\n\t\tsafe_ptr_base* mpNext;\n\t};\n\n\n\t/// safe_ptr\n\t///\n\t/// safe_ptr is an automatic, lightweight solution to the dangling pointer problem.\n\t/// This class is an alternative to weak_ptr which has the primary benefit of not \n\t/// allocating memory at the primary cost of being a tad slower and thread-unsafe.\n\t///\n\t/// During normal usage, safe_ptr<T> behaves exactly as a T*. When the\n\t/// raw pointer referenced by the safe_ptr is deleted, all of the SafePtrs\n\t/// for the raw pointer are set to NULL.\n\t///\n\t/// This works by making the raw objects derive from the class safe_object,\n\t/// which maintains a linked-list of the Safe pointers that reference it.\n\t/// When a safe_object is destroyed, it walks its linked list, setting the\n\t/// object reference for each of its SafePtrs to NULL.\n\t///\n\t/// The overhead for this is light - a single pointer is added to the\n\t/// size of the pointed to object, and a safePtr is the size of a raw \n\t/// pointer plus one list pointer.\n\t///\n\t/// This class is not thread-safe. In particular, manipulation of safe_ptr\n\t/// objects that refer to the same underlying object cannot be done safely\n\t/// from multiple threads. safe_ptr objects that are unrelated can be used\n\t/// safely from multiple threads.\n\t///\n\t/// Example usage:\n\t///     class RandomLifetimeObject : public safe_object\n\t///     {\n\t///     public:\n\t///         RandomLifetimeObject();\n\t///         Method();\n\t///         ...\n\t///     };\n\t///     \n\t///     safe_ptr<RandomLifetimeObject> pSafePtr(new RandomLifetimeObject);\n\t///     safe_ptr<RandomLifetimeObject> pSafePtrCopy = pSafePtr;\n\t///\n\t///     pSafePtr->Method();\n\t///     delete pSafePtr;\n\t///     At this point, pSafePtrCopy evaluates to NULL.\n\t///\n\ttemplate<class T>\n\tclass safe_ptr : public safe_ptr_base\n\t{\n\tpublic:\n\t\ttypedef T           value_type;\n\t\ttypedef safe_ptr<T> this_type;\n\n\tpublic:\n\t\tsafe_ptr();                                         /// Default constructor.\n\t\texplicit safe_ptr(T* pObject);                      /// Construct a safeptr from a naked pointer.\n\t\tsafe_ptr(const this_type& safePtr);                 /// Copy constructor.\n\t\t//~safe_ptr() {}                                    /// No need to implement this; the compiler-generated destructor is OK.\n\n\t\tthis_type& operator=(const this_type& safePtr);     /// Assignment operator.\n\t\tthis_type& operator=(T* const pObject);             /// Assign this to a naked pointer.\n\n\t\tbool operator==(const this_type& safePtr) const;    /// Returns true if safePtr points to the same object as this.\n\n\tpublic:\n\t\tT* get() const;                                     /// Get the naked pointer from this safe ptr.\n\t\toperator T*() const;                                /// Implicit safe_ptr<T> -> T* conversion operator.\n\t\tT* operator->() const;                              /// Member operator.\n\t\tT& operator*() const;                               /// Dereference operator.\n\t\tbool operator!() const;                             /// Boolean negation operator.\n\n\t\ttypedef T* (this_type::*bool_)() const;             /// Allows for a more portable version of testing an instance of this class as a bool.\n\t\toperator bool_() const                              // A bug in the CodeWarrior compiler forces us to implement this inline instead of below.\n\t\t{\n\t\t\tif(mpObject)\n\t\t\t\treturn &this_type::get;\n\t\t\treturn NULL;\n\t\t}\n\t};\n\n} // namespace eastl\n\n\n\n\n\n\n/////////////////////////////////////////////////////////////////////////\n// Inlines\n/////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// safe_object\n///////////////////////////////////////////////////////////////////////////////\n\ninline eastl::safe_object::safe_object()\n  :  mpSafePtrList(0)\n{\n}\n\n\ninline bool eastl::safe_object::is_unreferenced() const\n{\n\treturn (mpSafePtrList == NULL);\n}\n\n\ninline void eastl::safe_object::clear_references()\n{\n\twhile(mpSafePtrList != NULL)\n\t{\n\t\tsafe_ptr_base* const pNext = mpSafePtrList->mpNext;\n\t\tmpSafePtrList->mpNext = NULL;\n\t\tmpSafePtrList->mpObject = NULL;\n\t\tmpSafePtrList = pNext;\n\t}\n}\n\n\ninline eastl::safe_object::~safe_object()\n{\n\tsafe_ptr_base* pIter = mpSafePtrList;\n\n\twhile(pIter)\n\t{\n\t\tsafe_ptr_base* const pNext = pIter->mpNext;\n\t\tpIter->mpNext = NULL;\n\t\tpIter->mpObject = NULL;\n\t\tpIter = pNext;\n\t}\n}\n\n\ninline void eastl::safe_object::add(safe_ptr_base* pBase) const\n{\n\tpBase->mpNext = mpSafePtrList;\n\tmpSafePtrList = pBase;\n}\n\n\ninline void eastl::safe_object::remove(safe_ptr_base* pBase) const\n{\n\t// We have a singly-linked list (starting with mpSafePtrList) and need to \n\t// remove an element from within it.\n\tif(pBase == mpSafePtrList)\n\t\tmpSafePtrList = mpSafePtrList->mpNext;\n\telse\n\t{\n\t\tfor(safe_ptr_base *pPrev = mpSafePtrList, *pCurrent = mpSafePtrList->mpNext; \n\t\t\tpCurrent;\n\t\t\tpPrev = pCurrent, pCurrent = pCurrent->mpNext)\n\t\t{\n\t\t\tif(pCurrent == pBase)\n\t\t\t{\n\t\t\t\tpPrev->mpNext = pCurrent->mpNext;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// safe_ptr_base\n///////////////////////////////////////////////////////////////////////////////\n\ninline eastl::safe_ptr_base::safe_ptr_base(const safe_ptr_base& safePtrBase)\n  : mpObject(safePtrBase.mpObject),\n\tmpNext(NULL)    \n{\n\tEASTL_ASSERT(this != &safePtrBase);\n\n\tif(mpObject)\n\t\tmpObject->add(this);\n}\n\n\ninline eastl::safe_ptr_base::safe_ptr_base()\n  : mpObject(NULL),\n\tmpNext(NULL)\n{\n}\n\n\ninline eastl::safe_ptr_base::safe_ptr_base(const safe_object* pObject)\n  : mpObject(pObject),\n\tmpNext(NULL)\n{\n\tif(mpObject)\n\t\tmpObject->add(this);\n}\n\n\ninline eastl::safe_ptr_base::~safe_ptr_base()\n{\n\tif(mpObject)\n\t\tmpObject->remove(this);\n}\n\n\ninline void eastl::safe_ptr_base::reset()\n{\n\tif(mpObject)\n\t{\n\t\tmpObject->remove(this);\n\t\tmpObject = NULL;\n\t}\n}\n\n\ninline bool eastl::safe_ptr_base::empty() const\n{\n\treturn (mpObject == NULL);\n}\n\n\ninline void eastl::safe_ptr_base::reset(const safe_object* pNewObject)\n{\n\tif(mpObject != pNewObject)\n\t{\n\t\tif(mpObject)\n\t\t\tmpObject->remove(this);\n\n\t\tmpObject = pNewObject;\n\n\t\tif(mpObject)\n\t\t\tmpObject->add(this);\n\t}\n}\n\n\ninline bool eastl::safe_ptr_base::unique() const\n{\n\treturn (mpNext == NULL) && ((mpObject == NULL) || (mpObject->mpSafePtrList == this));\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// safe_object\n///////////////////////////////////////////////////////////////////////////////\n\n\n// This function is defined here below safe_ptr_base because some compilers \n// (GCC in particular) generate warnings about inline functions (e.g. unique below) \n// being used before their inline implementations. \ninline bool eastl::safe_object::has_unique_reference() const\n{\n\treturn mpSafePtrList ? mpSafePtrList->unique() : false;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// safe_ptr<T>\n///////////////////////////////////////////////////////////////////////////////\n\ntemplate<class T>\ninline eastl::safe_ptr<T>::safe_ptr() \n  : safe_ptr_base()\n{\n}\n\n\ntemplate<class T>\ninline eastl::safe_ptr<T>::safe_ptr(T* pObject)\n  : safe_ptr_base(pObject)\n{\n}\n\n\ntemplate<class T>\ninline eastl::safe_ptr<T>::safe_ptr(const this_type& safePtr)\n  : safe_ptr_base(safePtr)\n{\n}\n\n\ntemplate<class T>\ninline typename eastl::safe_ptr<T>::this_type& eastl::safe_ptr<T>::operator=(const this_type& safePtr)\n{\n\tif(this != &safePtr)\n\t\treset(safePtr.mpObject);\n\treturn *this;\n}\n\n\ntemplate<class T>\ninline typename eastl::safe_ptr<T>::this_type& eastl::safe_ptr<T>::operator=(T* const pObject)\n{\n\treset(pObject);\n\treturn *this;\n}\n\n\ntemplate<class T>\ninline bool eastl::safe_ptr<T>::operator==(const this_type& rhs) const\n{\n\treturn (mpObject == rhs.mpObject);\n}\n\n\ntemplate<class T>\ninline T* eastl::safe_ptr<T>::get() const\n{\n\treturn static_cast<T*>(const_cast<safe_object*>(mpObject));\n}\n\n\ntemplate<class T>\ninline eastl::safe_ptr<T>::operator T*() const\n{\n\treturn static_cast<T*>(const_cast<safe_object*>(mpObject));\n}\n\n\ntemplate<class T>\ninline T* eastl::safe_ptr<T>::operator->() const\n{\n\treturn static_cast<T*>(const_cast<safe_object*>(mpObject));\n}\n\n\ntemplate<class T>\ninline T& eastl::safe_ptr<T>::operator*() const\n{\n\treturn *static_cast<T*>(const_cast<safe_object*>(mpObject));\n}\n\n\ntemplate<class T>\ninline bool eastl::safe_ptr<T>::operator!() const\n{\n\treturn (mpObject == NULL);\n}\n\n// A bug in the CodeWarrior compiler forces us to implement this inline in the class instead of here.\n// template<class T>\n// inline eastl::safe_ptr<T>::operator bool_() const\n// {\n//     if(mpObject)\n//         return &this_type::get;\n//     return NULL;\n// }\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// global operators\n///////////////////////////////////////////////////////////////////////////////\n\ntemplate<class T>\ninline bool operator==(const eastl::safe_ptr<T>& safePtr, const T* pObject)\n{\n\treturn (safePtr.get() == pObject);\n}\n\n\ntemplate<class T>\ninline bool operator!=(const eastl::safe_ptr<T>& safePtr, const T* pObject)\n{\n\treturn (safePtr.get() != pObject);\n}\n\n\ntemplate<class T>\ninline bool operator<(const eastl::safe_ptr<T>& safePtrA, const eastl::safe_ptr<T>& safePtrB)\n{\n\treturn (safePtrA.get() < safePtrB.get());\n}\n\n\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/scoped_array.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// *** Note ***\n// *** This code is deprecated in favor of the C++11-conforming             *** \n// *** eastl::unique_ptr template class found in <EASTL/unique_ptr.h>       *** \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SCOPED_ARRAY_H\n#define EASTL_SCOPED_ARRAY_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/smart_ptr.h>   // Defines smart_array_deleter\n#include <stddef.h>                     // Definition of ptrdiff_t\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// class scoped_array\n\t///\n\t/// A scoped_array is the same as scoped_ptr but for arrays. \n\t///\n\ttemplate <typename T, typename Deleter = smart_array_deleter<T> >\n\tclass scoped_array\n\t{\n\tprotected:\n\t\t/// this_type\n\t\t/// This is an alias for scoped_array<T>, this class.\n\t\ttypedef scoped_array<T> this_type;\n\n\t\t/// deleter_type\n\t\ttypedef Deleter deleter_type;\n\n\t\t/// mpArray\n\t\t/// The owned pointer. Points to an array of T.\n\t\tT* mpArray;\n\n\t\t/// scoped_array\n\t\t/// This function is private in order to prevent copying, for safety.\n\t\tscoped_array(const scoped_array&);\n\n\t\t/// scoped_array\n\t\t/// This function is private in order to prevent copying, for safety.\n\t\tscoped_array& operator=(const scoped_array&);\n\n\t\t/// scoped_ptr\n\t\t/// This function is private in order to prevent copying, for safety.\n\t\tscoped_array& operator=(T* pValue);\n\n\tpublic:\n\t\ttypedef T element_type;\n\n\t\t/// scoped_ptr\n\t\t/// Construct a scoped_ptr from a pointer allocated via new.\n\t\t/// Example usage:\n\t\t///    scoped_array<int> ptr(new int[6]);\n\t\texplicit scoped_array(T* pArray = NULL)\n\t\t\t: mpArray(pArray) {}\n\n\t\t/// ~scoped_array\n\t\t/// Destroys the owned pointer. The destructors for each of the objects\n\t\t/// in the owned array will be called. \n\t\t~scoped_array()\n\t\t{\n\t\t\tDeleter del;\n\t\t\tdel(mpArray);\n\t\t}\n\n\t\t/// reset\n\t\t/// Deletes the owned pointer and takes ownership of the \n\t\t/// passed in pointer. If the passed in pointer is the same\n\t\t/// as the owned pointer, nothing is done.\n\t\t/// Example usage:\n\t\t///    scoped_array<int> ptr(new int[6]);\n\t\t///    ptr.reset(new int[7]);  // deletes int[6]\n\t\t///    ptr.reset(NULL);        // deletes int[7]\n\t\tvoid reset(T* pArray = NULL)\n\t\t{\n\t\t\tif(pArray != mpArray)\n\t\t\t{\n\t\t\t\tDeleter del;\n\t\t\t\tdel(mpArray);\n\t\t\t\tmpArray = pArray;\n\t\t\t}\n\t\t}\n\n\t\t/// detach\n\t\t/// This simply forgets the owned pointer. It doesn't \n\t\t/// free it but rather assumes that the user does.\n\t\t/// Example usage:\n\t\t///    scoped_array<int> ptr(new int[6]);\n\t\t///    int* pIntArray = ptr.get();\n\t\t///    ptr.detach();\n\t\t///    delete[] pIntArray;\n\t\tT* detach()\n\t\t{\n\t\t\tT* const pTemp = mpArray;\n\t\t\tmpArray = NULL;\n\t\t\treturn pTemp;\n\t\t}\n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer beween two scoped_array objects. \n\t\tvoid swap(this_type& scopedArray)\n\t\t{\n\t\t\t// std::swap(mpArray, scopedArray.mpArray); // Not used so that we can reduce a dependency.\n\t\t\tT* const pArray     = scopedArray.mpArray;\n\t\t\tscopedArray.mpArray = mpArray;\n\t\t\tmpArray             = pArray;\n\t\t}\n\n\t\t/// operator[]\n\t\t/// Returns a reference to the specified item in the owned pointer\n\t\t/// array. \n\t\t/// Example usage:\n\t\t///    scoped_array<int> ptr(new int[6]);\n\t\t///    int x = ptr[2];\n\t\ttypename add_lvalue_reference<T>::type operator[](ptrdiff_t i) const\n\t\t{\n\t\t\t// assert(mpArray && (i >= 0));\n\t\t\treturn mpArray[i];\n\t\t}\n\n\t\t/// get\n\t\t/// Returns the owned array pointer. \n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    scoped_array<int> ptr(new X[8]);\n\t\t///    X** ppX = ptr.get();\n\t\t///    ppX[2]->DoSomething();\n\t\tT* get() const\n\t\t{\n\t\t\treturn mpArray;\n\t\t}\n\n\t\t/// Implicit operator bool\n\t\t/// Allows for using a scoped_ptr as a boolean. \n\t\t/// Example usage:\n\t\t///    scoped_array<int> ptr(new int[8]);\n\t\t///    if(ptr)\n\t\t///        ++ptr[2];\n\t\t///     \n\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t/// The result is that this: if(scopedArray == 1) would yield true (bad).\n\t\ttypedef T* (this_type::*bool_)() const;\n\t\toperator bool_() const\n\t\t{\n\t\t\tif(mpArray)\n\t\t\t\treturn &this_type::get;\n\t\t\treturn NULL;\n\t\t}\n\n\t\t/// operator!\n\t\t/// This returns the opposite of operator bool; it returns true if \n\t\t/// the owned pointer is null. Some compilers require this and some don't.\n\t\t///    scoped_array<int> ptr(new int(3));\n\t\t///    if(!ptr)\n\t\t///        assert(false);\n\t\tbool operator!() const\n\t\t{\n\t\t\treturn (mpArray == NULL);\n\t\t}\n\n\t}; // class scoped_array\n\n\n\t/// unique_array\n\t///\n\t/// Example usage:\n\t///    unique_array<int> uniqueIntArray;\n\t/// Example usage:\n\t///    UNIQUE_ARRAY_T(int, eastl::smart_ptr_deleter<int>) uniqueIntArray;\n\t///\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t#define UNIQUE_ARRAY_T(T, Deleter) scoped_array<T, Deleter>\n\t#else\n\t\ttemplate <typename T, typename Deleter = smart_ptr_deleter<T> >\n\t\tusing unique_array = scoped_array<T, Deleter>;\n\t\t#define UNIQUE_ARRAY_T(T, Deleter) unique_array<T, Deleter>\n\t#endif\n\n\n\n\t/// scoped_array\n\t/// returns scoped_array::get() via the input scoped_array. \n\ttemplate <typename T, typename D>\n\tinline T* get_pointer(const scoped_array<T, D>& scopedArray)\n\t{\n\t\treturn scopedArray.get();\n\t}\n\n\n\t/// swap\n\t/// Exchanges the owned pointer beween two scoped_array objects.\n\t/// This non-member version is useful for compatibility of scoped_array\n\t/// objects with the C++ Standard Library and other libraries.\n\ttemplate <typename T, typename D>\n\tinline void swap(scoped_array<T, D>& scopedArray1, scoped_array<T, D>& scopedArray2)\n\t{\n\t\tscopedArray1.swap(scopedArray2);\n\t}\n\n\n\t/// operator<\n\t/// Returns which scoped_array is 'less' than the other. Useful when storing\n\t/// sorted containers of scoped_array objects.\n\ttemplate <typename T, typename D>\n\tinline bool operator<(const scoped_array<T, D>& scopedArray1, const scoped_array<T, D>& scopedArray2)\n\t{\n\t\treturn (scopedArray1.get() < scopedArray2.get()); // Alternatively use: std::less<T*>(scopedArray1.get(), scopedArray2.get());\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/scoped_ptr.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// *** Note ***\n// *** This code is deprecated in favor of the C++11-conforming             *** \n// *** eastl::unique_ptr template class found in <EASTL/unique_ptr.h>       *** \n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SCOPED_PTR_H\n#define EASTL_SCOPED_PTR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/smart_ptr.h>   // Defines smart_ptr_deleter\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t/// class scoped_ptr\n\t///\n\t/// This class is intended to be the same as the C++11 unique_ptr class, \n\t/// but was created before there was such a thing. \n\t///\n\t/// This class implements a scoped_ptr template. This is a class which is \n\t/// similar to the C++ auto_ptr template, except that it prohibits copying \n\t/// of itself, for safety.\n\t///\n\t/// More specifically, the scoped_ptr class template stores a pointer to a \n\t/// dynamically allocated object.  The object pointed to is automatically \n\t/// deleted on destructor of scoped_ptr or can be manually deleted via the \n\t/// scopted_ptr::reset function. \n\t///\n\t/// scoped_ptr cannot be used in C++ Standard Library containers; you'll need \n\t/// to use the shared_ptr template if you want to do this. The reason you can't\n\t/// use scoped_ptr is that it prohibits copying. You can't (safely) use auto_ptr\n\t/// in C++ Standard Library containers because copying of an auto_ptr will \n\t/// create a situation whereby objects are multiply freed.\n\t/// \n\t/// scoped_ptr cannot be used with arrays of objects. The reason for this is\n\t/// that it calls delete on the owned pointer and not delete[]. The latter\n\t/// allows for the calling of the destructors for the objects of the owned pointer.\n\t/// If you want to use scoped_ptr with a dynamically allocated array, use the\n\t/// scoped_array function instead.\n\t/// \n\ttemplate <typename T, typename Deleter = smart_ptr_deleter<T> > \n\tclass scoped_ptr\n\t{\n\tprotected:\n\t\t/// this_type\n\t\t/// This is an alias for scoped_ptr<T>, this class.\n\t\ttypedef scoped_ptr<T> this_type;\n\n\t\t/// deleter_type\n\t\ttypedef Deleter deleter_type;\n\n\t\t/// mpValue\n\t\t/// The owned pointer.\n\t\tT* mpValue;\n\n\t\t/// scoped_ptr\n\t\t/// This function is private in order to prevent copying, for safety.\n\t\tscoped_ptr(const scoped_ptr&);\n\n\t\t/// scoped_ptr\n\t\t/// This function is private in order to prevent copying, for safety.\n\t\tscoped_ptr& operator=(const scoped_ptr&);\n\n\t\t/// scoped_ptr\n\t\t/// This function is private in order to prevent copying, for safety.\n\t\tscoped_ptr& operator=(T* pValue);\n\n\tpublic:\n\t\ttypedef T element_type;\n\n\t\t/// scoped_ptr\n\t\t/// Construct a scoped_ptr from a pointer allocated via new.\n\t\t/// Example usage:\n\t\t///    scoped_ptr<int> ptr(new int(3));\n\t\texplicit scoped_ptr(T* pValue = NULL) noexcept\n\t\t\t: mpValue(pValue) {}\n\n\t\t/// ~scoped_ptr\n\t\t/// Destroys the owned pointer. The destructor for the object\n\t\t/// referred to by the owned pointer will be called.\n\t\t~scoped_ptr()\n\t\t{\n\t\t\tDeleter del;\n\t\t\tdel(mpValue);\n\t\t}\n\n\t\t/// reset\n\t\t/// Deletes the owned pointer and takes ownership of the \n\t\t/// passed in pointer. If the passed in pointer is the same\n\t\t/// as the owned pointer, nothing is done.\n\t\t/// Example usage:\n\t\t///    scoped_ptr<int> ptr(new int(3));\n\t\t///    ptr.reset(new int(4));  // deletes int(3)\n\t\t///    ptr.reset(NULL);        // deletes int(4)\n\t\tvoid reset(T* pValue = NULL) noexcept\n\t\t{\n\t\t\tif(pValue != mpValue)\n\t\t\t{\n\t\t\t\tDeleter del;\n\t\t\t\tdel(mpValue);\n\t\t\t\tmpValue = pValue;\n\t\t\t}\n\t\t}\n\n\t\t/// detach\n\t\t/// This simply forgets the owned pointer. It doesn't \n\t\t/// free it but rather assumes that the user does.\n\t\t/// Example usage:\n\t\t///    scoped_ptr<int> ptr(new int(3));\n\t\t///    int* pInt = ptr.detach();\n\t\t///    delete pInt;\n\t\tT* detach() noexcept\n\t\t{\n\t\t\tT* const pTemp = mpValue;\n\t\t\tmpValue = NULL;\n\t\t\treturn pTemp;\n\t\t}\n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer beween two scoped_ptr objects. \n\t\tvoid swap(this_type& scopedPtr) noexcept\n\t\t{\n\t\t\t// std::swap(mpValue, scopedPtr.mpValue); // Not used so that we can reduce a dependency.\n\t\t\tT* const pValue   = scopedPtr.mpValue;\n\t\t\tscopedPtr.mpValue = mpValue;\n\t\t\tmpValue           = pValue;\n\t\t}\n\n\t\t/// operator*\n\t\t/// Returns the owner pointer dereferenced.\n\t\t/// Example usage:\n\t\t///    scoped_ptr<int> ptr(new int(3));\n\t\t///    int x = *ptr;\n\t\ttypename add_lvalue_reference<T>::type operator*() const\n\t\t{\n\t\t\t// assert(mpValue);\n\t\t\treturn *mpValue;\n\t\t}\n\n\t\t/// operator->\n\t\t/// Allows access to the owned pointer via operator->()\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    scoped_ptr<int> ptr(new X);\n\t\t///    ptr->DoSomething();\n\t\tT* operator->() const\n\t\t{\n\t\t\t// assert(mpValue);\n\t\t\treturn mpValue;\n\t\t}\n\n\t\t/// get\n\t\t/// Returns the owned pointer. Note that this class does \n\t\t/// not provide an operator T() function. This is because such\n\t\t/// a thing (automatic conversion) is deemed unsafe.\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    scoped_ptr<int> ptr(new X);\n\t\t///    X* pX = ptr.get();\n\t\t///    pX->DoSomething();\n\t\tT* get() const noexcept\n\t\t{\n\t\t\treturn mpValue;\n\t\t}\n\n\t\t/// Implicit operator bool\n\t\t/// Allows for using a scoped_ptr as a boolean. \n\t\t/// Example usage:\n\t\t///    scoped_ptr<int> ptr(new int(3));\n\t\t///    if(ptr)\n\t\t///        ++*ptr;\n\t\t///\n\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t/// The result is that this: if(scopedPtr == 1) would yield true (bad).\n\t\ttypedef T* (this_type::*bool_)() const;\n\t\toperator bool_() const noexcept\n\t\t{\n\t\t\tif(mpValue)\n\t\t\t\treturn &this_type::get;\n\t\t\treturn NULL;\n\t\t}\n\n\t\t/// operator!\n\t\t/// This returns the opposite of operator bool; it returns true if \n\t\t/// the owned pointer is null. Some compilers require this and some don't.\n\t\t///    scoped_ptr<int> ptr(new int(3));\n\t\t///    if(!ptr)\n\t\t///        assert(false);\n\t\tbool operator!() const noexcept\n\t\t{\n\t\t\treturn (mpValue == NULL);\n\t\t}\n\n\t}; // class scoped_ptr\n\n\n\n\t/// get_pointer\n\t/// returns scoped_ptr::get() via the input scoped_ptr. \n\ttemplate <typename T, typename D>\n\tinline T* get_pointer(const scoped_ptr<T, D>& scopedPtr)\n\t{\n\t\treturn scopedPtr.get();\n\t}\n\n\n\t/// swap\n\t/// Exchanges the owned pointer beween two scoped_ptr objects.\n\t/// This non-member version is useful for compatibility of scoped_ptr\n\t/// objects with the C++ Standard Library and other libraries.\n\ttemplate <typename T, typename D>\n\tinline void swap(scoped_ptr<T, D>& scopedPtr1, scoped_ptr<T, D>& scopedPtr2)\n\t{\n\t\tscopedPtr1.swap(scopedPtr2);\n\t}\n\n\n\t/// operator<\n\t/// Returns which scoped_ptr is 'less' than the other. Useful when storing\n\t/// sorted containers of scoped_ptr objects.\n\ttemplate <typename T, typename D>\n\tinline bool operator<(const scoped_ptr<T, D>& scopedPtr1, const scoped_ptr<T, D>& scopedPtr2)\n\t{\n\t\treturn (scopedPtr1.get() < scopedPtr2.get()); // Alternatively use: std::less<T*>(scopedPtr1.get(), scopedPtr2.get());\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/segmented_vector.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_SEGMENTED_VECTOR_H\n#define EASTL_SEGMENTED_VECTOR_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once \n#endif\n\n#include <EASTL/internal/config.h>\n\n#include <EASTL/algorithm.h>\n#include <EASTL/allocator.h>\n#include <EASTL/memory.h>\n\nnamespace eastl\n{\n\t// TODO: this really shouldn't be a public class, deprecate it and hide it.\n\ttemplate<typename T, size_t Count, typename Allocator = EASTLAllocatorType>\n\tclass segment\n\t{\n\tpublic:\n\t\ttypedef eastl_size_t\t\t\t\t\tsize_type;\n\t\ttypedef segment<T, Count, Allocator>\tthis_type;\n\t\ttypedef T*\t\t\t\t\t\t\t\titerator;\n\t\ttypedef const T*\t\t\t\t\t\tconst_iterator;\n\n\t\tconst this_type*\t\tnext_segment() const;\n\t\tthis_type*\t\t\t\tnext_segment();\n\n\t\tconst_iterator\t\t\tbegin() const;\n\t\titerator\t\t\t\tbegin();\n\n\t\tconst_iterator\t\t\tend() const;\n\t\titerator\t\t\t\tend();\n\n\t\tsegment() = default;\n\t\t// TODO: should we implement copy/move ctor/assign?\n\t\tsegment(const segment& other) = delete;\n\t\tsegment& operator=(const segment&) = delete;\n\t\t// move ctor/assignment implicitly deleted.\n\n\t\t// The owning segment_vector is in charge of destroying the\n\t\t// data before the destructor of the segment runs, so we leave\n\t\t// the destructor as trivial. This class can't be copied and\n\t\t// it's public API doesn't really let you do anything, only\n\t\t// segmented_vector can really use these.\n\t\t//\n\t\t//~segment();\n\n\tprivate:\n\t\t// Destroys all the elements in the segment.\n\t\tvoid                    DestroyData();\n\n\t\tstatic const uintptr_t\tkIsLastSegment = 1 << 0;\n\t\tuintptr_t\t\t\t\tmPrev;\n\n\t\tunion\n\t\t{\n\t\t\t// When the segment is not the last one in the segmented\n\t\t\t// vector, mNext is the link to the next segment.\n\t\t\tthis_type*\t\t\tmNext;\n\t\t\t// When the segment is the last one in the segmented\n\t\t\t// vector, mSize is the number elements in this current\n\t\t\t// segment. Note: if a segment is not the last one, it\n\t\t\t// must be completely full i.e. it must contain exactly\n\t\t\t// Count elements so there's no need to store anything in\n\t\t\t// mSize.\n\t\t\tsize_type\t\t\tmSize;\n\t\t};\n\n\t\t// Storage for the segment. Type-erased because we want to\n\t\t// support types which are not default constructible.\n\t\t// TODO: Should we be using std::byte here instead of\n\t\t// unsigned char?\n\t\talignas(T) unsigned char mData[Count * sizeof(T)];\n\n\t\ttemplate<typename, size_t, typename> friend class segmented_vector;\n\t\ttemplate<typename, size_t, typename> friend struct segmented_vector_iterator;\n\t};\n\n\n\ttemplate <typename T, size_t Count, typename Allocator = EASTLAllocatorType>\n\tstruct segmented_vector_iterator\n\t{\n\tpublic:\n        typedef segmented_vector_iterator<T, Count, Allocator>\tthis_type;\n\t\ttypedef segment<T, Count, Allocator>\t\t\t\t\tsegment_type;\n\n\t\t// does not conform to any Iterator concept. could be a bidirectional iterator, but not random access iterator because segment is a double-linked list.\n\n        T*\t\t\t\t\t\toperator->() const;\n        T&\t\t\t\t\t\toperator*() const;\n\n        this_type&\t\t\t\toperator++();\n        this_type\t\t\t\toperator++(int);\n\t\t\n\tpublic:\n\t\tT*\t\t\t\t\t\tmCurrent;\n\t\tT*\t\t\t\t\t\tmEnd;\n\t\tsegment_type*\t\t\tmSegment;\n\t};\n\n\n\ttemplate <typename T, size_t Count, typename Allocator = EASTLAllocatorType>\n\tclass segmented_vector\n\t{\n\tpublic:\n\t\ttypedef eastl_size_t\t\t\t\t\t\t\t\t\t\t\t\tsize_type;\n\t\ttypedef segmented_vector<T, Count, Allocator>\t\t\t\t\t\tthis_type;\n\t\ttypedef segment<T, Count, Allocator>\t\t\t\t\t\t\t\tsegment_type;\n        typedef Allocator\t\t\t\t\t\t\t\t\t\t\t\t\tallocator_type;\n\t\ttypedef segmented_vector_iterator<const T, Count, Allocator>\t\tconst_iterator;\n\t\ttypedef segmented_vector_iterator<T, Count, Allocator>\t\t\t\titerator;\n\t\ttypedef T\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue_type;\n\n\n\t\tsegmented_vector(const Allocator& allocator = Allocator());\n\t\tsegmented_vector(const segmented_vector& other);\n\t\tsegmented_vector(segmented_vector&& other);\n\t\tsegmented_vector& operator=(const segmented_vector& other);\n\t\tsegmented_vector& operator=(segmented_vector&& other);\n\t\t~segmented_vector();\n\n\t\t// constructors that initialize from a range, etc. missing\n\n\t\tsegmented_vector(std::initializer_list<value_type> ilist, const Allocator& allocator = Allocator());\n\n\t\tconst allocator_type& get_allocator() const noexcept;\n\t\tallocator_type& get_allocator() noexcept;\n\n\t\t// TODO: deprecate these? what's the point of having them in\n\t\t// the API? We don't want people messing around with the\n\t\t// segments directly.\n\t\tconst segment_type* first_segment() const noexcept;\n\t\tsegment_type* first_segment() noexcept;\n\n\t\tconst_iterator begin() const noexcept;\n\t\titerator begin() noexcept;\n\n\t\tconst_iterator end() const noexcept;\n\t\titerator end() noexcept;\n\n\t\t// The number of elements in the container.\n\t\tsize_type size() const noexcept;\n\n\t\t// The total capacity of the container.\n\t\tsize_type capacity() const noexcept;\n\n\t\t// TODO: Deprecate this?\n\t\t// The number of \"active\" segments (does not include segments\n\t\t// in the free list).\n\t\tsize_type segment_count() const noexcept;\n\n\t\t// These are UB if the container is empty.\n\t\tT& front() noexcept;\n\t\tT& back() noexcept;\n\n\t\t// Return true if the container has no elements and false\n\t\t// otherwise.\n\t\tbool empty() const noexcept;\n\n\t\t// Destroys the elements in the container, but does not\n\t\t// relinquish any memory (i.e. capacity() is unchanged)\n\t\tvoid clear();\n\n\t\t// Increase the capacity so it fits at least `n` elements.\n\t\t// This is less useful than in normal vectors since this will\n\t\t// allocate multiple segments, resulting in the same number of\n\t\t// allocations as if you'd pushed the elements one by one\n\t\t// without reserving.\n\t\tvoid reserve(size_type n);\n\n\t\t// Resizes the container to contain exactly `n` elements.\n\t\t//   - If `size() > n` it destroys the last `size() - n` elements.\n\t\t//   - If `size() < n` it inserts `n - size()` copies of `v`.\n\t\tvoid resize(size_type n, const value_type& v);\n\n\t\t// Equivalent to resize(n, value_type());\n\t\tvoid resize(size_type n);\n\n\t\t// Frees all the segments not currently in use, i.e makes it\n\t\t// so capacity() is the lowest multiple of Count greater than\n\t\t// or equal to size().\n\t\tvoid shrink_to_fit() noexcept;\n\n\t\t// missing (could be implemented):\n\t\t//\t\tassign()\n\t\t//\t\tset_allocator()\n\t\t//\t\tset_capacity()\n\t\t//\t\tvalidate()\n\t\t//\t\tvalidate_iterator()\n\n\t\t// segmented_vector is almost a deque, but cannot provide:\n\t\t//\t\toperator[]\n\t\t//\t\tat()\n\t\t//\t\tinsert()\n\t\t//\t\tpush_front()\n\t\t//\t\templace()\n\t\t//\t\templace_front()\n\t\t//\t\terase()\n\t\t// because it is not a random access container and can only push/pop elements from the back.\n\n\t\tT& push_back();\n\t\tT& push_back(const T& value);\n\t\tT& push_back(T&& value);\n\t\tvoid* push_back_uninitialized();\n\n\t\ttemplate <class... Args>\n\t\tT& emplace_back(Args&&... args);\n\n\t\tvoid pop_back();\n\n\t\tvoid erase_unsorted(segment_type& segment, typename segment_type::iterator it);\n\t\titerator erase_unsorted(const iterator& i);\n\n\t\tvoid swap(this_type& other);\n\n\tprotected:\n\t\t// This does not initialize the entry, it just makes returns a\n\t\t// pointer to an address where one could initialize one.\n\t\tvoid* DoPushBack();\n\n\t\t// Moves the segment into the free list\n\t\tvoid AddToFreeList(segment_type* segment);\n\n\t\t// Get a segment from the free list, or allocate a segment if\n\t\t// there are none.  Sets up the segment's \"last segment\" flag.\n\t\tsegment_type* GetUnusedSegmentForLastSegment(segment_type* prevSegment);\n\n\t\t// Allocate a new segment.\n\t\tsegment_type* AllocateNewSegment();\n\n\t\t// Destroys the elements in the container. Optionally also\n\t\t// frees all the memory.\n\t\ttemplate <bool bFreeMemory>\n\t\tvoid Clear();\n\n\t\t// If the last segment is empty, this function will move it to\n\t\t// the free list and update mLastSegment with the previous\n\t\t// segment.\n\t\tvoid UpdateLastSegment();\n\n\t\t// Remove the last `n` elements in the container.\n\t\tvoid EraseFromBack(size_type n);\n\n\t\t// Pushes `n` copies of `v`\n\t\tvoid PushBack(size_type n, const value_type& v);\n\n\t\ttemplate<bool bDoMove, typename ForwardIt>\n\t\tvoid InsertRange(ForwardIt begin, ForwardIt end);\n\n\t\tallocator_type mAllocator;\n\t\tsegment_type* mFirstSegment{};\n\t\tsegment_type* mLastSegment{};\n\t\tsegment_type* mFreeList{};\n\t\tsize_type mInUseSegmentCount{};\n\n\t\t// TODO: consider storing this in the first free segment (if\n\t\t// there is one), it'd save the memory for this member but\n\t\t// would make things like `capacity()` less cache coherent and\n\t\t// branchy (we need to check if there's a free segment)\n\t\tsize_type mFreeListSegmentCount{};\n\t};\n\n\n\t/////////////////////////////////////\n\t//   segment\n\t/////////////////////////////////////\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline const segment<T, Count, Allocator>*\n\tsegment<T, Count, Allocator>::next_segment() const\n\t{\n\t\tif (mPrev & kIsLastSegment)\n\t\t\treturn nullptr;\n\t\telse\n\t\t\treturn mNext;\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline segment<T, Count, Allocator>*\n\tsegment<T, Count, Allocator>::next_segment()\n\t{\n\t\tif (mPrev & kIsLastSegment)\n\t\t\treturn nullptr;\n\t\telse\n\t\t\treturn mNext;\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline typename segment<T, Count, Allocator>::const_iterator\n\tsegment<T, Count, Allocator>::begin() const\n\t{\n\t\treturn reinterpret_cast<const T*>(&mData);\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline typename segment<T, Count, Allocator>::iterator\n\tsegment<T, Count, Allocator>::begin()\n\t{\n\t\treturn reinterpret_cast<T*>(&mData);\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline typename segment<T, Count, Allocator>::const_iterator\n\tsegment<T, Count, Allocator>::end() const\n\t{\n\t\tif (mPrev & kIsLastSegment)\n\t\t\treturn begin() + mSize;\n\t\telse\n\t\t\treturn begin() + Count;\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline typename segment<T, Count, Allocator>::iterator\n\tsegment<T, Count, Allocator>::end()\n\t{\n\t\tif (mPrev & kIsLastSegment)\n\t\t\treturn begin() + mSize;\n\t\telse\n\t\t\treturn begin() + Count;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void segment<T, Count, Allocator>::DestroyData()\n\t{\n\t\t// TODO: Our current call sites know the value of\n\t\t// (mPrev & kIsLastSegment), consider having 2 implementations\n\t\t// of this which don't branch or something like that.\n\t\tT* ptr = begin();\n\t\tconst size_type count = (mPrev & kIsLastSegment) ? mSize : Count;\n\t\tfor (size_type i = 0; i < count; ++i)\n\t\t{\n\t\t\teastl::destroy_at(ptr);\n\t\t\tptr++;\n\t\t}\n\t\tmSize = 0;\n\t}\n\n\n\t/////////////////////////////////////\n\t//   segmented_vector_iterator\n\t/////////////////////////////////////\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    T*\n\tsegmented_vector_iterator<T, Count, Allocator>::operator->() const\n\t{\n\t\treturn mCurrent;\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    T&\n\tsegmented_vector_iterator<T, Count, Allocator>::operator*() const\n\t{\n\t\treturn *mCurrent;\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    segmented_vector_iterator<T, Count, Allocator>&\n\tsegmented_vector_iterator<T, Count, Allocator>::operator++()\n\t{\n\t\t++mCurrent;\n        if(EASTL_UNLIKELY(mCurrent == mEnd))\n        {\n\t\t\tif (!(mSegment->mPrev & segment_type::kIsLastSegment))\n\t\t\t{\n\t\t\t\tmSegment = mSegment->mNext;\n\t\t\t\tmCurrent = mSegment->begin();\n\t\t\t\tmEnd = mSegment->end();\n\t\t\t}\n\t\t\telse\n\t\t\t\tmCurrent = nullptr;\n        }\n        return *this;\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    segmented_vector_iterator<T, Count, Allocator>\n\tsegmented_vector_iterator<T, Count, Allocator>::operator++(int)\n\t{\n\t\tthis_type i(*this);\n\t\toperator++();\n\t\treturn i;\n\t}\n\n\n\t/////////////////////////////////////\n\t//   segmented_vector\n\t/////////////////////////////////////\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline segmented_vector<T, Count, Allocator>::segmented_vector(const Allocator& allocator)\n\t:\tmAllocator(allocator)\n\t{\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline segmented_vector<T, Count, Allocator>::segmented_vector(const segmented_vector& other)\n\t    : mAllocator(other.mAllocator)\n\t{\n\t\tInsertRange<false>(other.begin(), other.end());\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline segmented_vector<T, Count, Allocator>::segmented_vector(segmented_vector&& other)\n\t    : mAllocator(other.mAllocator)\n\t{\n\t\tswap(other);\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline segmented_vector<T, Count, Allocator>::segmented_vector(std::initializer_list<value_type> ilist, const Allocator& allocator)\n\t\t: mAllocator(allocator)\n\t{\n\t\tInsertRange<false>(ilist.begin(), ilist.end());\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline segmented_vector<T, Count, Allocator>& segmented_vector<T, Count, Allocator>::operator=(\n\t    const segmented_vector& other)\n\t{\n\t\tif (EA_UNLIKELY(this == &other))\n\t\t{\n\t\t\treturn *this;\n\t\t}\n\t\t// EASTL behaves as if propagate_on_container_copy_assignment\n\t\t// is globally false, so we don't propagate the allocator\n\t\t// here.\n\t\tif (size() > other.size())\n\t\t{\n\t\t\tEraseFromBack(size() - other.size());\n\t\t}\n\n\t\t// At this point size() <= other.size()\n\t\t// copy-assign elements which are already initialized.\n\t\tauto fromIt = other.begin();\n\t\t// TODO: consider doing segment copies, which do memcpy on\n\t\t// trivially copyable types.\n\t\tfor (auto toIt = begin(); toIt != end(); ++toIt, ++fromIt)\n\t\t{\n\t\t\t*toIt = *fromIt;\n\t\t}\n\n\t\t// Now we insert (copy construct) all the missing elements\n\t\t// in-place\n\t\tInsertRange<false>(fromIt, other.end());\n\n\t\treturn *this;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline segmented_vector<T, Count, Allocator>& segmented_vector<T, Count, Allocator>::operator=(\n\t    segmented_vector&& other)\n\t{\n\t\tif (EA_UNLIKELY(this == &other))\n\t\t{\n\t\t\treturn *this;\n\t\t}\n\n\t\t// EASTL behaves as if propagate_on_container_move_assignment\n\t\t// and propagate_on_container_swap are both globally true, so\n\t\t// we just swap and clear the one we're returning.\n\t\tswap(other);\n\t\tother.Clear<true>();\n\t\treturn *this;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline segmented_vector<T, Count, Allocator>::~segmented_vector()\n\t{\n\t\tClear<true>();\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline const typename segmented_vector<T, Count, Allocator>::allocator_type&\n\tsegmented_vector<T, Count, Allocator>::get_allocator() const noexcept\n\t{\n\t\treturn mAllocator;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::allocator_type&\n\tsegmented_vector<T, Count, Allocator>::get_allocator() noexcept\n\t{\n\t\treturn mAllocator;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline const typename segmented_vector<T, Count, Allocator>::segment_type*\n\tsegmented_vector<T, Count, Allocator>::first_segment() const noexcept\n\t{\n\t\treturn mFirstSegment;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::segment_type*\n\tsegmented_vector<T, Count, Allocator>::first_segment() noexcept\n\t{\n\t\treturn mFirstSegment;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::const_iterator\n\tsegmented_vector<T, Count, Allocator>::begin() const noexcept\n\t{\n\t\titerator i;\n\t\ti.mSegment = mFirstSegment;\n\t\tif (mFirstSegment)\n\t\t{\n\t\t\ti.mCurrent = mFirstSegment->begin();\n\t\t\ti.mEnd = mFirstSegment->end();\n\t\t}\n\t\telse\n\t\t{\n\t\t\ti.mCurrent = nullptr;\n\t\t}\n\t\treturn (const_iterator&)i;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::iterator\n\tsegmented_vector<T, Count, Allocator>::begin() noexcept\n\t{\n\t\titerator i;\n\t\ti.mSegment = mFirstSegment;\n\t\tif (mFirstSegment)\n\t\t{\n\t\t\ti.mCurrent = mFirstSegment->begin();\n\t\t\ti.mEnd = mFirstSegment->end();\n\t\t}\n\t\telse\n\t\t\ti.mCurrent = nullptr;\n\t\treturn i;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::const_iterator\n\tsegmented_vector<T, Count, Allocator>::end() const noexcept\n\t{\n\t\titerator i;\n\t\ti.mCurrent = nullptr;\n\t\treturn (const_iterator&)i;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::iterator\n\tsegmented_vector<T, Count, Allocator>::end() noexcept\n\t{\n\t\titerator i;\n\t\ti.mCurrent = nullptr;\n\t\treturn i;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::size_type\n\tsegmented_vector<T, Count, Allocator>::size() const noexcept\n\t{\n\t\tif (segment_type* segment = mLastSegment)\n\t\t\treturn (mInUseSegmentCount-1)*Count + segment->mSize;\n\t\treturn 0;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::size_type\n\tsegmented_vector<T, Count, Allocator>::capacity() const noexcept\n\t{\n\t\treturn (mInUseSegmentCount + mFreeListSegmentCount) * Count;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::size_type\n\tsegmented_vector<T, Count, Allocator>::segment_count() const noexcept\n\t{\n\t\treturn mInUseSegmentCount;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline T&\n\tsegmented_vector<T, Count, Allocator>::front() noexcept\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(mFirstSegment == nullptr)) // We don't allow the user to reference an empty container.\n\t\t\tEASTL_FAIL_MSG(\"segmented_vector::front -- empty container\");\n#endif\n\n\t\treturn mFirstSegment->begin()[0];\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline T&\n\tsegmented_vector<T, Count, Allocator>::back() noexcept\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(mLastSegment == nullptr)) // We don't allow the user to reference an empty container.\n\t\t\tEASTL_FAIL_MSG(\"segmented_vector::back -- empty container\");\n#endif\n\n\t\tsegment_type* lastSegment = mLastSegment;\n\t\treturn lastSegment->begin()[lastSegment->mSize-1];\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline bool\n\tsegmented_vector<T, Count, Allocator>::empty() const noexcept\n\t{\n\t\treturn mFirstSegment == nullptr;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void\n\tsegmented_vector<T, Count, Allocator>::clear()\n\t{\n\t\tClear<false>();\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void segmented_vector<T, Count, Allocator>::reserve(size_type n)\n\t{\n\t\twhile (capacity() < n)\n\t\t{\n\t\t\tsegment_type* segment = AllocateNewSegment();\n\t\t\tAddToFreeList(segment);\n\t\t}\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void segmented_vector<T, Count, Allocator>::resize(size_type n, const value_type& v)\n\t{\n\t\tif (size() < n)\n\t\t{\n\t\t\tPushBack(n - size(), v);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tEraseFromBack(size() - n);\n\t\t}\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void\n\tsegmented_vector<T, Count, Allocator>::resize(size_type n)\n\t{\n\t\tresize(n, value_type());\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void segmented_vector<T, Count, Allocator>::shrink_to_fit() noexcept\n\t{\n\t\tstatic_assert(eastl::is_trivially_destructible_v<segment_type>,\n\t\t              \"segment_type doesn't call it's destructor here!\");\n\t\twhile (mFreeList)\n\t\t{\n\t\t\tsegment_type* toFree = mFreeList;\n\t\t\tmFreeList = reinterpret_cast<segment_type*>(toFree->mPrev);\n\t\t\tEASTLFree(mAllocator, toFree, sizeof(segment_type));\n\t\t}\n\n\t\tmFreeListSegmentCount = 0;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline T&\n\tsegmented_vector<T, Count, Allocator>::push_back()\n\t{\n\t\treturn *(::new (DoPushBack()) T());\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline T&\n\tsegmented_vector<T, Count, Allocator>::push_back(const T& value)\n\t{\n\t\treturn *(::new (DoPushBack()) T(value));\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline T&\n\tsegmented_vector<T, Count, Allocator>::push_back(T&& value)\n\t{\n\t\treturn *(::new (DoPushBack()) T(eastl::move(value)));\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void*\n\tsegmented_vector<T, Count, Allocator>::push_back_uninitialized()\n\t{\n\t\treturn DoPushBack();\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\ttemplate <class... Args>\n\tT& segmented_vector<T, Count, Allocator>::emplace_back(Args&&... args)\n\t{\n\t\treturn *(::new (DoPushBack()) T(eastl::forward<Args>(args)... ));\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void\n\tsegmented_vector<T, Count, Allocator>::pop_back()\n\t{\n\t\tsegment_type* lastSegment = mLastSegment;\n        #if EASTL_ASSERT_ENABLED\n            if(EASTL_UNLIKELY(!lastSegment))\n                EASTL_FAIL_MSG(\"segmented_vector::pop_back -- segmented vector is empty\");\n        #endif\n\t\t--lastSegment->mSize;\n\t\tT* const toDestroy = lastSegment->begin() + lastSegment->mSize;\n\t\teastl::destroy_at(toDestroy);\n\n\t\tUpdateLastSegment();\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void\n\tsegmented_vector<T, Count, Allocator>::erase_unsorted(segment_type& segment, typename segment_type::iterator it)\n\t{\n\t\tEA_UNUSED(segment);\n\n\t\t*it = back();\n\t\tpop_back();\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::iterator\n\tsegmented_vector<T, Count, Allocator>::erase_unsorted(const iterator& i)\n\t{\n\t\titerator ret(i);\n\t\t*i = back();\n\t\tif (i.mSegment == mLastSegment && mLastSegment->mSize == 1)\n\t\t\tret.mCurrent = nullptr;\n\t\tpop_back();\n\t\treturn ret;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tvoid\n\tsegmented_vector<T, Count, Allocator>::swap(this_type& other)\n\t{\n\t\tusing eastl::swap;\n\t\t//\n\t\t// EASTL doesn't have allocator_traits it has the effective\n\t\t// behavior of propagate_on_container_swap = true for all\n\t\t// allocators.\n\t\tswap(mAllocator, other.mAllocator);\n\t\tswap(mFirstSegment, other.mFirstSegment);\n\t\tswap(mLastSegment, other.mLastSegment);\n\t\tswap(mFreeList, other.mFreeList);\n\t\tswap(mInUseSegmentCount, other.mInUseSegmentCount);\n\t\tswap(mFreeListSegmentCount, other.mFreeListSegmentCount);\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void*\n\tsegmented_vector<T, Count, Allocator>::DoPushBack()\n\t{\n\t\t// This does not initialize the entry, it just makes room for it.\n\t\tif (segment_type* segment = mLastSegment)\n\t\t{\n\t\t\tsize_type size = segment->mSize;\n\t\t\tif (size < Count)\n\t\t\t{\n\t\t\t\t++segment->mSize;\n\t\t\t\treturn segment->begin() + size;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsegment_type* lastSegment = mLastSegment;\n\t\t\t\tsegment_type* newSegment = mLastSegment = GetUnusedSegmentForLastSegment(mLastSegment);\n\t\t\t\tlastSegment->mPrev &= ~segment_type::kIsLastSegment;\n\t\t\t\tlastSegment->mNext = newSegment;\n\t\t\t\tnewSegment->mSize = 1;\n\t\t\t\treturn newSegment->begin();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsegment = mFirstSegment = mLastSegment = GetUnusedSegmentForLastSegment(nullptr);\n\t\t\tsegment->mSize = 1;\n\t\t\treturn segment->begin();\n\t\t}\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void\n\tsegmented_vector<T, Count, Allocator>::AddToFreeList(segment_type* segment)\n\t{\n\t\tsegment->mPrev = reinterpret_cast<uintptr_t>(mFreeList);\n\t\tmFreeList = segment;\n\t\tmFreeListSegmentCount++;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::segment_type*\n\tsegmented_vector<T, Count, Allocator>::GetUnusedSegmentForLastSegment(segment_type* prevSegment)\n\t{\n\t\tsegment_type* const newSegment = [&]\n\t\t{\n\t\t\tif (mFreeList)\n\t\t\t{\n\t\t\t\tmFreeListSegmentCount--;\n\t\t\t\tsegment_type* const freeSegment = mFreeList;\n\t\t\t\tmFreeList = reinterpret_cast<segment_type*>(freeSegment->mPrev);\n\t\t\t\treturn freeSegment;\n\t\t\t}\n\n\t\t\treturn AllocateNewSegment();\n\t\t}();\n\n\t\tmInUseSegmentCount++;\n\t\tnewSegment->mPrev = uintptr_t(prevSegment) | segment_type::kIsLastSegment;\n\t\tnewSegment->mSize = 0;\n\t\treturn newSegment;\n\t}\n\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline typename segmented_vector<T, Count, Allocator>::segment_type*\n\tsegmented_vector<T, Count, Allocator>::AllocateNewSegment()\n\t{\n\t\tstatic_assert(eastl::is_trivially_constructible_v<segment_type>, \"We're not initializing segment_type here\");\n\t\treturn (segment_type*)allocate_memory(mAllocator, sizeof(segment_type), EASTL_ALIGN_OF(segment_type), 0);\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\ttemplate <bool bFreeMemory>\n\tinline void segmented_vector<T, Count, Allocator>::Clear()\n\t{\n\t\tif (bFreeMemory)\n\t\t{\n\t\t\t// Delete what was already in the free list before this\n\t\t\t// call.\n\t\t\tshrink_to_fit();\n\t\t}\n\n\t\tsegment_type* segment = mFirstSegment;\n\t\tif (segment == nullptr)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tconst auto& wrapUp = [this](segment_type* s)\n\t\t{\n\t\t\ts->DestroyData();\n\t\t\tif (!bFreeMemory)\n\t\t\t{\n\t\t\t\tAddToFreeList(s);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEASTLFree(mAllocator, s, sizeof(segment_type));\n\t\t\t}\n\t\t};\n\n\t\t// Note: the last segment is special because its active member\n\t\t// is mSize not mNext, so we need to deal with it separately.\n\t\twhile (segment != mLastSegment)\n\t\t{\n\t\t\tsegment_type* nextSegment = segment->mNext;\n\t\t\twrapUp(segment);\n\t\t\tsegment = nextSegment;\n\t\t}\n\n\t\twrapUp(segment);\n\n\t\tmFirstSegment = nullptr;\n\t\tmLastSegment = nullptr;\n\t\tmInUseSegmentCount = 0;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void segmented_vector<T, Count, Allocator>::UpdateLastSegment()\n\t{\n\t\t// Assumes there is a last segment.\n\t\tsegment_type* lastSegment = mLastSegment;\n\t\tif (lastSegment->mSize == 0)\n\t\t{\n\t\t\t--mInUseSegmentCount;\n\t\t\tmLastSegment = (segment_type*)(lastSegment->mPrev & (~segment_type::kIsLastSegment));\n\t\t\tAddToFreeList(lastSegment);\n\t\t\tif (mLastSegment)\n\t\t\t{\n\t\t\t\tmLastSegment->mPrev |= segment_type::kIsLastSegment;\n\t\t\t\tmLastSegment->mSize = Count;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmFirstSegment = nullptr;\n\t\t\t}\n\t\t}\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void segmented_vector<T, Count, Allocator>::EraseFromBack(size_type toRemoveCount)\n\t{\n\t\t// This is only marginally better than doing consecutive pop_back() calls, is it worth it?\n\n\t\t// No bounds checking for this, we assume we have at least `toRemoveCount` elements.\n\n\t\t// Drop whole segments while we can.\n\t\twhile (toRemoveCount >= mLastSegment->mSize)\n\t\t{\n\t\t\tconst size_type removed = mLastSegment->mSize;\n\t\t\tmLastSegment->DestroyData();\n\t\t\tUpdateLastSegment();\n\t\t\ttoRemoveCount -= removed;\n\t\t}\n\n\t\t// There's a chance we completely emptied the container here.\n\t\tif (mLastSegment == nullptr)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// at this point we know there's more entries in the last\n\t\t// segment that there are elements left to remove.\n\t\tfor (size_type i = 1; i <= toRemoveCount; ++i)\n\t\t{\n\t\t\tconst size_type toRemoveIndex = mLastSegment->mSize - i;\n\t\t\tT* const toRemove = mLastSegment->begin() + toRemoveIndex;\n\t\t\teastl::destroy_at(toRemove);\n\t\t}\n\t\tmLastSegment->mSize -= toRemoveCount;\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\tinline void segmented_vector<T, Count, Allocator>::PushBack(size_type toAddCount, const value_type& v)\n\t{\n\t\t// This is only marginally better than doing consecutive push_back(v) calls, is it worth it?\n\n\t\tif (!mLastSegment && (toAddCount > 0))\n\t\t{\n\t\t\tmFirstSegment = mLastSegment = GetUnusedSegmentForLastSegment(nullptr);\n\t\t}\n\n\t\tconst auto& fillLastSegment = [&]()\n\t\t{\n\t\t\tconst size_type spaceInSegment = Count - mLastSegment->mSize;\n\t\t\tconst size_type addedThisLoop = eastl::min(toAddCount, spaceInSegment);\n\t\t\tfor (size_type i = 0; i < addedThisLoop; ++i)\n\t\t\t{\n\t\t\t\tT* slot = mLastSegment->begin() + mLastSegment->mSize + i;\n\t\t\t\tnew (slot) T(v);\n\t\t\t}\n\t\t\tmLastSegment->mSize += addedThisLoop;\n\t\t\ttoAddCount -= addedThisLoop;\n\t\t};\n\n\t\t// fill the current last segment.\n\t\tfillLastSegment();\n\n\t\t// if there's still stuff to add, we need to add new segments as we go.\n\t\twhile (toAddCount > 0)\n\t\t{\n\t\t\tmLastSegment = GetUnusedSegmentForLastSegment(mLastSegment);\n\t\t\tfillLastSegment();\n\t\t}\n\t}\n\n\ttemplate <typename T, size_t Count, typename Allocator>\n\ttemplate<bool bDoMove, typename ForwardIt>\n\tinline void segmented_vector<T, Count, Allocator>::InsertRange(ForwardIt begin, ForwardIt end)\n\t{\n\t\t// TODO: this can be greatly improved, e.g. memcpy entire\n\t\t// segments when the element types are trivially_copyable and\n\t\t// things like that, for now just do the trivial thing.\n\t\tfor (auto it = begin; it != end; ++it)\n\t\t{\n\t\t\tif (bDoMove)\n\t\t\t{\n\t\t\t\tpush_back(eastl::move(*it));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpush_back(*it);\n\t\t\t}\n\t\t}\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    inline bool operator==(const segmented_vector_iterator<const T, Count, Allocator>& a, const segmented_vector_iterator<const T, Count, Allocator>& b)\n    {\n        return a.mCurrent == b.mCurrent;\n    }\n\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    inline bool operator!=(const segmented_vector_iterator<const T, Count, Allocator>& a, const segmented_vector_iterator<const T, Count, Allocator>& b)\n    {\n        return a.mCurrent != b.mCurrent;\n    }\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    inline bool operator==(const segmented_vector_iterator<T, Count, Allocator>& a, const segmented_vector_iterator<T, Count, Allocator>& b)\n    {\n        return a.mCurrent == b.mCurrent;\n    }\n\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n    inline bool operator!=(const segmented_vector_iterator<T, Count, Allocator>& a, const segmented_vector_iterator<T, Count, Allocator>& b)\n    {\n        return a.mCurrent != b.mCurrent;\n    }\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline bool operator==(const segmented_vector<T, Count, Allocator>& a, const segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin());\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline synth_three_way_result<T> operator<=>(const segmented_vector<T, Count, Allocator>& a, const segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#endif\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline bool operator!=(const segmented_vector<T, Count, Allocator>& a, const segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline bool operator<(const segmented_vector<T, Count, Allocator>& a, const segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline bool operator>(const segmented_vector<T, Count, Allocator>& a, const segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline bool operator<=(const segmented_vector<T, Count, Allocator>& a, const segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline bool operator>=(const segmented_vector<T, Count, Allocator>& a, const segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\ttemplate<typename T, size_t Count, typename Allocator>\n\tinline void swap(segmented_vector<T, Count, Allocator>& a, segmented_vector<T, Count, Allocator>& b)\n\t{\n\t\ta.swap(b);\n\t}\n}\n\n#endif\n"
  },
  {
    "path": "include/EASTL/set.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SET_H\n#define EASTL_SET_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/red_black_tree.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_SET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_SET_DEFAULT_NAME\n\t\t#define EASTL_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" set\" // Unless the user overrides something, this is \"EASTL set\".\n\t#endif\n\n\n\t/// EASTL_MULTISET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_MULTISET_DEFAULT_NAME\n\t\t#define EASTL_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" multiset\" // Unless the user overrides something, this is \"EASTL multiset\".\n\t#endif\n\n\n\t/// EASTL_SET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_SET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_SET_DEFAULT_ALLOCATOR allocator_type(EASTL_SET_DEFAULT_NAME)\n\t#endif\n\n\t/// EASTL_MULTISET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_MULTISET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_MULTISET_DEFAULT_ALLOCATOR allocator_type(EASTL_MULTISET_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// set\n\t///\n\t/// Implements a canonical set. \n\t///\n\t/// The large majority of the implementation of this class is found in the rbtree\n\t/// base class. We control the behaviour of rbtree via template parameters.\n\t///\n\t/// Note that the 'bMutableIterators' template parameter to rbtree is set to false.\n\t/// This means that set::iterator is const and the same as set::const_iterator.\n\t/// This is by design and it follows the C++ standard defect report recommendation.\n\t/// If the user wants to modify a container element, the user needs to either use\n\t/// mutable data members or use const_cast on the iterator's data member. Both of \n\t/// these solutions are recommended by the C++ standard defect report.\n\t/// To consider: Expose the bMutableIterators template policy here at the set level\n\t/// so the user can have non-const set iterators via a template parameter.\n\t///\n\t/// Pool allocation\n\t/// If you want to make a custom memory pool for a set container, your pool \n\t/// needs to contain items of type set::node_type. So if you have a memory\n\t/// pool that has a constructor that takes the size of pool items and the\n\t/// count of pool items, you would do this (assuming that MemoryPool implements\n\t/// the Allocator interface):\n\t///     typedef set<Widget, less<Widget>, MemoryPool> WidgetSet;    // Delare your WidgetSet type.\n\t///     MemoryPool myPool(sizeof(WidgetSet::node_type), 100);       // Make a pool of 100 Widget nodes.\n\t///     WidgetSet mySet(&myPool);                                   // Create a map that uses the pool.\n\t///\n\ttemplate <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>\n\tclass set\n\t\t: public rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, true>\n\t{\n\tpublic:\n\t\ttypedef rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, true> base_type;\n\t\ttypedef set<Key, Compare, Allocator>                                            this_type;\n\t\ttypedef typename base_type::size_type                                           size_type;\n\t\ttypedef typename base_type::value_type                                          value_type;\n\t\ttypedef typename base_type::iterator                                            iterator;\n\t\ttypedef typename base_type::const_iterator                                      const_iterator;\n\t\ttypedef typename base_type::reverse_iterator                                    reverse_iterator;\n\t\ttypedef typename base_type::const_reverse_iterator                              const_reverse_iterator;\n\t\ttypedef typename base_type::allocator_type                                      allocator_type;\n\t\ttypedef Compare                                                                 value_compare;\n\t\ttypedef typename base_type::insert_return_type\t\t\t\t\t\t\t\t\tinsert_return_type;\n\t\t// Other types are inherited from the base class.\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::find;\n\t\tusing base_type::lower_bound;\n\t\tusing base_type::upper_bound;\n\t\tusing base_type::insert;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"set<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"set<T> value_type must be non-volatile.\");\n\n\tprotected:\n\t\tusing base_type::compare;\n\t\tusing base_type::get_compare;\n\n\tpublic:\n\t\tset(const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR);\n\t\t// some differences with the standard in what is marked as explicit in these constructors:\n\t\tset(const Compare& compare, const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR);\n\t\tset(const this_type& x);\n\t\tset(this_type&& x);\n\t\tset(this_type&& x, const allocator_type& allocator);\n\t\tset(std::initializer_list<value_type> ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR);\n\t\tset(std::initializer_list<value_type> ilist, const allocator_type& allocator);\n\n\t\ttemplate <typename Iterator>\n\t\tset(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\t// missing constructors, to implement:\n\t\t// \n\t\t// set(const this_type& x, const allocator_type& allocator);\n\t\t// \n\t\t// template <typename InputIterator>\n\t\t// set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());\n\t\t//\n\t\t// template <typename InputIterator>\n\t\t// set(InputIterator first, InputIterator last, const Allocator& alloc);\n\n\t\t// The (this_type&& x) ctor above has the side effect of forcing us to make operator= visible in this subclass.\n\t\tthis_type& operator=(const this_type& x) { return (this_type&)base_type::operator=(x); }\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist) { return (this_type&)base_type::operator=(ilist); }\n\t\tthis_type& operator=(this_type&& x) { return (this_type&)base_type::operator=(eastl::move(x)); }\n\n\tpublic:\n\t\tvalue_compare value_comp() const;\n\n\t\tsize_type erase(const Key& k) { return DoErase(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, iterator> && !eastl::is_convertible_v<KX&&, const_iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type erase(KX&& k) { return DoErase(eastl::forward<KX>(k)); }\n\t\titerator  erase(const_iterator position);\n\t\titerator  erase(const_iterator first, const_iterator last);\n\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\t// this function was incorrectly defined in the rbtree base type.\n\t\t// this function implicitly converts to value_type, which it shouldn't. Additionally, it does not correctly support heterogeneous insertion (unconditionally creates a key_type).\n\t\ttemplate <typename P, typename Cmp = Compare, eastl::enable_if_t<!eastl::is_convertible_v<P&&, value_type> && !eastl::detail::is_transparent_comparison_v<Cmp> && eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Replace call with insert(value_type(...)) or emplace(...) or declare container with a transparent comparator.\")\n\t\tinsert_return_type insert(P&& otherValue) { return base_type::emplace(eastl::forward<P>(otherValue)); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tinsert_return_type insert(KX&& key)\n\t\t{\n\t\t\t// There's no function in the base type that we can re-use here. insert(value_type&&) is implemented in terms of DoInsertValue(), but that\n\t\t\t// unconditionally creates a node and therefore the key_type. So we create our own appropriate implementation.\n\n\t\t\tbool       canInsert;\n\t\t\trbtree_node_base* pPosition = base_type::DoGetKeyInsertionPositionUniqueKeys(canInsert, key);\n\n\t\t\tif (canInsert)\n\t\t\t{\n\t\t\t\ttypename base_type::node_type* const pNodeNew = base_type::DoCreateNode(eastl::forward<KX>(key)); // Note that pNodeNew->mpLeft, mpRight, mpParent, will be uninitialized.\n\t\t\t\titerator itResult = base_type::DoInsertValueImpl(pPosition, false, pNodeNew->mValue, pNodeNew);\n\t\t\t\treturn pair<iterator, bool>(itResult, true);\n\t\t\t}\n\n\t\t\treturn pair<iterator, bool>(iterator(pPosition), false);\n\t\t}\n\n\t\tsize_type count(const Key& k) const;\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& key) const { return (find(key) != end()) ? 1 : 0; }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const Key& key) { return DoEqualRange(key); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return DoEqualRange(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& key) { return DoEqualRange(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& key) const { return DoEqualRange(key); }\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tsize_type DoErase(KX&& k);\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& key) const;\n\t}; // set\n\n\n\n\n\n\t/// multiset\n\t///\n\t/// Implements a canonical multiset.\n\t///\n\t/// The large majority of the implementation of this class is found in the rbtree\n\t/// base class. We control the behaviour of rbtree via template parameters.\n\t///\n\t/// See notes above in 'set' regarding multable iterators.\n\t///\n\t/// Pool allocation\n\t/// If you want to make a custom memory pool for a multiset container, your pool \n\t/// needs to contain items of type multiset::node_type. So if you have a memory\n\t/// pool that has a constructor that takes the size of pool items and the\n\t/// count of pool items, you would do this (assuming that MemoryPool implements\n\t/// the Allocator interface):\n\t///     typedef multiset<Widget, less<Widget>, MemoryPool> WidgetSet;   // Delare your WidgetSet type.\n\t///     MemoryPool myPool(sizeof(WidgetSet::node_type), 100);           // Make a pool of 100 Widget nodes.\n\t///     WidgetSet mySet(&myPool);                                       // Create a map that uses the pool.\n\t///\n\ttemplate <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>\n\tclass multiset\n\t\t: public rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, false>\n\t{\n\tpublic:\n\t\ttypedef rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, false>    base_type;\n\t\ttypedef multiset<Key, Compare, Allocator>                                           this_type;\n\t\ttypedef typename base_type::size_type                                               size_type;\n\t\ttypedef typename base_type::value_type                                              value_type;\n\t\ttypedef typename base_type::iterator                                                iterator;\n\t\ttypedef typename base_type::const_iterator                                          const_iterator;\n\t\ttypedef typename base_type::reverse_iterator                                        reverse_iterator;\n\t\ttypedef typename base_type::const_reverse_iterator                                  const_reverse_iterator;\n\t\ttypedef typename base_type::allocator_type                                          allocator_type;\n\t\ttypedef Compare                                                                     value_compare;\n\t\ttypedef typename base_type::insert_return_type\t\t\t\t\t\t\t\t\t\tinsert_return_type;\n\t\t// Other types are inherited from the base class.\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::find;\n\t\tusing base_type::lower_bound;\n\t\tusing base_type::upper_bound;\n\t\tusing base_type::insert;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"multiset<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"multiset<T> value_type must be non-volatile.\");\n\n\tprotected:\n\t\tusing base_type::compare;\n\t\tusing base_type::get_compare;\n\n\tpublic:\n\t\tmultiset(const allocator_type& allocator = EASTL_MULTISET_DEFAULT_ALLOCATOR);\n\t\tmultiset(const Compare& compare, const allocator_type& allocator = EASTL_MULTISET_DEFAULT_ALLOCATOR);\n\t\tmultiset(const this_type& x);\n\t\tmultiset(this_type&& x);\n\t\tmultiset(this_type&& x, const allocator_type& allocator);\n\t\tmultiset(std::initializer_list<value_type> ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_MULTISET_DEFAULT_ALLOCATOR);\n\t\tmultiset(std::initializer_list<value_type> ilist, const allocator_type& allocator);\n\n\t\ttemplate <typename Iterator>\n\t\tmultiset(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\t// missing constructors, to implement:\n\t\t// \n\t\t// multiset(const this_type& x, const allocator_type& allocator);\n\t\t// \n\t\t// template <typename InputIterator>\n\t\t// multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());\n\t\t//\n\t\t// template <typename InputIterator>\n\t\t// multiset(InputIterator first, InputIterator last, const Allocator& alloc);\n\t\t\n\t\t// The (this_type&& x) ctor above has the side effect of forcing us to make operator= visible in this subclass.\n\t\tthis_type& operator=(const this_type& x) { return (this_type&)base_type::operator=(x); }\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist) { return (this_type&)base_type::operator=(ilist); }\n\t\tthis_type& operator=(this_type&& x) { return (this_type&)base_type::operator=(eastl::move(x)); }\n\n\tpublic:\n\t\tvalue_compare value_comp() const;\n\n\t\tsize_type erase(const Key& k) { return DoErase(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, iterator> && !eastl::is_convertible_v<KX&&, const_iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type erase(KX&& k) { return DoErase(eastl::forward<KX>(k)); }\n\t\titerator  erase(const_iterator position);\n\t\titerator  erase(const_iterator first, const_iterator last);\n\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\t// this function was incorrectly defined in the rbtree base type.\n\t\t// this function implicitly converts to value_type, which it shouldn't.\n\t\ttemplate <typename P, eastl::enable_if_t<!eastl::is_convertible_v<P&&, value_type> && eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Replace call with insert(value_type(...)) or emplace(...).\")\n\t\tinsert_return_type insert(P&& otherValue) { return base_type::emplace(eastl::forward<P>(otherValue)); }\n\n\t\tsize_type count(const Key& key) const { return DoCount(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& key) const { return DoCount(key); }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const Key& key) { return DoEqualRange(key); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return DoEqualRange(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& key) { return DoEqualRange(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& key) const { return DoEqualRange(key); }\n\n\t\t/// equal_range_small\n\t\t/// This is a special version of equal_range which is optimized for the \n\t\t/// case of there being few or no duplicated keys in the tree.\n\t\teastl::pair<iterator, iterator>             equal_range_small(const Key& key) { return DoEqualRangeSmall(key); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const Key& key) const { return DoEqualRangeSmall(key); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range_small(const KX& key) { return DoEqualRangeSmall(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const KX& key) const { return DoEqualRangeSmall(key); }\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tsize_type DoErase(KX&& k);\n\n\t\ttemplate<typename KX>\n\t\tsize_type\t\t\t\t\t\t\t\t\tDoCount(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRangeSmall(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRangeSmall(const KX& key) const;\n\t}; // multiset\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// set\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline set<Key, Compare, Allocator>::set(const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline set<Key, Compare, Allocator>::set(const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline set<Key, Compare, Allocator>::set(const this_type& x)\n\t\t: base_type(x)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline set<Key, Compare, Allocator>::set(this_type&& x)\n\t\t: base_type(eastl::move(x))\n\t{\n\t}\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline set<Key, Compare, Allocator>::set(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(eastl::move(x), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline set<Key, Compare, Allocator>::set(std::initializer_list<value_type> ilist, const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline set<Key, Compare, Allocator>::set(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), Compare(), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate <typename Iterator>\n\tinline set<Key, Compare, Allocator>::set(Iterator itBegin, Iterator itEnd)\n\t\t: base_type(itBegin, itEnd, Compare(), EASTL_SET_DEFAULT_ALLOCATOR)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename set<Key, Compare, Allocator>::value_compare\n\tset<Key, Compare, Allocator>::value_comp() const\n\t{\n\t\treturn get_compare();\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline typename set<Key, Compare, Allocator>::size_type\n\tset<Key, Compare, Allocator>::DoErase(KX&& k)\n\t{\n\t\tconst iterator it(find(k));\n\n\t\tif(it != end()) // If it exists...\n\t\t{\n\t\t\tbase_type::erase(it);\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename set<Key, Compare, Allocator>::iterator\n\tset<Key, Compare, Allocator>::erase(const_iterator position)\n\t{\n\t\t// We need to provide this version because we override another version \n\t\t// and C++ hiding rules would make the base version of this hidden.\n\t\treturn base_type::erase(position);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename set<Key, Compare, Allocator>::iterator\n\tset<Key, Compare, Allocator>::erase(const_iterator first, const_iterator last)\n\t{\n\t\t// We need to provide this version because we override another version \n\t\t// and C++ hiding rules would make the base version of this hidden.\n\t\treturn base_type::erase(first, last);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename set<Key, Compare, Allocator>::size_type\n\tset<Key, Compare, Allocator>::count(const Key& k) const\n\t{\n\t\tconst const_iterator it(find(k));\n\t\treturn (it != end()) ? (size_type)1 : (size_type)0;\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename set<Key, Compare, Allocator>::reverse_iterator\n\tset<Key, Compare, Allocator>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename set<Key, Compare, Allocator>::reverse_iterator\n\tset<Key, Compare, Allocator>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename set<Key, Compare, Allocator>::iterator,\n\t\t\t\t\t   typename set<Key, Compare, Allocator>::iterator>\n\tset<Key, Compare, Allocator>::DoEqualRange(const KX& k)\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst iterator itLower(lower_bound(k));\n\n\t\tif((itLower == end()) || compare(k, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<iterator, iterator>(itLower, itLower);\n\n\t\titerator itUpper(itLower);\n\t\treturn eastl::pair<iterator, iterator>(itLower, ++itUpper);\n\t}\n\t\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename set<Key, Compare, Allocator>::const_iterator,\n\t\t\t\t\t   typename set<Key, Compare, Allocator>::const_iterator>\n\tset<Key, Compare, Allocator>::DoEqualRange(const KX& k) const\n\t{\n\t\t// See equal_range above for comments.\n\t\tconst const_iterator itLower(lower_bound(k));\n\n\t\tif((itLower == end()) || compare(k, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itLower);\n\n\t\tconst_iterator itUpper(itLower);\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_if \n\t//\n\t// https://en.cppreference.com/w/cpp/container/set/erase_if\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class Key, class Compare, class Allocator, class Predicate>\n\ttypename set<Key, Compare, Allocator>::size_type erase_if(set<Key, Compare, Allocator>& c, Predicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <class Key, class Compare, class Allocator>\n\tsynth_three_way_result<Key> operator<=>(const set<Key, Compare, Allocator>& a, const set<Key, Compare, Allocator>& b)\n\t{\n\t    return eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// multiset\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline multiset<Key, Compare, Allocator>::multiset(const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline multiset<Key, Compare, Allocator>::multiset(const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline multiset<Key, Compare, Allocator>::multiset(const this_type& x)\n\t\t: base_type(x)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline multiset<Key, Compare, Allocator>::multiset(this_type&& x)\n\t\t: base_type(eastl::move(x))\n\t{\n\t}\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline multiset<Key, Compare, Allocator>::multiset(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(eastl::move(x), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline multiset<Key, Compare, Allocator>::multiset(std::initializer_list<value_type> ilist, const Compare& compare, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), compare, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline multiset<Key, Compare, Allocator>::multiset(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(ilist.begin(), ilist.end(), Compare(), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate <typename Iterator>\n\tinline multiset<Key, Compare, Allocator>::multiset(Iterator itBegin, Iterator itEnd)\n\t\t: base_type(itBegin, itEnd, Compare(), EASTL_MULTISET_DEFAULT_ALLOCATOR)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename multiset<Key, Compare, Allocator>::value_compare\n\tmultiset<Key, Compare, Allocator>::value_comp() const\n\t{\n\t\treturn get_compare();\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate <typename KX>\n\tinline typename multiset<Key, Compare, Allocator>::size_type\n\tmultiset<Key, Compare, Allocator>::DoErase(KX&& k)\n\t{\n\t\tconst eastl::pair<iterator, iterator> range(equal_range(k));\n\t\tconst size_type n = (size_type)eastl::distance(range.first, range.second);\n\t\tbase_type::erase(range.first, range.second);\n\t\treturn n;\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename multiset<Key, Compare, Allocator>::iterator\n\tmultiset<Key, Compare, Allocator>::erase(const_iterator position)\n\t{\n\t\t// We need to provide this version because we override another version \n\t\t// and C++ hiding rules would make the base version of this hidden.\n\t\treturn base_type::erase(position);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename multiset<Key, Compare, Allocator>::iterator\n\tmultiset<Key, Compare, Allocator>::erase(const_iterator first, const_iterator last)\n\t{\n\t\t// We need to provide this version because we override another version \n\t\t// and C++ hiding rules would make the base version of this hidden.\n\t\treturn base_type::erase(first, last);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline typename multiset<Key, Compare, Allocator>::size_type\n\tmultiset<Key, Compare, Allocator>::DoCount(const KX& k) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> range(equal_range(k));\n\t\treturn (size_type)eastl::distance(range.first, range.second);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename multiset<Key, Compare, Allocator>::reverse_iterator\n\tmultiset<Key, Compare, Allocator>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\tinline typename multiset<Key, Compare, Allocator>::reverse_iterator\n\tmultiset<Key, Compare, Allocator>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multiset<Key, Compare, Allocator>::iterator,\n\t\t\t\t\t   typename multiset<Key, Compare, Allocator>::iterator>\n\tmultiset<Key, Compare, Allocator>::DoEqualRange(const KX& k)\n\t{\n\t\t// There are multiple ways to implement equal_range. The implementation mentioned\n\t\t// in the C++ standard and which is used by most (all?) commercial STL implementations\n\t\t// is this:\n\t\t//    return eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));\n\t\t//\n\t\t// This does two tree searches -- one for the lower bound and one for the \n\t\t// upper bound. This works well for the case whereby you have a large container\n\t\t// and there are lots of duplicated values. We provide an alternative version\n\t\t// of equal_range called equal_range_small for cases where the user is confident\n\t\t// that the number of duplicated items is only a few.\n\n\t\treturn eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multiset<Key, Compare, Allocator>::const_iterator, \n\t\t\t\t\t   typename multiset<Key, Compare, Allocator>::const_iterator>\n\tmultiset<Key, Compare, Allocator>::DoEqualRange(const KX& k) const\n\t{\n\t\t// See comments above in the non-const version of equal_range.\n\t\treturn eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multiset<Key, Compare, Allocator>::iterator,\n\t\t\t\t\t   typename multiset<Key, Compare, Allocator>::iterator>\n\tmultiset<Key, Compare, Allocator>::DoEqualRangeSmall(const KX& k)\n\t{\n\t\t// We provide alternative version of equal_range here which works faster\n\t\t// for the case where there are at most small number of potential duplicated keys.\n\t\tconst iterator itLower(lower_bound(k));\n\t\titerator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !compare(k, *itUpper))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<iterator, iterator>(itLower, itUpper);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator>\n\ttemplate<typename KX>\n\tinline eastl::pair<typename multiset<Key, Compare, Allocator>::const_iterator, \n\t\t\t\t\t   typename multiset<Key, Compare, Allocator>::const_iterator>\n\tmultiset<Key, Compare, Allocator>::DoEqualRangeSmall(const KX& k) const\n\t{\n\t\t// We provide alternative version of equal_range here which works faster\n\t\t// for the case where there are at most small number of potential duplicated keys.\n\t\tconst const_iterator itLower(lower_bound(k));\n\t\tconst_iterator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !compare(k, *itUpper))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itUpper);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_if\n\t//\n\t// https://en.cppreference.com/w/cpp/container/multiset/erase_if\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class Key, class Compare, class Allocator, class Predicate>\n\ttypename multiset<Key, Compare, Allocator>::size_type erase_if(multiset<Key, Compare, Allocator>& c, Predicate predicate)\n\t{\n\t\tauto oldSize = c.size();\n\t\t// Erases all elements that satisfy the predicate pred from the container.\n\t\tfor (auto i = c.begin(), last = c.end(); i != last;)\n\t\t{\n\t\t\tif (predicate(*i))\n\t\t\t{\n\t\t\t\ti = c.erase(i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\treturn oldSize - c.size();\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <class Key, class Compare, class Allocator>\n\tsynth_three_way_result<Key> operator<=>(const multiset<Key, Compare, Allocator>& a, const multiset<Key, Compare, Allocator>& b)\n\t{\n\t    return eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#endif\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/shared_array.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Note (March 2014): shared_array is not a full implementation of an array version \n// of C++11 shared_ptr, and there currently are no plans to make it so. A future\n// version of shared_ptr would likely take on the ability to store arrays,\n// same as unique_ptr has array support. This class isn't deprecated, but it\n// is frozen until some future decision is made on what to do about arrays.\n//\n///////////////////////////////////////////////////////////////////////////////\n// This class implements a shared_array template. This is a class which is \n// similar to the C++ shared_ptr template, except that it works with arrays\n// instead of individual objects.\n//\n// Important notice:\n// As of this writing (9/2003), the implementation provided here has \n// limitations that you should be aware of. These limitations will be shortly\n// rectified. Most significantly, this implementation has the following \n// weaknesses:\n//     - It cannot safely deal with exceptions that occur during the \n//       construction of shared_ptr objects. \n//     - It cannot safely deal with recursive shared_ptr objects. \n//       If a shared_ptr<A> holds a pointer to an instance of A and \n//       class A owns an instance of shared_ptr<A> that refers to,\n//       the original instance, the memory will leak.\n//     - A template of type shared_ptr<void> will not call the destructor\n//       for an object that it stores. You thus must declare a shared_ptr\n//       template specifically for the class type.\n//     - It doesn't safely handle multiple instances of shared_ptr\n//       which own the same pointer accessed from multiple threads.\n//       This weakness is by design, for performance reasons. You should\n//       use shared_ptr_mt for multi-thread safe access.\n//\n// The rectification of the above issues are discussed in the C++ standardization\n// documents for the next C++ standard (as of 2003):\n//     http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html#Implementation-difficulty\n// \n// This current implementation will be eventually (hopefully by 1/2004) rectified \n// to be in line with the second generation C++ standard proposal.\n//\n// The intended design of this class is based somewhat on the design of the Boost\n// shared_array template. This design is also being considered for the next C++ \n// standard (as of 2003). The C++ standard update proposal is currently available at:\n//     http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html\n// Boost smart pointers, including shared_array are documented at:\n//     http://www.boost.org/libs/smart_ptr/\n//\n// As of this writing (10/2003), this class has received approval from EA legal\n// for use. The potential issue is the similarity of the class name and class \n// interface to existing open source code.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SHARED_ARRAY_H\n#define EASTL_SHARED_ARRAY_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/smart_ptr.h>   // Defines smart_array_deleter\n#include <EASTL/memory.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\n\nEA_DISABLE_ALL_VC_WARNINGS();\n\n\t#include <new>\n\t#include <stddef.h>\n\nEA_RESTORE_ALL_VC_WARNINGS();\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_SHARED_ARRAY_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_SHARED_ARRAY_DEFAULT_NAME\n\t\t#define EASTL_SHARED_ARRAY_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" shared_array\" // Unless the user overrides something, this is \"EASTL shared_array\".\n\t#endif\n\n\n\t/// EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR\n\t\t#define EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR allocator_type(EASTL_SHARED_ARRAY_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// class shared_array\n\t/// A shared_array is the same as shared_ptr but for arrays. \n\ttemplate <typename T, typename Allocator = EASTLAllocatorType, typename Deleter = smart_array_deleter<T> >\n\tclass shared_array\n\t{\n\tprotected:\n\t\t/// this_type\n\t\t/// This is an alias for shared_array<T>, this class.\n\t\ttypedef shared_array<T> this_type;\n\n\t\t/// allocator_type\n\t\ttypedef Allocator allocator_type;\n\n\t\t/// deleter_type\n\t\ttypedef Deleter deleter_type;\n\n\t\t/// ref_count\n\t\t/// An internal reference count type. Must be convertable to int\n\t\t/// so that the public use_count function can work.\n\t\ttypedef int ref_count;\n\n\t\tT*              mpArray;       /// The owned pointer. Points to an array of T.\n\t\tref_count*      mpRefCount;    /// Reference count for owned pointer.\n\t\tallocator_type  mAllocator;    /// The allocator used to manage new/delete of mpRefCount.\n\n\tpublic:\n\t\ttypedef T element_type;\n\n\t\t/// shared_array\n\t\t/// Takes ownership of the pointer and sets the reference count\n\t\t/// to the pointer to 1. It is OK if the input pointer is null.\n\t\t/// The shared reference count is allocated on the heap via operator new.\n\t\t/// If an exception occurs during the allocation of the shared \n\t\t/// reference count, the owned pointer is deleted and the exception\n\t\t/// is rethrown. A null pointer is given a reference count of 1.\n\t\texplicit shared_array(T* pArray = NULL, const allocator_type& allocator = EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR)\n\t\t\t: mpArray(pArray),\n\t\t\t  mpRefCount(NULL),\n\t\t\t  mAllocator(allocator)\n\t\t{\n\t\t\t// Allocate memory for the reference count.\n\t\t\tmpRefCount = (ref_count*) EASTLAlloc(mAllocator, sizeof(ref_count));\n\t\t\tif(mpRefCount)\n\t\t\t\tdetail::allocator_construct(mAllocator, mpRefCount, 1);\n\t\t}\n\n\n\t\t/// shared_array\n\t\t/// Shares ownership of a pointer with another instance of shared_array.\n\t\t/// This function increments the shared reference count on the pointer.\n\t\t/// If we want a shared_array constructor that is templated on shared_array<U>,\n\t\t/// then we need to make it in addition to this function, as otherwise \n\t\t/// the compiler will generate this function and things will go wrong.\n\t\tshared_array(const shared_array& sharedArray)\n\t\t\t: mpArray(sharedArray.mpArray),\n\t\t\t  mpRefCount(sharedArray.mpRefCount),\n\t\t\t  mAllocator(sharedArray.mAllocator)\n\t\t{\n\t\t\t++*mpRefCount;\n\t\t}\n\n\n\t\t/// ~shared_array\n\t\t/// Decrements the reference count for the owned pointer. If the \n\t\t/// reference count goes to zero, the owned pointer is deleted and\n\t\t/// the shared reference count is deleted.\n\t\t~shared_array()\n\t\t{\n\t\t\tconst ref_count newRefCount(--*mpRefCount); \n\t\t\t// assert(newRefCount >= 0);\n\t\t\tif(newRefCount == 0)\n\t\t\t{\n\t\t\t\tEASTLFree(mAllocator, mpRefCount, sizeof(ref_count));\n\t\t\t\tDeleter del;\n\t\t\t\tdel(mpArray);\n\t\t\t}\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Copies another shared_array to this object. Note that this object\n\t\t/// may already own a shared pointer with another different pointer\n\t\t/// (but still of the same type) before this call. In that case,\n\t\t/// this function releases the old pointer, decrementing its reference\n\t\t/// count and deleting it if zero, takes shared ownership of the new \n\t\t/// pointer and increments its reference count.\n\t\t/// If we want a shared_array operator= that is templated on shared_array<U>,\n\t\t/// then we need to make it in addition to this function, as otherwise \n\t\t/// the compiler will generate this function and things will go wrong.\n\t\tshared_array& operator=(const shared_array& sharedArray)\n\t\t{\n\t\t\tif(mpArray != sharedArray.mpArray)\n\t\t\t{\n\t\t\t\t// The easiest thing to do is to create a temporary and \n\t\t\t\t// copy ourselves ourselves into it. This is a standard \n\t\t\t\t// method for switching pointer ownership in systems like this.\n\t\t\t\tshared_array(sharedArray).swap(*this);\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Assigns a new pointer, while decrementing the reference count on\n\t\t/// the current pointer. The new pointer can be NULL and the current\n\t\t/// pointer can NULL. If the new pointer is equivalent to the current\n\t\t/// pointer, then nothing is done.\n\t\tshared_array& operator=(T* pValue)\n\t\t{\n\t\t\treset(pValue);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Releases the owned pointer and takes ownership of the \n\t\t/// passed in pointer. If the passed in pointer is the same\n\t\t/// as the owned pointer, nothing is done. The passed in pointer\n\t\t/// can be null, in which case the use count is set to 1.\n\t\tvoid reset(T* pArray = NULL)\n\t\t{\n\t\t\tif(pArray != mpArray)\n\t\t\t{\n\t\t\t\t// The easiest thing to do is to create a temporary and \n\t\t\t\t// copy ourselves ourselves into it. This is a standard \n\t\t\t\t// method for switching pointer ownership in systems like this.\n\t\t\t\tshared_array(pArray, mAllocator).swap(*this);\n\t\t\t}\n\t\t}\n\n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer beween two shared_array objects.\n\t\tvoid swap(this_type& sharedArray)\n\t\t{\n\t\t\t// We leave mAllocator as-is.\n\n\t\t\t// eastl::swap(mpArray, sharedArray.mpArray);\n\t\t\tT* const pArray     = sharedArray.mpArray;\n\t\t\tsharedArray.mpArray = mpArray;\n\t\t\tmpArray             = pArray;\n\n\t\t\t// eastl::swap(mpRefCount, sharedArray.mpRefCount);\n\t\t\tref_count* const pRefCount = sharedArray.mpRefCount;\n\t\t\tsharedArray.mpRefCount     = mpRefCount;\n\t\t\tmpRefCount                 = pRefCount;\n\t\t}\n\n\n\t\t/// operator[]\n\t\t/// Returns a reference to the specified item in the owned pointer\n\t\t/// array. \n\t\t/// Example usage:\n\t\t///    shared_array<int> ptr = new int[6];\n\t\t///    int x = ptr[2];\n\t\tT& operator[](ptrdiff_t i) const\n\t\t{\n\t\t\t// assert(mpArray && (i >= 0));\n\t\t\treturn mpArray[i];\n\t\t}\n\n\t\t/// operator*\n\t\t/// Returns the owner pointer dereferenced.\n\t\t/// Example usage:\n\t\t///    shared_array<int> ptr = new int(3);\n\t\t///    int x = *ptr;\n\t\tT& operator*() const\n\t\t{\n\t\t\t// assert(mpArray);\n\t\t\treturn *mpArray;\n\t\t}\n\n\t\t/// operator->\n\t\t/// Allows access to the owned pointer via operator->()\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    shared_array<int> ptr = new X;\n\t\t///    ptr->DoSomething();\n\t\tT* operator->() const EA_NOEXCEPT\n\t\t{\n\t\t\t// assert(mpArray);\n\t\t\treturn mpArray;\n\t\t}\n\n\t\t/// get\n\t\t/// Returns the owned pointer. Note that this class does \n\t\t/// not provide an operator T() function. This is because such\n\t\t/// a thing (automatic conversion) is deemed unsafe.\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    shared_array<int> ptr = new X;\n\t\t///    X* pX = ptr.get();\n\t\t///    pX->DoSomething();\n\t\tT* get() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mpArray;\n\t\t}\n\n\t\t/// use_count\n\t\t/// Returns the reference count on the owned pointer.\n\t\t/// The return value is one if the owned pointer is null.\n\t\tint use_count() const\n\t\t{\n\t\t\t// assert(mpRefCount);\n\t\t\treturn (int)*mpRefCount;\n\t\t}\n\n\t\t/// unique\n\t\t/// Returns true if the reference count on the owned pointer is one.\n\t\t/// The return value is true if the owned pointer is null.\n\t\tbool unique() const\n\t\t{\n\t\t\t// assert(mpRefCount);\n\t\t\treturn (*mpRefCount == 1);\n\t\t}\n\n\t\t/// Implicit operator bool\n\t\t/// Allows for using a scoped_ptr as a boolean. \n\t\t/// Example usage:\n\t\t///    shared_array<int> ptr = new int(3);\n\t\t///    if(ptr)\n\t\t///        ++*ptr;\n\t\t///     \n\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t/// The result is that this: if(sharedArray == 1) would yield true (bad).\n\t\ttypedef T* (this_type::*bool_)() const;\n\t\toperator bool_() const EA_NOEXCEPT\n\t\t{\n\t\t\tif(mpArray)\n\t\t\t\treturn &this_type::get;\n\t\t\treturn NULL;\n\t\t}\n\n\t\t/// operator!\n\t\t/// This returns the opposite of operator bool; it returns true if \n\t\t/// the owned pointer is null. Some compilers require this and some don't.\n\t\t///    shared_array<int> ptr = new int(3);\n\t\t///    if(!ptr)\n\t\t///        assert(false);\n\t\tbool operator!() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (mpArray == NULL);\n\t\t}\n\n\t\t/// get_allocator\n\t\t/// Returns the memory allocator associated with this class.\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mAllocator;\n\t\t}\n\t\tallocator_type& get_allocator() EA_NOEXCEPT\n\t\t{\n\t\t\treturn mAllocator;\n\t\t}\n\n\t\t/// set_allocator\n\t\t/// Sets the memory allocator associated with this class.\n\t\tvoid set_allocator(const allocator_type& allocator)\n\t\t{\n\t\t\tif(mpRefCount && mAllocator != allocator)\n\t\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"shared_array::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\t\tmAllocator = allocator;\n\t\t}\n\n\t}; // class shared_array\n\n\n\n\t/// get_pointer\n\t/// returns shared_array::get() via the input shared_array. \n\ttemplate <typename T, typename A, typename D>\n\tinline T* get_pointer(const shared_array<T, A, D>& sharedArray)\n\t{\n\t\treturn sharedArray.get();\n\t}\n\n\t/// swap\n\t/// Exchanges the owned pointer beween two shared_array objects.\n\t/// This non-member version is useful for compatibility of shared_array\n\t/// objects with the C++ Standard Library and other libraries.\n\ttemplate <typename T, typename A, typename D>\n\tinline void swap(shared_array<T, A, D>& sharedArray1, shared_array<T, A, D>& sharedArray2)\n\t{\n\t\tsharedArray1.swap(sharedArray2);\n\t}\n\n\n\t/// operator!=\n\t/// Compares two shared_array objects for equality. Equality is defined as \n\t/// being true when the pointer shared between two shared_array objects is equal.\n\t/// It is debatable what the appropriate definition of equality is between two\n\t/// shared_array objects, but we follow the current 2nd generation C++ standard proposal.\n\ttemplate <typename T, typename TA, typename TD, typename U, typename UA, typename UD>\n\tinline bool operator==(const shared_array<T, TA, TD>& sharedArray1, const shared_array<U, UA, UD>& sharedArray2)\n\t{\n\t\t// assert((sharedArray1.get() != sharedArray2.get()) || (sharedArray1.use_count() == sharedArray2.use_count()));\n\t\treturn (sharedArray1.get() == sharedArray2.get());\n\t}\n\n\n\t/// operator!=\n\t/// Compares two shared_array objects for inequality. Equality is defined as \n\t/// being true when the pointer shared between two shared_array objects is equal.\n\t/// It is debatable what the appropriate definition of equality is between two\n\t/// shared_array objects, but we follow the current 2nd generation C++ standard proposal.\n\ttemplate <typename T, typename TA, typename TD, typename U, typename UA, typename UD>\n\tinline bool operator!=(const shared_array<T, TA, TD>& sharedArray1, const shared_array<U, UA, UD>& sharedArray2)\n\t{\n\t\t// assert((sharedArray1.get() != sharedArray2.get()) || (sharedArray1.use_count() == sharedArray2.use_count()));\n\t\treturn (sharedArray1.get() != sharedArray2.get());\n\t}\n\n\n\t/// operator<\n\t/// Returns which shared_array is 'less' than the other. Useful when storing\n\t/// sorted containers of scoped_ptr objects.\n\ttemplate <typename T, typename TA, typename TD, typename U, typename UA, typename UD>\n\tinline bool operator<(const shared_array<T, TA, TD>& sharedArray1, const shared_array<U, UA, UD>& sharedArray2)\n\t{\n\t\treturn (sharedArray1.get() < sharedArray2.get()); // Alternatively use: std::less<T*>(a.get(), b.get());\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/shared_ptr.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This class implements the C++11 shared_ptr template. A shared_ptr is like  \n// the C++ Standard Library unique_ptr except that it allows sharing of pointers \n// between instances via reference counting. shared_ptr objects can safely be \n// copied and can  safely be used in containers such as vector or list.\n//\n// Notes regarding safe usage of shared_ptr:\n//     - http://www.boost.org/doc/libs/1_53_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety\n//     - If you construct a shared_ptr with a raw pointer, you cannot construct another shared_ptr\n//       with just that raw pointer. Insted you need to construct additional shared_ptrs with \n//       the originally created shared_ptr. Otherwise you will get a crash.\n//     - Usage of shared_ptr is thread-safe, but what it points to isn't automatically thread safe. \n//       Multiple shared_ptrs that refer to the same object can be used arbitrarily by multiple threads.\n//     - You can use a single shared_ptr between multiple threads in all ways except one: assigment\n//       to that shared_ptr. The following is not thread-safe, and needs to be guarded by a mutex \n//       or the shared_ptr atomic functions:\n//           shared_ptr<Foo> pFoo;\n//           // Thread 1:\n//           shared_ptr<Foo> pFoo2 = pFoo;\n//           // Thread 2:\n//           pFoo = make_shared<Foo>();\n//\n// Compatibility note:\n// This version of shared_ptr updates the previous version to have full C++11 \n// compatibility. However, in order to add C++11 compatibility there needed to \n// be a few breaking changes which may affect some users. It's likely that most\n// or all breaking changes can be rectified by doing the same thing in a slightly\n// different way. Here's a list of the primary signficant breaking changes:\n//     - shared_ptr now takes just one template parameter instead of three.\n//       (allocator and deleter). You now specify the allocator and deleter\n//       as part of the shared_ptr constructor at runtime.\n//     - shared_ptr has thread safety, which \n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SHARED_PTR_H\n#define EASTL_SHARED_PTR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/smart_ptr.h>\n#include <EASTL/internal/thread_support.h>\n#include <EASTL/unique_ptr.h>\n#include <EASTL/functional.h>\n#include <EASTL/allocator.h>\n#include <EASTL/atomic.h>\n#include <EASTL/memory.h>\n#if EASTL_RTTI_ENABLED\n\t#include <typeinfo>\n#endif\n#if EASTL_EXCEPTIONS_ENABLED\n\t#include <exception>\n#endif\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <new>\n#include <stddef.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4530 4571 4512 4626);\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////\n\t// shared_ptr\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// EASTL_SHARED_PTR_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_SHARED_PTR_DEFAULT_NAME\n\t\t#define EASTL_SHARED_PTR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" shared_ptr\" // Unless the user overrides something, this is \"EASTL shared_ptr\".\n\t#endif\n\n\n\t/// EASTL_SHARED_PTR_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_SHARED_PTR_DEFAULT_ALLOCATOR\n\t\t#define EASTL_SHARED_PTR_DEFAULT_ALLOCATOR EASTLAllocatorType(EASTL_SHARED_PTR_DEFAULT_NAME)\n\t#endif\n\n\n\t// Forward declarations\n\ttemplate <typename T, typename Deleter> class unique_ptr;\n\ttemplate <typename T> class weak_ptr;\n\ttemplate <typename T> class enable_shared_from_this;\n\n\n\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t// We define eastl::bad_weak_ptr as opposed to std::bad_weak_ptr. The reason is that \n\t\t// we can't easily know of std::bad_weak_ptr exists and we would have to #include <memory>\n\t\t// to use it. EASTL \"owns\" the types that are defined in EASTL headers, and std::bad_weak_ptr \n\t\t// is declared in <memory>.\n\n\t\tstruct bad_weak_ptr : std::exception\n\t\t{\n\t\t\tconst char* what() const EA_NOEXCEPT EA_OVERRIDE\n\t\t\t\t{ return \"bad weak_ptr\"; }\n\t\t};\n\t#endif\n\n\n\t/// ref_count_sp\n\t///\n\t/// This is a small utility class used by shared_ptr and weak_ptr.\n\tstruct ref_count_sp\n\t{\n\t\tatomic<int32_t> mRefCount;            /// Reference count on the contained pointer. Starts as 1 by default.\n\t\tatomic<int32_t> mWeakRefCount;        /// Reference count on contained pointer plus this ref_count_sp object itself. Starts as 1 by default.\n\n\tpublic:\n\t\tref_count_sp(int32_t refCount = 1, int32_t weakRefCount = 1) EA_NOEXCEPT;\n\t\tvirtual ~ref_count_sp() EA_NOEXCEPT {}\n\n\t\tint32_t       use_count() const EA_NOEXCEPT;\n\t\tvoid          addref() EA_NOEXCEPT;\n\t\tvoid          release();\n\t\tvoid          weak_addref() EA_NOEXCEPT;\n\t\tvoid          weak_release();\n\t\tref_count_sp* lock() EA_NOEXCEPT;\n\n\t\tvirtual void free_value() EA_NOEXCEPT = 0;          // Release the contained object.\n\t\tvirtual void free_ref_count_sp() EA_NOEXCEPT = 0;   // Release this instance.\n\n\t\t#if EASTL_RTTI_ENABLED\n\t\t\tvirtual void* get_deleter(const std::type_info& type) const EA_NOEXCEPT = 0;\n\t\t#else\n\t\t\tvirtual void* get_deleter() const EA_NOEXCEPT = 0;\n\t\t#endif\n\t};\n\n\n\tinline ref_count_sp::ref_count_sp(int32_t refCount, int32_t weakRefCount) EA_NOEXCEPT\n\t\t: mRefCount(refCount), mWeakRefCount(weakRefCount) {}\n\n\tinline int32_t ref_count_sp::use_count() const EA_NOEXCEPT\n\t{\n\t\treturn mRefCount.load(memory_order_relaxed);   // To figure out: is this right?\n\t}\n\n\tinline void ref_count_sp::addref() EA_NOEXCEPT\n\t{\n\t\tmRefCount.fetch_add(1, memory_order_relaxed);\n\t\tmWeakRefCount.fetch_add(1, memory_order_relaxed);\n\t}\n\n\tinline void ref_count_sp::release()\n\t{\n\t\tEASTL_ASSERT((mRefCount.load(memory_order_relaxed) > 0));\n\t\tif(mRefCount.fetch_sub(1, memory_order_release) == 1)\n\t\t{\n\t\t\tmRefCount.acquire_fence();\n\t\t\tfree_value();\n\t\t}\n\n\t\tweak_release();\n\t}\n\n\tinline void ref_count_sp::weak_addref() EA_NOEXCEPT\n\t{\n\t\tmWeakRefCount.fetch_add(1, memory_order_relaxed);\n\t}\n\n\tinline void ref_count_sp::weak_release()\n\t{\n\t\tEASTL_ASSERT(mWeakRefCount.load(memory_order_relaxed) > 0);\n\t\tif(mWeakRefCount.fetch_sub(1, memory_order_release) == 1)\n\t\t{\n\t\t\tmWeakRefCount.acquire_fence();\n\t\t\tfree_ref_count_sp();\n\t\t}\n\t}\n\n\tinline ref_count_sp* ref_count_sp::lock() EA_NOEXCEPT\n\t{\n\t\tfor(int32_t refCountTemp = mRefCount.load(memory_order_relaxed); refCountTemp != 0; )\n\t\t{\n\t\t\tif(mRefCount.compare_exchange_weak(refCountTemp, refCountTemp + 1, memory_order_relaxed))\n\t\t\t{\n\t\t\t\tmWeakRefCount.fetch_add(1, memory_order_relaxed);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}\n\n\t\treturn nullptr;\n\t}\n\n\n\n\t/// ref_count_sp_t\n\t///\n\t/// This is a version of ref_count_sp which is used to delete the contained pointer.\n\ttemplate <typename T, typename Allocator, typename Deleter>\n\tclass ref_count_sp_t : public ref_count_sp\n\t{\n\tpublic:\n\t\ttypedef ref_count_sp_t<T, Allocator, Deleter>   this_type;\n\t\ttypedef T                                       value_type;\n\t\ttypedef Allocator                               allocator_type;\n\t\ttypedef Deleter                                 deleter_type;\n\n\t\tvalue_type     mValue; // This is expected to be a pointer.\n\t\tdeleter_type   mDeleter;\n\t\tallocator_type mAllocator;\n\n\t\tref_count_sp_t(value_type value, deleter_type deleter, allocator_type allocator)\n\t\t\t: ref_count_sp(), mValue(value), mDeleter(eastl::move(deleter)), mAllocator(eastl::move(allocator))\n\t\t{}\n\n\t\tvoid free_value() EA_NOEXCEPT\n\t\t{\n\t\t\tmDeleter(mValue);\n\t\t\tmValue = nullptr;\n\t\t}\n\n\t\tvoid free_ref_count_sp() EA_NOEXCEPT\n\t\t{\n\t\t\tallocator_type allocator = mAllocator;\n\t\t\tthis->~ref_count_sp_t();\n\t\t\tEASTLFree(allocator, this, sizeof(*this));\n\t\t}\n\n\t\t#if EASTL_RTTI_ENABLED\n\t\t\tvoid* get_deleter(const std::type_info& type) const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn (type == typeid(deleter_type)) ? (void*)&mDeleter : nullptr;\n\t\t\t}\n\t\t#else\n\t\t\tvoid* get_deleter() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn (void*)&mDeleter;\n\t\t\t}\n\t\t#endif\n\t};\n\n\t/// ref_count_sp_t_inst\n\t///\n\t/// This is a version of ref_count_sp which is used to actually hold an instance of\n\t/// T (instead of a pointer). This is useful to allocate the object and ref count\n\t/// in a single memory allocation.\n\ttemplate<typename T, typename Allocator>\n\tclass ref_count_sp_t_inst : public ref_count_sp\n\t{\n\tpublic:\n\t\ttypedef ref_count_sp_t_inst<T, Allocator>                                        this_type;\n\t\ttypedef T                                                                        value_type;\n\t\ttypedef Allocator                                                                allocator_type;\n\t\ttypedef typename aligned_storage<sizeof(T), eastl::alignment_of<T>::value>::type storage_type;\n\n\t\tstorage_type   mMemory;\n\t\tallocator_type mAllocator;\n\n\t\tvalue_type* GetValue() { return static_cast<value_type*>(static_cast<void*>(&mMemory)); }\n\n\t\ttemplate <typename... Args>\n\t\tref_count_sp_t_inst(allocator_type allocator, Args&&... args)\n\t\t\t: ref_count_sp(), mAllocator(eastl::move(allocator))\n\t\t{\n\t\t\tnew (&mMemory) value_type(eastl::forward<Args>(args)...);\n\t\t}\n\n\t\tvoid free_value() EA_NOEXCEPT\n\t\t{\n\t\t\tGetValue()->~value_type();\n\t\t}\n\n\t\tvoid free_ref_count_sp() EA_NOEXCEPT\n\t\t{\n\t\t\tallocator_type allocator = mAllocator;\n\t\t\tthis->~ref_count_sp_t_inst();\n\t\t\tEASTLFree(allocator, this, sizeof(*this));\n\t\t}\n\n\t\t#if EASTL_RTTI_ENABLED\n\t\t\tvoid* get_deleter(const std::type_info&) const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn nullptr; // Default base implementation.\n\t\t\t}\n\t\t#else\n\t\t\tvoid* get_deleter() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn nullptr;\n\t\t\t}\n\t\t#endif\n\t};\n\n\n\t/// do_enable_shared_from_this\n\t///\n\t/// If a user calls this function, it sets up mWeakPtr member of \n\t/// the enable_shared_from_this parameter to point to the ref_count_sp \n\t/// object that's passed in. Normally, the user doesn't need to call \n\t/// this function, as the shared_ptr constructor will do it for them.\n\t///\n\ttemplate <typename T, typename U>\n\tvoid do_enable_shared_from_this(const ref_count_sp* pRefCount,\n\t                                const enable_shared_from_this<T>* pEnableSharedFromThis,\n\t                                const U* pValue)\n\t{\n\t\tif (pEnableSharedFromThis)\n\t\t\tpEnableSharedFromThis->mWeakPtr.assign(const_cast<U*>(pValue), const_cast<ref_count_sp*>(pRefCount));\n\t}\n\n\tinline void do_enable_shared_from_this(const ref_count_sp*, ...) {} // Empty specialization. This no-op version is\n\t                                                                    // called by shared_ptr when shared_ptr's T type\n\t                                                                    // is anything but an enabled_shared_from_this\n\t                                                                    // class.\n\n\n\t/// shared_ptr_traits\n\t/// This exists for the sole purpose of creating a typedef called\n\t/// reference_type which is specialized for type void. The reason\n\t/// for this is that shared_ptr::operator*() returns a reference\n\t/// to T but if T is void, it needs to return void, not *void, \n\t/// as the latter is not valid C++.\n\ttemplate <typename T> struct shared_ptr_traits\n\t\t{ typedef T& reference_type; };\n\n\ttemplate <> struct shared_ptr_traits<void>\n\t\t{ typedef void reference_type; };\n\n\ttemplate <> struct shared_ptr_traits<void const>\n\t\t{ typedef void reference_type; };\n\n\ttemplate <> struct shared_ptr_traits<void volatile>\n\t\t{ typedef void reference_type; };\n\n\ttemplate <> struct shared_ptr_traits<void const volatile>\n\t\t{ typedef void reference_type; };\n\n\n\n\t/// shared_ptr\n\t///\n\t/// This class implements the C++11 shared_ptr template. A shared_ptr is like the C++\n\t/// Standard Library unique_ptr except that it allows sharing of pointers between\n\t/// instances via reference counting. shared_ptr objects can safely be copied and\n\t/// can safely be used in C++ Standard Library containers such as std::vector or\n\t/// std::list.\n\t///\n\t/// This class is not thread safe in that you cannot use an instance of it from \n\t/// two threads at the same time and cannot use two separate instances of it, which \n\t/// own the same pointer, at the same time. Use standard multithread mutex techniques\n\t/// to address the former problems and use shared_ptr_mt to address the latter.\n\t/// Note that this is contrary to the C++11 standard.\n\t///\n\t/// As of this writing, arrays aren't supported, but they are planned in the future \n\t/// based on the C++17 proposal: http://isocpp.org/files/papers/N3920.html\n\t///\n\ttemplate <typename T>\n\tclass shared_ptr\n\t{\n\tpublic:\n\t\ttypedef shared_ptr<T>                                    this_type;\n\t\ttypedef T                                                element_type; \n\t\ttypedef typename shared_ptr_traits<T>::reference_type    reference_type;   // This defines what a reference to a T is. It's always simply T&, except for the case where T is void, whereby the reference is also just void.\n\t\ttypedef EASTLAllocatorType                               default_allocator_type;\n\t\ttypedef default_delete<T>                                default_deleter_type;\n\t\ttypedef weak_ptr<T>                                      weak_type;\n\n\tprotected:\n\t\telement_type*  mpValue;\n\t\tref_count_sp*  mpRefCount;           /// Base pointer to Reference count for owned pointer and the owned pointer.\n\n\tpublic:\n\t\t/// Initializes and \"empty\" shared_ptr.\n\t\t/// Postcondition: use_count() == zero and get() == 0\n\t\tshared_ptr() EA_NOEXCEPT\n\t\t\t: mpValue(nullptr),\n\t\t\t  mpRefCount(nullptr)\n\t\t{\n\t\t\t// Intentionally leaving mpRefCount as NULL. Can't allocate here due to noexcept.\n\t\t}\n\n\t\t/// Takes ownership of the pointer and sets the reference count\n\t\t/// to the pointer to 1. It is OK if the input pointer is null.\n\t\t/// The shared reference count is allocated on the heap using the\n\t\t/// default eastl allocator.\n\t\t/// Throws: bad_alloc, or an implementation-defined exception when \n\t\t///         a resource other than memory could not be obtained.\n\t\t/// Exception safety: If an exception is thrown, delete p is called.\n\t\t/// Postcondition in the event of no exception: use_count() == 1 && get() == p\n\t\ttemplate <typename U>\n\t\texplicit shared_ptr(U* pValue,\n\t\t                    typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0)\n\t\t    : mpValue(nullptr), mpRefCount(nullptr) // alloc_internal will set this.\n\t\t{\n\t\t\t// We explicitly use default_delete<U>. You can use the other version of this constructor to provide a\n\t\t\t// custom version.\n\t\t\talloc_internal(pValue, default_allocator_type(),\n\t\t\t               default_delete<U>()); // Problem: We want to be able to use default_deleter_type() instead of\n\t\t\t                                     // default_delete<U>, but if default_deleter_type's type is void or\n\t\t\t                                     // otherwise mismatched then this will fail to compile. What we really\n\t\t\t                                     // want to be able to do is \"rebind\" default_allocator_type to U\n\t\t\t                                     // instead of its original type.\n\t\t}\n\n\n\t\tshared_ptr(std::nullptr_t) EA_NOEXCEPT\n\t\t\t: mpValue(nullptr),\n\t\t\t  mpRefCount(nullptr)\n\t\t{\n\t\t\t// Intentionally leaving mpRefCount as NULL. Can't allocate here due to noexcept.\n\t\t}\n\n\n\t\t/// Takes ownership of the pointer and sets the reference count\n\t\t/// to the pointer to 1. It is OK if the input pointer is null.\n\t\t/// The shared reference count is allocated on the heap using the\n\t\t/// default eastl allocator. The pointer will be disposed using the\n\t\t/// provided deleter.\n\t\t/// If an exception occurs during the allocation of the shared \n\t\t/// reference count, the owned pointer is deleted and the exception\n\t\t/// is rethrown.\n\t\t/// Postcondition: use_count() == 1 && get() == p\n\t\ttemplate <typename U, typename Deleter>\n\t\tshared_ptr(U* pValue,\n\t\t           Deleter deleter,\n\t\t           typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0)\n\t\t    : mpValue(nullptr), mpRefCount(nullptr)\n\t\t{\n\t\t\talloc_internal(pValue, default_allocator_type(), eastl::move(deleter));\n\t\t}\n\n\t\ttemplate <typename Deleter>\n\t\tshared_ptr(std::nullptr_t, Deleter deleter)\n\t\t    : mpValue(nullptr), mpRefCount(nullptr) // alloc_internal will set this.\n\t\t{\n\t\t\talloc_internal(nullptr, default_allocator_type(), eastl::move(deleter));\n\t\t}\n\n\n\t\t/// Takes ownership of the pointer and sets the reference count\n\t\t/// to the pointer to 1. It is OK if the input pointer is null.\n\t\t/// The shared reference count is allocated on the heap using the\n\t\t/// supplied allocator. The pointer will be disposed using the\n\t\t/// provided deleter.\n\t\t/// If an exception occurs during the allocation of the shared \n\t\t/// reference count, the owned pointer is deleted and the exception\n\t\t/// is rethrown.\n\t\t/// Postcondition: use_count() == 1 && get() == p\n\t\ttemplate <typename U, typename Deleter, typename Allocator>\n\t\texplicit shared_ptr(U* pValue,\n\t\t                    Deleter deleter,\n\t\t                    const Allocator& allocator,\n\t\t                    typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0)\n\t\t    : mpValue(nullptr), mpRefCount(nullptr) // alloc_internal will set this.\n\t\t{\n\t\t\talloc_internal(pValue, eastl::move(allocator), eastl::move(deleter));\n\t\t}\n\n\t\ttemplate <typename Deleter, typename Allocator>\n\t\tshared_ptr(std::nullptr_t, Deleter deleter, Allocator allocator)\n\t\t\t: mpValue(nullptr),\n\t\t\t  mpRefCount(nullptr) // alloc_internal will set this.\n\t\t{\n\t\t\talloc_internal(nullptr, eastl::move(allocator), eastl::move(deleter));\n\t\t}\n\n\n\t\t/// shared_ptr\n\t\t/// construction with self type.\n\t\t/// If we want a shared_ptr constructor that is templated on shared_ptr<U>,\n\t\t/// then we need to make it in addition to this function, as otherwise \n\t\t/// the compiler will generate this function and things will go wrong.\n\t\t/// To accomplish this in a thread-safe way requires use of shared_ptr atomic_store.\n\t\tshared_ptr(const shared_ptr& sharedPtr) EA_NOEXCEPT\n\t\t\t: mpValue(sharedPtr.mpValue),\n\t\t\t  mpRefCount(sharedPtr.mpRefCount)\n\t\t{\n\t\t\tif(mpRefCount)\n\t\t\t\tmpRefCount->addref();\n\t\t}\n\n\n\t\t/// shared_ptr\n\t\t/// Shares ownership of a pointer with another instance of shared_ptr.\n\t\t/// This function increments the shared reference count on the pointer.\n\t\t/// To accomplish this in a thread-safe way requires use of shared_ptr atomic_store.\n\t\ttemplate <typename U>\n\t\tshared_ptr(const shared_ptr<U>& sharedPtr,\n\t\t           typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0) EA_NOEXCEPT\n\t\t    : mpValue(sharedPtr.mpValue),\n\t\t      mpRefCount(sharedPtr.mpRefCount)\n\t\t{\n\t\t\tif (mpRefCount)\n\t\t\t\tmpRefCount->addref();\n\t\t}\n\n\n\t\t/// shared_ptr\n\t\t/// \n\t\t/// 20.7.2.2.1p13: Constructs a shared_ptr instance that stores p and shares ownership with r.\n\t\t/// Postconditions: get() == pValue && use_count() == sharedPtr.use_count().\n\t\t/// To avoid the possibility of a dangling pointer, the user of this constructor must \n\t\t/// ensure that pValue remains valid at least until the ownership group of sharedPtr is destroyed. \n\t\t/// This constructor allows creation of an empty shared_ptr instance with a non-NULL stored pointer. \n\t\t///\n\t\t/// Shares ownership of a pointer with another instance of shared_ptr while storing a potentially \n\t\t/// different pointer. This function increments the shared reference count on the sharedPtr if it exists.\n\t\t/// If sharedPtr has no shared reference then a shared reference is not created an pValue is not \n\t\t/// deleted in our destructor and effectively the pointer is not actually shared.\n\t\t///\n\t\t/// To accomplish this in a thread-safe way requires the user to maintain the lifetime of sharedPtr\n\t\t/// as described above.\n\t\t///\n\t\ttemplate <typename U>\n\t\tshared_ptr(const shared_ptr<U>& sharedPtr, element_type* pValue) EA_NOEXCEPT\n\t\t\t: mpValue(pValue),\n\t\t\t  mpRefCount(sharedPtr.mpRefCount)\n\t\t{\n\t\t\tif(mpRefCount)\n\t\t\t\tmpRefCount->addref();\n\t\t}\n\n\n\t\tshared_ptr(shared_ptr&& sharedPtr) EA_NOEXCEPT\n\t\t\t: mpValue(sharedPtr.mpValue),\n\t\t\t  mpRefCount(sharedPtr.mpRefCount)\n\t\t{\n\t\t\tsharedPtr.mpValue = nullptr;\n\t\t\tsharedPtr.mpRefCount = nullptr;\n\t\t}\n\n\n\t\ttemplate <typename U>\n\t\tshared_ptr(shared_ptr<U>&& sharedPtr,\n\t\t           typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0) EA_NOEXCEPT\n\t\t    : mpValue(sharedPtr.mpValue),\n\t\t      mpRefCount(sharedPtr.mpRefCount)\n\t\t{\n\t\t\tsharedPtr.mpValue = nullptr;\n\t\t\tsharedPtr.mpRefCount = nullptr;\n\t\t}\n\n\t\t// unique_ptr constructor\n\t\ttemplate <typename U, typename Deleter>\n\t\tshared_ptr(unique_ptr<U, Deleter>&& uniquePtr,\n\t\t           typename eastl::enable_if<!eastl::is_array<U>::value && !is_lvalue_reference<Deleter>::value &&\n\t\t                                     eastl::is_convertible<U*, element_type*>::value>::type* = 0)\n\t\t    : mpValue(nullptr), mpRefCount(nullptr)\n\t\t{\n\t\t\talloc_internal(uniquePtr.release(), default_allocator_type(), uniquePtr.get_deleter());\n\t\t}\n\n\t\t// unique_ptr constructor\n\t\t// The following is not in the C++11 Standard.\n\t\ttemplate <typename U, typename Deleter, typename Allocator>\n\t\tshared_ptr(unique_ptr<U, Deleter>&& uniquePtr,\n\t\t           const Allocator& allocator,\n\t\t           typename eastl::enable_if<!eastl::is_array<U>::value && !is_lvalue_reference<Deleter>::value &&\n\t\t                                     eastl::is_convertible<U*, element_type*>::value>::type* = 0)\n\t\t    : mpValue(nullptr), mpRefCount(nullptr)\n\t\t{\n\t\t\talloc_internal(uniquePtr.release(), allocator, uniquePtr.get_deleter());\n\t\t}\n\n\n\t\t/// shared_ptr(weak_ptr)\n\t\t/// Shares ownership of a pointer with an instance of weak_ptr.\n\t\t/// This function increments the shared reference count on the pointer.\n\t\ttemplate <typename U>\n\t\texplicit shared_ptr(const weak_ptr<U>& weakPtr,\n\t\t                    typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0)\n\t\t    : mpValue(weakPtr.mpValue)\n\t\t    , mpRefCount(weakPtr.mpRefCount ?\n\t\t                     weakPtr.mpRefCount->lock() :\n\t\t                     weakPtr.mpRefCount) // mpRefCount->lock() addref's the return value for us.\n\t\t{\n\t\t\tif (!mpRefCount)\n\t\t\t{\n\t\t\t\tmpValue = nullptr; // Question: Is it right for us to NULL this or not?\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow eastl::bad_weak_ptr();\n\t\t\t#else\n\t\t\t\tEASTL_FAIL_MSG(\"eastl::shared_ptr -- bad_weak_ptr\");\n\t\t\t#endif\n\t\t\t}\n\t\t}\n\n\n\t\t/// ~shared_ptr\n\t\t/// Decrements the reference count for the owned pointer. If the \n\t\t/// reference count goes to zero, the owned pointer is deleted and\n\t\t/// the shared reference count is deleted.\n\t\t~shared_ptr()\n\t\t{\n\t\t\tif (mpRefCount)\n\t\t\t{\n\t\t\t\tmpRefCount->release();\n\t\t\t}\n\t\t\t// else if mpValue is non-NULL then we just lose it because it wasn't actually shared (can happen with\n\t\t\t// shared_ptr(const shared_ptr<U>& sharedPtr, element_type* pValue) constructor).\n\n\t\t\t#if EASTL_DEBUG\n\t\t\t\tmpValue = nullptr;\n\t\t\t\tmpRefCount = nullptr;\n\t\t\t#endif\n\t\t}\n\n\n\t\t// The following is disabled because it is not specified by the C++11 Standard, as it leads to \n\t\t// potential collisions. Use the reset(p) and reset() functions instead.\n\t\t//\n\t\t// template <typename U>\n\t\t// typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t\t// operator=(const U* pValue) EA_NOEXCEPT\n\t\t// {\n\t\t//     reset(pValue);\n\t\t//     return *this;\n\t\t// }\n\t\t//\n\t\t// template <typename U>\n\t\t// this_type& operator=(std::nullptr_t) EA_NOEXCEPT\n\t\t// {\n\t\t//     reset();\n\t\t//     return *this;\n\t\t// }\n\n\n\t\t/// operator=\n\t\t/// Assignment to self type.\n\t\t/// If we want a shared_ptr operator= that is templated on shared_ptr<U>,\n\t\t/// then we need to make it in addition to this function, as otherwise \n\t\t/// the compiler will generate this function and things will go wrong.\n\t\tshared_ptr& operator=(const shared_ptr& sharedPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tif(&sharedPtr != this)\n\t\t\t\tthis_type(sharedPtr).swap(*this);\n\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Copies another shared_ptr to this object. Note that this object\n\t\t/// may already own a shared pointer with another different pointer\n\t\t/// (but still of the same type) before this call. In that case,\n\t\t/// this function releases the old pointer, decrementing its reference\n\t\t/// count and deleting it if zero, takes shared ownership of the new \n\t\t/// pointer and increments its reference count.\n\t\ttemplate <typename U>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t\toperator=(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tif(!equivalent_ownership(sharedPtr))\n\t\t\t\tthis_type(sharedPtr).swap(*this);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Assignment to self type.\n\t\t/// If we want a shared_ptr operator= that is templated on shared_ptr<U>,\n\t\t/// then we need to make it in addition to this function, as otherwise \n\t\t/// the compiler will generate this function and things will go wrong.\n\t\tthis_type& operator=(shared_ptr&& sharedPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tif(&sharedPtr != this)\n\t\t\t\tthis_type(eastl::move(sharedPtr)).swap(*this);\n\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=\n\t\t/// Moves another shared_ptr to this object. Note that this object\n\t\t/// may already own a shared pointer with another different pointer\n\t\t/// (but still of the same type) before this call. In that case,\n\t\t/// this function releases the old pointer, decrementing its reference\n\t\t/// count and deleting it if zero, takes shared ownership of the new \n\t\t/// pointer and increments its reference count.\n\t\ttemplate <typename U>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t\toperator=(shared_ptr<U>&& sharedPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tif(!equivalent_ownership(sharedPtr))\n\t\t\t\tshared_ptr(eastl::move(sharedPtr)).swap(*this);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t// unique_ptr operator=\n\t\ttemplate <typename U, typename Deleter>\n\t\ttypename eastl::enable_if<!eastl::is_array<U>::value && eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t\toperator=(unique_ptr<U, Deleter>&& uniquePtr)\n\t\t{\n\t\t\t// Note that this will use the default EASTL allocator\n\t\t\tthis_type(eastl::move(uniquePtr)).swap(*this);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Releases the owned pointer.\n\t\tvoid reset() EA_NOEXCEPT\n\t\t{\n\t\t\tthis_type().swap(*this);\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Releases the owned pointer and takes ownership of the \n\t\t/// passed in pointer.\n\t\ttemplate <typename U>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, void>::type\n\t\treset(U* pValue)\n\t\t{\n\t\t\tthis_type(pValue).swap(*this);\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Releases the owned pointer and takes ownership of the \n\t\t/// passed in pointer.\n\t\ttemplate <typename U, typename Deleter>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, void>::type\n\t\treset(U* pValue, Deleter deleter)\n\t\t{\n\t\t\tshared_ptr(pValue, deleter).swap(*this);\n\t\t}\n\n\n\t\t/// reset\n\t\t/// Resets the shared_ptr\n\t\ttemplate <typename U, typename Deleter, typename Allocator>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, void>::type\n\t\treset(U* pValue, Deleter deleter, const Allocator& allocator)\n\t\t{\n\t\t\tshared_ptr(pValue, deleter, allocator).swap(*this);\n\t\t}\n\n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer between two shared_ptr objects.\n\t\t/// This function is not intrinsically thread-safe. You must use atomic_exchange(shared_ptr<T>*, shared_ptr<T>)\n\t\t/// or manually coordinate the swap.\n\t\tvoid swap(this_type& sharedPtr) EA_NOEXCEPT\n\t\t{\n\t\t\telement_type* const pValue = sharedPtr.mpValue;\n\t\t\tsharedPtr.mpValue = mpValue;\n\t\t\tmpValue           = pValue;\n\n\t\t\tref_count_sp* const pRefCount = sharedPtr.mpRefCount;\n\t\t\tsharedPtr.mpRefCount = mpRefCount;\n\t\t\tmpRefCount           = pRefCount;\n\t\t}\n\n\n\t\t/// operator*\n\t\t/// Returns the owner pointer dereferenced.\n\t\t/// Example usage:\n\t\t///    shared_ptr<int> ptr(new int(3));\n\t\t///    int x = *ptr;\n\t\treference_type operator*() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn *mpValue;\n\t\t}\n\n\t\t/// operator->\n\t\t/// Allows access to the owned pointer via operator->()\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    shared_ptr<int> ptr(new X);\n\t\t///    ptr->DoSomething();\n\t\telement_type* operator->() const EA_NOEXCEPT\n\t\t{\n\t\t\t// assert(mpValue);\n\t\t\treturn mpValue;\n\t\t}\n\n\t\t/// operator[]\n\t\t/// Index into the array pointed to by the owned pointer.\n\t\t/// The behaviour is undefined if the owned pointer is nullptr, if the user specified index is negative, or if\n\t\t/// the index is outside the referred array bounds.\n\t\t///\n\t\t/// When T is not an array type, it is unspecified whether this function is declared. If the function is declared,\n\t\t/// it is unspecified what its return type is, except that the declaration (although not necessarily the\n\t\t/// definition) of the function is guaranteed to be legal.\n\t\t//\n\t\t// TODO(rparolin): This is disabled because eastl::shared_ptr needs array support.\n\t\t// element_type& operator[](ptrdiff_t idx)\n\t\t// {\n\t\t//     return get()[idx];\n\t\t// }\n\n\t\t/// get\n\t\t/// Returns the owned pointer. Note that this class does \n\t\t/// not provide an operator T() function. This is because such\n\t\t/// a thing (automatic conversion) is deemed unsafe.\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    shared_ptr<int> ptr(new X);\n\t\t///    X* pX = ptr.get();\n\t\t///    pX->DoSomething();\n\t\telement_type* get() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mpValue;\n\t\t}\n\n\t\t/// use_count\n\t\t/// Returns: the number of shared_ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.\n\t\tint use_count() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mpRefCount ? mpRefCount->use_count() : 0;\n\t\t}\n\n\t\t/// unique\n\t\t/// Returns: use_count() == 1.\n\t\tbool unique() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (mpRefCount && (mpRefCount->use_count() == 1));\n\t\t}\n\n\n\t\t/// owner_before\n\t\t/// C++11 function for ordering.\n\t\ttemplate <typename U>\n\t\tbool owner_before(const shared_ptr<U>& sharedPtr) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (mpRefCount < sharedPtr.mpRefCount);\n\t\t}\n\n\t\ttemplate <typename U>\n\t\tbool owner_before(const weak_ptr<U>& weakPtr) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (mpRefCount < weakPtr.mpRefCount);\n\t\t}\n\n\n\t\ttemplate <typename Deleter>\n\t\tDeleter* get_deleter() const EA_NOEXCEPT\n\t\t{\n\t\t\t#if EASTL_RTTI_ENABLED\n\t\t\t\treturn mpRefCount ? static_cast<Deleter*>(mpRefCount->get_deleter(typeid(typename remove_cv<Deleter>::type))) : nullptr;\n\t\t\t#else\n\t\t\t\t// This is probably unsafe but without typeid there is no way to ensure that the\n\t\t\t\t// stored deleter is actually of the templated Deleter type.\n\t\t\t\treturn nullptr;\n\n\t\t\t\t// Alternatively:\n\t\t\t\t// return mpRefCount ? static_cast<Deleter*>(mpRefCount->get_deleter()) : nullptr;\n\t\t\t#endif\n\t\t}\n\n\t\t#ifdef EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS\n\t\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t\t/// The result is that this: if(sharedPtr == 1) would yield true (bad).\n\t\t\ttypedef T* (this_type::*bool_)() const;\n\t\t\toperator bool_() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tif(mpValue)\n\t\t\t\t\treturn &this_type::get;\n\t\t\t\treturn nullptr;\n\t\t\t}\n\n\t\t\tbool operator!() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn (mpValue == nullptr);\n\t\t\t}\n\t\t#else\n\t\t\t/// Explicit operator bool\n\t\t\t/// Allows for using a shared_ptr as a boolean. \n\t\t\t/// Example usage:\n\t\t\t///    shared_ptr<int> ptr(new int(3));\n\t\t\t///    if(ptr)\n\t\t\t///        ++*ptr;\n\t\t\texplicit operator bool() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn (mpValue != nullptr);\n\t\t\t}\n\t\t#endif\n\n\t\t/// Returns true if the given shared_ptr ows the same T pointer that we do.\n\t\ttemplate <typename U>\n\t\tbool equivalent_ownership(const shared_ptr<U>& sharedPtr) const\n\t\t{\n\t\t\t// We compare mpRefCount instead of mpValue, because it's feasible that there are two sets of shared_ptr \n\t\t\t// objects that are unconnected to each other but happen to own the same value pointer. \n\t\t\treturn (mpRefCount == sharedPtr.mpRefCount); \n\t\t}\n\n\tprotected:\n\t\t// Friend declarations.\n\t\ttemplate <typename U> friend class shared_ptr;\n\t\ttemplate <typename U> friend class weak_ptr;\n\t\ttemplate <typename U> friend void allocate_shared_helper(shared_ptr<U>&, ref_count_sp*, U*);\n\n\t\t// Handles the allocating of mpRefCount, while assigning mpValue.\n\t\t// The provided pValue may be NULL, as with constructing with a deleter and allocator but NULL pointer.\n\t\ttemplate <typename U, typename Allocator, typename Deleter>\n\t\tvoid alloc_internal(U pValue, Allocator allocator, Deleter deleter)\n\t\t{\n\t\t\ttypedef ref_count_sp_t<U, Allocator, Deleter> ref_count_type;\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tref_count_type* const pMemory = (ref_count_type*) EASTLAlloc(allocator, sizeof(ref_count_type));\n\t\t\t\t\tif(!pMemory)\n\t\t\t\t\t\tthrow std::bad_alloc();\n\t\t\t\t\tdetail::allocator_construct(allocator, pMemory, pValue, eastl::move(deleter), allocator);\n\t\t\t\t\tmpRefCount = pMemory;\n\t\t\t\t\tmpValue = pValue;\n\t\t\t\t\tdo_enable_shared_from_this(mpRefCount, pValue, pValue);\n\t\t\t\t}\n\t\t\t\tcatch(...) // The exception would usually be std::bad_alloc.\n\t\t\t\t{\n\t\t\t\t\tdeleter(pValue); // 20.7.2.2.1 p7: If an exception is thrown, delete p is called.\n\t\t\t\t\tthrow;           // Throws: bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tref_count_type* const pMemory = (ref_count_type*)EASTLAlloc(allocator, sizeof(ref_count_type));\n\t\t\t\tif(pMemory)\n\t\t\t\t{\n\t\t\t\t\tdetail::allocator_construct(allocator, pMemory, pValue, eastl::move(deleter), allocator);\n\t\t\t\t\tmpRefCount = pMemory;\n\t\t\t\t\tmpValue = pValue;\n\t\t\t\t\tdo_enable_shared_from_this(mpRefCount, pValue, pValue);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdeleter(pValue);    // We act the same as we do above with exceptions enabled.\n\t\t\t\t}\n\t\t\t#endif\n\t\t}\n\n\t}; // class shared_ptr\n\n\n\t/// get_pointer\n\t/// returns shared_ptr::get() via the input shared_ptr. \n\ttemplate <typename T>\n\tinline typename shared_ptr<T>::element_type* get_pointer(const shared_ptr<T>& sharedPtr) EA_NOEXCEPT\n\t{\n\t\treturn sharedPtr.get();\n\t}\n\n\t/// get_deleter\n\t/// returns the deleter in the input shared_ptr.\n\ttemplate <typename Deleter, typename T>\n\tDeleter* get_deleter(const shared_ptr<T>& sharedPtr) EA_NOEXCEPT\n\t{\n\t\treturn sharedPtr.template get_deleter<Deleter>();\n\t}\n\n\t/// swap\n\t/// Exchanges the owned pointer beween two shared_ptr objects.\n\t/// This non-member version is useful for compatibility of shared_ptr\n\t/// objects with the C++ Standard Library and other libraries.\n\ttemplate <typename T>\n\tinline void swap(shared_ptr<T>& a, shared_ptr<T>& b) EA_NOEXCEPT\n\t{\n\t\ta.swap(b);\n\t}\n\n\n\t/// shared_ptr comparison operators\n\ttemplate <typename T, typename U> \n\tinline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) EA_NOEXCEPT\n\t{\n\t\t// assert((a.get() != b.get()) || (a.use_count() == b.use_count()));\n\t\treturn (a.get() == b.get());\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename U>\n\tstd::strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) EA_NOEXCEPT\n\t{\n\t\treturn a.get() <=> b.get();\n\t}\n#else\n\ttemplate <typename T, typename U> \n\tinline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) EA_NOEXCEPT\n\t{\n\t\t// assert((a.get() != b.get()) || (a.use_count() == b.use_count()));\n\t\treturn (a.get() != b.get());\n\t}\n\n\ttemplate <typename T, typename U> \n\tinline bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) EA_NOEXCEPT\n\t{\n\t\t//typedef typename eastl::common_type<T*, U*>::type CPointer;\n\t\t//return less<CPointer>()(a.get(), b.get());\n\n\t\ttypedef typename eastl::common_type<T*, U*>::type CPointer; // We currently need to make these temporary variables, as otherwise clang complains about CPointer being int*&&&.\n\t\tCPointer pT = a.get();                                      // I wonder if there's something wrong with our common_type type trait implementation.\n\t\tCPointer pU = b.get();                                      // \"in instantiation of function template specialization 'eastl::operator<<int, int>, no known conversion from 'element_type *' (aka 'int *') to 'int *&&&' for 1st argument\"\n\t\treturn less<CPointer>()(pT, pU);                            // It looks like common_type is making CPointer be (e.g.) int*&& instead of int*, though the problem may be in how less<> deals with that.\n\t}\n\n\ttemplate <typename T, typename U> \n\tinline bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) EA_NOEXCEPT\n\t{\n\t\treturn (b < a);\n\t}\n\n\ttemplate <typename T, typename U> \n\tinline bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) EA_NOEXCEPT\n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate <typename T, typename U> \n\tinline bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) EA_NOEXCEPT\n\t{\n\t\treturn !(a < b);\n\t}\n#endif\n\n\ttemplate <typename T>\n\tinline bool operator==(const shared_ptr<T>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !a;\n\t}\n\n\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T>\n\tinline std::strong_ordering operator<=>(const shared_ptr<T>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn a.get() <=> nullptr;\n\t}\n\t#else\n\ttemplate <typename T>\n\tinline bool operator==(std::nullptr_t, const shared_ptr<T>& b) EA_NOEXCEPT\n\t{\n\t\treturn !b;\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator!=(const shared_ptr<T>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<bool>(a);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator!=(std::nullptr_t, const shared_ptr<T>& b) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<bool>(b);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator<(const shared_ptr<T>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn less<T*>()(a.get(), nullptr);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator<(std::nullptr_t, const shared_ptr<T>& b) EA_NOEXCEPT\n\t{\n\t\treturn less<T*>()(nullptr, b.get());\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator>(const shared_ptr<T>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn (nullptr < a);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator>(std::nullptr_t, const shared_ptr<T>& b) EA_NOEXCEPT\n\t{\n\t\treturn (b < nullptr);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator<=(const shared_ptr<T>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !(nullptr < a);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator<=(std::nullptr_t, const shared_ptr<T>& b) EA_NOEXCEPT\n\t{\n\t\treturn !(b < nullptr);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator>=(const shared_ptr<T>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !(a < nullptr);\n\t}\n\n\ttemplate <typename T>\n\tinline bool operator>=(std::nullptr_t, const shared_ptr<T>& b) EA_NOEXCEPT\n\t{\n\t\treturn !(nullptr < b);\n\t}\n#endif\n\n\n\n\t/// reinterpret_pointer_cast\n\t///\n\t/// Returns a shared_ptr<T> reinterpret-casted from a const shared_ptr<U>&.\n\t/// http://isocpp.org/files/papers/N3920.html\n\t///\n\t/// Requires: The expression reinterpret_cast<T*>(sharedPtr.get()) shall be well formed.\n\t/// Returns: If sharedPtr is empty, an empty shared_ptr<T>; otherwise, a shared_ptr<T>\n\t///          object that stores const_cast<T*>(sharedPtr.get()) and shares ownership with sharedPtr.\n\t/// Postconditions: w.get() == const_cast<T*>(sharedPtr.get()) and w.use_count() == sharedPtr.use_count(), \n\t///                 where w is the return value.\n\ttemplate <typename T, typename U>\n\tinline shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const& sharedPtr) EA_NOEXCEPT\n\t{\n\t\treturn shared_ptr<T>(sharedPtr, reinterpret_cast<T*>(sharedPtr.get()));\n\t}\n\n\n\t/// static_pointer_cast\n\t///\n\t/// Returns a shared_ptr<T> static-casted from a shared_ptr<U>&.\n\t///\n\t/// Requires: The expression const_cast<T*>(sharedPtr.get()) shall be well formed.\n\t/// Returns: If sharedPtr is empty, an empty shared_ptr<T>; otherwise, a shared_ptr<T> \n\t/// object that stores const_cast<T*>(sharedPtr.get()) and shares ownership with sharedPtr.\n\t/// Postconditions: w.get() == const_cast<T*>(sharedPtr.get()) and w.use_count() == sharedPtr.use_count(), \n\t///                 where w is the return value.\n\ttemplate <typename T, typename U> \n\tinline shared_ptr<T> static_pointer_cast(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t{\n\t\treturn shared_ptr<T>(sharedPtr, static_cast<T*>(sharedPtr.get()));\n\t}\n\n\ttemplate <typename T, typename U> // Retained for support for pre-C++11 shared_ptr.\n\tinline shared_ptr<T> static_shared_pointer_cast(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t\t{ return static_pointer_cast<T, U>(sharedPtr); }\n\n\n\n\t/// const_pointer_cast\n\t///\n\t/// Returns a shared_ptr<T> const-casted from a const shared_ptr<U>&.\n\t/// Normally, this means that the source shared_ptr holds a const data type.\n\t//\n\t/// Requires: The expression const_cast<T*>(sharedPtr.get()) shall be well formed.\n\t/// Returns: If sharedPtr is empty, an empty shared_ptr<T>; otherwise, a shared_ptr<T>\n\t///          object that stores const_cast<T*>(sharedPtr.get()) and shares ownership with sharedPtr.\n\t/// Postconditions: w.get() == const_cast<T*>(sharedPtr.get()) and w.use_count() == sharedPtr.use_count(), \n\t///                 where w is the return value.\n\ttemplate <typename T, typename U> \n\tinline shared_ptr<T> const_pointer_cast(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t{\n\t\treturn shared_ptr<T>(sharedPtr, const_cast<T*>(sharedPtr.get()));\n\t}\n\n\ttemplate <typename T, typename U> // Retained for support for pre-C++11 shared_ptr.\n\tinline shared_ptr<T> const_shared_pointer_cast(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t\t{ return const_pointer_cast<T, U>(sharedPtr); }\n\n\n\n\t#if EASTL_RTTI_ENABLED\n\t\t/// dynamic_pointer_cast\n\t\t/// \n\t\t/// Returns a shared_ptr<T> dynamic-casted from a const shared_ptr<U>&.\n\t\t/// \n\t\t/// Requires: The expression dynamic_cast<T*>(sharedPtr.get()) shall be well formed and shall have well defined behavior.\n\t\t/// Returns: When dynamic_cast<T*>(sharedPtr.get()) returns a nonzero value, a shared_ptr<T> object that stores \n\t\t///          a copy of it and shares ownership with sharedPtr; Otherwise, an empty shared_ptr<T> object.\n\t\t/// Postcondition: w.get() == dynamic_cast<T*>(sharedPtr.get()), where w is the return value\n\t\t/// \n\t\ttemplate <typename T, typename U>\n\t\tinline shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tif(T* p = dynamic_cast<T*>(sharedPtr.get()))\n\t\t\t\treturn shared_ptr<T>(sharedPtr, p);\n\t\t\treturn shared_ptr<T>();\n\t\t}\n\n\t\ttemplate <typename T, typename U> // Retained for support for pre-C++11 shared_ptr.\n\t\tinline typename eastl::enable_if<!eastl::is_array<T>::value && !eastl::is_array<U>::value, shared_ptr<T> >::type\n\t\tdynamic_shared_pointer_cast(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t\t\t{ return dynamic_pointer_cast<T, U>(sharedPtr); }\n\t#endif\n\n\n\t/// hash specialization for shared_ptr.\n\t/// It simply returns eastl::hash(x.get()). If your unique_ptr pointer type (the return value of shared_ptr<T>::get) is \n\t/// a custom type and not a built-in pointer type then you will need to independently define eastl::hash for that type.\n\ttemplate <typename T> \n\tstruct hash< shared_ptr<T> >\n\t{ \n\t\tsize_t operator()(const shared_ptr<T>& x) const EA_NOEXCEPT\n\t\t\t{ return eastl::hash<T*>()(x.get()); }\n\t};\n\n\n\ttemplate <typename T>\n\tvoid allocate_shared_helper(eastl::shared_ptr<T>& sharedPtr, ref_count_sp* pRefCount, T* pValue)\n\t{\n\t\tsharedPtr.mpRefCount = pRefCount;\n\t\tsharedPtr.mpValue = pValue;\n\t\tdo_enable_shared_from_this(pRefCount, pValue, pValue);\n\t}\n\n\ttemplate <typename T, typename Allocator, typename... Args>\n\tshared_ptr<T> allocate_shared(const Allocator& allocator, Args&&... args)\n\t{\n\t\ttypedef ref_count_sp_t_inst<T, Allocator> ref_count_type;\n\t\tshared_ptr<T> ret;\n\t\tref_count_type* pRefCount = (ref_count_type*) EASTLAlloc(const_cast<Allocator&>(allocator), sizeof(ref_count_type));\n\t\tif(pRefCount)\n\t\t{\n\t\t\tdetail::allocator_construct(allocator, pRefCount, allocator, eastl::forward<Args>(args)...);\n\t\t\tallocate_shared_helper(ret, pRefCount, pRefCount->GetValue());\n\t\t}\n\t\treturn ret;\n\t}\n\n\ttemplate <typename T, typename... Args>\n\tshared_ptr<T> make_shared(Args&&... args)\n\t{\n\t\t// allocate with the default allocator.\n\t\treturn eastl::allocate_shared<T>(EASTL_SHARED_PTR_DEFAULT_ALLOCATOR, eastl::forward<Args>(args)...);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// shared_ptr atomic access\n\t//\n\t// These functions allow shared_ptr to act like other C++11 atomic operations.\n\t// So the same way you can use atomic_load on a raw pointer, you can also\n\t// use it on a shared_ptr. This allows for transparent use of shared_ptr in\n\t// place of raw pointers (e.g. in templates). You do not need to use these\n\t// functions for regular thread-safe direct usage of shared_ptr construction\n\t// and copying, as it's intrinsically thread-safe for that already.\n\t//\n\t// That being said, the following is not thread-safe and needs to be guarded by \n\t// a mutex or the following atomic functions, as it's assigning the *same*\n\t// shared_ptr object from multiple threads as opposed to different shared_ptr\n\t// objects underlying object:\n\t//      shared_ptr<Foo> pFoo;\n\t//      // Thread 1:\n\t//      shared_ptr<Foo> pFoo2 = pFoo;\n\t//      // Thread 2:\n\t//      pFoo = make_shared<Foo>();\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T>\n\tinline bool atomic_is_lock_free(const shared_ptr<T>*)\n\t{\n\t\t// Return true if atomic access to the provided shared_ptr instance is lock-free, false otherwise.\n\t\t// For this to be lock-free, we would have to be able to copy shared_ptr objects in an atomic way \n\t\t// as opposed to wrapping it with a mutex like we do below. Given the nature of shared_ptr, it's \n\t\t// probably not feasible to implement these operations without a mutex. atomic_is_lock_free exists\n\t\t// in the C++11 Standard because it also applies to other types such as built-in types which can\n\t\t// be lock-free in their access.\n\t\treturn false;\n\t}\n\n\ttemplate <typename T>\n\tinline shared_ptr<T> atomic_load(const shared_ptr<T>* pSharedPtr)\n\t{\n\t\tInternal::shared_ptr_auto_mutex autoMutex(pSharedPtr);\n\t\treturn *pSharedPtr;\n\t}\n  \n\ttemplate <typename T>\n\tinline shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* pSharedPtr, ... /*std::memory_order memoryOrder*/)\n\t{\n\t\treturn atomic_load(pSharedPtr);\n\t}\n\n\ttemplate <typename T>\n\tinline void atomic_store(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB)\n\t{\n\t\tInternal::shared_ptr_auto_mutex autoMutex(pSharedPtrA);\n\t\tpSharedPtrA->swap(sharedPtrB);\n\t}\n\n\ttemplate <typename T>\n\tinline void atomic_store_explicit(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB, ... /*std::memory_order memoryOrder*/)\n\t{\n\t\tatomic_store(pSharedPtrA, sharedPtrB);\n\t}\n\n\ttemplate <typename T>\n\tshared_ptr<T> atomic_exchange(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB)\n\t{\n\t\tInternal::shared_ptr_auto_mutex autoMutex(pSharedPtrA);\n\t\tpSharedPtrA->swap(sharedPtrB);\n\t\treturn sharedPtrB;\n\t}\n  \n\ttemplate <typename T>\n\tinline shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB, ... /*std::memory_order memoryOrder*/)\n\t{\n\t\treturn atomic_exchange(pSharedPtrA, sharedPtrB);\n\t}\n\n\t// Compares the shared pointers pointed-to by p and expected. If they are equivalent (share ownership of the \n\t// same pointer and refer to the same pointer), assigns sharedPtrNew into *pSharedPtr using the memory ordering constraints \n\t// specified by success and returns true. If they are not equivalent, assigns *pSharedPtr into *pSharedPtrCondition using the \n\t// memory ordering constraints specified by failure and returns false.\n\ttemplate <typename T>\n\tbool atomic_compare_exchange_strong(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew)\n\t{\n\t\tInternal::shared_ptr_auto_mutex autoMutex(pSharedPtr);\n\n\t\tif(pSharedPtr->equivalent_ownership(*pSharedPtrCondition))\n\t\t{\n\t\t\t*pSharedPtr = sharedPtrNew;\n\t\t\treturn true;\n\t\t}\n\n\t\t*pSharedPtrCondition = *pSharedPtr;\n\t\treturn false;\n\t}\n\n\ttemplate <typename T>\n\tinline bool atomic_compare_exchange_weak(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew)\n\t{\n\t\treturn atomic_compare_exchange_strong(pSharedPtr, pSharedPtrCondition, sharedPtrNew);\n\t}\n\n\ttemplate <typename T> // Returns true if pSharedPtr was equivalent to *pSharedPtrCondition.\n\tinline bool atomic_compare_exchange_strong_explicit(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew, ... /*memory_order memoryOrderSuccess, memory_order memoryOrderFailure*/)\n\t{\n\t\treturn atomic_compare_exchange_strong(pSharedPtr, pSharedPtrCondition, sharedPtrNew);\n\t}\n\n\ttemplate <typename T>\n\tinline bool atomic_compare_exchange_weak_explicit(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew, ... /*memory_order memoryOrderSuccess, memory_order memoryOrderFailure*/)\n\t{\n\t\treturn atomic_compare_exchange_weak(pSharedPtr, pSharedPtrCondition, sharedPtrNew);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// weak_ptr\n\t///////////////////////////////////////////////////////////////////////////\n\n\t/// EASTL_WEAK_PTR_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_WEAK_PTR_DEFAULT_NAME\n\t\t#define EASTL_WEAK_PTR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" weak_ptr\" // Unless the user overrides something, this is \"EASTL weak_ptr\".\n\t#endif\n\n\n\t/// EASTL_WEAK_PTR_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_WEAK_PTR_DEFAULT_ALLOCATOR\n\t\t#define EASTL_WEAK_PTR_DEFAULT_ALLOCATOR allocator_type(EASTL_WEAK_PTR_DEFAULT_NAME)\n\t#endif\n\n\n\t/// weak_ptr\n\t///\n\t/// The weak_ptr class template stores a \"weak reference\" to an object \n\t/// that's already managed by a shared_ptr. To access the object, a weak_ptr \n\t/// can be converted to a shared_ptr using the shared_ptr constructor or \n\t/// the lock() member function. When the last shared_ptr to the object goes \n\t/// away and the object is deleted, the attempt to obtain a shared_ptr \n\t/// from the weak_ptr instances that refer to the deleted object will fail via\n\t/// lock() returning an empty shared_ptr.\n\t///\n\t/// The Allocator template argument manages the memory of the shared reference\n\t/// count and not the stored object. weak_ptr will not delete the stored object\n\t/// but instead can only delete the reference count on that object.\n\t///\n\ttemplate <typename T>\n\tclass weak_ptr\n\t{\n\tpublic:\n\t\ttypedef weak_ptr<T>     this_type;\n\t\ttypedef T               element_type;\n\n\tpublic:\n\t\t/// weak_ptr\n\t\tweak_ptr() EA_NOEXCEPT\n\t\t\t: mpValue(nullptr),\n\t\t\t  mpRefCount(nullptr)\n\t\t{\n\t\t}\n\n\n\t\t/// weak_ptr\n\t\t/// Construction with self type.\n\t\tweak_ptr(const this_type& weakPtr) EA_NOEXCEPT\n\t\t\t: mpValue(weakPtr.mpValue),\n\t\t\t  mpRefCount(weakPtr.mpRefCount)\n\t\t{\n\t\t\tif(mpRefCount)\n\t\t\t\tmpRefCount->weak_addref();\n\t\t}\n\n\n\t\t/// weak_ptr\n\t\t/// Move construction with self type.\n\t\tweak_ptr(this_type&& weakPtr) EA_NOEXCEPT\n\t\t\t: mpValue(weakPtr.mpValue),\n\t\t\t  mpRefCount(weakPtr.mpRefCount)\n\t\t{\n\t\t\tweakPtr.mpValue = nullptr;\n\t\t\tweakPtr.mpRefCount = nullptr;\n\t\t}\n\n\n\t\t/// weak_ptr\n\t\t/// Constructs a weak_ptr from another weak_ptr.\n\t\ttemplate <typename U>\n\t\tweak_ptr(const weak_ptr<U>& weakPtr, typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0) EA_NOEXCEPT\n\t\t\t: mpValue(weakPtr.mpValue),\n\t\t\t\tmpRefCount(weakPtr.mpRefCount)\n\t\t{\n\t\t\tif(mpRefCount)\n\t\t\t\tmpRefCount->weak_addref();\n\t\t}\n\n\n\t\t/// weak_ptr\n\t\t/// Move constructs a weak_ptr from another weak_ptr.\n\t\ttemplate <typename U>\n\t\tweak_ptr(weak_ptr<U>&& weakPtr,\n\t\t         typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0) EA_NOEXCEPT\n\t\t    : mpValue(weakPtr.mpValue),\n\t\t      mpRefCount(weakPtr.mpRefCount)\n\t\t{\n\t\t\tweakPtr.mpValue = nullptr;\n\t\t\tweakPtr.mpRefCount = nullptr;\n\t\t}\n\n\n\t\t/// weak_ptr\n\t\t/// Constructs a weak_ptr from a shared_ptr.\n\t\ttemplate <typename U>\n\t\tweak_ptr(const shared_ptr<U>& sharedPtr,\n\t\t         typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0) EA_NOEXCEPT\n\t\t    : mpValue(sharedPtr.mpValue),\n\t\t      mpRefCount(sharedPtr.mpRefCount)\n\t\t{\n\t\t\tif (mpRefCount)\n\t\t\t\tmpRefCount->weak_addref();\n\t\t}\n\n\n\t\t/// ~weak_ptr\n\t\t~weak_ptr()\n\t\t{\n\t\t\tif(mpRefCount)\n\t\t\t\tmpRefCount->weak_release();\n\t\t}\n\n\n\t\t/// operator=(weak_ptr)\n\t\t/// assignment to self type.\n\t\tthis_type& operator=(const this_type& weakPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tassign(weakPtr);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\tthis_type& operator=(this_type&& weakPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tweak_ptr(eastl::move(weakPtr)).swap(*this);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=(weak_ptr)\n\t\ttemplate <typename U>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t\toperator=(const weak_ptr<U>& weakPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tassign(weakPtr);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\ttemplate <typename U>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t\toperator=(weak_ptr<U>&& weakPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tweak_ptr(eastl::move(weakPtr)).swap(*this);\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t/// operator=(shared_ptr)\n\t\t/// Assigns to a weak_ptr from a shared_ptr.\n\t\ttemplate <typename U>\n\t\ttypename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t\toperator=(const shared_ptr<U>& sharedPtr) EA_NOEXCEPT\n\t\t{\n\t\t\tif(mpRefCount != sharedPtr.mpRefCount) // This check encompasses assignment to self.\n\t\t\t{\n\t\t\t\t// Release old reference\n\t\t\t\tif(mpRefCount)\n\t\t\t\t\tmpRefCount->weak_release();\n\n\t\t\t\tmpValue    = sharedPtr.mpValue;\n\t\t\t\tmpRefCount = sharedPtr.mpRefCount;\n\t\t\t\tif(mpRefCount)\n\t\t\t\t\tmpRefCount->weak_addref();\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\n\t\tshared_ptr<T> lock() const EA_NOEXCEPT\n\t\t{\n\t\t\t// We can't just return shared_ptr<T>(*this), as the object may go stale while we are doing this.\n\t\t\tshared_ptr<T> temp;\n\t\t\ttemp.mpRefCount = mpRefCount ? mpRefCount->lock() : mpRefCount; // mpRefCount->lock() addref's the return value for us.\n\t\t\tif(temp.mpRefCount)\n\t\t\t\ttemp.mpValue = mpValue;\n\t\t\treturn temp;\n\t\t}\n\n\t\t// Returns: 0 if *this is empty ; otherwise, the number of shared_ptr instances that share ownership with *this.\n\t\tint use_count() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mpRefCount ? mpRefCount->use_count() : 0;\n\t\t}\n\n\t\t// Returns: use_count() == 0\n\t\tbool expired() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (!mpRefCount || (mpRefCount->use_count() == 0));\n\t\t}\n\n\t\tvoid reset()\n\t\t{\n\t\t\tif(mpRefCount)\n\t\t\t\tmpRefCount->weak_release();\n\n\t\t\tmpValue    = nullptr;\n\t\t\tmpRefCount = nullptr;\n\t\t}\n\n\t\tvoid swap(this_type& weakPtr)\n\t\t{\n\t\t\tT* const pValue = weakPtr.mpValue;\n\t\t\tweakPtr.mpValue = mpValue;\n\t\t\tmpValue         = pValue;\n\n\t\t\tref_count_sp* const pRefCount = weakPtr.mpRefCount;\n\t\t\tweakPtr.mpRefCount = mpRefCount;\n\t\t\tmpRefCount         = pRefCount;\n\t\t}\n\n\n\t\t/// assign\n\t\t///\n\t\t/// Assignment via another weak_ptr. \n\t\t///\n\t\ttemplate <typename U>\n\t\tvoid assign(const weak_ptr<U>& weakPtr,\n\t\t            typename eastl::enable_if<eastl::is_convertible<U*, element_type*>::value>::type* = 0) EA_NOEXCEPT\n\t\t{\n\t\t\tif(mpRefCount != weakPtr.mpRefCount) // This check encompasses assignment to self.\n\t\t\t{\n\t\t\t\t// Release old reference\n\t\t\t\tif(mpRefCount)\n\t\t\t\t\tmpRefCount->weak_release();\n\n\t\t\t\t// Add new reference\n\t\t\t\tmpValue    = weakPtr.mpValue;\n\t\t\t\tmpRefCount = weakPtr.mpRefCount;\n\t\t\t\tif(mpRefCount)\n\t\t\t\t\tmpRefCount->weak_addref();\n\t\t\t}\n\t\t}\n\n\n\t\t/// owner_before\n\t\t/// C++11 function for ordering.\n\t\ttemplate <typename U>\n\t\tbool owner_before(const weak_ptr<U>& weakPtr) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (mpRefCount < weakPtr.mpRefCount);\n\t\t}\n\n\t\t/// owner_before\n\t\ttemplate <typename U>\n\t\tbool owner_before(const shared_ptr<U>& sharedPtr) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (mpRefCount < sharedPtr.mpRefCount);\n\t\t}\n\n\n\t\t/// less_than\n\t\t/// For compatibility with pre-C++11 weak_ptr. Use owner_before instead.\n\t\ttemplate <typename U>\n\t\tbool less_than(const weak_ptr<U>& weakPtr) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (mpRefCount < weakPtr.mpRefCount);\n\t\t}\n\n\n\t\t/// assign\n\t\t///\n\t\t/// Assignment through a T/ref_count_sp pair. This is used by \n\t\t/// external utility functions.\n\t\t///\n\t\tvoid assign(element_type* pValue, ref_count_sp* pRefCount)\n\t\t{\n\t\t\tmpValue = pValue;\n\n\t\t\tif(pRefCount != mpRefCount)\n\t\t\t{\n\t\t\t\tif(mpRefCount)\n\t\t\t\t\tmpRefCount->weak_release();\n\n\t\t\t\tmpRefCount = pRefCount;\n\n\t\t\t\tif(mpRefCount)\n\t\t\t\t\tmpRefCount->weak_addref();\n\t\t\t}\n\t\t}\n\n\tprotected:\n\t\telement_type*  mpValue;       /// The (weakly) owned pointer.\n\t\tref_count_sp*  mpRefCount;    /// Reference count for owned pointer.\n\n\t\t// Friend declarations\n\t\ttemplate <typename U> friend class shared_ptr;\n\t\ttemplate <typename U> friend class weak_ptr;\n\n\t}; // class weak_ptr\n\n\n\n\t/// Note that the C++11 Standard does not specify that weak_ptr has comparison operators,\n\t/// though it does specify that the owner_before function exists in weak_ptr.\n\ttemplate <typename T, typename U>\n\tinline bool operator<(const weak_ptr<T>& weakPtr1, const weak_ptr<U>& weakPtr2)\n\t{\n\t\treturn weakPtr1.owner_before(weakPtr2);\n\t}\n\n\n\ttemplate <typename T>\n\tvoid swap(weak_ptr<T>& weakPtr1, weak_ptr<T>& weakPtr2)\n\t{\n\t\tweakPtr1.swap(weakPtr2);\n\t}\n\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// owner_less\n\t//\n\t// Implements less (operator <) for shared_ptr and thus allows it to participate\n\t// in algorithms and containers that use strict weak ordering, such as map.\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T> \n\tstruct owner_less;\n\n\ttemplate <typename T>\n\tstruct owner_less< shared_ptr<T> >\n\t{\n\t\tbool operator()(shared_ptr<T> const& a, shared_ptr<T> const& b) const EA_NOEXCEPT\n\t\t\t{ return a.owner_before(b); }\n\n\t\tbool operator()(shared_ptr<T> const& a, weak_ptr<T> const& b) const EA_NOEXCEPT\n\t\t\t{ return a.owner_before(b); }\n\n\t\tbool operator()(weak_ptr<T> const& a, shared_ptr<T> const& b) const EA_NOEXCEPT\n\t\t\t{ return a.owner_before(b); }\n\t};\n\n\ttemplate <typename T>\n\tstruct owner_less< weak_ptr<T> >\n\t{\n\t\tbool operator()(weak_ptr<T> const& a, weak_ptr<T> const& b) const EA_NOEXCEPT\n\t\t\t{ return a.owner_before(b); }\n\n\t\tbool operator()(weak_ptr<T> const& a, shared_ptr<T> const& b) const EA_NOEXCEPT\n\t\t\t{ return a.owner_before(b); }\n\n\t\tbool operator()(shared_ptr<T> const& a, weak_ptr<T> const& b) const EA_NOEXCEPT\n\t\t\t{ return a.owner_before(b); }\n\t};\n\n\ttemplate <>\n\tstruct owner_less<void>\n\t{\n\t\ttypedef int is_transparent;\n\n\t\ttemplate<typename T, typename U>\n\t\tbool operator()(shared_ptr<T> const& a, shared_ptr<U> const& b) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn a.owner_before(b);\n\t\t}\n\n\t\ttemplate<typename T, typename U>\n\t\tbool operator()(shared_ptr<T> const& a, weak_ptr<U> const& b) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn a.owner_before(b);\n\t\t}\n\n\t\ttemplate<typename T, typename U>\n\t\tbool operator()(weak_ptr<T> const& a, shared_ptr<U> const& b) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn a.owner_before(b);\n\t\t}\n\n\t\ttemplate<typename T, typename U>\n\t\tbool operator()(weak_ptr<T> const& a, weak_ptr<U> const& b) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn a.owner_before(b);\n\t\t}\n\t};\n\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n// We have to either #include enable_shared.h here or we need to move the enable_shared source code to here.\n#include <EASTL/internal/enable_shared.h>\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/slist.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// An slist is a singly-linked list. The C++ standard library doesn't define\n// such a thing as an slist, nor does the C++ TR1. Our implementation of slist\n// largely follows the design of the SGI STL slist container, which is also \n// found in STLPort. Singly-linked lists use less memory than doubly-linked \n// lists, but are less flexible. \n//\n// In looking at slist, you will notice a lot of references to things like\n// 'before first', 'before last', 'insert after', and 'erase after'. This is \n// due to the fact that std::list insert and erase works on the node before\n// the referenced node, whereas slist is singly linked and operations are only\n// efficient if they work on the node after the referenced node. This is because\n// with an slist node you know the node after it but not the node before it.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef EASTL_SLIST_H\n#define EASTL_SLIST_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/memory.h>\n#include <EASTL/sort.h>\n#include <EASTL/bonus/compressed_pair.h>\n#include <stddef.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\nEA_DISABLE_ALL_VC_WARNINGS();\n\n\t#include <new>\n\nEA_RESTORE_ALL_VC_WARNINGS();\n\nEA_DISABLE_SN_WARNING(828); // The EDG SN compiler has a bug in its handling of variadic template arguments and mistakenly reports \"parameter \"args\" was never referenced\"\n\n\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4345 - Behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\nEA_DISABLE_VC_WARNING(4530 4345 4571);\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_SLIST_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_SLIST_DEFAULT_NAME\n\t\t#define EASTL_SLIST_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" slist\" // Unless the user overrides something, this is \"EASTL slist\".\n\t#endif\n\n\n\t/// EASTL_SLIST_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_SLIST_DEFAULT_ALLOCATOR\n\t\t#define EASTL_SLIST_DEFAULT_ALLOCATOR allocator_type(EASTL_SLIST_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// SListNodeBase\n\t///\n\t/// This is a standalone struct so that operations on it can be done without templates\n\t/// and so that an empty slist can have an SListNodeBase and thus not create any \n\t/// instances of T.\n\t///\n\tstruct SListNodeBase\n\t{\n\t\tSListNodeBase* mpNext;\n\t};\n\n\n\ttemplate <typename T>\n\tstruct SListNode : public SListNodeBase\n\t{\n\t\tT mValue;\n\t};\n\n\t/// SListIterator\n\t///\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tstruct SListIterator\n\t{\n\t\ttypedef SListIterator<T, Pointer, Reference>   this_type;\n\t\ttypedef SListIterator<T, T*, T&>               iterator;\n\t\ttypedef SListIterator<T, const T*, const T&>   const_iterator;\n\t\ttypedef eastl_size_t                           size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                              difference_type;\n\t\ttypedef T                                      value_type;\n\t\ttypedef SListNodeBase                          base_node_type;\n\t\ttypedef SListNode<T>                           node_type;\n\t\ttypedef Pointer                                pointer;\n\t\ttypedef Reference                              reference;\n\t\ttypedef eastl::forward_iterator_tag     iterator_category;\n\n\tpublic:\n\t\tbase_node_type* mpNode;\n\n\tpublic:\n\t\tSListIterator();\n\t\tSListIterator(const SListNodeBase* pNode);\n\t\t\n\t\ttemplate <typename This = this_type, enable_if_t<!is_same_v<This, iterator>, bool> = true>\n\t\tinline SListIterator(const iterator& x)\n\t\t\t: mpNode(x.mpNode)\n\t\t{\n\t\t\t// Empty\n\t\t}\n\n\t\treference operator*() const;\n\t\tpointer   operator->() const;\n\n\t\tthis_type& operator++();\n\t\tthis_type  operator++(int);\n\t};\n\n\n\n\t/// SListBase\n\t///\n\t/// See VectorBase (class vector) for an explanation of why we \n\t/// create this separate base class.\n\t///\n\ttemplate <typename T, typename Allocator>\n\tstruct SListBase\n\t{\n\tpublic:\n\t\ttypedef Allocator                              allocator_type;\n\t\ttypedef SListNode<T>                           node_type;\n\t\ttypedef eastl_size_t                           size_type;     // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                              difference_type;\n\t\ttypedef SListNodeBase                      base_node_type; // We use SListNodeBase instead of SListNode<T> because we don't want to create a T.\n\n\tprotected:\n\t\teastl::compressed_pair<base_node_type, allocator_type>  mNodeAllocator;\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\tsize_type  mSize;\n\t\t#endif\n\n\t\tbase_node_type& internalNode() EA_NOEXCEPT { return mNodeAllocator.first(); }\n\t\tbase_node_type const& internalNode() const EA_NOEXCEPT { return mNodeAllocator.first(); }\n\t\tallocator_type& internalAllocator() EA_NOEXCEPT { return mNodeAllocator.second(); }\n\t\tconst allocator_type& internalAllocator() const EA_NOEXCEPT { return mNodeAllocator.second(); }\n\n\tpublic:\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT;\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT;\n\t\tvoid                  set_allocator(const allocator_type& allocator);\n\n\tprotected:\n\t\tSListBase();\n\t\tSListBase(const allocator_type& a);\n\t   ~SListBase();\n\n\t\tnode_type* DoAllocateNode();\n\t\tvoid       DoFreeNode(node_type* pNode);\n\n\t\tSListNodeBase* DoEraseAfter(SListNodeBase* pNode);\n\t\tSListNodeBase* DoEraseAfter(SListNodeBase* pNode, SListNodeBase* pNodeLast);\n\n\t}; // class SListBase\n\n\n\n\t/// slist\n\t///\n\t/// This is the equivalent of C++11's forward_list.\n\t///\n\t/// -- size() is O(n) --\n\t/// Note that as of this writing, list::size() is an O(n) operation when EASTL_SLIST_SIZE_CACHE is disabled. \n\t/// That is, getting the size of the list is not a fast operation, as it requires traversing the list and \n\t/// counting the nodes. We could make list::size() be fast by having a member mSize variable. There are reasons \n\t/// for having such functionality and reasons for not having such functionality. We currently choose\n\t/// to not have a member mSize variable as it would add four bytes to the class, add a tiny amount\n\t/// of processing to functions such as insert and erase, and would only serve to improve the size\n\t/// function, but no others. The alternative argument is that the C++ standard states that std::list\n\t/// should be an O(1) operation (i.e. have a member size variable), most C++ standard library list\n\t/// implementations do so, the size is but an integer which is quick to update, and many users \n\t/// expect to have a fast size function. The EASTL_SLIST_SIZE_CACHE option changes this.\n\t/// To consider: Make size caching an optional template parameter.\n\t///\n\t/// Pool allocation\n\t/// If you want to make a custom memory pool for a list container, your pool \n\t/// needs to contain items of type slist::node_type. So if you have a memory\n\t/// pool that has a constructor that takes the size of pool items and the\n\t/// count of pool items, you would do this (assuming that MemoryPool implements\n\t/// the Allocator interface):\n\t///     typedef slist<Widget, MemoryPool> WidgetList;          // Delare your WidgetList type.\n\t///     MemoryPool myPool(sizeof(WidgetList::node_type), 100); // Make a pool of 100 Widget nodes.\n\t///     WidgetList myList(&myPool);                            // Create a list that uses the pool.\n\t///\n\ttemplate <typename T, typename Allocator = EASTLAllocatorType >\n\tclass slist : public SListBase<T, Allocator>\n\t{\n\t\ttypedef SListBase<T, Allocator>              base_type;\n\t\ttypedef slist<T, Allocator>                  this_type;\n\n\tprotected:\n\t\tusing base_type::mNodeAllocator;\n\t\tusing base_type::DoEraseAfter;\n\t\tusing base_type::DoAllocateNode;\n\t\tusing base_type::DoFreeNode;\n#if EASTL_SLIST_SIZE_CACHE\n\t\tusing base_type::mSize;\n#endif\n\t\tusing base_type::internalNode;\n\t\tusing base_type::internalAllocator;\n\n\tpublic:\n\t\ttypedef T                                    value_type;\n\t\ttypedef value_type*                          pointer;\n\t\ttypedef const value_type*                    const_pointer;\n\t\ttypedef value_type&                          reference;\n\t\ttypedef const value_type&                    const_reference;\n\t\ttypedef SListIterator<T, T*, T&>             iterator;\n\t\ttypedef SListIterator<T, const T*, const T&> const_iterator;\n\t\ttypedef typename base_type::size_type        size_type;\n\t\ttypedef typename base_type::difference_type  difference_type;\n\t\ttypedef typename base_type::allocator_type   allocator_type;\n\t\ttypedef typename base_type::node_type        node_type;\n\t\ttypedef typename base_type::base_node_type   base_node_type;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"slist<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"slist<T> value_type must be non-volatile.\");\n\n\tpublic:\n\t\tslist();\n\t\tslist(const allocator_type& allocator);\n\t\texplicit slist(size_type n, const allocator_type& allocator = EASTL_SLIST_DEFAULT_ALLOCATOR);\n\t\tslist(size_type n, const value_type& value, const allocator_type& allocator = EASTL_SLIST_DEFAULT_ALLOCATOR);\n\t\tslist(const this_type& x);\n\t\tslist(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_SLIST_DEFAULT_ALLOCATOR);\n\t\tslist(this_type&& x);\n\t\tslist(this_type&& x, const allocator_type& allocator);\n\n\t\ttemplate <typename InputIterator>\n\t\tslist(InputIterator first, InputIterator last); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type>);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tvoid assign(size_type n, const value_type& value);\n\t\tvoid assign(std::initializer_list<value_type> ilist);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid assign(InputIterator first, InputIterator last);\n\n\t\titerator       begin() EA_NOEXCEPT;\n\t\tconst_iterator begin() const EA_NOEXCEPT;\n\t\tconst_iterator cbegin() const EA_NOEXCEPT;\n\n\t\titerator       end() EA_NOEXCEPT;\n\t\tconst_iterator end() const EA_NOEXCEPT;\n\t\tconst_iterator cend() const EA_NOEXCEPT;\n\n\t\titerator       before_begin() EA_NOEXCEPT;\n\t\tconst_iterator before_begin() const EA_NOEXCEPT;\n\t\tconst_iterator cbefore_begin() const EA_NOEXCEPT;\n\n\t\titerator        previous(const_iterator position);\n\t\tconst_iterator  previous(const_iterator position) const;\n\n\t\treference       front();\n\t\tconst_reference front() const;\n\n\t\ttemplate <class... Args>\n\t\treference emplace_front(Args&&... args);\n\n\t\tvoid      push_front(const value_type& value);\n\t\treference push_front();\n\t\tvoid      push_front(value_type&& value);\n\n\t\tvoid      pop_front();\n\n\t\tbool      empty() const EA_NOEXCEPT;\n\t\tsize_type size() const EA_NOEXCEPT;\n\n\t\tvoid resize(size_type n, const value_type& value);\n\t\tvoid resize(size_type n);\n\n\t\titerator insert(const_iterator position);\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\tvoid     insert(const_iterator position, size_type n, const value_type& value);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(const_iterator position, InputIterator first, InputIterator last);\n\n\t\t// Returns an iterator pointing to the last inserted element, or position if insertion count is zero.\n\t\titerator insert_after(const_iterator position);\n\t\titerator insert_after(const_iterator position, const value_type& value);\n\t\titerator insert_after(const_iterator position, size_type n, const value_type& value);\n\t\titerator insert_after(const_iterator position, std::initializer_list<value_type> ilist);\n\t\titerator insert_after(const_iterator position, value_type&& value);\n\n\t\ttemplate <class... Args>\n\t\titerator emplace_after(const_iterator position, Args&&... args);\n\n\t\ttemplate <typename InputIterator>\n\t\titerator insert_after(const_iterator position, InputIterator first, InputIterator last);\n\n\t\titerator erase(const_iterator position);\n\t\titerator erase(const_iterator first, const_iterator last);\n\n\t\titerator erase_after(const_iterator position);\n\t\titerator erase_after(const_iterator before_first, const_iterator last);\n\n\t\tvoid clear() EA_NOEXCEPT;\n\t\tvoid reset_lose_memory() EA_NOEXCEPT;    // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tsize_type remove(const value_type& value);\n\n\t\ttemplate <typename Predicate>\n\t\tsize_type remove_if(Predicate predicate);\n\n\t\tvoid reverse() EA_NOEXCEPT;\n\n\t\t// splice splices to before position, like with the list container. However, in order to do so \n\t\t// it must walk the list from beginning to position, which is an O(n) operation that can thus \n\t\t// be slow. It's recommended that the splice_after functions be used whenever possible as they are O(1).\n\t\tvoid splice(const_iterator position, this_type& x);\n\t\tvoid splice(const_iterator position, this_type& x, const_iterator i);\n\t\tvoid splice(const_iterator position, this_type& x, const_iterator first, const_iterator last);\n\t\tvoid splice(const_iterator position, this_type&& x);\n\t\tvoid splice(const_iterator position, this_type&& x, const_iterator i);\n\t\tvoid splice(const_iterator position, this_type&& x, const_iterator first, const_iterator last);\n\n\t\tvoid splice_after(const_iterator position, this_type& x);\n\t\tvoid splice_after(const_iterator position, this_type& x, const_iterator i);\n\t\tvoid splice_after(const_iterator position, this_type& x, const_iterator first, const_iterator last);\n\t\tvoid splice_after(const_iterator position, this_type&& x);\n\t\tvoid splice_after(const_iterator position, this_type&& x, const_iterator i);\n\t\tvoid splice_after(const_iterator position, this_type&& x, const_iterator first, const_iterator last);\n\n\t\tsize_type unique();\n\n\t\ttemplate <typename BinaryPredicate>\n\t\tsize_type unique(BinaryPredicate);\n\n\t\t// Sorting functionality\n\t\t// This is independent of the global sort algorithms, as lists are \n\t\t// linked nodes and can be sorted more efficiently by moving nodes\n\t\t// around in ways that global sort algorithms aren't privy to.\n\t\tvoid sort();\n\n\t\ttemplate <class Compare>\n\t\tvoid sort(Compare compare);\n\n\t\t// Not yet implemented:\n\t\t// void merge(this_type& x);\n\t\t// void merge(this_type&& x);\n\t\t// template <class Compare>\n\t\t// void merge(this_type& x, Compare compare);\n\t\t// template <class Compare>\n\t\t// void merge(this_type&& x, Compare compare);\n\t\t// If these get implemented then make sure to override them in fixed_slist.\n\n\t\tbool validate() const;\n\t\tint  validate_iterator(const_iterator i) const;\n\n\tprotected:\n\t\tnode_type* DoCreateNode();\n\n\t\ttemplate<typename... Args>\n\t\tnode_type* DoCreateNode(Args&&... args);\n\n\t\ttemplate <typename Integer>\n\t\tvoid DoAssign(Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoAssign(InputIterator first, InputIterator last, false_type);\n\n\t\tvoid DoAssignValues(size_type n, const value_type& value);\n\n\t\ttemplate <typename InputIterator>\n\t\tnode_type* DoInsertAfter(SListNodeBase* pNode, InputIterator first, InputIterator last);\n\n\t\ttemplate <typename Integer>\n\t\tnode_type* DoInsertAfter(SListNodeBase* pNode, Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tnode_type* DoInsertAfter(SListNodeBase* pNode, InputIterator first, InputIterator last, false_type);\n\n\t\tnode_type* DoInsertValueAfter(SListNodeBase* pNode);\n\t\tnode_type* DoInsertValuesAfter(SListNodeBase* pNode, size_type n, const value_type& value);\n\n\t\ttemplate<typename... Args>\n\t\tnode_type* DoInsertValueAfter(SListNodeBase* pNode, Args&&... args);\n\n\t\tvoid DoSwap(this_type& x);\n\n\t}; // class slist\n\n\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// SListNodeBase functions\n\t///////////////////////////////////////////////////////////////////////\n\n\tinline SListNodeBase* SListNodeInsertAfter(SListNodeBase* pPrevNode, SListNodeBase* pNode)\n\t{\n\t\tpNode->mpNext = pPrevNode->mpNext;\n\t\tpPrevNode->mpNext = pNode;\n\t\treturn pNode;\n\t}\n\n\tinline SListNodeBase* SListNodeGetPrevious(SListNodeBase* pNodeBase, const SListNodeBase* pNode)\n\t{\n\t\twhile(pNodeBase && (pNodeBase->mpNext != pNode))\n\t\t\tpNodeBase = pNodeBase->mpNext;\n\t\treturn pNodeBase;\n\t}\n\n\tinline const SListNodeBase* SListNodeGetPrevious(const SListNodeBase* pNodeBase, const SListNodeBase* pNode)\n\t{\n\t\twhile(pNodeBase && (pNodeBase->mpNext != pNode))\n\t\t\tpNodeBase = pNodeBase->mpNext;\n\t\treturn pNodeBase;\n\t}\n\n\tinline void SListNodeSpliceAfter(SListNodeBase* pNode, SListNodeBase* pNodeBeforeFirst, SListNodeBase* pNodeBeforeLast)\n\t{\n\t\tif((pNode != pNodeBeforeFirst) && (pNode != pNodeBeforeLast))\n\t\t{\n\t\t\tSListNodeBase* const pFirst    = pNodeBeforeFirst->mpNext;\n\t\t\tSListNodeBase* const pPosition = pNode->mpNext;\n\n\t\t\tpNodeBeforeFirst->mpNext = pNodeBeforeLast->mpNext;\n\t\t\tpNode->mpNext            = pFirst;\n\t\t\tpNodeBeforeLast->mpNext  = pPosition;\n\t\t}\n\t}\n\n\tinline void SListNodeSpliceAfter(SListNodeBase* pNode, SListNodeBase* pNodeBase)\n\t{\n\t\tSListNodeBase* const pNodeBeforeLast = SListNodeGetPrevious(pNodeBase, NULL);\n\n\t\tif(pNodeBeforeLast != pNodeBase)\n\t\t{\n\t\t\tSListNodeBase* const pPosition = pNode->mpNext;\n\t\t\tpNode->mpNext           = pNodeBase->mpNext;\n\t\t\tpNodeBase->mpNext       = NULL;\n\t\t\tpNodeBeforeLast->mpNext = pPosition;\n\t\t}\n\t}\n\n\tinline SListNodeBase* SListNodeReverse(SListNodeBase* pNode)\n\t{\n\t\tSListNodeBase* pNodeFirst = pNode;\n\t\tpNode = pNode->mpNext;\n\t\tpNodeFirst->mpNext = NULL;\n\n\t\twhile(pNode)\n\t\t{\n\t\t\tSListNodeBase* const pTemp = pNode->mpNext;\n\t\t\tpNode->mpNext = pNodeFirst;\n\t\t\tpNodeFirst    = pNode;\n\t\t\tpNode         = pTemp;\n\t\t}\n\t\treturn pNodeFirst;\n\t}\n\n\tinline uint32_t SListNodeGetSize(SListNodeBase* pNode)\n\t{\n\t\tuint32_t n = 0;\n\t\twhile(pNode)\n\t\t{\n\t\t\t++n;\n\t\t\tpNode = pNode->mpNext;\n\t\t}\n\t\treturn n;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// SListIterator functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline SListIterator<T, Pointer, Reference>::SListIterator()\n\t\t: mpNode(NULL)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline SListIterator<T, Pointer, Reference>::SListIterator(const SListNodeBase* pNode)\n\t\t: mpNode(const_cast<base_node_type*>(pNode))\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename SListIterator<T, Pointer, Reference>::reference\n\tSListIterator<T, Pointer, Reference>::operator*() const\n\t{\n\t\treturn static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename SListIterator<T, Pointer, Reference>::pointer\n\tSListIterator<T, Pointer, Reference>::operator->() const\n\t{\n\t\treturn &static_cast<node_type*>(mpNode)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename SListIterator<T, Pointer, Reference>::this_type&\n\tSListIterator<T, Pointer, Reference>::operator++()\n\t{\n\t\tmpNode = mpNode->mpNext;\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline typename SListIterator<T, Pointer, Reference>::this_type\n\tSListIterator<T, Pointer, Reference>::operator++(int)\n\t{\n\t\tthis_type temp(*this);\n\t\tmpNode = mpNode->mpNext;\n\t\treturn temp;\n\t}\n\n\t// The C++ defect report #179 requires that we support comparisons between const and non-const iterators.\n\t// Thus we provide additional template paremeters here to support this. The defect report does not\n\t// require us to support comparisons between reverse_iterators and const_reverse_iterators.\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator==(const SListIterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const SListIterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode == b.mpNode;\n\t}\n\n\n\ttemplate <typename T, typename PointerA, typename ReferenceA, typename PointerB, typename ReferenceB>\n\tinline bool operator!=(const SListIterator<T, PointerA, ReferenceA>& a, \n\t\t\t\t\t\t   const SListIterator<T, PointerB, ReferenceB>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\t// We provide a version of operator!= for the case where the iterators are of the \n\t// same type. This helps prevent ambiguity errors in the presence of rel_ops.\n\ttemplate <typename T, typename Pointer, typename Reference>\n\tinline bool operator!=(const SListIterator<T, Pointer, Reference>& a, \n\t\t\t\t\t\t   const SListIterator<T, Pointer, Reference>& b)\n\t{\n\t\treturn a.mpNode != b.mpNode;\n\t}\n\n\n\n\n\t\n\t///////////////////////////////////////////////////////////////////////\n\t// SListBase functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline SListBase<T, Allocator>::SListBase()\n\t\t: mNodeAllocator(base_node_type(), allocator_type(EASTL_SLIST_DEFAULT_NAME))\n\t\t  #if EASTL_SLIST_SIZE_CACHE\n\t\t  , mSize(0)\n\t\t  #endif\n\t{ \n\t\tinternalNode().mpNext = NULL;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline SListBase<T, Allocator>::SListBase(const allocator_type& allocator)\n\t\t: mNodeAllocator(base_node_type(), allocator)\n\t\t  #if EASTL_SLIST_SIZE_CACHE\n\t\t  , mSize(0)\n\t\t  #endif\n\t{ \n\t\tinternalNode().mpNext = NULL;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline SListBase<T, Allocator>::~SListBase()\n\t{\n\t\tDoEraseAfter(&internalNode(), NULL);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline const typename SListBase<T, Allocator>::allocator_type&\n\tSListBase<T, Allocator>::get_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename SListBase<T, Allocator>::allocator_type&\n\tSListBase<T, Allocator>::get_allocator() EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid\n\tSListBase<T, Allocator>::set_allocator(const allocator_type& allocator)\n\t{\n\t\tif((internalAllocator() != allocator) && (static_cast<node_type*>(internalNode().mpNext) != NULL))\n\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"slist::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\tinternalAllocator() = allocator;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline SListNode<T>* SListBase<T, Allocator>::DoAllocateNode()\n\t{\n\t\treturn (node_type*)allocate_memory(internalAllocator(), sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void SListBase<T, Allocator>::DoFreeNode(node_type* pNode)\n\t{\n\t\tEASTLFree(internalAllocator(), pNode, sizeof(node_type));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tSListNodeBase* SListBase<T, Allocator>::DoEraseAfter(SListNodeBase* pNode)\n\t{\n\t\tnode_type*     const pNodeNext     = static_cast<node_type*>((base_node_type*)pNode->mpNext);\n\t\tSListNodeBase* const pNodeNextNext = pNodeNext->mpNext;\n\n\t\tpNode->mpNext = pNodeNextNext;\n\t\tpNodeNext->~node_type();\n\t\tDoFreeNode(pNodeNext);\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t   --mSize;\n\t\t#endif\n\t\treturn pNodeNextNext;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tSListNodeBase* SListBase<T, Allocator>::DoEraseAfter(SListNodeBase* pNode, SListNodeBase* pNodeLast)\n\t{\n\t\tnode_type* pNodeCurrent = static_cast<node_type*>((base_node_type*)pNode->mpNext);\n\n\t\twhile(pNodeCurrent != (base_node_type*)pNodeLast)\n\t\t{\n\t\t\tnode_type* const pNodeTemp = pNodeCurrent;\n\t\t\tpNodeCurrent = static_cast<node_type*>((base_node_type*)pNodeCurrent->mpNext);\n\t\t\tpNodeTemp->~node_type();\n\t\t\tDoFreeNode(pNodeTemp);\n\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t--mSize;\n\t\t\t#endif\n\t\t}\n\t\tpNode->mpNext = pNodeLast;\n\t\treturn pNodeLast;\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// slist functions\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline slist<T, Allocator>::slist()\n\t\t: base_type()\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline slist<T, Allocator>::slist(const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline slist<T, Allocator>::slist(size_type n, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInsertValuesAfter(&internalNode(), n, value_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline slist<T, Allocator>::slist(size_type n, const value_type& value, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInsertValuesAfter(&internalNode(), n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline slist<T, Allocator>::slist(const slist& x)\n\t\t: base_type(x.internalAllocator())\n\t{\n\t\tDoInsertAfter(&internalNode(), const_iterator(x.internalNode().mpNext), const_iterator(NULL), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tslist<T, Allocator>::slist(this_type&& x)\n\t\t: base_type(x.internalAllocator())\n\t{\n\t\tswap(x);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tslist<T, Allocator>::slist(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tswap(x); // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline slist<T, Allocator>::slist(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInsertAfter(&internalNode(), ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline slist<T, Allocator>::slist(InputIterator first, InputIterator last)\n\t\t: base_type(EASTL_SLIST_DEFAULT_ALLOCATOR)\n\t{\n\t\tDoInsertAfter(&internalNode(), first, last);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::begin() EA_NOEXCEPT\n\t{\n\t\treturn iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_iterator\n\tslist<T, Allocator>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_iterator\n\tslist<T, Allocator>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::end() EA_NOEXCEPT\n\t{\n\t\treturn iterator(NULL);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_iterator\n\tslist<T, Allocator>::end() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(NULL);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_iterator\n\tslist<T, Allocator>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(NULL);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::before_begin() EA_NOEXCEPT\n\t{\n\t\treturn iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_iterator\n\tslist<T, Allocator>::before_begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_iterator\n\tslist<T, Allocator>::cbefore_begin() const EA_NOEXCEPT\n\t{\n\t\treturn const_iterator(&internalNode());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::previous(const_iterator position)\n\t{\n\t\treturn iterator(SListNodeGetPrevious(&internalNode(), position.mpNode));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_iterator\n\tslist<T, Allocator>::previous(const_iterator position) const\n\t{\n\t\treturn const_iterator(SListNodeGetPrevious(&internalNode(), position.mpNode));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::reference\n\tslist<T, Allocator>::front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(internalNode().mpNext == NULL))\n\t\t\t\tEASTL_FAIL_MSG(\"slist::front -- empty container\");\n\t\t#endif\n\n\t\tEA_ANALYSIS_ASSUME(internalNode().mpNext != NULL);\n\n\t\treturn ((node_type*)internalNode().mpNext)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::const_reference\n\tslist<T, Allocator>::front() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(internalNode().mpNext == NULL))\n\t\t\t\tEASTL_FAIL_MSG(\"slist::front -- empty container\");\n\t\t#endif\n\n\t\tEA_ANALYSIS_ASSUME(internalNode().mpNext != NULL);\n\n\t\treturn static_cast<node_type*>(internalNode().mpNext)->mValue;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <class... Args>\n\ttypename slist<T, Allocator>::reference slist<T, Allocator>::emplace_front(Args&&... args)\n\t{\n\t\tDoInsertValueAfter(&internalNode(), eastl::forward<Args>(args)...);\n\t\treturn static_cast<node_type*>(internalNode().mpNext)->mValue; // Same as return front();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::push_front(const value_type& value)\n\t{\n\t\tSListNodeInsertAfter(&internalNode(), DoCreateNode(value));\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t   ++mSize;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::reference\n\tslist<T, Allocator>::push_front()\n\t{\n\t\tSListNodeInsertAfter(&internalNode(), DoCreateNode());\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t   ++mSize;\n\t\t#endif\n\t\treturn ((node_type*)internalNode().mpNext)->mValue; // Same as return front();\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tvoid slist<T, Allocator>::push_front(value_type&& value)\n\t{\n\t\templace_after(before_begin(), eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid slist<T, Allocator>::pop_front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(internalNode().mpNext == NULL))\n\t\t\t\tEASTL_FAIL_MSG(\"slist::front -- empty container\");\n\t\t#endif\n\n\t\tEA_ANALYSIS_ASSUME(internalNode().mpNext != NULL);\n\n\t\tnode_type* const pNode = static_cast<node_type*>(internalNode().mpNext);\n\t\tinternalNode().mpNext = pNode->mpNext;\n\t\tpNode->~node_type();\n\t\tDoFreeNode(pNode);\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t   --mSize;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename slist<T, Allocator>::this_type& slist<T, Allocator>::operator=(const this_type& x)\n\t{\n\t\tif(&x != this)\n\t\t{\n\t\t\t// If (EASTL_ALLOCATOR_COPY_ENABLED == 1) and the current contents are allocated by an \n\t\t\t// allocator that's unequal to x's allocator, we need to reallocate our elements with \n\t\t\t// our current allocator and reallocate it with x's allocator. If the allocators are \n\t\t\t// equal then we can use a more optimal algorithm that doesn't reallocate our elements\n\t\t\t// but instead can copy them in place.\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tbool bSlowerPathwayRequired = (internalAllocator() != x.internalAllocator());\n\t\t\t#else\n\t\t\t\tbool bSlowerPathwayRequired = false;\n\t\t\t#endif\n\n\t\t\tif(bSlowerPathwayRequired)\n\t\t\t{\n\t\t\t\tclear();\n\n\t\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\t\tinternalAllocator() = x.internalAllocator();\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tDoAssign(x.begin(), x.end(), eastl::false_type());\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename slist<T, Allocator>::this_type& slist<T, Allocator>::operator=(this_type&& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tclear();        // To consider: Are we really required to clear here? x is going away soon and will clear itself in its dtor.\n\t\t\tswap(x);        // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename slist<T, Allocator>::this_type& slist<T, Allocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tDoAssign(ilist.begin(), ilist.end(), false_type());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::assign(std::initializer_list<value_type> ilist)\n\t{\n\t\tDoAssign(ilist.begin(), ilist.end(), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>                                                // It turns out that the C++ std::list specifies a two argument\n\tinline void slist<T, Allocator>::assign(InputIterator first, InputIterator last) // version of assign that takes (int size, int value). These are not \n\t{                                                                                // iterators, so we need to do a template compiler trick to do the right thing.\n\t\tDoAssign(first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::assign(size_type n, const value_type& value)\n\t{\n\t\t// To do: get rid of DoAssignValues and put its implementation directly here.\n\t\tDoAssignValues(n, value);\n\t}\n\n\t\n\t// does not propagate allocators on swap.\n\t// in addition, requires T be copy constructible and copy assignable, which isn't required by the standard.\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::swap(this_type& x)\n\t{\n\t\tif(internalAllocator() == x.internalAllocator()) // If allocators are equivalent...\n\t\t\tDoSwap(x);\n\t\telse // else swap the contents.\n\t\t{\n\t\t\tconst this_type temp(*this); // Can't call eastl::swap because that would\n\t\t\t*this = x;                   // itself call this member swap function.\n\t\t\tx     = temp;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool slist<T, Allocator>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn internalNode().mpNext == NULL;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::size_type\n\tslist<T, Allocator>::size() const EA_NOEXCEPT\n\t{\n\t\treturn SListNodeGetSize(internalNode().mpNext);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::clear() EA_NOEXCEPT\n\t{\n\t\tDoEraseAfter(&internalNode(), NULL);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::reset_lose_memory() EA_NOEXCEPT\n\t{\n\t\t// The reset function is a special extension function which unilaterally \n\t\t// resets the container to an empty state without freeing the memory of \n\t\t// the contained objects. This is useful for very quickly tearing down a \n\t\t// container built into scratch memory.\n\t\tinternalNode().mpNext = NULL;\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\tmSize = 0;\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid slist<T, Allocator>::resize(size_type n, const value_type& value)\n\t{\n\t\tSListNodeBase* pNode = &internalNode();\n\n\t\tfor(; pNode->mpNext && (n > 0); --n)\n\t\t\tpNode = pNode->mpNext;\n\n\t\tif(pNode->mpNext)\n\t\t\tDoEraseAfter(pNode, NULL);\n\t\telse\n\t\t\tDoInsertValuesAfter(pNode, n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::resize(size_type n)\n\t{\n\t\tresize(n, value_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert(const_iterator position)\n\t{\n\t\treturn iterator(DoInsertValueAfter(SListNodeGetPrevious(&internalNode(), position.mpNode), value_type()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert(const_iterator position, const value_type& value)\n\t{\n\t\treturn iterator(DoInsertValueAfter(SListNodeGetPrevious(&internalNode(), position.mpNode), value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::insert(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\t// To do: get rid of DoAssignValues and put its implementation directly here.\n\t\tDoInsertValuesAfter(SListNodeGetPrevious(&internalNode(), position.mpNode), n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline void slist<T, Allocator>::insert(const_iterator position, InputIterator first, InputIterator last)\n\t{\n\t\tDoInsertAfter(SListNodeGetPrevious(&internalNode(), position.mpNode), first, last);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert_after(const_iterator position)\n\t{\n\t\treturn insert_after(position, value_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert_after(const_iterator position, const value_type& value)\n\t{\n\t\treturn iterator(DoInsertValueAfter(position.mpNode, value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert_after(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\treturn iterator(DoInsertValuesAfter(position.mpNode, n, value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert_after(const_iterator position, std::initializer_list<value_type> ilist)\n\t{\n\t\treturn iterator(DoInsertAfter(position.mpNode, ilist.begin(), ilist.end(), false_type()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert_after(const_iterator position, InputIterator first, InputIterator last)\n\t{\n\t\treturn iterator(DoInsertAfter(position.mpNode, first, last));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::insert_after(const_iterator position, value_type&& value)\n\t{\n\t\treturn emplace_after(position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <class... Args>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::emplace_after(const_iterator position, Args&&... args)\n\t{\n\t\treturn iterator(DoInsertValueAfter(position.mpNode, eastl::forward<Args>(args)...));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::erase(const_iterator position)\n\t{\n\t\treturn DoEraseAfter(SListNodeGetPrevious(&internalNode(), position.mpNode));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::erase(const_iterator first, const_iterator last)\n\t{\n\t\treturn DoEraseAfter(SListNodeGetPrevious(&internalNode(), first.mpNode), last.mpNode);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::erase_after(const_iterator position)\n\t{\n\t\treturn iterator(DoEraseAfter(position.mpNode));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::iterator\n\tslist<T, Allocator>::erase_after(const_iterator before_first, const_iterator last)\n\t{\n\t\treturn iterator(DoEraseAfter(before_first.mpNode, last.mpNode));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename slist<T, Allocator>::size_type slist<T, Allocator>::remove(const value_type& value)\n\t{ \n\t\tbase_node_type* pNode = &internalNode();\n\t\tsize_type numErased = 0;\n\n\t\twhile(pNode && pNode->mpNext)\n\t\t{\n\t\t\tif (static_cast<node_type*>(pNode->mpNext)->mValue == value)\n\t\t\t{\n\t\t\t\tDoEraseAfter(pNode); // This will take care of modifying pNode->mpNext.\n\t\t\t\t++numErased;\n\t\t\t}\n\t\t\telse\n\t\t\t\tpNode = pNode->mpNext;\n\t\t}\n\t\treturn numErased;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Predicate>\n\tinline typename slist<T, Allocator>::size_type slist<T, Allocator>::remove_if(Predicate predicate)\n\t{\n\t\tbase_node_type* pNode = &internalNode();\n\t\tsize_type numErased = 0;\n\n\t\twhile(pNode && pNode->mpNext)\n\t\t{\n\t\t\tif (predicate(static_cast<node_type*>(pNode->mpNext)->mValue))\n\t\t\t{\n\t\t\t\tDoEraseAfter(pNode); // This will take care of modifying pNode->mpNext.\n\t\t\t\t++numErased;\n\t\t\t}\n\t\t\telse\n\t\t\t\tpNode = pNode->mpNext;\n\t\t}\n\t\treturn numErased;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice(const_iterator position, this_type& x)\n\t{\n\t\t// Splicing operations cannot succeed if the two containers use unequal allocators.\n\t\t// This issue is not addressed in the C++ 1998 standard but is discussed in the \n\t\t// LWG defect reports, such as #431. There is no simple solution to this problem.\n\t\t// One option is to throw an exception. Another option which probably captures the\n\t\t// user intent most of the time is to copy the range from the source to the dest and \n\t\t// remove it from the source. Until then it's simply disallowed to splice with unequal allocators.\n\t\t// EASTL_ASSERT(internalAllocator() == x.internalAllocator()); // Disabled because our member sort function uses splice but with allocators that may be unequal. There isn't a simple workaround aside from disabling this assert.\n\n\t\tif(x.internalNode().mpNext) // If there is anything to splice...\n\t\t{\n\t\t\tif(internalAllocator() == x.internalAllocator())\n\t\t\t{\n\t\t\t\tSListNodeSpliceAfter(SListNodeGetPrevious(&internalNode(), position.mpNode),\n\t\t\t\t\t\t\t\t\t &x.internalNode(),\n\t\t\t\t\t\t\t\t\t SListNodeGetPrevious(&x.internalNode(), NULL));\n\n\t\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\t\tmSize += x.mSize;\n\t\t\t\t\tx.mSize = 0;\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinsert(position, x.begin(), x.end());\n\t\t\t\tx.clear();\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice(const_iterator position, this_type& x, const_iterator i)\n\t{\n\t\tif(internalAllocator() == x.internalAllocator())\n\t\t{\n\t\t\tSListNodeSpliceAfter(SListNodeGetPrevious(&internalNode(), position.mpNode),\n\t\t\t\t\t\t\t\t SListNodeGetPrevious(&x.internalNode(), i.mpNode),\n\t\t\t\t\t\t\t\t i.mpNode);\n\n\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\t++mSize;\n\t\t\t\t--x.mSize;\n\t\t\t#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinsert(position, *i);\n\t\t\tx.erase(i);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice(const_iterator position, this_type& x, const_iterator first, const_iterator last)\n\t{\n\t\tif(first != last) // If there is anything to splice...\n\t\t{\n\t\t\tif(internalAllocator() == x.internalAllocator())\n\t\t\t{\n\t\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\t\tconst size_type n = (size_type)eastl::distance(first, last);\n\t\t\t\t\tmSize += n;\n\t\t\t\t\tx.mSize -= n;\n\t\t\t\t#endif\n\n\t\t\t\tSListNodeSpliceAfter(SListNodeGetPrevious(&internalNode(),       position.mpNode),\n\t\t\t\t\t\t\t\t\t SListNodeGetPrevious(&x.internalNode(),     first.mpNode),\n\t\t\t\t\t\t\t\t\t SListNodeGetPrevious(first.mpNode, last.mpNode));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinsert(position, first, last);\n\t\t\t\tx.erase(first, last);\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid slist<T, Allocator>::splice(const_iterator position, this_type&& x)\n\t{\n\t\treturn splice(position, x); // This will splice(const_iterator, this_type&)\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tvoid slist<T, Allocator>::splice(const_iterator position, this_type&& x, const_iterator i)\n\t{\n\t\treturn splice(position, x, i); // This will splice_after(const_iterator, this_type&, const_iterator)\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tvoid slist<T, Allocator>::splice(const_iterator position, this_type&& x, const_iterator first, const_iterator last)\n\t{\n\t\treturn splice(position, x, first, last); // This will splice(const_iterator, this_type&, const_iterator, const_iterator)\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice_after(const_iterator position, this_type& x)\n\t{\n\t\tif(!x.empty()) // If there is anything to splice...\n\t\t{\n\t\t\tif(internalAllocator() == x.internalAllocator())\n\t\t\t{\n\t\t\t\tSListNodeSpliceAfter(position.mpNode, &x.internalNode());\n\n\t\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\t\tmSize += x.mSize;\n\t\t\t\t\tx.mSize = 0;\n\t\t\t\t#endif\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinsert_after(position, x.begin(), x.end());\n\t\t\t\tx.clear();\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice_after(const_iterator position, this_type& x, const_iterator i)\n\t{\n\t\tif(internalAllocator() == x.internalAllocator())\n\t\t{\n\t\t\tSListNodeSpliceAfter(position.mpNode, i.mpNode);\n\n\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\tmSize++;\n\t\t\t\tx.mSize--;\n\t\t\t#endif\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst_iterator iNext(i);\n\t\t\tinsert_after(position, i, ++iNext);\n\t\t\tx.erase(i);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice_after(const_iterator position, this_type& x, const_iterator first, const_iterator last)\n\t{\n\t\tif(first != last) // If there is anything to splice...\n\t\t{\n\t\t\tif(internalAllocator() == x.internalAllocator())\n\t\t\t{\n\t\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\t\tconst size_type n = (size_type)eastl::distance(first, last);\n\t\t\t\t\tmSize += n;\n\t\t\t\t\tx.mSize -= n;\n\t\t\t\t#endif\n\n\t\t\t\tSListNodeSpliceAfter(position.mpNode, first.mpNode, last.mpNode);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinsert_after(position, first, last);\n\t\t\t\tx.erase(first, last);\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice_after(const_iterator position, this_type&& x)\n\t{\n\t\treturn splice_after(position, x);  // This will call splice_after(const_iterator, this_type&)\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice_after(const_iterator position, this_type&& x, const_iterator i) \n\t{\n\t\treturn splice_after(position, x, i);  // This will call splice_after(const_iterator, this_type&, const_iterator)\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::splice_after(const_iterator position, this_type&& x, const_iterator first, const_iterator last)\n\t{\n\t\treturn splice_after(position, x, first, last);  // This will call splice_after(const_iterator, this_type&, const_iterator, const_iterator)\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename slist<T, Allocator>::size_type slist<T, Allocator>::unique()\n\t{\n\t\tsize_type      numRemoved = 0;\n\t\titerator       first(begin());\n\t\tconst iterator last(end());\n\n\t\tif (first != last)\n\t\t{\n\t\t\titerator next(first);\n\n\t\t\twhile (++next != last)\n\t\t\t{\n\t\t\t\tif (*first == *next)\n\t\t\t\t{\n\t\t\t\t\tDoEraseAfter(first.mpNode);\n\t\t\t\t\t++numRemoved;\n\t\t\t\t\tnext = first;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfirst = next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn numRemoved;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename BinaryPredicate>\n\ttypename slist<T, Allocator>::size_type slist<T, Allocator>::unique(BinaryPredicate predicate)\n\t{\n\t\tsize_type      numRemoved = 0;\n\t\titerator       first(begin());\n\t\tconst iterator last(end());\n\n\t\tif (first != last)\n\t\t{\n\t\t\titerator next(first);\n\n\t\t\twhile (++next != last)\n\t\t\t{\n\t\t\t\tif (predicate(*first, *next))\n\t\t\t\t{\n\t\t\t\t\tDoEraseAfter(first.mpNode);\n\t\t\t\t\t++numRemoved;\n\t\t\t\t\tnext = first;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfirst = next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn numRemoved;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::sort()\n\t{\n\t\t// To do: look at using a merge sort, which may well be faster. \n\t\teastl::comb_sort(begin(), end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <class Compare>\n\tinline void slist<T, Allocator>::sort(Compare compare)\n\t{\n\t\t// To do: look at using a merge sort, which may well be faster. \n\t\teastl::comb_sort(begin(), end(), compare);\n\t}\n\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::reverse() EA_NOEXCEPT\n\t{\n\t\tif(internalNode().mpNext)\n\t\t\tinternalNode().mpNext = static_cast<node_type*>((base_node_type*)SListNodeReverse(internalNode().mpNext));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate<typename... Args>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoCreateNode(Args&&... args)\n\t{\n\t\tnode_type* const pNode = DoAllocateNode();  // pNode is of type node_type, but it's uninitialized memory.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue, eastl::forward<Args>(args)...);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue, eastl::forward<Args>(args)...);\n\t\t#endif\n\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoCreateNode()\n\t{\n\t\tnode_type* const pNode = DoAllocateNode();\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tDoFreeNode(pNode);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n\t\t\tdetail::allocator_construct(internalAllocator(), &pNode->mValue);\n\t\t#endif\n\t\treturn pNode;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Integer>\n\tvoid slist<T, Allocator>::DoAssign(Integer n, Integer value, true_type)\n\t{\n\t\tDoAssignValues(static_cast<size_type>(n), static_cast<value_type>(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tvoid slist<T, Allocator>::DoAssign(InputIterator first, InputIterator last, false_type)\n\t{\n\t\tbase_node_type* pNodePrev = &internalNode();\n\t\tbase_node_type* pNode     = internalNode().mpNext;\n\n\t\tfor(; pNode && (first != last); ++first)\n\t\t{\n\t\t\tstatic_cast<node_type*>(pNode)->mValue = *first;\n\t\t\tpNodePrev     = pNode;\n\t\t\tpNode         = pNode->mpNext;\n\t\t}\n\n\t\tif(first == last)\n\t\t\tDoEraseAfter(pNodePrev, NULL);\n\t\telse\n\t\t\tDoInsertAfter(pNodePrev, first, last);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid slist<T, Allocator>::DoAssignValues(size_type n, const value_type& value)\n\t{\n\t\tbase_node_type* pNodePrev = &internalNode();\n\t\tbase_node_type* pNode     = internalNode().mpNext;\n\n\t\tfor(; pNode && (n > 0); --n)\n\t\t{\n\t\t\tstatic_cast<node_type*>(pNode)->mValue = value;\n\t\t\tpNodePrev     = pNode;\n\t\t\tpNode         = pNode->mpNext;\n\t\t}\n\n\t\tif(n)\n\t\t\tDoInsertValuesAfter(pNodePrev, n, value);\n\t\telse\n\t\t\tDoEraseAfter(pNodePrev, NULL);\n\t}\n\t\t\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoInsertAfter(SListNodeBase* pNode, InputIterator first, InputIterator last)\n\t{\n\t\treturn DoInsertAfter(pNode, first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Integer>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoInsertAfter(SListNodeBase* pNode, Integer n, Integer value, true_type)\n\t{\n\t\treturn DoInsertValuesAfter(pNode, n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoInsertAfter(SListNodeBase* pNode, InputIterator first, InputIterator last, false_type)\n\t{\n\t\tfor(; first != last; ++first)\n\t\t{\n\t\t\tpNode = SListNodeInsertAfter(pNode, DoCreateNode(*first));\n\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\t++mSize;\n\t\t\t#endif\n\t\t}\n\n\t\treturn static_cast<node_type*>((base_node_type*)pNode);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoInsertValueAfter(SListNodeBase* pNode)\n\t{\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\tpNode = SListNodeInsertAfter(pNode, DoCreateNode());\n\t\t\t++mSize;\n\t\t\treturn static_cast<node_type*>((base_node_type*)pNode);\n\t\t#else\n\t\t\treturn static_cast<node_type*>((base_node_type*)SListNodeInsertAfter(pNode, DoCreateNode()));\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate<typename... Args>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoInsertValueAfter(SListNodeBase* pNode, Args&&... args)\n\t{\n\t\tSListNodeBase* pNodeNew = DoCreateNode(eastl::forward<Args>(args)...);\n\t\tpNode = SListNodeInsertAfter(pNode, pNodeNew);\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\t++mSize; // Increment the size after the node creation because we need to assume an exception can occur in the creation.\n\t\t#endif\n\t\treturn static_cast<node_type*>((base_node_type*)pNode);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename slist<T, Allocator>::node_type*\n\tslist<T, Allocator>::DoInsertValuesAfter(SListNodeBase* pNode, size_type n, const value_type& value)\n\t{\n\t\tfor(size_type i = 0; i < n; ++i)\n\t\t{\n\t\t\tpNode = SListNodeInsertAfter(pNode, DoCreateNode(value));\n\t\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\t\t++mSize; // We don't do a single mSize += n at the end because an exception may result in only a partial range insertion.\n\t\t\t#endif\n\t\t}\n\t\treturn static_cast<node_type*>((base_node_type*)pNode);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void slist<T, Allocator>::DoSwap(this_type& x)\n\t{\n\t\teastl::swap(internalNode().mpNext, x.internalNode().mpNext);\n\t\teastl::swap(internalAllocator(), x.internalAllocator()); // We do this even if EASTL_ALLOCATOR_COPY_ENABLED is 0.\n\t\t#if EASTL_LIST_SIZE_CACHE\n\t\t\teastl::swap(mSize, x.mSize);\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool slist<T, Allocator>::validate() const\n\t{\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\tsize_type n = 0;\n\t\t\t\n\t\t\tfor(const_iterator i(begin()), iEnd(end()); i != iEnd; ++i)\n\t\t\t\t++n;\n\n\t\t\tif(n != mSize)\n\t\t\t\treturn false;\n\t\t#endif\n\n\t\t// To do: More validation.\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int slist<T, Allocator>::validate_iterator(const_iterator i) const\n\t{\n\t\t// To do: Come up with a more efficient mechanism of doing this.\n\n\t\tfor(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)\n\t\t{\n\t\t\tif(temp == i)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\t\t}\n\n\t\tif(i == end())\n\t\t\treturn (isf_valid | isf_current); \n\n\t\treturn isf_none;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tbool operator==(const slist<T, Allocator>& a, const slist<T, Allocator>& b)\n\t{\n\t\ttypename slist<T, Allocator>::const_iterator ia   = a.begin();\n\t\ttypename slist<T, Allocator>::const_iterator ib   = b.begin();\n\t\ttypename slist<T, Allocator>::const_iterator enda = a.end();\n\n\t\t#if EASTL_SLIST_SIZE_CACHE\n\t\t\tif(a.size() == b.size())\n\t\t\t{\n\t\t\t\twhile((ia != enda) && (*ia == *ib))\n\t\t\t\t{\n\t\t\t\t\t++ia;\n\t\t\t\t\t++ib;\n\t\t\t\t}\n\t\t\t\treturn (ia == enda);\n\t\t\t}\n\t\t\treturn false;\n\t\t#else\n\t\t\ttypename slist<T, Allocator>::const_iterator endb = b.end();\n\n\t\t\twhile((ia != enda) && (ib != endb) && (*ia == *ib))\n\t\t\t{\n\t\t\t\t++ia;\n\t\t\t\t++ib;\n\t\t\t}\n\t\t\treturn (ia == enda) && (ib == endb);\n\t\t#endif\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Allocator>\n\tinline synth_three_way_result<T> operator<=>(const slist<T, Allocator>& a, const slist<T, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#else\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<(const slist<T, Allocator>& a, const slist<T, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const slist<T, Allocator>& a, const slist<T, Allocator>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>(const slist<T, Allocator>& a, const slist<T, Allocator>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<=(const slist<T, Allocator>& a, const slist<T, Allocator>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>=(const slist<T, Allocator>& a, const slist<T, Allocator>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n#endif\n\n\ttemplate <typename T, typename Allocator>\n\tinline void swap(slist<T, Allocator>& a, slist<T, Allocator>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n\t/// erase / erase_if\n\t///\n\t/// https://en.cppreference.com/w/cpp/container/forward_list/erase2\n\ttemplate <class T, class Allocator, class U>\n\ttypename slist<T, Allocator>::size_type erase(slist<T, Allocator>& c, const U& value)\n\t{\n\t\t// Erases all elements that compare equal to value from the container.\n\t\treturn c.remove(value);\n\t}\n\n\ttemplate <class T, class Allocator, class Predicate>\n\ttypename slist<T, Allocator>::size_type erase_if(slist<T, Allocator>& c, Predicate predicate)\n\t{\n\t\t// Erases all elements that satisfy the predicate pred from the container.\n\t\treturn c.remove_if(predicate);\n\t}\n\n\n\t/// insert_iterator\n\t///\n\t/// We borrow a trick from SGI STL here and define an insert_iterator \n\t/// specialization for slist. This allows slist insertions to be O(1) \n\t/// instead of O(n/2), due to caching of the previous node.\n\t///\n\ttemplate <typename T, typename Allocator>\n\tclass insert_iterator< slist<T, Allocator> >\n\t{\n\tpublic:\n\t\ttypedef slist<T, Allocator>                 Container;\n\t\ttypedef typename Container::const_reference const_reference;\n\t\ttypedef typename Container::iterator        iterator_type;\n\t\ttypedef eastl::output_iterator_tag   iterator_category;\n\t\ttypedef void                                value_type;\n\t\ttypedef void                                difference_type;\n\t\ttypedef void                                pointer;\n\t\ttypedef void                                reference;\n\n\tprotected:\n\t\tContainer&    container;\n\t\titerator_type it;\n\n\tpublic:\n\t\tinsert_iterator(Container& x, iterator_type i)\n\t\t\t: container(x)\n\t\t{\n\t\t\tif(i == x.begin())\n\t\t\t\tit = x.before_begin();\n\t\t\telse\n\t\t\t\tit = x.previous(i);\n\t\t}\n\n\t\tinsert_iterator<Container>& operator=(const_reference value)\n\t\t\t{ it = container.insert_after(it, value); return *this; }\n\n\t\tinsert_iterator<Container>& operator*()\n\t\t\t{ return *this; }\n\n\t\tinsert_iterator<Container>& operator++()\n\t\t\t{ return *this; } // This is by design.\n\n\t\tinsert_iterator<Container>& operator++(int)\n\t\t\t{ return *this; } // This is by design.\n\n\t}; // insert_iterator<slist>\n\n\n} // namespace eastl\n\nEA_RESTORE_SN_WARNING()\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/sort.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//////////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////////\n// This file implements sorting algorithms. Some of these are equivalent to \n// std C++ sorting algorithms, while others don't have equivalents in the \n// C++ standard. We implement the following sorting algorithms:\n//    is_sorted             -- \n//    sort                  -- Unstable.    The implementation of this is mapped to quick_sort by default.\n//    quick_sort            -- Unstable.    This is actually an intro-sort (quick sort with switch to insertion sort).\n//    tim_sort              -- Stable.\n//    tim_sort_buffer       -- Stable.\n//    partial_sort          -- Unstable.\n//    insertion_sort        -- Stable. \n//    shell_sort            -- Unstable.\n//    heap_sort             -- Unstable. \n//    stable_sort           -- Stable.      The implementation of this is simply mapped to merge_sort.\n//    merge                 -- \n//    merge_sort            -- Stable. \n//    merge_sort_buffer     -- Stable. \n//    nth_element           -- Unstable.\n//    radix_sort            -- Stable.      Important and useful sort for integral data, and faster than all others for this.\n//    comb_sort             -- Unstable.    Possibly the best combination of small code size but fast sort.\n//    bubble_sort           -- Stable.      Useful in practice for sorting tiny sets of data (<= 10 elements).\n//    selection_sort*       -- Unstable.\n//    shaker_sort*          -- Stable.\n//    bucket_sort*          -- Stable. \n//\n// * Found in sort_extra.h.\n//\n// Additional sorting and related algorithms we may want to implement:\n//    partial_sort_copy     This would be like the std STL version.\n//    paritition            This would be like the std STL version. This is not categorized as a sort routine by the language standard.\n//    stable_partition      This would be like the std STL version.\n//    counting_sort         Maybe we don't want to implement this.\n//\n//////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_SORT_H\n#define EASTL_SORT_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/bit.h>\n#include <EASTL/iterator.h>\n#include <EASTL/memory.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/functional.h>\n#include <EASTL/heap.h>\n#include <EASTL/allocator.h>\n#include <EASTL/memory.h>\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n// EASTL_PLATFORM_PREFERRED_ALIGNMENT\n//\n// Allows for slightly faster buffers in some cases.\n//\n#if !defined(EASTL_PLATFORM_PREFERRED_ALIGNMENT)\n\t#if defined(EA_PROCESSOR_ARM)\n\t\t#define EASTL_PLATFORM_PREFERRED_ALIGNMENT 8\n\t#else\n\t\t#define EASTL_PLATFORM_PREFERRED_ALIGNMENT 16\n\t#endif\n#endif\n\n\nnamespace eastl\n{\n\n\t/// is_sorted\n\t///\n\t/// Returns true if the range [first, last) is sorted.\n\t/// An empty range is considered to be sorted.\n\t/// To test if a range is reverse-sorted, use 'greater' as the comparison \n\t/// instead of 'less'.\n\t///\n\t/// Example usage:\n\t///    vector<int> intArray;\n\t///    bool bIsSorted        = is_sorted(intArray.begin(), intArray.end());\n\t///    bool bIsReverseSorted = is_sorted(intArray.begin(), intArray.end(), greater<int>());\n\t///\n\ttemplate <typename ForwardIterator, typename StrictWeakOrdering>\n\tbool is_sorted(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator current = first;\n\n\t\t\tfor(++current; current != last; first = current, ++current)\n\t\t\t{\n\t\t\t\tif(compare(*current, *first))\n\t\t\t\t{\n\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first, *current)); // Validate that the compare function is sane.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\ttemplate <typename ForwardIterator>\n\tinline bool is_sorted(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;\n\n\t\treturn eastl::is_sorted<ForwardIterator, Less>(first, last, Less());\n\t}\n\n\n\n\t/// is_sorted_until\n\t///\n\t/// Returns an iterator to the first element in the range [first,last) which does not follow an ascending order.\n\t/// The range between first and the iterator returned is sorted.\n\t/// If the entire range is sorted, the function returns last.\n\t/// The elements are compared using operator< for the first version, and comp for the second.\n\t///\n\t/// Example usage:\n\t///     vector<int> intArray;\n\t///     vector<int>::iterator unsorted_element = is_sorted_until(eastl::end(intArray), eastl::end(intArray));\n\t///     vector<int>::iterator unsorted_element_with_user_compare = is_sorted_until(eastl::end(intArray), eastl::end(intArray), eastl::less<int>());\n\t///\n\ttemplate<typename ForwardIterator>\n\tForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator next = first;\n\n\t\t\twhile(++next != last)\n\t\t\t{\n\t\t\t\tif(*next < *first)\n\t\t\t\t\treturn next;\n\n\t\t\t\tfirst = next;\n\t\t\t}\n\t\t}\n\n\t\treturn last;\n\t}\n\n\ttemplate<typename ForwardIterator, typename Compare>\n\tForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last, Compare compare)\n\t{\n\t\tif(first != last)\n\t\t{\n\t\t\tForwardIterator next = first;\n\n\t\t\twhile(++next != last)\n\t\t\t{\n\t\t\t\tif(compare(*next, *first))\n\t\t\t\t\treturn next;\n\n\t\t\t\tfirst = next;\n\t\t\t}\n\t\t}\n\n\t\treturn last;\n\t}\n\n\n\n\t/// merge\n\t///\n\t/// This function merges two sorted input sorted ranges into a result sorted range.\n\t/// This merge is stable in that no element from the first range will be changed\n\t/// in order relative to other elements from the first range.\n\t///\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>\n\tOutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare compare)\n\t{\n\t\twhile((first1 != last1) && (first2 != last2))\n\t\t{\n\t\t\tif(compare(*first2, *first1))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first1, *first2)); // Validate that the compare function is sane.\n\t\t\t\t*result = *first2;\n\t\t\t\t++first2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result = *first1;\n\t\t\t\t++first1;\n\t\t\t}\n\t\t\t++result;\n\t\t}\n\n\t\t// Check which list is empty and explicitly copy remaining items from the other list.\n\t\t// For performance reasons, only a single copy operation is invoked to avoid the potential overhead\n\t\t// introduced by chaining two copy operations together.  Even if a copy is of zero size there can\n\t\t// be overhead from calling memmove with a zero size copy.\n\t\tif (first1 == last1)\n\t\t{\n\t\t\treturn eastl::copy(first2, last2, result);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn eastl::copy(first1, last1, result);\n\t\t}\n\t}\n\n\ttemplate <typename InputIterator1, typename InputIterator2, typename OutputIterator>\n\tinline OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<InputIterator1>::value_type> Less;\n\n\t\treturn eastl::merge<InputIterator1, InputIterator2, OutputIterator, Less>\n\t\t\t\t\t\t   (first1, last1, first2, last2, result, Less());\n\t}\n\n\n\t//////////////////////////////////////////////////////////////////////////////\n\t/// insertion_sort\n\t///\n\t/// insertion_sort is an O(n^2) stable sorting algorithm that starts at the\n\t/// (k + 1) element and assumes the first (k) elements are sorted.\n\t/// Then copy_backwards from (k + 1) to the begining any elements where the\n\t/// (k + 1) element is less than [0, k] elements. The position of k when\n\t/// (k + 1) element is not less than k is the sorted position of the (k + 1) element.\n\t///\n\t/// Example With Intermediate Steps:\n\t/// (k + 1) == 2 : [3, 2, 1] -> [3, 3, 1] -> [2, 3, 1]\n\t/// (k + 1) == 1 : [2, 3, 1] -> [2, 3, 3] -> [2, 2, 3] -> [1, 2, 3]\n\t///              : [1, 2, 3]\n\ttemplate <typename BidirectionalIterator, typename StrictWeakOrdering>\n\tvoid insertion_sort(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator>::value_type value_type;\n\n\t\tif (first != last)\n\t\t{\n\t\t\tBidirectionalIterator i = first;\n\n\t\t\tfor (++i; i != last; ++i)\n\t\t\t{\n\t\t\t\tvalue_type insertValue(eastl::move(*i));\n\t\t\t\tBidirectionalIterator insertPosition = i;\n\n\t\t\t\tfor (BidirectionalIterator movePosition = i; movePosition != first && compare(insertValue, *(--movePosition)); --insertPosition)\n\t\t\t\t{\n\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*movePosition, insertValue));\n\t\t\t\t\t*insertPosition = eastl::move(*movePosition);\n\t\t\t\t}\n\n\t\t\t\t*insertPosition = eastl::move(insertValue);\n\t\t\t}\n\t\t}\n\t} // insertion_sort\n\n\n\ttemplate <typename BidirectionalIterator>\n\tvoid insertion_sort(BidirectionalIterator first, BidirectionalIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<BidirectionalIterator>::value_type> Less;\n\n\t\tinsertion_sort<BidirectionalIterator>(first, last, Less());\n\n\t} // insertion_sort\n\n\n\t/// shell_sort\n\t///\n\t/// Implements the ShellSort algorithm. This algorithm is a serious algorithm for larger \n\t/// data sets, as reported by Sedgewick in his discussions on QuickSort. Note that shell_sort\n\t/// requires a random access iterator, which usually means an array (eg. vector, deque).\n\t/// ShellSort has good performance with presorted sequences.\n\t/// The term \"shell\" derives from the name of the inventor, David Shell.\n\t///\n\t/// To consider: Allow the user to specify the \"h-sequence\" array.\n\t///\n\ttemplate <typename RandomAccessIterator, typename StrictWeakOrdering>\n\tvoid shell_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\n\t\t// We use the Knuth 'h' sequence below, as it is easy to calculate at runtime. \n\t\t// However, possibly we are better off using a different sequence based on a table.\n\t\t// One such sequence which averages slightly better than Knuth is:\n\t\t//    1, 5, 19, 41, 109, 209, 505, 929, 2161, 3905, 8929, 16001, 36289, \n\t\t//    64769, 146305, 260609, 587521, 1045505, 2354689, 4188161, 9427969, 16764929\n\n\t\tif(first != last)\n\t\t{\n\t\t\tconst difference_type   nSize  = last - first;\n\t\t\tdifference_type         nSpace = 1; // nSpace is the 'h' value of the ShellSort algorithm.\n\n\t\t\twhile(nSpace < nSize)\n\t\t\t\tnSpace = (nSpace * 3) + 1; // This is the Knuth 'h' sequence: 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484, 7174453, 21523360, 64570081, 193710244, \n\n\t\t\t// nSpace will iterate from the largest Knuth 'h' element smaller than the size of the range down to 1 (inclusive).\n\t\t\tfor(nSpace = (nSpace - 1) / 3; nSpace >= 1; nSpace = (nSpace - 1) / 3)  // Integer division is less than ideal.\n\t\t\t{\n\t\t\t\tfor(difference_type i = 0; i < nSpace; i++)\n\t\t\t\t{\n\t\t\t\t\tconst RandomAccessIterator iInsertFirst = first + i; // range: [first, first + nSpace)\n\n\t\t\t\t\t// After completion of this next loop the elements\n\t\t\t\t\t//   iInsertFirst + K * nSpace\n\t\t\t\t\t// for K = [0, 1, 2, ...) form a sorted range.\n\t\t\t\t\t// This loop is essentially an insertion sort.\n\n\t\t\t\t\t// Note: we can only move the iterator forward if we know we won't overrun the\n\t\t\t\t\t// end(), otherwise we can invoke undefined behaviour. So we need to check we\n\t\t\t\t\t// have enough space before moving the iterator.\n\t\t\t\t\tRandomAccessIterator iSorted = iInsertFirst;\n\t\t\t\t\twhile(distance(iSorted, last) > nSpace)\n\t\t\t\t\t{\n\t\t\t\t\t\tRandomAccessIterator iLeft = iSorted;\n\t\t\t\t\t\tiSorted += nSpace;\n\t\t\t\t\t\tRandomAccessIterator iRight = iSorted;\n\n\t\t\t\t\t\t// the elements (with distance nSpace) prior to iRight are sorted.\n\t\t\t\t\t\t// move iRight into its sorted position.\n\t\t\t\t\t\twhile(compare(*iRight, *iLeft))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iLeft, *iRight)); // Validate that the compare function is sane.\n\n\t\t\t\t\t\t\teastl::iter_swap(iRight, iLeft);\n\n\t\t\t\t\t\t\tif (iLeft == iInsertFirst) // don't iterate iLeft past the valid range.\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tiRight = iLeft;\n\t\t\t\t\t\t\tiLeft -= nSpace;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} // shell_sort\n\n\ttemplate <typename RandomAccessIterator>\n\tinline void shell_sort(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;\n\n\t\teastl::shell_sort<RandomAccessIterator, Less>(first, last, Less());\n\t}\n\n\n\n\t/// heap_sort\n\t///\n\t/// Implements the HeapSort algorithm. \n\t/// Note that heap_sort requires a random access iterator, which usually means \n\t/// an array (eg. vector, deque).\n\t///\n\ttemplate <typename RandomAccessIterator, typename StrictWeakOrdering>\n\tvoid heap_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering compare)\n\t{\n\t\t// We simply call our heap algorithms to do the work for us.\n\t\teastl::make_heap<RandomAccessIterator, StrictWeakOrdering>(first, last, compare);\n\t\teastl::sort_heap<RandomAccessIterator, StrictWeakOrdering>(first, last, compare);\n\t}\n\n\ttemplate <typename RandomAccessIterator>\n\tinline void heap_sort(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;\n\n\t\teastl::heap_sort<RandomAccessIterator, Less>(first, last, Less());\n\t}\n\n\n\n\tnamespace Internal\n\t{\n\t\t// Sorts a range whose initial (start - first) entries are already sorted.\n\t\t// This function is a useful helper to the tim_sort function.\n\t\t// This is the same as insertion_sort except that it has a start parameter which indicates\n\t\t// where the start of the unsorted data is.\n\t\ttemplate <typename BidirectionalIterator, typename StrictWeakOrdering>\n\t\tvoid insertion_sort_already_started(BidirectionalIterator first, BidirectionalIterator last, BidirectionalIterator start, StrictWeakOrdering compare)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<BidirectionalIterator>::value_type value_type;\n\n\t\t\tif (first != last) // if the range is non-empty...\n\t\t\t{\n\t\t\t\tBidirectionalIterator iCurrent, iNext, iSorted = start - 1;\n\n\t\t\t\tfor (++iSorted; iSorted != last; ++iSorted)\n\t\t\t\t{\n\t\t\t\t\tconst value_type temp(*iSorted);\n\n\t\t\t\t\tiNext = iCurrent = iSorted;\n\n\t\t\t\t\tfor (--iCurrent; (iNext != first) && compare(temp, *iCurrent); --iNext, --iCurrent)\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iCurrent, temp)); // Validate that the compare function is sane.\n\t\t\t\t\t\t*iNext = *iCurrent;\n\t\t\t\t\t}\n\n\t\t\t\t\t*iNext = temp;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\t/// merge_sort_buffer\n\t///\n\t/// Implements the MergeSort algorithm with a user-supplied buffer.\n\t/// The input buffer must be able to hold a number of items equal to 'last - first'.\n\t/// Note that merge_sort_buffer requires a random access iterator, which usually means \n\t/// an array (eg. vector, deque).\n\t///\n\t/// The algorithm used for merge sort is not the standard merge sort.  It has been modified\n\t/// to improve performance for data that is already partially sorted.  In fact, if data\n\t/// is completely sorted, then performance is O(n), but even data with partially sorted\n\t/// regions can benefit from the modifications.\n\t///\n\t/// 'InsertionSortLimit' specifies a size limit for which the algorithm will use insertion sort.\n\t/// Due to the overhead of merge sort, it is often faster to use insertion sort once the size of a region\n\t/// is fairly small.  However, insertion sort is not as efficient (in terms of assignments orcomparisons)\n\t/// so choosing a value that is too large will reduce performance.  Generally a value of 16 to 32 is reasonable,\n\t/// but the best choose will depend on the data being sorted.\n\ttemplate <typename RandomAccessIterator, typename T, typename StrictWeakOrdering, typename difference_type, int InsertionSortLimit>\n\tclass MergeSorter\n\t{\n\tpublic:\n\t\tstatic void sort(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer, StrictWeakOrdering compare)\n\t\t{\n\t\t\tif (sort_impl(first, last, pBuffer, difference_type(0), compare) == RL_Buffer)\n\t\t\t{\n\t\t\t\tconst difference_type nCount = last - first;\n\t\t\t\teastl::copy<T*, RandomAccessIterator>(pBuffer, pBuffer + nCount, first);\n\t\t\t}\n\t\t\tEASTL_DEV_ASSERT((eastl::is_sorted<RandomAccessIterator, StrictWeakOrdering>(first, last, compare)));\n\t\t}\n\n\tprivate:\n\t\tstatic_assert(InsertionSortLimit > 1, \"Sequences of length 1 are already sorted.  Use a larger value for InsertionSortLimit\");\n\n\t\tenum ResultLocation\n\t\t{\n\t\t\tRL_SourceRange,\t// i.e. result is in the range defined by [first, last)\n\t\t\tRL_Buffer,\t\t// i.e. result is in pBuffer\n\t\t};\n\n\t\t// sort_impl\n\t\t//\n\t\t// This sort routine sorts the data in [first, last) and places the result in pBuffer or in the original range of the input.  The actual\n\t\t// location of the data is indicated by the enum returned.\n\t\t// \n\t\t// lastSortedEnd is used to specify a that data in the range [first, first + lastSortedEnd] is already sorted.  This information is used\n\t\t// to avoid unnecessary merge sorting of already sorted data.  lastSortedEnd is a hint, and can be an under estimate of the sorted elements\n\t\t// (i.e. it is legal to pass 0).\n\t\tstatic ResultLocation sort_impl(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer, difference_type lastSortedEnd, StrictWeakOrdering compare)\n\t\t{\n\t\t\tconst difference_type nCount = last - first;\n\n\t\t\tif (lastSortedEnd < 1)\n\t\t\t{\n\t\t\t\tlastSortedEnd = eastl::is_sorted_until<RandomAccessIterator, StrictWeakOrdering>(first, last, compare) - first;\n\t\t\t}\n\n\t\t\t// Sort the region unless lastSortedEnd indicates it is already sorted.\n\t\t\tif (lastSortedEnd < nCount)\n\t\t\t{\n\t\t\t\t// If the size is less than or equal to InsertionSortLimit use insertion sort instead of recursing further.\n\t\t\t\tif (nCount <= InsertionSortLimit)\n\t\t\t\t{\n\t\t\t\t\teastl::Internal::insertion_sort_already_started<RandomAccessIterator, StrictWeakOrdering>(first, last, first + lastSortedEnd, compare);\n\t\t\t\t\treturn RL_SourceRange;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tconst difference_type nMid = nCount / 2;\n\n\t\t\t\t\tResultLocation firstHalfLocation = RL_SourceRange;\n\t\t\t\t\t// Don't sort the first half if it is already sorted.\n\t\t\t\t\tif (lastSortedEnd < nMid)\n\t\t\t\t\t{\n\t\t\t\t\t\tfirstHalfLocation = sort_impl(first, first + nMid, pBuffer, lastSortedEnd, compare);\n\t\t\t\t\t}\n\n\t\t\t\t\tResultLocation secondHalfLocation = sort_impl(first + nMid, last, pBuffer + nMid, lastSortedEnd - nMid, compare);\n\n\t\t\t\t\treturn merge_halves(first, last, nMid, pBuffer, firstHalfLocation, secondHalfLocation, compare);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEASTL_DEV_ASSERT((eastl::is_sorted<RandomAccessIterator, StrictWeakOrdering>(first, last, compare)));\n\t\t\t\treturn RL_SourceRange;\n\t\t\t}\n\t\t}\n\n\t\t// merge_halves\n\t\t//\n\t\t// Merge two sorted regions of elements.\n\t\t// The inputs to this method effectively define two large buffers.  The variables 'firstHalfLocation' and 'secondHalfLocation' define where the data to be\n\t\t// merged is located within the two buffers.  It is entirely possible that the two areas to be merged could be entirely located in either of the larger buffers.\n\t\t// Upon returning the merged results will be in one of the two buffers (indicated by the return result).\n\t\tstatic ResultLocation merge_halves(RandomAccessIterator first, RandomAccessIterator last, difference_type nMid, T* pBuffer, ResultLocation firstHalfLocation, ResultLocation secondHalfLocation, StrictWeakOrdering compare)\n\t\t{\n\t\t\tconst difference_type nCount = last - first;\n\t\t\tif (firstHalfLocation == RL_SourceRange)\n\t\t\t{\n\t\t\t\tif (secondHalfLocation == RL_SourceRange)\n\t\t\t\t{\n\t\t\t\t\teastl::merge<RandomAccessIterator, RandomAccessIterator, T*, StrictWeakOrdering>(first, first + nMid, first + nMid, last, pBuffer, compare);\n\t\t\t\t\tEASTL_DEV_ASSERT((eastl::is_sorted<T*, StrictWeakOrdering>(pBuffer, pBuffer + nCount, compare)));\n\t\t\t\t\treturn RL_Buffer;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teastl::copy(first, first + nMid, pBuffer);\n\t\t\t\t\teastl::merge<T*, T*, RandomAccessIterator, StrictWeakOrdering>(pBuffer, pBuffer + nMid, pBuffer + nMid, pBuffer + nCount, first, compare);\n\t\t\t\t\tEASTL_DEV_ASSERT((eastl::is_sorted<RandomAccessIterator, StrictWeakOrdering>(first, last, compare)));\n\t\t\t\t\treturn RL_SourceRange;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (secondHalfLocation == RL_SourceRange)\n\t\t\t\t{\n\t\t\t\t\teastl::copy(first + nMid, last, pBuffer + nMid);\n\t\t\t\t\teastl::merge<T*, T*, RandomAccessIterator, StrictWeakOrdering>(pBuffer, pBuffer + nMid, pBuffer + nMid, pBuffer + nCount, first, compare);\n\t\t\t\t\tEASTL_DEV_ASSERT((eastl::is_sorted<RandomAccessIterator, StrictWeakOrdering>(first, last, compare)));\n\t\t\t\t\treturn RL_SourceRange;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teastl::merge<T*, T*, RandomAccessIterator, StrictWeakOrdering>(pBuffer, pBuffer + nMid, pBuffer + nMid, pBuffer + nCount, first, compare);\n\t\t\t\t\tEASTL_DEV_ASSERT((eastl::is_sorted<RandomAccessIterator, StrictWeakOrdering>(first, last, compare)));\n\t\t\t\t\treturn RL_SourceRange;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t};\n\n\n\ttemplate <typename RandomAccessIterator, typename T, typename StrictWeakOrdering>\n\tvoid merge_sort_buffer(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer, StrictWeakOrdering compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\tMergeSorter<RandomAccessIterator, T, StrictWeakOrdering, difference_type, 16>::sort(first, last, pBuffer, compare);\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename T>\n\tinline void merge_sort_buffer(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;\n\n\t\teastl::merge_sort_buffer<RandomAccessIterator, T, Less>(first, last, pBuffer, Less());\n\t}\n\n\n\n\t/// merge_sort\n\t///\n\t/// Implements the MergeSort algorithm.\n\t/// This algorithm allocates memory via the user-supplied allocator. Use merge_sort_buffer\n\t/// function if you want a version which doesn't allocate memory.\n\t/// Note that merge_sort requires a random access iterator, which usually means \n\t/// an array (eg. vector, deque).\n\t/// \n\ttemplate <typename RandomAccessIterator, typename Allocator, typename StrictWeakOrdering>\n\tvoid merge_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator, StrictWeakOrdering compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\tconst difference_type nCount = last - first;\n\n\t\tif(nCount > 1)\n\t\t{\n\t\t\t// We need to allocate an array of nCount value_type objects as a temporary buffer.\n\t\t\tvalue_type* const pBuffer = (value_type*)allocate_memory(allocator, nCount * sizeof(value_type), EASTL_ALIGN_OF(value_type), 0);\n\t\t\teastl::uninitialized_fill(pBuffer, pBuffer + nCount, value_type());\n\n\t\t\teastl::merge_sort_buffer<RandomAccessIterator, value_type, StrictWeakOrdering>\n\t\t\t\t\t\t\t\t\t(first, last, pBuffer, compare);\n\n\t\t\teastl::destruct(pBuffer, pBuffer + nCount);\n\t\t\tEASTLFree(allocator, pBuffer, nCount * sizeof(value_type));\n\t\t}\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename Allocator>\n\tinline void merge_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<RandomAccessIterator>::value_type> Less;\n\n\t\teastl::merge_sort<RandomAccessIterator, Allocator, Less>(first, last, allocator, Less());\n\t}\n\n\n\n\t/// partition\n\t///\n\t/// Implements the partition algorithm.\n\t/// Rearranges the elements in the range [first, last), in such a way that all the elements \n\t/// for which pred returns true precede all those for which it returns false. The iterator \n\t/// returned points to the first element of the second group.\n\t/// The relative ordering within each group is not necessarily the same as before the call. \n\t/// See function stable_partition for a function with a similar behavior and stability in \n\t/// the ordering.\n\t/// \n\t/// To do: Implement a version that uses a faster BidirectionalIterator algorithm for the \n\t///        case that the iterator range is a bidirectional iterator instead of just an\n\t///        input iterator (one direction).\n\t///\n\ttemplate<typename InputIterator, typename Predicate>\n\tInputIterator partition(InputIterator begin, InputIterator end, Predicate predicate)\n\t{\n\t\tif(begin != end) \n\t\t{\n\t\t\twhile(predicate(*begin))\n\t\t\t{\n\t\t\t\tif(++begin == end) \n\t\t\t\t\treturn begin;\n\t\t\t}\n\n\t\t\tInputIterator middle = begin;\n\n\t\t\twhile(++middle != end)\n\t\t\t{\n\t\t\t\tif(predicate(*middle))\n\t\t\t\t{\n\t\t\t\t\teastl::swap(*begin, *middle);\n\t\t\t\t\t++begin;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn begin;\n\t}\n\n\t/// stable_partition\n\t///\n\t/// Performs the same function as @p partition() with the additional\n\t/// guarantee that the relative ordering of elements in each group is\n\t/// preserved.\n\ttemplate <typename ForwardIterator, typename Predicate>\n\tForwardIterator stable_partition(ForwardIterator first, ForwardIterator last, Predicate pred)\n\t{\n\t\tfirst = eastl::find_if_not(first, last, pred);\n\n\t\tif (first == last)\n\t\t\treturn first;\n\n\t\ttypedef typename iterator_traits<ForwardIterator>::value_type value_type;\n\n\t\tconst auto requested_size = eastl::distance(first, last);\n\n\t\tauto allocator = *get_default_allocator(0);\n\t\tvalue_type* const buffer =\n\t\t    (value_type*)allocate_memory(allocator, requested_size * sizeof(value_type), EASTL_ALIGN_OF(value_type), 0);\n\t\teastl::uninitialized_fill(buffer, buffer + requested_size, value_type());\n\n\t\tForwardIterator result1 = first;\n\t\tvalue_type* result2 = buffer;\n\n\t\t*result2 = eastl::move(*first);\n\t\t++result2;\n\t\t++first;\n\t\tfor (; first != last; ++first)\n\t\t{\n\t\t\tif (pred(*first))\n\t\t\t{\n\t\t\t\t*result1 = eastl::move(*first);\n\t\t\t\t++result1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result2 = eastl::move(*first);\n\t\t\t\t++result2;\n\t\t\t}\n\t\t}\n\n\t\teastl::copy(buffer, result2, result1);\n\n\t\teastl::destruct(buffer, buffer + requested_size);\n\t\tEASTLFree(allocator, buffer, requested_size * sizeof(value_type));\n\t\t\n\t\treturn result1;\n\t}\n\n\t/////////////////////////////////////////////////////////////////////\n\t// quick_sort\n\t//\n\t// We do the \"introspection sort\" variant of quick sort which is now\n\t// well-known and understood. You can read about this algorithm in\n\t// many articles on quick sort, but briefly what it does is a median-\n\t// of-three quick sort whereby the recursion depth is limited to a\n\t// some value (after which it gives up on quick sort and switches to\n\t// a heap sort) and whereby after a certain amount of sorting the \n\t// algorithm stops doing quick-sort and finishes the sorting via\n\t// a simple insertion sort.\n\t/////////////////////////////////////////////////////////////////////\n\n\t#if (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))\n\t\tstatic const int kQuickSortLimit = 28; // For sorts of random arrays over 100 items, 28 - 32 have been found to be good numbers on x86.\n\t#else\n\t\tstatic const int kQuickSortLimit = 16; // It seems that on other processors lower limits are more beneficial, as they result in fewer compares.\n\t#endif\n\n\tnamespace Internal\n\t{\n\t\ttemplate <typename Size>\n\t\tinline Size Log2(Size n)\n\t\t{\n\t\t\tint i;\n\t\t\tfor(i = 0; n; ++i)\n\t\t\t\tn >>= 1;\n\t\t\treturn i - 1;\n\t\t}\n\n\t\t// To do: Investigate the speed of this bit-trick version of Log2.\n\t\t//        It may work better on some platforms but not others.\n\t\t//\n\t\t// union FloatUnion {\n\t\t//     float    f;\n\t\t//     uint32_t i;\n\t\t// };\n\t\t// \n\t\t// inline uint32_t Log2(uint32_t x)\n\t\t// {\n\t\t//     const FloatInt32Union u = { x };\n\t\t//     return (u.i >> 23) - 127;\n\t\t// }\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename T>\n\tinline RandomAccessIterator get_partition_impl(RandomAccessIterator first, RandomAccessIterator last, T&& pivotValue)\n\t{\n\t\tfor(; ; ++first)\n\t\t{\n\t\t\twhile(*first < pivotValue)\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!(pivotValue < *first)); // Validate that the compare function is sane.\n\t\t\t\t++first;\n\t\t\t}\n\t\t\t--last;\n\n\t\t\twhile(pivotValue < *last)\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!(*last < pivotValue)); // Validate that the compare function is sane.\n\t\t\t\t--last;\n\t\t\t}\n\n\t\t\tif(first >= last) // Random access iterators allow operator >=\n\t\t\t\treturn first;\n\n\t\t\teastl::iter_swap(first, last);\n\t\t}\n\t}\n\n\t/// get_partition\n\t///\n\t/// This function takes const T& instead of T because T may have special alignment\n\t/// requirements and some compilers (e.g. VC++) are don't respect alignment requirements\n\t/// for function arguments.\n\t///\n\ttemplate <typename RandomAccessIterator, typename T>\n\tinline RandomAccessIterator get_partition(RandomAccessIterator first, RandomAccessIterator last, const T& pivotValue)\n\t{\n\t\tconst T pivotCopy(pivotValue); // Need to make a temporary because the sequence below is mutating.\n\t\treturn get_partition_impl<RandomAccessIterator, const T&>(first, last, pivotCopy);\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename T>\n\tinline RandomAccessIterator get_partition(RandomAccessIterator first, RandomAccessIterator last, T&& pivotValue)\n\t{\n\t\t// Note: unlike the copy-constructible variant of get_partition... we can't create a temporary const move-constructible object\n\t\treturn get_partition_impl<RandomAccessIterator, T&&>(first, last, eastl::move(pivotValue));\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename T, typename Compare>\n\tinline RandomAccessIterator get_partition_impl(RandomAccessIterator first, RandomAccessIterator last, T&& pivotValue, Compare compare)\n\t{\n\t\tfor(; ; ++first)\n\t\t{\n\t\t\twhile(compare(*first, pivotValue))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(pivotValue, *first)); // Validate that the compare function is sane.\n\t\t\t\t++first;\n\t\t\t}\n\t\t\t--last;\n\n\t\t\twhile(compare(pivotValue, *last))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*last, pivotValue)); // Validate that the compare function is sane.\n\t\t\t\t--last;\n\t\t\t}\n\n\t\t\tif(first >= last) // Random access iterators allow operator >=\n\t\t\t\treturn first;\n\n\t\t\teastl::iter_swap(first, last);\n\t\t}\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename T, typename Compare> \n\tinline RandomAccessIterator get_partition(RandomAccessIterator first, RandomAccessIterator last, const T& pivotValue, Compare compare)\n\t{\n\t\tconst T pivotCopy(pivotValue); // Need to make a temporary because the sequence below is mutating.\n\t\treturn get_partition_impl<RandomAccessIterator, const T&, Compare>(first, last, pivotCopy, compare);\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename T, typename Compare>\n\tinline RandomAccessIterator get_partition(RandomAccessIterator first, RandomAccessIterator last, T&& pivotValue, Compare compare)\n\t{\n\t\t// Note: unlike the copy-constructible variant of get_partition... we can't create a temporary const move-constructible object\n\t\treturn get_partition_impl<RandomAccessIterator, T&&, Compare>(first, last, eastl::forward<T>(pivotValue), compare);\n\t}\n\n\n\tnamespace Internal\n\t{\n\t\t// This function is used by quick_sort and is not intended to be used by itself. \n\t\t// This is because the implementation below makes an assumption about the input\n\t\t// data that quick_sort satisfies but arbitrary data may not.\n\t\t// There is a standalone insertion_sort function. \n\t\ttemplate <typename RandomAccessIterator>\n\t\tinline void insertion_sort_simple(RandomAccessIterator first, RandomAccessIterator last)\n\t\t{\n\t\t\tfor(RandomAccessIterator current = first; current != last; ++current)\n\t\t\t{\n\t\t\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t\tRandomAccessIterator end(current), prev(current);\n\t\t\t\tvalue_type           value(eastl::forward<value_type>(*current));\n\n\t\t\t\tfor(--prev; value < *prev; --end, --prev) // We skip checking for (prev >= first) because quick_sort (our caller) makes this unnecessary.\n\t\t\t\t{\n\t\t\t\t\tEASTL_VALIDATE_COMPARE(!(*prev < value)); // Validate that the compare function is sane.\n\t\t\t\t\t*end = eastl::forward<value_type>(*prev);\n\t\t\t\t}\n\n\t\t\t\t*end = eastl::forward<value_type>(value);\n\t\t\t}\n\t\t}\n\n\n\t\t// This function is used by quick_sort and is not intended to be used by itself. \n\t\t// This is because the implementation below makes an assumption about the input\n\t\t// data that quick_sort satisfies but arbitrary data may not.\n\t\t// There is a standalone insertion_sort function. \n\t\ttemplate <typename RandomAccessIterator, typename Compare>\n\t\tinline void insertion_sort_simple(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t\t{\n\t\t\tfor(RandomAccessIterator current = first; current != last; ++current)\n\t\t\t{\n\t\t\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t\tRandomAccessIterator end(current), prev(current);\n\t\t\t\tvalue_type           value(eastl::forward<value_type>(*current));\n\n\t\t\t\tfor(--prev; compare(value, *prev); --end, --prev) // We skip checking for (prev >= first) because quick_sort (our caller) makes this unnecessary.\n\t\t\t\t{\n\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*prev, value)); // Validate that the compare function is sane.\n\t\t\t\t\t*end = eastl::forward<value_type>(*prev);\n\t\t\t\t}\n\n\t\t\t\t*end = eastl::forward<value_type>(value);\n\t\t\t}\n\t\t}\n\t} // namespace Internal\n\n\n\ttemplate <typename RandomAccessIterator>\n\tinline void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\teastl::make_heap<RandomAccessIterator>(first, middle);\n\n\t\tfor(RandomAccessIterator i = middle; i < last; ++i)\n\t\t{\n\t\t\tif(*i < *first)\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!(*first < *i)); // Validate that the compare function is sane.\n\t\t\t\tvalue_type temp(eastl::forward<value_type>(*i));\n\t\t\t\t*i = eastl::forward<value_type>(*first);\n\t\t\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type>\n\t\t\t\t\t\t\t\t  (first, difference_type(0), difference_type(middle - first), difference_type(0), eastl::forward<value_type>(temp));\n\t\t\t}\n\t\t}\n\n\t\teastl::sort_heap<RandomAccessIterator>(first, middle);\n\t}\n\n\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tinline void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type      value_type;\n\n\t\teastl::make_heap<RandomAccessIterator, Compare>(first, middle, compare);\n\n\t\tfor(RandomAccessIterator i = middle; i < last; ++i)\n\t\t{\n\t\t\tif(compare(*i, *first))\n\t\t\t{\n\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*first, *i)); // Validate that the compare function is sane.\n\t\t\t\tvalue_type temp(eastl::forward<value_type>(*i));\n\t\t\t\t*i = eastl::forward<value_type>(*first);\n\t\t\t\teastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>\n\t\t\t\t\t\t\t\t  (first, difference_type(0), difference_type(middle - first), difference_type(0), eastl::forward<value_type>(temp), compare);\n\t\t\t}\n\t\t}\n\n\t\teastl::sort_heap<RandomAccessIterator, Compare>(first, middle, compare);\n\t}\n\n\n\ttemplate<typename RandomAccessIterator>\n\tinline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\twhile((last - first) > 5)\n\t\t{\n\t\t\tconst value_type           midValue(eastl::median<value_type>(*first, *(first + (last - first) / 2), *(last - 1)));\n\t\t\tconst RandomAccessIterator midPos(eastl::get_partition<RandomAccessIterator, value_type>(first, last, midValue));\n\n\t\t\tif(midPos <= nth)\n\t\t\t\tfirst = midPos;\n\t\t\telse\n\t\t\t\tlast = midPos;\n\t\t}\n\n\t\teastl::insertion_sort<RandomAccessIterator>(first, last);\n\t}\n\n\n\ttemplate<typename RandomAccessIterator, typename Compare>\n\tinline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare compare)\n\t{\n\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\twhile((last - first) > 5)\n\t\t{\n\t\t\tconst value_type           midValue(eastl::median<value_type, Compare>(*first, *(first + (last - first) / 2), *(last - 1), compare));\n\t\t\tconst RandomAccessIterator midPos(eastl::get_partition<RandomAccessIterator, value_type, Compare>(first, last, midValue, compare));\n\n\t\t\tif(midPos <= nth)\n\t\t\t\tfirst = midPos;\n\t\t\telse\n\t\t\t\tlast = midPos;\n\t\t}\n\n\t\teastl::insertion_sort<RandomAccessIterator, Compare>(first, last, compare);\n\t}\n\n\n\tnamespace Internal\n\t{\n\t\tEA_DISABLE_VC_WARNING(4702) // unreachable code\n\t\ttemplate <typename RandomAccessIterator, typename Size, typename PivotValueType>\n\t\tinline void quick_sort_impl_helper(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount)\n\t\t{\n\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\twhile(((last - first) > kQuickSortLimit) && (kRecursionCount > 0))\n\t\t\t{\n\t\t\t\tconst RandomAccessIterator position(eastl::get_partition<RandomAccessIterator, value_type>(first, last,\n\t\t\t\t\teastl::forward<PivotValueType>(eastl::median<value_type>(eastl::forward<value_type>(*first), eastl::forward<value_type>(*(first + (last - first) / 2)), eastl::forward<value_type>(*(last - 1))))));\n\n\t\t\t\teastl::Internal::quick_sort_impl_helper<RandomAccessIterator, Size, PivotValueType>(position, last, --kRecursionCount);\n\t\t\t\tlast = position;\n\t\t\t}\n\n\t\t\tif(kRecursionCount == 0)\n\t\t\t\teastl::partial_sort<RandomAccessIterator>(first, last, last);\n\t\t}\n\n\t\ttemplate <typename RandomAccessIterator, typename Size, typename Compare, typename PivotValueType>\n\t\tinline void quick_sort_impl_helper(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount, Compare compare)\n\t\t{\n\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\twhile(((last - first) > kQuickSortLimit) && (kRecursionCount > 0))\n\t\t\t{\n\t\t\t\tconst RandomAccessIterator position(eastl::get_partition<RandomAccessIterator, value_type, Compare>(first, last,\n\t\t\t\t\teastl::forward<PivotValueType>(eastl::median<value_type, Compare>(eastl::forward<value_type>(*first), eastl::forward<value_type>(*(first + (last - first) / 2)), eastl::forward<value_type>(*(last - 1)), compare)), compare));\n\n\t\t\t\teastl::Internal::quick_sort_impl_helper<RandomAccessIterator, Size, Compare, PivotValueType>(position, last, --kRecursionCount, compare);\n\t\t\t\tlast = position;\n\t\t\t}\n\n\t\t\tif(kRecursionCount == 0)\n\t\t\t\teastl::partial_sort<RandomAccessIterator, Compare>(first, last, last, compare);\n\t\t}\n\t\tEA_RESTORE_VC_WARNING()\n\n\t\ttemplate <typename RandomAccessIterator, typename Size>\n\t\tinline void quick_sort_impl(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount,\n\t\t\ttypename eastl::enable_if<eastl::is_copy_constructible<typename iterator_traits<RandomAccessIterator>::value_type>::value>::type* = 0)\n\t\t{\n\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t// copy constructors require const value_type\n\t\t\tquick_sort_impl_helper<RandomAccessIterator, Size, const value_type>(first, last, kRecursionCount);\n\t\t}\n\n\t\ttemplate <typename RandomAccessIterator, typename Size>\n\t\tinline void quick_sort_impl(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount,\n\t\t\ttypename eastl::enable_if<eastl::is_move_constructible<typename iterator_traits<RandomAccessIterator>::value_type>::value\n\t\t\t&& !eastl::is_copy_constructible<typename iterator_traits<RandomAccessIterator>::value_type>::value>::type* = 0)\n\t\t{\n\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t// move constructors require non-const value_type\n\t\t\tquick_sort_impl_helper<RandomAccessIterator, Size, value_type>(first, last, kRecursionCount);\n\t\t}\n\n\t\ttemplate <typename RandomAccessIterator, typename Size, typename Compare>\n\t\tinline void quick_sort_impl(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount, Compare compare,\n\t\t\ttypename eastl::enable_if<eastl::is_copy_constructible<typename iterator_traits<RandomAccessIterator>::value_type>::value>::type* = 0)\n\t\t{\n\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t// copy constructors require const value_type\n\t\t\tquick_sort_impl_helper<RandomAccessIterator, Size, Compare, const value_type>(first, last, kRecursionCount, compare);\n\t\t}\n\n\t\ttemplate <typename RandomAccessIterator, typename Size, typename Compare>\n\t\tinline void quick_sort_impl(RandomAccessIterator first, RandomAccessIterator last, Size kRecursionCount, Compare compare,\n\t\t\ttypename eastl::enable_if<eastl::is_move_constructible<typename iterator_traits<RandomAccessIterator>::value_type>::value\n\t\t\t&& !eastl::is_copy_constructible<typename iterator_traits<RandomAccessIterator>::value_type>::value>::type* = 0)\n\t\t{\n\t\t\ttypedef typename iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t// move constructors require non-const value_type\n\t\t\tquick_sort_impl_helper<RandomAccessIterator, Size, Compare, value_type>(first, last, kRecursionCount, compare);\n\t\t}\n\t}\n\n\n\t/// quick_sort\n\t///\n\t/// This is an unstable sort.\n\t/// quick_sort sorts the elements in [first, last) into ascending order, \n\t/// meaning that if i and j are any two valid iterators in [first, last) \n\t/// such that i precedes j, then *j is not less than *i. quick_sort is not \n\t/// guaranteed to be stable. That is, suppose that *i and *j are equivalent: \n\t/// neither one is less than the other. It is not guaranteed that the \n\t/// relative order of these two elements will be preserved by sort.\n\t///\n\t/// We implement the \"introspective\" variation of quick-sort. This is \n\t/// considered to be the best general-purpose variant, as it avoids \n\t/// worst-case behaviour and optimizes the final sorting stage by \n\t/// switching to an insertion sort.\n\t///\n\ttemplate <typename RandomAccessIterator>\n\tvoid quick_sort(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\n\t\tif(first != last)\n\t\t{\n\t\t\teastl::Internal::quick_sort_impl<RandomAccessIterator, difference_type>(first, last, 2 * Internal::Log2(last - first));\n\n\t\t\tif((last - first) > (difference_type)kQuickSortLimit)\n\t\t\t{\n\t\t\t\teastl::insertion_sort<RandomAccessIterator>(first, first + kQuickSortLimit);\n\t\t\t\teastl::Internal::insertion_sort_simple<RandomAccessIterator>(first + kQuickSortLimit, last);\n\t\t\t}\n\t\t\telse\n\t\t\t\teastl::insertion_sort<RandomAccessIterator>(first, last);\n\t\t}\n\t}\n\n\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tvoid quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;\n\n\t\tif(first != last)\n\t\t{\n\t\t\teastl::Internal::quick_sort_impl<RandomAccessIterator, difference_type, Compare>(first, last, 2 * Internal::Log2(last - first), compare);\n\n\t\t\tif((last - first) > (difference_type)kQuickSortLimit)\n\t\t\t{\n\t\t\t\teastl::insertion_sort<RandomAccessIterator, Compare>(first, first + kQuickSortLimit, compare);\n\t\t\t\teastl::Internal::insertion_sort_simple<RandomAccessIterator, Compare>(first + kQuickSortLimit, last, compare);\n\t\t\t}\n\t\t\telse\n\t\t\t\teastl::insertion_sort<RandomAccessIterator, Compare>(first, last, compare);\n\t\t}\n\t}\n\n\n\n\n\tnamespace Internal\n\t{\n\t\t// Portions of the tim_sort code were originally written by Christopher Swenson.\n\t\t// https://github.com/swenson/sort\n\t\t// All code in this repository, unless otherwise specified, is hereby licensed under the \n\t\t// MIT Public License: Copyright (c) 2010 Christopher Swenson\n\n\t\tconst intptr_t kTimSortStackSize = 64; // Question: What's the upper-limit size requirement for this?\n\n\t\tstruct tim_sort_run\n\t\t{\n\t\t\tintptr_t start;\n\t\t\tintptr_t length;\n\t\t};\n\n\n\t\t// reverse_elements\n\t\t//\n\t\t// Reverses the range [first + start, first + start + size)\n\t\t// To consider: Use void eastl::reverse(BidirectionalIterator first, BidirectionalIterator last);\n\t\t//\n\t\ttemplate <typename RandomAccessIterator>\n\t\tvoid reverse_elements(RandomAccessIterator first, intptr_t start, intptr_t end)\n\t\t{\n\t\t\twhile(start < end)\n\t\t\t{\n\t\t\t\teastl::swap(*(first + start), *(first + end));\n\t\t\t\t++start;\n\t\t\t\t--end;\n\t\t\t}\n\t\t}\n\n\n\t\t// tim_sort_count_run\n\t\t//\n\t\t// Finds the length of a run which is already sorted (either up or down).\n\t\t// If the run is in reverse order, this function puts it in regular order.\n\t\t//\n\t\ttemplate <typename RandomAccessIterator, typename StrictWeakOrdering>\n\t\tintptr_t tim_sort_count_run(const RandomAccessIterator first, const intptr_t start, const intptr_t size, StrictWeakOrdering compare)\n\t\t{\n\t\t\tif((size - start) > 1) // If there is anything in the set...\n\t\t\t{\n\t\t\t\tintptr_t curr = (start + 2);\n\t\t\t\t\n\t\t\t\tif(!compare(*(first + start + 1), *(first + start))) // If (first[start + 1] >= first[start]) (If the run is increasing) ...\n\t\t\t\t{\n\t\t\t\t\tfor(;; ++curr)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(curr >= (size - 1)) // If we are at the end of the data... this run is done.\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tif(compare(*(first + curr), *(first + curr - 1))) // If this item is not in order... this run is done.\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse  // Else it is decreasing.\n\t\t\t\t{\n\t\t\t\t\tfor(;; ++curr)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(curr >= (size - 1))  // If we are at the end of the data... this run is done.\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tif(!compare(*(first + curr), *(first + curr - 1)))  // If this item is not in order... this run is done.\n\t\t\t\t\t\t\tbreak;                                          // Note that we intentionally compare against <= 0 and not just < 0. This is because \n\t\t\t\t\t}                                                       // The reverse_elements call below could reverse two equal elements and break our stability requirement.\n\n\t\t\t\t\treverse_elements(first, start, curr - 1);\n\t\t\t\t}\n\n\t\t\t\treturn (curr - start);\n\t\t\t}\n\n\t\t\t// Else we have just one item in the set.       \n\t\t\treturn 1;\n\t\t}\n\n\n\t\t// Input   Return\n\t\t// --------------\n\t\t//  64      32\n\t\t//  65      33\n\t\t//  66      33\n\t\t//  67      34\n\t\t//  68      34\n\t\t// ...\n\t\t// 125      63\n\t\t// 126      63\n\t\t// 127      64\n\t\t// 128      32\n\t\t// 129      33\n\t\t// 130      33\n\t\t// 131      33\n\t\t// 132      33\n\t\t// 133      34\n\t\t// 134      34\n\t\t// 135      34\n\t\t// 136      34\n\t\t// 137      35\n\t\t// ...\n\t\t//\n\t\t// This function will return a value that is always in the range of [32, 64].\n\t\t//\n\t\tstatic inline intptr_t timsort_compute_minrun(intptr_t size)\n\t\t{\n\t\t\tconst int32_t  top_bit = (int32_t)((sizeof(intptr_t) * 8) - countl_zero((uintptr_t)size));\n\t\t\tconst int32_t  shift   = (top_bit > 6) ? (top_bit - 6) : 0;\n\t\t\tconst intptr_t mask    = (intptr_t(1) << shift) - 1;\n\t\t\t\t  intptr_t minrun  = (intptr_t)(size >> shift);\n\n\t\t\tif(mask & size)\n\t\t\t\t++minrun;\n\n\t\t\treturn minrun;\n\t\t}\n\n\n\t\ttemplate <typename RandomAccessIterator, typename T, typename StrictWeakOrdering>\n\t\tvoid tim_sort_merge(RandomAccessIterator first, const tim_sort_run* run_stack, const intptr_t stack_curr, \n\t\t\t\t\t\t\tT* pBuffer, StrictWeakOrdering compare)\n\t\t{\n\t\t\tconst intptr_t A    = run_stack[stack_curr - 2].length;\n\t\t\tconst intptr_t B    = run_stack[stack_curr - 1].length;\n\t\t\tconst intptr_t curr = run_stack[stack_curr - 2].start;\n\n\t\t\tEASTL_DEV_ASSERT((A < 10000000) && (B < 10000000) && (curr < 10000000)); // Sanity check.\n\n\t\t\tif(A < B) // If the first run is shorter than the second run... merge left.\n\t\t\t{\n\t\t\t\t// Copy to another location so we have room in the main array to put the sorted items.\n\t\t\t\teastl::copy(first + curr, first + curr + A, pBuffer);\n\n\t\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\t\ttypedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;\n\n\t\t\t\t\tfor(intptr_t i = 0; i < A; i++)\n\t\t\t\t\t\t*(first + curr + i) = value_type();\n\t\t\t\t#endif\n\n\t\t\t\tintptr_t i = 0;\n\t\t\t\tintptr_t j = curr + A;\n\t\t\t\t\n\t\t\t\tfor(intptr_t k = curr; k < curr + A + B; k++)\n\t\t\t\t{\n\t\t\t\t\tif((i < A) && (j < (curr + A + B)))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!compare(*(first + j), *(pBuffer + i))) // If (first[j] >= pBuffer[i])...\n\t\t\t\t\t\t\t*(first + k) = *(pBuffer + i++);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t*(first + k) = *(first + j++);\n\t\t\t\t\t}\n\t\t\t\t\telse if(i < A)\n\t\t\t\t\t\t*(first + k) = *(pBuffer + i++);\n\t\t\t\t\telse\n\t\t\t\t\t\t*(first + k) = *(first + j++);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse // Else the second run is equal or shorter... merge right.\n\t\t\t{\n\t\t\t\teastl::copy(first + curr + A, first + curr + A + B, pBuffer);\n\n\t\t\t\tintptr_t i = B - 1;\n\t\t\t\tintptr_t j = curr + A - 1;\n\t\t\t\t\n\t\t\t\tfor(intptr_t k = curr + A + B - 1; k >= curr; k--)\n\t\t\t\t{\n\t\t\t\t\tif((i >= 0) && (j >= curr))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(compare(*(pBuffer + i), *(first + j))) // If (pBuffer[i] < first[j]) ...\n\t\t\t\t\t\t\t*(first + k) = *(first + j--);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t*(first + k) = *(pBuffer + i--);\n\t\t\t\t\t}\n\t\t\t\t\telse if(i >= 0)\n\t\t\t\t\t\t*(first + k) = *(pBuffer + i--);\n\t\t\t\t\telse\n\t\t\t\t\t\t*(first + k) = *(first + j--);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t// See the timsort.txt file for an explanation of this function.\n\t\t//\n\t\t// ------------------------------------------------------------------------\n\t\t// What turned out to be a good compromise maintains two invariants on the\n\t\t// stack entries, where A, B and C are the lengths of the three righmost \n\t\t// not-yet merged slices:\n\t\t//    1.  A > B+C\n\t\t//    2.  B > C\n\t\t// ------------------------------------------------------------------------\n\t\t//\n\t\tstatic inline bool timsort_check_invariant(tim_sort_run* run_stack, const intptr_t stack_curr)\n\t\t{\n\t\t\t// To do: Optimize this for the most common type of values.\n\t\t\tif(stack_curr > 2)\n\t\t\t{\n\t\t\t\tconst intptr_t A = run_stack[stack_curr - 3].length;\n\t\t\t\tconst intptr_t B = run_stack[stack_curr - 2].length;\n\t\t\t\tconst intptr_t C = run_stack[stack_curr - 1].length;\n\n\t\t\t\tEASTL_DEV_ASSERT((A < 10000000) && (B < 10000000) && (C < 10000000)); // Sanity check.\n\n\t\t\t\tif((A <= (B + C)) || (B <= C))\n\t\t\t\t\treturn true; // Merge the right-most runs.\n\t\t\t}\n\t\t\telse if(stack_curr == 2)\n\t\t\t{\n\t\t\t\tconst intptr_t A = run_stack[stack_curr - 2].length;\n\t\t\t\tconst intptr_t B = run_stack[stack_curr - 1].length;\n\n\t\t\t\tEASTL_DEV_ASSERT((A < 10000000) && (B < 10000000)); // Sanity check.\n\n\t\t\t\tif(A <= B)\n\t\t\t\t\treturn true; // Merge the right-most runs.\n\t\t\t}\n\n\t\t\treturn false; // Don't merge the right-most runs.\n\t\t}\n\n\n\t\ttemplate <typename RandomAccessIterator, typename T, typename StrictWeakOrdering>\n\t\tintptr_t tim_sort_collapse(RandomAccessIterator first, tim_sort_run* run_stack, intptr_t stack_curr, \n\t\t\t\t\t\t\t\t   T* pBuffer, const intptr_t size, StrictWeakOrdering compare)\n\t\t{\n\t\t\t// If the run_stack only has one thing on it, we are done with the collapse.\n\t\t\twhile(stack_curr > 1)\n\t\t\t{\n\t\t\t\t// If this is the last merge, just do it.\n\t\t\t\tif((stack_curr == 2) && ((run_stack[0].length + run_stack[1].length) == size))\n\t\t\t\t{\n\t\t\t\t\ttim_sort_merge<RandomAccessIterator, T, StrictWeakOrdering>(first, run_stack, stack_curr, pBuffer, compare);\n\t\t\t\t\trun_stack[0].length += run_stack[1].length;\n\t\t\t\t\tstack_curr--;\n\n\t\t\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\t\t\tmemset(&run_stack[stack_curr], 0, sizeof(run_stack[stack_curr]));\n\t\t\t\t\t#endif\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Check if the invariant is off for a run_stack of 2 elements.\n\t\t\t\telse if((stack_curr == 2) && (run_stack[0].length <= run_stack[1].length))\n\t\t\t\t{\n\t\t\t\t\ttim_sort_merge<RandomAccessIterator, T, StrictWeakOrdering>(first, run_stack, stack_curr, pBuffer, compare);\n\t\t\t\t\trun_stack[0].length += run_stack[1].length;\n\t\t\t\t\tstack_curr--;\n\n\t\t\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\t\t\tmemset(&run_stack[stack_curr], 0, sizeof(run_stack[stack_curr]));\n\t\t\t\t\t#endif\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse if (stack_curr == 2)\n\t\t\t\t\tbreak;\n\n\t\t\t\tconst intptr_t A = run_stack[stack_curr - 3].length;\n\t\t\t\tconst intptr_t B = run_stack[stack_curr - 2].length;\n\t\t\t\tconst intptr_t C = run_stack[stack_curr - 1].length;\n\t\t\t\t\n\t\t\t\tif(A <= (B + C)) // Check first invariant.\n\t\t\t\t{\n\t\t\t\t\tif(A < C)\n\t\t\t\t\t{\n\t\t\t\t\t\ttim_sort_merge<RandomAccessIterator, T, StrictWeakOrdering>(first, run_stack, stack_curr - 1, pBuffer, compare);\n\n\t\t\t\t\t\tstack_curr--;\n\t\t\t\t\t\trun_stack[stack_curr - 2].length += run_stack[stack_curr - 1].length;   // Merge A and B.\n\t\t\t\t\t\trun_stack[stack_curr - 1] = run_stack[stack_curr];\n\n\t\t\t\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\t\t\t\tEASTL_DEV_ASSERT((run_stack[stack_curr - 2].start + run_stack[stack_curr - 2].length) <= size);\n\t\t\t\t\t\t\tEASTL_DEV_ASSERT((run_stack[stack_curr - 1].start + run_stack[stack_curr - 1].length) <= size);\n\t\t\t\t\t\t\tmemset(&run_stack[stack_curr], 0, sizeof(run_stack[stack_curr]));\n\t\t\t\t\t\t#endif\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ttim_sort_merge<RandomAccessIterator, T, StrictWeakOrdering>(first, run_stack, stack_curr, pBuffer, compare);                  // Merge B and C.\n\n\t\t\t\t\t\tstack_curr--;\n\t\t\t\t\t\trun_stack[stack_curr - 1].length += run_stack[stack_curr].length;\n\n\t\t\t\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\t\t\t\tEASTL_DEV_ASSERT((run_stack[stack_curr - 1].start + run_stack[stack_curr - 1].length) <= size);\n\t\t\t\t\t\t\tmemset(&run_stack[stack_curr], 0, sizeof(run_stack[stack_curr]));\n\t\t\t\t\t\t#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(B <= C) // Check second invariant\n\t\t\t\t{\n\t\t\t\t\ttim_sort_merge<RandomAccessIterator, T, StrictWeakOrdering>(first, run_stack, stack_curr, pBuffer, compare);\n\n\t\t\t\t\tstack_curr--;\n\t\t\t\t\trun_stack[stack_curr - 1].length += run_stack[stack_curr].length;       // Merge B and C.\n\n\t\t\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\t\t\tEASTL_DEV_ASSERT((run_stack[stack_curr - 1].start + run_stack[stack_curr - 1].length) <= size);\n\t\t\t\t\t\tmemset(&run_stack[stack_curr], 0, sizeof(run_stack[stack_curr]));\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn stack_curr;\n\t\t}\n\n\n\t\t// tim_sort_add_run\n\t\t//\n\t\t// Return true if the sort is done.\n\t\t//\n\t\ttemplate <typename RandomAccessIterator, typename T, typename StrictWeakOrdering>\n\t\tbool tim_sort_add_run(tim_sort_run* run_stack, RandomAccessIterator first, T* pBuffer, const intptr_t size, const intptr_t minrun, \n\t\t\t\t\t\t\t  intptr_t& len, intptr_t& run, intptr_t& curr, intptr_t& stack_curr, StrictWeakOrdering compare)\n\t\t{\n\t\t\tlen = tim_sort_count_run<RandomAccessIterator, StrictWeakOrdering>(first, curr, size, compare); // This will count the length of the run and reverse the run if it is backwards.\n\t\t\trun = minrun;\n\n\t\t\tif(run < minrun)            // Always make runs be of minrun length (we'll sort the additional data as needed below)\n\t\t\t   run = minrun;\n\n\t\t\tif(run > (size - curr))     // But if there isn't minrun data remaining, just sort what's remaining.\n\t\t\t   run = (size - curr);\n\n\t\t\tif(run > len)               // If there is any additional data we want to sort to bring up the run length to minrun.\n\t\t\t{\n\t\t\t\tinsertion_sort_already_started<RandomAccessIterator, StrictWeakOrdering>(first + curr, first + curr + run, first + curr + len, compare);\n\t\t\t\tlen = run;\n\t\t\t}\n\n\t\t\t// At this point, run will be equal to minrun or will go to the end of our data.\n\t\t\t// Add this run to our stack of runs.\n\t\t\tEASTL_DEV_ASSERT(stack_curr < kTimSortStackSize);\n\t\t\tEASTL_DEV_ASSERT((curr >= 0) && (curr < size) && ((curr + len) <= size));\n\n\t\t\trun_stack[stack_curr].start  = curr;\n\t\t\trun_stack[stack_curr].length = len;\n\t\t\tstack_curr++;\n\n\t\t\t// Move to the beginning of the next run in the data.\n\t\t\tcurr += len;\n\n\t\t\tif(curr == size)    // If we have hit the end of the data...\n\t\t\t{\n\t\t\t\twhile(stack_curr > 1) // If there is any more than one run... (else all the data is sorted)\n\t\t\t\t{\n\t\t\t\t\ttim_sort_merge<RandomAccessIterator, T, StrictWeakOrdering>(first, run_stack, stack_curr, pBuffer, compare);\n\n\t\t\t\t\trun_stack[stack_curr - 2].length += run_stack[stack_curr - 1].length;\n\t\t\t\t\tstack_curr--;\n\n\t\t\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\t\t\tEASTL_DEV_ASSERT((run_stack[stack_curr - 1].start + run_stack[stack_curr - 1].length) <= size);\n\t\t\t\t\t\tmemset(&run_stack[stack_curr], 0, sizeof(run_stack[stack_curr]));\n\t\t\t\t\t#endif\n\t\t\t\t}\n\n\t\t\t\treturn true; // We are done with sorting.\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t} // namespace Internal\n\n\n\t// tim_sort_buffer\n\t//\n\t/// This is a stable sort.\n\t// Implements the tim-sort sorting algorithm with a user-provided scratch buffer.\n\t// http://en.wikipedia.org/wiki/Timsort\n\t// This sort is the fastest sort when sort stability (maintaining order of equal values) is required and\n\t// data sets are non-trivial (size >= 15). It's also the fastest sort (e.g. faster than quick_sort) for \n\t// the case that at at least half your data is already sorted. Otherwise, eastl::quick_sort is about 10% \n\t// faster than tim_sort_buffer but is not a stable sort. There are some reports that tim_sort outperforms\n\t// quick_sort but most of these aren't taking into account that optimal quick_sort implementations use\n\t// a hybrid approach called \"introsort\" (http://en.wikipedia.org/wiki/Introsort) which improves quick_sort\n\t// considerably in practice.\n\t//\n\t// Strengths:\n\t//     - Fastest stable sort for most sizes of data.\n\t//     - Fastest sort for containers of data already mostly sorted.\n\t//     - Simpler to understand than quick_sort.\n\t//\n\t// Weaknesses:\n\t//     - User must provide a scratch buffer, otherwise the buffer is dynamically allocated during runtime.\n\t//     - Not as fast as quick_sort for the general case of randomized data.\n\t//     - Requires a RandomAccessIterator; thus must be on an array container type and not a list container type.\n\t//     - Uses a lot of code to implement; thus it's not great when there is little room for more code.\n\t//\n\t// The pBuffer parameter must hold at least ((last-first)/2) elements (i.e. half the elements of the container).\n\t// This minimum size is a worst-case size requirement, but handles all possible cases. pBuffer is just a scratch\n\t// buffer and is not needed after the return of this function, and doesn't need to be seeded with any particular\n\t// values upon entering this function.\n\t//\n\t// Example usage:\n\t//     int intArray[64];\n\t//     int buffer[32];\n\t//     ...\n\t//     tim_sort_buffer(intArray, intArray + 64, buffer);\n\t//\n\ttemplate <typename RandomAccessIterator, typename T, typename StrictWeakOrdering>\n\tvoid tim_sort_buffer(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer, StrictWeakOrdering compare)\n\t{\n\t\tusing namespace Internal;\n\n\t\t// To consider: Convert the implementation to use first/last instead of first/size.\n\t\tconst intptr_t size = (intptr_t)(last - first);\n\t\tif (size == 0)\n\t\t{\n\t\t\t// This branch is necessary because the expression `first + 1` below is undefined\n\t\t\t// behaviour when first is nullptr (for example when it is the begin() iterator of an\n\t\t\t// empty vector).\n\t\t\treturn;\n\t\t}\n\t\telse if (size < 64)\n\t\t{\n\t\t\tinsertion_sort_already_started(first, first + size, first + 1, compare);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttim_sort_run   run_stack[kTimSortStackSize];\n\t\t\tintptr_t       stack_curr = 0;\n\t\t\tintptr_t       len, run;\n\t\t\tintptr_t       curr = 0;\n\t\t\tconst intptr_t minrun = timsort_compute_minrun(size);\n\n\t\t\t#if EASTL_DEV_DEBUG\n\t\t\t\tmemset(run_stack, 0, sizeof(run_stack));\n\t\t\t#endif\n\n\t\t\tif(tim_sort_add_run<RandomAccessIterator, T, StrictWeakOrdering>(run_stack, first, pBuffer, size, minrun, len, run, curr, stack_curr, compare))\n\t\t\t\treturn;\n\t\t\tif(tim_sort_add_run<RandomAccessIterator, T, StrictWeakOrdering>(run_stack, first, pBuffer, size, minrun, len, run, curr, stack_curr, compare))\n\t\t\t\treturn;\n\t\t\tif(tim_sort_add_run<RandomAccessIterator, T, StrictWeakOrdering>(run_stack, first, pBuffer, size, minrun, len, run, curr, stack_curr, compare))\n\t\t\t\treturn;\n\n\t\t\tfor(;;)\n\t\t\t{\n\t\t\t\tif(timsort_check_invariant(run_stack, stack_curr))\n\t\t\t\t\tstack_curr = tim_sort_collapse<RandomAccessIterator, T, StrictWeakOrdering>(first, run_stack, stack_curr, pBuffer, size, compare);\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(tim_sort_add_run<RandomAccessIterator, T, StrictWeakOrdering>(run_stack, first, pBuffer, size, minrun, len, run, curr, stack_curr, compare))\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename RandomAccessIterator, typename T>\n\tinline void tim_sort_buffer(RandomAccessIterator first, RandomAccessIterator last, T* pBuffer)\n\t{\n\t\ttypedef eastl::less<T> Less;\n\n\t\teastl::tim_sort_buffer<RandomAccessIterator, T, Less>(first, last, pBuffer, Less());\n\t}\n\n\n\n\n\t/// radix_sort\n\t///\n\t/// Implements a classic LSD (least significant digit) radix sort.\n\t/// See http://en.wikipedia.org/wiki/Radix_sort.\n\t/// This sort requires that the sorted data be of a type that has a member\n\t/// radix_type typedef and an mKey member of that type. The type must be\n\t/// an integral type. This limits what can be sorted, but radix_sort is \n\t/// very fast -- typically faster than any other sort.\n\t/// For example:\n\t///     struct Sortable {\n\t///         typedef int radix_type;\n\t///         radix_type mKey;\n\t///         // User data goes here, or the user can inherit from Sortable.\n\t///     };\n\t/// or, more generally:\n\t///     template <typname Integer>\n\t///     struct Sortable {\n\t///         typedef Integer radix_type;\n\t///         Integer mKey;\n\t///     };\n\t/// \n\t/// Example usage:\n\t///     struct Element {\n\t///         typedef uint16_t radix_type;\n\t///         uint16_t mKey;\n\t///         uint16_t mUserData;\n\t///     };\n\t///\n\t///     Element elementArray[100];\n\t///     Element buffer[100];\n\t///\n\t///     radix_sort<Element*, extract_radix_key<Element> >(elementArray, elementArray + 100, buffer);\n\t///\n\t/// To consider: A static linked-list implementation may be faster than the version here.\n\n\tnamespace Internal\n\t{\n\t\t/// extract_radix_key\n\t\t///\n\t\t/// Default radix sort integer value reader. It expects the sorted elements \n\t\t/// to have an integer member of type radix_type and of name \"mKey\". \n\t\t///\n\t\ttemplate <typename Node>\n\t\tstruct extract_radix_key\n\t\t{\n\t\t\ttypedef typename Node::radix_type radix_type;\n\n\t\t\tconst radix_type operator()(const Node& x) const\n\t\t\t\t{ return x.mKey; }\n\t\t};\n\n\t\t// The radix_sort implementation uses two optimizations that are not part of a typical radix sort implementation.\n\t\t// 1. Computing a histogram (i.e. finding the number of elements per bucket) for the next pass is done in parallel with the loop that \"scatters\"\n\t\t//    elements in the current pass.  The advantage is that it avoids the memory traffic / cache pressure of reading keys in a separate operation.\n\t\t//    Note: It would also be possible to compute all histograms in a single pass.  However, that would increase the amount of stack space used and\n\t\t//    also increase cache pressure slightly.  However, it could still be faster under some situations.\n\t\t// 2. If all elements are mapped to a single bucket, then there is no need to perform a scatter operation.  Instead the elements are left in place\n\t\t//    and only copied if they need to be copied to the final output buffer.\n\t\ttemplate <typename RandomAccessIterator, typename ExtractKey, int DigitBits, typename IntegerType>\n\t\tvoid radix_sort_impl(RandomAccessIterator first,\n\t\t\tRandomAccessIterator last,\n\t\t\tRandomAccessIterator buffer,\n\t\t\tExtractKey extractKey,\n\t\t\tIntegerType)\n\t\t{\n\t\t\tRandomAccessIterator srcFirst = first;\n\t\t\tEA_CONSTEXPR_OR_CONST size_t numBuckets = 1 << DigitBits;\n\t\t\tEA_CONSTEXPR_OR_CONST IntegerType bucketMask = numBuckets - 1;\n\n\t\t\t// The alignment of this variable isn't required; it merely allows the code below to be faster on some platforms.\n\t\t\tuint32_t EA_PREFIX_ALIGN(EASTL_PLATFORM_PREFERRED_ALIGNMENT) bucketSize[numBuckets];\n\t\t\tuint32_t EA_PREFIX_ALIGN(EASTL_PLATFORM_PREFERRED_ALIGNMENT) bucketPosition[numBuckets];\n\n\t\t\tRandomAccessIterator temp;\n\t\t\tuint32_t i;\n\t\t\tbool doSeparateHistogramCalculation = true;\n\n\t\t\tconstexpr uint32_t kMaxDigitBits = 8 * sizeof(IntegerType);\n\t\t\tfor (uint32_t j = 0; j < kMaxDigitBits; j += DigitBits)\n\t\t\t{\n\t\t\t\tif (doSeparateHistogramCalculation)\n\t\t\t\t{\n\t\t\t\t\tmemset(bucketSize, 0, sizeof(bucketSize));\n\t\t\t\t\t// Calculate histogram for the first scatter operation\n\t\t\t\t\tfor (temp = srcFirst; temp != last; ++temp)\n\t\t\t\t\t\t++bucketSize[(extractKey(*temp) >> j) & bucketMask];\n\t\t\t\t}\n\n\t\t\t\t// If a single bucket contains all of the elements, then don't bother redistributing all elements to the\n\t\t\t\t// same bucket.\n\t\t\t\tif (bucketSize[((extractKey(*srcFirst) >> j) & bucketMask)] == uint32_t(last - srcFirst))\n\t\t\t\t{\n\t\t\t\t\t// Set flag to ensure histogram is computed for next digit position.\n\t\t\t\t\tdoSeparateHistogramCalculation = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// The histogram is either not needed or it will be calculated in parallel with the scatter operation below for better cache efficiency.\n\t\t\t\t\tdoSeparateHistogramCalculation = false;\n\n\t\t\t\t\t// If this is the last digit position, then don't calculate a histogram\n\t\t\t\t\tconst uint32_t jNext = j + DigitBits;\n\t\t\t\t\tif (jNext >= kMaxDigitBits)\n\t\t\t\t\t{\n\t\t\t\t\t\tbucketPosition[0] = 0;\n\t\t\t\t\t\tfor (i = 0; i < numBuckets - 1; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbucketPosition[i + 1] = bucketPosition[i] + bucketSize[i];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (temp = srcFirst; temp != last; ++temp)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tIntegerType key = extractKey(*temp);\n\t\t\t\t\t\t\tconst size_t digit = (key >> j) & bucketMask;\n\t\t\t\t\t\t\tbuffer[bucketPosition[digit]++] = *temp;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Compute the histogram while performing the scatter operation\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbucketPosition[0] = 0;\n\t\t\t\t\t\tfor (i = 0; i < numBuckets - 1; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbucketPosition[i + 1] = bucketPosition[i] + bucketSize[i];\n\t\t\t\t\t\t\tbucketSize[i] = 0;\t// Clear the bucket for the next pass\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbucketSize[numBuckets - 1] = 0; \n\n\t\t\t\t\t\tfor (temp = srcFirst; temp != last; ++temp)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst IntegerType key = extractKey(*temp);\n\t\t\t\t\t\t\tconst size_t digit = (key >> j) & bucketMask;\n\t\t\t\t\t\t\tbuffer[bucketPosition[digit]++] = *temp;\n\n\t\t\t\t\t\t\t// Update histogram for the next scatter operation\n\t\t\t\t\t\t\t++bucketSize[(key >> jNext) & bucketMask];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlast = buffer + (last - srcFirst);\n\t\t\t\t\ttemp = srcFirst;\n\t\t\t\t\tsrcFirst = buffer;\n\t\t\t\t\tbuffer = temp;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (srcFirst != first)\n\t\t\t{\n\t\t\t\t// Copy values back into the expected buffer\n\t\t\t\tfor (temp = srcFirst; temp != last; ++temp)\n\t\t\t\t\t*buffer++ = *temp;\n\t\t\t}\n\t\t}\n\t} // namespace Internal\n\n\ttemplate <typename RandomAccessIterator, typename ExtractKey, int DigitBits = 8>\n\tvoid radix_sort(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator buffer)\n\t{\n\t\tstatic_assert(DigitBits > 0, \"DigitBits must be > 0\");\n\t\tstatic_assert(DigitBits <= (sizeof(typename ExtractKey::radix_type) * 8), \"DigitBits must be <= the size of the key (in bits)\");\n\t\teastl::Internal::radix_sort_impl<RandomAccessIterator, ExtractKey, DigitBits>(first, last, buffer, ExtractKey(), typename ExtractKey::radix_type());\n\t}\n\n\n\n\t/// comb_sort\n\t///\n\t/// This is an unstable sort.\n\t/// Implements the CombSort algorithm; in particular, implements the CombSort11 variation \n\t/// of the CombSort algorithm, based on the reference to '11' in the implementation.\n\t///\n\t/// To consider: Use a comb sort table instead of the '((nSpace * 10) + 3) / 13' expression.\n\t///              Ideal tables can be found on the Internet by looking up \"comb sort table\".\n\t///\n\ttemplate <typename ForwardIterator, typename StrictWeakOrdering>\n\tvoid comb_sort(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::difference_type difference_type;\n\n\t\tForwardIterator iCurrent, iNext;\n\t\tdifference_type length = eastl::distance(first, last);\n\t\tdifference_type nSpace = length;\n\n\t\tfor(bool bSwapped = false; (nSpace > 1) || bSwapped; )\n\t\t{\n\t\t\tnSpace = ((nSpace * 10) + 3) / 13; // Integer division is less than ideal.\n\n\t\t\tif((nSpace == 9) || (nSpace == 10))\n\t\t\t\tnSpace = 11;\n\n\t\t\tiCurrent = iNext = first;\n\t\t\teastl::advance(iNext, nSpace);\n\t\t\t\n\t\t\tfor(bSwapped = false; iNext != last; iCurrent++, iNext++)\n\t\t\t{\n\t\t\t\tif(compare(*iNext, *iCurrent))\n\t\t\t\t{\n\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.\n\t\t\t\t\teastl::iter_swap(iCurrent, iNext);\n\t\t\t\t\tbSwapped = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} // comb_sort\n\n\ttemplate <typename ForwardIterator>\n\tinline void comb_sort(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;\n\n\t\teastl::comb_sort<ForwardIterator, Less>(first, last, Less());\n\t}\n\n\n\n\n\t/// bubble_sort\n\t///\n\t/// This is a stable sort.\n\t/// Implements the BubbleSort algorithm. This algorithm is only useful for \n\t/// small range sizes, such as 10 or less items. You may be better off using\n\t/// insertion_sort for cases where bubble_sort works.\n\t///\n\tnamespace Internal\n\t{\n\t\ttemplate <typename ForwardIterator, typename StrictWeakOrdering>\n\t\tvoid bubble_sort_impl(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare, eastl::forward_iterator_tag)\n\t\t{\n\t\t\tForwardIterator iCurrent, iNext;\n\n\t\t\twhile(first != last)\n\t\t\t{\n\t\t\t\tiNext = iCurrent = first;\n\t\t\t\t\n\t\t\t\tfor(++iNext; iNext != last; iCurrent = iNext, ++iNext) \n\t\t\t\t{\n\t\t\t\t\tif(compare(*iNext, *iCurrent))\n\t\t\t\t\t{\n\t\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.\n\t\t\t\t\t\teastl::iter_swap(iCurrent, iNext);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlast = iCurrent;\n\t\t\t}\n\t\t}\n\n\t\ttemplate <typename BidirectionalIterator, typename StrictWeakOrdering>\n\t\tvoid bubble_sort_impl(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering compare, eastl::bidirectional_iterator_tag)\n\t\t{\n\t\t\tif(first != last)\n\t\t\t{\n\t\t\t\tBidirectionalIterator iCurrent, iNext, iLastModified;\n\n\t\t\t\tlast--;\n\n\t\t\t\twhile(first != last)\n\t\t\t\t{\n\t\t\t\t\tiLastModified = iNext = iCurrent = first;\n\t\t\t\t\t\n\t\t\t\t\tfor(++iNext; iCurrent != last; iCurrent = iNext, ++iNext)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(compare(*iNext, *iCurrent))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tEASTL_VALIDATE_COMPARE(!compare(*iCurrent, *iNext)); // Validate that the compare function is sane.\n\t\t\t\t\t\t\tiLastModified = iCurrent;\n\t\t\t\t\t\t\teastl::iter_swap(iCurrent, iNext);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlast = iLastModified;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} // namespace Internal\n\n\ttemplate <typename ForwardIterator, typename StrictWeakOrdering>\n\tinline void bubble_sort(ForwardIterator first, ForwardIterator last, StrictWeakOrdering compare)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;\n\n\t\teastl::Internal::bubble_sort_impl<ForwardIterator, StrictWeakOrdering>(first, last, compare, IC());\n\t}\n\n\ttemplate <typename ForwardIterator>\n\tinline void bubble_sort(ForwardIterator first, ForwardIterator last)\n\t{\n\t\ttypedef eastl::less<typename eastl::iterator_traits<ForwardIterator>::value_type> Less;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;\n\n\t\teastl::Internal::bubble_sort_impl<ForwardIterator, Less>(first, last, Less(), IC());\n\t}\n\n\n\n\t/// sort\n\t/// \n\t/// We use quick_sort by default. See quick_sort for details.\n\t///\n\t/// EASTL_DEFAULT_SORT_FUNCTION\n\t/// If a default sort function is specified then call it, otherwise use EASTL's default quick_sort.\n\t/// EASTL_DEFAULT_SORT_FUNCTION must be namespace-qualified and include any necessary template\n\t/// parameters (e.g. eastl::comb_sort instead of just comb_sort), and it must be visible to this code. \n\t/// The EASTL_DEFAULT_SORT_FUNCTION must be provided in two versions: \n\t///     template <typename RandomAccessIterator>\n\t///     void EASTL_DEFAULT_SORT_FUNCTION(RandomAccessIterator first, RandomAccessIterator last);\n\t///\n\t///     template <typename RandomAccessIterator, typename Compare>\n\t///     void EASTL_DEFAULT_SORT_FUNCTION(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t///\n\ttemplate <typename RandomAccessIterator>\n\tinline void sort(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\t#if defined(EASTL_DEFAULT_SORT_FUNCTION)\n\t\t\tEASTL_DEFAULT_SORT_FUNCTION(first, last);\n\t\t#else\n\t\t\teastl::quick_sort<RandomAccessIterator>(first, last);\n\t\t#endif\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename Compare>\n\tinline void sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare)\n\t{\n\t\t#if defined(EASTL_DEFAULT_SORT_FUNCTION)\n\t\t\tEASTL_DEFAULT_SORT_FUNCTION(first, last, compare);\n\t\t#else\n\t\t\teastl::quick_sort<RandomAccessIterator, Compare>(first, last, compare);\n\t\t#endif\n\t}\n\n\n\n\t/// stable_sort\n\t/// \n\t/// We use merge_sort by default. See merge_sort for details.\n\t/// Beware that the used merge_sort -- and thus stable_sort -- allocates \n\t/// memory during execution. Try using merge_sort_buffer if you want\n\t/// to avoid memory allocation.\n\t///\n\t/// EASTL_DEFAULT_STABLE_SORT_FUNCTION\n\t/// If a default sort function is specified then call it, otherwise use EASTL's default merge_sort.\n\t/// EASTL_DEFAULT_STABLE_SORT_FUNCTION must be namespace-qualified and include any necessary template\n\t/// parameters (e.g. eastl::tim_sort instead of just tim_sort), and it must be visible to this code. \n\t/// The EASTL_DEFAULT_STABLE_SORT_FUNCTION must be provided in three versions, though the third\n\t/// allocation implementation may choose to ignore the allocator parameter: \n\t///     template <typename RandomAccessIterator, typename StrictWeakOrdering>\n\t///     void EASTL_DEFAULT_STABLE_SORT_FUNCTION(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering compare);\n\t///     \n\t///     template <typename RandomAccessIterator>\n\t///     void EASTL_DEFAULT_STABLE_SORT_FUNCTION(RandomAccessIterator first, RandomAccessIterator last);\n\t///\n\t///     template <typename RandomAccessIterator, typename Allocator, typename StrictWeakOrdering>\n\t///     void EASTL_DEFAULT_STABLE_SORT_FUNCTION(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator, StrictWeakOrdering compare);\n\t///\n\ttemplate <typename RandomAccessIterator, typename StrictWeakOrdering>\n\tvoid stable_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering compare)\n\t{\n\t\t#if defined(EASTL_DEFAULT_STABLE_SORT_FUNCTION)\n\t\t\tEASTL_DEFAULT_STABLE_SORT_FUNCTION(first, last, *get_default_allocator(0), compare);\n\t\t#else\n\t\t\teastl::merge_sort<RandomAccessIterator, EASTLAllocatorType, StrictWeakOrdering>\n\t\t\t\t\t\t\t (first, last, *get_default_allocator(0), compare);\n\t\t#endif\n\t}\n\n\ttemplate <typename RandomAccessIterator>\n\tvoid stable_sort(RandomAccessIterator first, RandomAccessIterator last)\n\t{\n\t\t#if defined(EASTL_DEFAULT_STABLE_SORT_FUNCTION)\n\t\t\tEASTL_DEFAULT_STABLE_SORT_FUNCTION(first, last, *get_default_allocator(0));\n\t\t#else\n\t\t\teastl::merge_sort<RandomAccessIterator, EASTLAllocatorType>\n\t\t\t\t\t\t\t (first, last, *get_default_allocator(0));\n\t\t#endif\n\t}\n\n\ttemplate <typename RandomAccessIterator, typename Allocator, typename StrictWeakOrdering>\n\tvoid stable_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator, StrictWeakOrdering compare)\n\t{\n\t\t#if defined(EASTL_DEFAULT_STABLE_SORT_FUNCTION)\n\t\t\tEASTL_DEFAULT_STABLE_SORT_FUNCTION(first, last, allocator, compare);\n\t\t#else\n\t\t\teastl::merge_sort<RandomAccessIterator, Allocator, StrictWeakOrdering>(first, last, allocator, compare);\n\t\t#endif\n\t}\n\n\t// This is not defined because it would cause compiler errors due to conflicts with a version above. \n\t//template <typename RandomAccessIterator, typename Allocator>\n\t//void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Allocator& allocator)\n\t//{\n\t//    #if defined(EASTL_DEFAULT_STABLE_SORT_FUNCTION)\n\t//        EASTL_DEFAULT_STABLE_SORT_FUNCTION<RandomAccessIterator, Allocator>(first, last, allocator);\n\t//    #else\n\t//        eastl::merge_sort<RandomAccessIterator, Allocator>(first, last, allocator);\n\t//    #endif\n\t//}\n\n\n\n\n\t/* \n\t// Something to consider adding: An eastl sort which uses qsort underneath. \n\t// The primary purpose of this is to have an eastl interface for sorting which\n\t// results in very little code generation, since all instances map to the \n\t// C qsort function.\n\n\ttemplate <typename T>\n\tint small_footprint_sort_func(const void* a, const void* b)\n\t{\n\t\tif(*(const T*)a < *(const T*)b)\n\t\t\treturn -1;\n\t\tif(*(const T*)a > *(const T*)b)\n\t\t\treturn +1;\n\t\treturn 0;\n\t}\n\n\ttemplate <typename ContiguousIterator>\n\tvoid small_footprint_sort(ContiguousIterator first, ContiguousIterator last)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ContiguousIterator>::value_type value_type;\n\n\t\tqsort(first, (size_t)eastl::distance(first, last), sizeof(value_type), small_footprint_sort_func<value_type>);\n\t}\n\t*/\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n"
  },
  {
    "path": "include/EASTL/span.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the eastl::span which is part of the C++ standard\n// STL library specification.\n//\n// eastl::span is a non-owning container that refers to a contiguous block of\n// memory.  It bundles up the classic pattern of a pointer and a size into a\n// single type.  A span can either have a static extent, in which case the\n// number of elements in the sequence is known and encoded in the type, or a\n// dynamic extent.\n//\n// http://en.cppreference.com/w/cpp/container/span\n// http://eel.is/c++draft/views#span.syn\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_SPAN_H\n#define EASTL_SPAN_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once \n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/array.h>\n\nnamespace eastl\n{\n\tstatic EA_CONSTEXPR size_t dynamic_extent = size_t(-1);\n\n\tnamespace Internal\n\t{\n\t\t// HasSizeAndData\n\t\t// \n\t\t// custom type trait to determine if eastl::data(Container) and eastl::size(Container) are well-formed.\n\t\t//\n\t\ttemplate <typename, typename = void>\n\t\tstruct HasSizeAndData : eastl::false_type {};\n\n\t\ttemplate <typename T>\n\t\tstruct HasSizeAndData<T, void_t<decltype(eastl::size(eastl::declval<T>())), decltype(eastl::data(eastl::declval<T>()))>> : eastl::true_type {};\n\n\t\t// SubspanExtent\n\t\t//\n\t\t// Integral constant that calculates the resulting extent of a templated subspan operation.\n\t\t//\n\t\t//   If Count is not dynamic_extent then SubspanExtent::value is Count,\n\t\t//   otherwise, if Extent is not dynamic_extent, SubspanExtent::value is (Extent - Offset),\n\t\t//   otherwise, SubspanExtent::value is dynamic_extent.\n\t\t//\n\t\ttemplate<size_t Extent, size_t Offset, size_t Count>\n\t\tstruct SubspanExtent : eastl::integral_constant<size_t, (Count != dynamic_extent ? Count : (Extent != dynamic_extent ? (Extent - Offset) : dynamic_extent))> {};\n\n\t\t// is_eastl_array<PossiblyArray, T>\n\t\t// \n\t\t// is an eastl::array<T, N> with elements T?\n\t\t// NOT the same as is_array, which is a type trait for the C-style array type.\n\t\ttemplate<typename PossiblyArray, typename T>\n\t\tstruct is_eastl_array : public eastl::false_type {};\n\n\t\ttemplate<typename T, size_t N>\n\t\tstruct is_eastl_array<eastl::array<T, N>, T> : public eastl::true_type {};\n\n\t\t// SpanStorage\n\t\t//\n\t\t// Holds all of the member variables for span, specialized to remove the size variable when\n\t\t// given a static extent.\n\t\t//\n\t\ttemplate <typename T, size_t Extent>\n\t\tstruct SpanStorage\n\t\t{\n\t\t\tT* mpData = nullptr;\n\t\t\tstatic EA_CONSTEXPR eastl_size_t mnSize = Extent;\n\n\t\t\tEA_CONSTEXPR SpanStorage() EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tstatic_assert(Extent == 0, \"impossible to default construct a span with a fixed Extent different than 0\");\n\t\t\t}\n\n\t\t\tEA_CONSTEXPR SpanStorage(T* ptr, eastl_size_t size)\n\t\t\t\t: mpData(ptr)\n\t\t\t{\n\t\t\t\tEA_UNUSED(size);\n\t\t\t\tEASTL_ASSERT_MSG(Extent == size, \"impossible to create a span with a fixed Extent different than the size of the supplied buffer\");\n\t\t\t}\n\t\t};\n\n\t\ttemplate <typename T>\n\t\tstruct SpanStorage<T, eastl::dynamic_extent>\n\t\t{\n\t\t\tT* mpData = nullptr;\n\t\t\teastl_size_t mnSize = 0;\n\n\t\t\tEA_CONSTEXPR SpanStorage() EA_NOEXCEPT = default;\n\t\t\tEA_CONSTEXPR SpanStorage(T* ptr, eastl_size_t size) : mpData(ptr), mnSize(size) {}\n\t\t};\n\t}\n\n\ttemplate <typename T, size_t Extent = eastl::dynamic_extent>\n\tclass span\n\t{\n\tpublic:\n\t\ttypedef T                                       element_type;\n\t\ttypedef remove_cv_t<T>                          value_type;\n\t\ttypedef eastl_size_t                            index_type;\n\t\ttypedef ptrdiff_t                               difference_type;\n\t\ttypedef T*                                      pointer;\n\t\ttypedef const T*                                const_pointer;\n\t\ttypedef T&                                      reference;\n\t\ttypedef const T&                                const_reference;\n\t\ttypedef T*                                      iterator;\n\t\ttypedef const T*                                const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>       reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator> const_reverse_iterator;\n\n\t\tstatic EA_CONSTEXPR size_t extent = Extent;\n\n\t\t// constructors / destructor\n\t\tEA_CONSTEXPR span() EA_NOEXCEPT = default;\n\t\tEA_CONSTEXPR span(const span& other) EA_NOEXCEPT = default;\n\t\tEA_CONSTEXPR span(pointer ptr, index_type count);\n\t\tEA_CONSTEXPR span(pointer pBegin, pointer pEnd);\n\t\t            ~span() EA_NOEXCEPT = default;\n\n\t\t// copy-assignment operator\n\t\tEA_CPP14_CONSTEXPR span& operator=(const span& other) EA_NOEXCEPT = default;\n\n\t\t// conversion constructors for c-array and eastl::array\n\t\ttemplate <size_t N, typename = enable_if_t<(Extent == eastl::dynamic_extent || N == Extent)>> \n\t\tEA_CONSTEXPR span(element_type (&arr)[N]) EA_NOEXCEPT;\n\n\t\ttemplate <size_t N, typename = enable_if_t<(Extent == eastl::dynamic_extent || N == Extent)>>\n\t\tEA_CONSTEXPR span(eastl::array<value_type, N>& arr) EA_NOEXCEPT;\n\t\t\n\t\ttemplate <size_t N, typename = enable_if_t<(Extent == eastl::dynamic_extent || N == Extent)>>\n\t\tEA_CONSTEXPR span(const eastl::array<value_type, N>& arr) EA_NOEXCEPT;\n\n\t\t// SfinaeForGenericContainers\n\t\t//\n\t\ttemplate <typename Container>\n\t\tusing SfinaeForGenericContainers =\n\t\t    enable_if_t<!is_same_v<Container, span> && !Internal::is_eastl_array<Container, value_type>::value &&\n\t\t                !is_array_v<Container> &&\n\t\t                Internal::HasSizeAndData<Container>::value &&\n\t\t                is_convertible_v<remove_pointer_t<decltype(eastl::data(eastl::declval<Container&>()))> (*)[], element_type (*)[]>>;\n\n\t\t// generic container conversion constructors\n\t\ttemplate <typename Container, typename = SfinaeForGenericContainers<Container>>\n\t\tEA_CONSTEXPR span(Container& cont);\n\n\t\ttemplate <typename Container, typename = SfinaeForGenericContainers<const Container>>\n\t\tEA_CONSTEXPR span(const Container& cont);\n\n\t\ttemplate <typename U, size_t N, typename = enable_if_t<(Extent == eastl::dynamic_extent || N == Extent) && (is_convertible_v<U(*)[], element_type(*)[]>)>>\n\t\tEA_CONSTEXPR span(const span<U, N>& s) EA_NOEXCEPT;\n\n\t\t// subviews\n\t\ttemplate<size_t Count>\n\t\tEA_CPP14_CONSTEXPR span<element_type, Count> first() const;\n\t\tEA_CPP14_CONSTEXPR span<element_type, dynamic_extent> first(size_t Count) const;\n\n\t\ttemplate<size_t Count>\n\t\tEA_CPP14_CONSTEXPR span<element_type, Count> last() const;\n\t\tEA_CPP14_CONSTEXPR span<element_type, dynamic_extent> last(size_t Count) const;\n\n\t\ttemplate <size_t Offset, size_t Count = dynamic_extent>\n\t\tEA_CONSTEXPR span<element_type, Internal::SubspanExtent<Extent, Offset, Count>::value> subspan() const;\n\t\tEA_CONSTEXPR span<element_type, dynamic_extent> subspan(size_t Offset, size_t Count = dynamic_extent) const;\n\n\t\t// observers\n\t\tEA_CONSTEXPR pointer    data() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR index_type size() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR index_type size_bytes() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR bool       empty() const EA_NOEXCEPT;\n\n\t\t// subscript operators, element access\n\t\tEA_CONSTEXPR reference front() const;\n\t\tEA_CONSTEXPR reference back() const;\n\t\tEA_CONSTEXPR reference operator[](index_type idx) const;\n\t\tEA_CONSTEXPR reference operator()(index_type idx) const;\n\n\t\t// iterator support\n\t\tEA_CONSTEXPR iterator begin() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR iterator end() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR const_iterator cend() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR reverse_iterator rend() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT;\n\t\tEA_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT;\n\n\tprivate:\n\t\tInternal::SpanStorage<T, Extent> mStorage;\n\n\tprivate:\n\t\tEA_CONSTEXPR bool bounds_check(size_t) const;  // utility used in asserts\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// template deduction guides \n\t///////////////////////////////////////////////////////////////////////////\n\t#ifdef __cpp_deduction_guides\n\t\ttemplate<class T, size_t N> span(T (&)[N]) ->           span <T, N>;\n\t\ttemplate<class T, size_t N> span(array<T, N>&) ->       span <T, N>;\n\t\ttemplate<class T, size_t N> span(const array<T, N>&) -> span <const T, N>;\n\t\ttemplate<class Container>   span(Container&) ->         span <typename Container::value_type>;\n\t\ttemplate<class Container>   span(const Container&) ->   span <const typename Container::value_type>;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// comparison operators\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <class T, size_t X, class U, size_t Y>\n\tEA_CONSTEXPR bool operator==(span<T, X> l, span<U, Y> r)\n\t{\n\t\treturn (l.size() == r.size()) && eastl::equal(l.begin(), l.end(), r.begin());\n\t}\n\n\ttemplate <class T, size_t X, class U, size_t Y>\n\tEA_CONSTEXPR bool operator<(span<T, X> l, span<U, Y> r)\n\t{\n\t\treturn eastl::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());\n\t}\n\n\ttemplate <class T, size_t X, class U, size_t Y>\n\tEA_CONSTEXPR bool operator!=(span<T, X> l, span<U, Y> r) { return !(l == r); }\n\n\ttemplate <class T, size_t X, class U, size_t Y>\n\tEA_CONSTEXPR bool operator<=(span<T, X> l, span<U, Y> r) { return !(r < l); }\n\n\ttemplate <class T, size_t X, class U, size_t Y>\n\tEA_CONSTEXPR bool operator>(span<T, X> l, span<U, Y> r) { return r < l; }\n\n\ttemplate <class T, size_t X, class U, size_t Y>\n\tEA_CONSTEXPR bool operator>=(span<T, X> l, span<U, Y> r) { return !(l < r); }\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// ctor implementations\n\t///////////////////////////////////////////////////////////////////////////\n\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR span<T, Extent>::span(pointer ptr, index_type size)\n\t    : mStorage(ptr, size)\n\t{\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR span<T, Extent>::span(pointer pBegin, pointer pEnd)\n\t    : mStorage(pBegin, static_cast<index_type>(pEnd - pBegin))\n\t{\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <size_t N, typename>\n\tEA_CONSTEXPR span<T, Extent>::span(element_type(&arr)[N]) EA_NOEXCEPT \n\t\t: span(arr, static_cast<index_type>(N))\n\t{\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <size_t N, typename>\n\tEA_CONSTEXPR span<T, Extent>::span(eastl::array<value_type, N> &arr) EA_NOEXCEPT \n\t\t: span(arr.data(), arr.size())\n\t{\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <size_t N, typename>\n\tEA_CONSTEXPR span<T, Extent>::span(const eastl::array<value_type, N>& arr) EA_NOEXCEPT\n\t\t: span(arr.data(), arr.size())\n\t{\n\t}\n\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <typename Container, typename>\n\tEA_CONSTEXPR span<T, Extent>::span(Container& cont)\n\t\t: span(static_cast<pointer>(eastl::data(cont)), static_cast<index_type>(eastl::size(cont)))\n\t{\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <typename Container, typename>\n\tEA_CONSTEXPR span<T, Extent>::span(const Container& cont)\n\t\t: span(static_cast<pointer>(eastl::data(cont)), static_cast<index_type>(eastl::size(cont)))\n\t{\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <typename U, size_t N, typename>\n\tEA_CONSTEXPR span<T, Extent>::span(const span<U, N>& s) EA_NOEXCEPT\n\t\t: span(s.data(), s.size())\n\t{\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// member function implementations\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::pointer span<T, Extent>::data() const EA_NOEXCEPT\n\t{\n\t\treturn mStorage.mpData;\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::index_type span<T, Extent>::size() const EA_NOEXCEPT\n\t{\n\t\treturn mStorage.mnSize;\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::index_type span<T, Extent>::size_bytes() const EA_NOEXCEPT\n\t{\n\t\treturn size() * sizeof(element_type);\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR bool span<T, Extent>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn size() == 0;\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::reference span<T, Extent>::front() const\n\t{\n\t\tEASTL_ASSERT_MSG(!empty(), \"undefined behavior accessing an empty span\");\n\n\t\treturn mStorage.mpData[0];\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::reference span<T, Extent>::back() const\n\t{\n\t\tEASTL_ASSERT_MSG(!empty(), \"undefined behavior accessing an empty span\");\n\n\t\treturn mStorage.mpData[mStorage.mnSize - 1];\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::reference span<T, Extent>::operator[](index_type idx) const\n\t{\n\t\tEASTL_ASSERT_MSG(!empty(),          \"undefined behavior accessing an empty span\");\n\t\tEASTL_ASSERT_MSG(bounds_check(idx), \"undefined behavior accessing out of bounds\");\n\n\t\treturn mStorage.mpData[idx];\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::reference span<T, Extent>::operator()(index_type idx) const\n\t{\n\t\tEASTL_ASSERT_MSG(!empty(),          \"undefined behavior accessing an empty span\");\n\t\tEASTL_ASSERT_MSG(bounds_check(idx), \"undefined behavior accessing out of bounds\");\n\n\t\treturn mStorage.mpData[idx];\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::iterator span<T, Extent>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn mStorage.mpData;\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::iterator span<T, Extent>::end() const EA_NOEXCEPT\n\t{\n\t\treturn mStorage.mpData + mStorage.mnSize;\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::const_iterator span<T, Extent>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn mStorage.mpData;\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::const_iterator span<T, Extent>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn mStorage.mpData + mStorage.mnSize;\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::reverse_iterator span<T, Extent>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(mStorage.mpData + mStorage.mnSize);\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::reverse_iterator span<T, Extent>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(mStorage.mpData);\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::const_reverse_iterator span<T, Extent>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mStorage.mpData + mStorage.mnSize);\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR typename span<T, Extent>::const_reverse_iterator span<T, Extent>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mStorage.mpData);\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <size_t Count>\n\tEA_CPP14_CONSTEXPR span<typename span<T, Extent>::element_type, Count> span<T, Extent>::first() const\n\t{\n\t\tEASTL_ASSERT_MSG(Count <= size(), \"undefined behavior accessing out of bounds\");\n\t\treturn {data(), static_cast<index_type>(Count)};\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CPP14_CONSTEXPR span<typename span<T, Extent>::element_type, dynamic_extent> \n\tspan<T, Extent>::first(size_t sz) const\n\t{\n\t\tEASTL_ASSERT_MSG(sz <= size(), \"undefined behavior accessing out of bounds\");\n\t\treturn {data(), static_cast<index_type>(sz)};\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <size_t Count>\n\tEA_CPP14_CONSTEXPR span<typename span<T, Extent>::element_type, Count> span<T, Extent>::last() const\n\t{\n\t\tEASTL_ASSERT_MSG(Count <= size(), \"undefined behavior accessing out of bounds\");\n\t\treturn {data() + size() - Count, static_cast<index_type>(Count)};\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CPP14_CONSTEXPR span<typename span<T, Extent>::element_type, dynamic_extent> \n\tspan<T, Extent>::last(size_t sz) const\n\t{\n\t\tEASTL_ASSERT_MSG(sz <= size(), \"undefined behavior accessing out of bounds\");\n\t\treturn {data() + size() - sz, static_cast<index_type>(sz)};\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\ttemplate <size_t Offset, size_t Count>\n\tEA_CONSTEXPR span<typename span<T, Extent>::element_type, Internal::SubspanExtent<Extent, Offset, Count>::value>\n\tspan<T, Extent>::subspan() const\n\t{\n\t\tEASTL_ASSERT_MSG(Offset <= size(),                                       \"undefined behaviour accessing out of bounds\");\n\t\tEASTL_ASSERT_MSG(Count == dynamic_extent || Count <= (size() - Offset), \"undefined behaviour exceeding size of span\");\n\n\t\treturn {data() + Offset, eastl_size_t(Count == dynamic_extent ? size() - Offset : Count)};\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR span<typename span<T, Extent>::element_type, dynamic_extent>\n\tspan<T, Extent>::subspan(size_t offset, size_t count) const\n\t{\n\t\tEASTL_ASSERT_MSG(offset <= size(),                                      \"undefined behaviour accessing out of bounds\");\n\t\tEASTL_ASSERT_MSG(count == dynamic_extent || count <= (size() - offset), \"undefined behaviour exceeding size of span\");\n\n\t\treturn {data() + offset, eastl_size_t(count == dynamic_extent ? size() - offset : count)};\n\t}\n\n\ttemplate <typename T, size_t Extent>\n\tEA_CONSTEXPR bool span<T, Extent>::bounds_check(size_t offset) const\n\t{\n\t\treturn offset < size();\n\t}\n}\n\n#endif // EASTL_SPAN_H  \n"
  },
  {
    "path": "include/EASTL/stack.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a stack that is just like the C++ std::stack adapter class.\n// The only significant difference is that the stack here provides a get_container\n// function to provide access to the underlying container.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_STACK_H\n#define EASTL_STACK_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/vector.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_STACK_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_STACK_DEFAULT_NAME\n\t\t#define EASTL_STACK_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" stack\" // Unless the user overrides something, this is \"EASTL stack\".\n\t#endif\n\n\t/// EASTL_STACK_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_STACK_DEFAULT_ALLOCATOR\n\t\t#define EASTL_STACK_DEFAULT_ALLOCATOR allocator_type(EASTL_STACK_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// stack\n\t///\n\t/// stack is an adapter class provides a LIFO (last-in, first-out) interface\n\t/// via wrapping a sequence container (https://en.cppreference.com/w/cpp/named_req/SequenceContainer)\n\t/// that additionally provides the following operations:\n\t///     push_back\n\t///     pop_back\n\t///     back\n\t///\n\t/// In practice this means vector, deque, list, intrusive_list and (the pseudo-container) string.\n\t/// \n\t/// Note: the default underlying container is vector, rather than the standard's deque.\n\t///\n\ttemplate <typename T, typename Container = eastl::vector<T> >\n\tclass stack\n\t{\n\tpublic:\n\t\ttypedef stack<T, Container>                  this_type;\n\t\ttypedef          Container                   container_type;\n\t  //typedef typename Container::allocator_type   allocator_type;  // We can't currently declare this because the container may be a type that doesn't have an allocator. \n\t\ttypedef typename Container::value_type       value_type;\n\t\ttypedef typename Container::reference        reference;\n\t\ttypedef typename Container::const_reference  const_reference;\n\t\ttypedef typename Container::size_type        size_type;\n\n\tpublic:               // We declare public so that global comparison operators can be implemented without adding an inline level and without tripping up GCC 2.x friend declaration failures. GCC (through at least v4.0) is poor at inlining and performance wins over correctness.\n\t\tcontainer_type c; // The C++ standard specifies that you declare a protected member variable of type Container called 'c'.\n\n\tpublic:\n\t\tstack();\n\n\t\t// Allocator is templated here because we aren't allowed to infer the allocator_type from the Container, as some containers (e.g. array) don't \n\t\t// have allocators. For containers that don't have allocator types, you could use void or char as the Allocator template type.\n\n\t\ttemplate <class Allocator>                      \n\t\texplicit stack(const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t  : c(allocator)\n\t\t{\n\t\t}    \n\n\t\ttemplate <class Allocator>\n\t\tstack(const this_type& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t  : c(x.c, allocator)\n\t\t{\n\t\t}\n\n\t\ttemplate <class Allocator>\n\t\tstack(this_type&& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL)\n\t\t  : c(eastl::move(x.c), allocator)\n\t\t{\n\t\t}\n\n\t\texplicit stack(const container_type& x);\n\t\texplicit stack(container_type&& x);\n\n\t\t// Additional C++11 support to consider:\n\t\t//\n\t\t// template <class Allocator>\n\t\t// stack(const container_type& x, const Allocator& allocator);\n\t\t//\n\t\t// template <class Allocator>\n\t\t// stack(container_type&& x, const Allocator& allocator);\n\t\t//\n\t\t// template <class InputIt>\n\t\t// stack(InputIt first, InputIt last);\n\t\t//\n\t\t// template <class InputIt, class Allocator>\n\t\t// stack(InputIt first, InputIt last, const Allocator& allocator);\n\n\t\tstack(std::initializer_list<value_type> ilist); // The first item in the initializer list is pushed first. C++11 doesn't specify that std::stack has initializer list support.\n\n\t\tbool      empty() const;\n\t\tsize_type size() const;\n\n\t\treference       top();\n\t\tconst_reference top() const;\n\n\t\tvoid push(const value_type& value);\n\t\tvoid push(value_type&& x);\n\n\t\ttemplate <class... Args> EASTL_REMOVE_AT_2024_SEPT void emplace_back(Args&&... args); // use emplace() instead. they are equivalent.\n\t\ttemplate <class... Args> decltype(auto) emplace(Args&&... args);\n\n\t\tvoid pop();\n\n\t\tcontainer_type&       get_container();\n\t\tconst container_type& get_container() const;\n\n\t\tvoid swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<this_type::container_type>::value);\n\n\t\tbool validate() const;\n\n\t}; // class stack\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// stack\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container>\n\tinline stack<T, Container>::stack()\n\t\t: c() // To consider: use c(EASTL_STACK_DEFAULT_ALLOCATOR) here, though that would add the requirement that the user supplied container support this.\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline stack<T, Container>::stack(const Container& x)\n\t\t: c(x)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline stack<T, Container>::stack(Container&& x)\n\t\t: c(eastl::move(x))\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline stack<T, Container>::stack(std::initializer_list<value_type> ilist)\n\t\t: c() // We could alternatively use c(ilist) here, but that would require c to have an ilist constructor.\n\t{\n\t\t// Better solution but requires an insert function.\n\t\t// c.insert(ilist.begin(), ilist.end());\n\n\t\t// Possibly slower solution but doesn't require an insert function.\n\t\tfor(const auto& value : ilist)\n\t\t{\n\t\t\tc.push_back(value);\n\t\t}\n\t}\n\n\ttemplate <typename T, typename Container>\n\tinline bool stack<T, Container>::empty() const\n\t{\n\t\treturn c.empty();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename stack<T, Container>::size_type\n\tstack<T, Container>::size() const\n\t{\n\t\treturn c.size();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename stack<T, Container>::reference\n\tstack<T, Container>::top()\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"stack::top -- empty container\");\n#endif\n\n\t\treturn c.back();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename stack<T, Container>::const_reference\n\tstack<T, Container>::top() const\n\t{\n#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"stack::top -- empty container\");\n#endif\n\n\t\treturn c.back();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline void stack<T, Container>::push(const value_type& value)\n\t{\n\t\tc.push_back(const_cast<value_type&>(value)); // const_cast so that intrusive_list can work. We may revisit this.\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline void stack<T, Container>::push(value_type&& x) \n\t{\n\t\tc.push_back(eastl::move(x));\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\ttemplate <class... Args>\n\tinline void stack<T, Container>::emplace_back(Args&&... args)\n\t{\n\t\templace(eastl::forward<Args>(args)...);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\ttemplate <class... Args>\n\tinline decltype(auto) stack<T, Container>::emplace(Args&&... args)\n\t{\n\t\treturn c.emplace_back(eastl::forward<Args>(args)...);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline void stack<T, Container>::pop()\n\t{\n#if EASTL_ASSERT_ENABLED\n\t\tif (EASTL_UNLIKELY(c.empty()))\n\t\t\tEASTL_FAIL_MSG(\"stack::pop -- empty container\");\n#endif\n\n\t\tc.pop_back();\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline typename stack<T, Container>::container_type&\n\tstack<T, Container>::get_container()\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline const typename stack<T, Container>::container_type&\n\tstack<T, Container>::get_container() const\n\t{\n\t\treturn c;\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tvoid stack<T, Container>::swap(this_type& x) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<this_type::container_type>::value)\n\t{\n\t\tusing eastl::swap;\n\t\tswap(c, x.c);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tbool stack<T, Container>::validate() const\n\t{\n\t\treturn c.validate();\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator==(const stack<T, Container>& a, const stack<T, Container>& b)\n\t{\n\t\treturn (a.c == b.c);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Container> requires std::three_way_comparable<Container>\n\tinline synth_three_way_result<T> operator<=>(const stack<T, Container>& a, const stack<T, Container>& b)\n\t{\n\t\treturn a.c <=> b.c;\n\t}\n#endif\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator!=(const stack<T, Container>& a, const stack<T, Container>& b)\n\t{\n\t\treturn !(a.c == b.c);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator<(const stack<T, Container>& a, const stack<T, Container>& b)\n\t{\n\t\treturn (a.c < b.c);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator>(const stack<T, Container>& a, const stack<T, Container>& b)\n\t{\n\t\treturn (b.c < a.c);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator<=(const stack<T, Container>& a, const stack<T, Container>& b)\n\t{\n\t\treturn !(b.c < a.c);\n\t}\n\n\n\ttemplate <typename T, typename Container>\n\tinline bool operator>=(const stack<T, Container>& a, const stack<T, Container>& b)\n\t{\n\t\treturn !(a.c < b.c);\n\t}\n\n\ttemplate <typename T, typename Container>\n\tinline void swap(stack<T, Container>& a, stack<T, Container>& b) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable<typename stack<T, Container>::container_type>::value))\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/string.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Implements a basic_string class, much like the C++ std::basic_string.\n// The primary distinctions between basic_string and std::basic_string are:\n//    - basic_string has a few extension functions that allow for increased performance.\n//    - basic_string has a few extension functions that make use easier,\n//      such as a member sprintf function and member tolower/toupper functions.\n//    - basic_string supports debug memory naming natively.\n//    - basic_string is easier to read, debug, and visualize.\n//    - basic_string internally manually expands basic functions such as begin(),\n//      size(), etc. in order to improve debug performance and optimizer success.\n//    - basic_string is savvy to an environment that doesn't have exception handling,\n//      as is sometimes the case with console or embedded environments.\n//    - basic_string has less deeply nested function calls and allows the user to\n//      enable forced inlining in debug builds in order to reduce bloat.\n//    - basic_string doesn't use char traits. As a result, EASTL assumes that\n//      strings will hold characters and not exotic things like widgets. At the\n//      very least, basic_string assumes that the value_type is a POD.\n//    - basic_string::size_type is defined as eastl_size_t instead of size_t in\n//      order to save memory and run faster on 64 bit systems.\n//    - basic_string data is guaranteed to be contiguous.\n//    - basic_string data is guaranteed to be 0-terminated, and the c_str() function\n//      is guaranteed to return the same pointer as the data() which is guaranteed\n//      to be the same value as &string[0].\n//    - basic_string has a set_capacity() function which frees excess capacity.\n//      The only way to do this with std::basic_string is via the cryptic non-obvious\n//      trick of using: basic_string<char>(x).swap(x);\n//    - basic_string has a force_size() function, which unilaterally moves the string\n//      end position (mpEnd) to the given location. Useful for when the user writes\n//      into the string via some external means such as C strcpy or sprintf.\n//    - basic_string substr() deviates from the standard and returns a string with\n//\t\ta copy of this->get_allocator()\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Copy on Write (cow)\n//\n// This string implementation does not do copy on write (cow). This is by design,\n// as cow penalizes 95% of string uses for the benefit of only 5% of the uses\n// (these percentages are qualitative, not quantitative). The primary benefit of\n// cow is that it allows for the sharing of string data between two string objects.\n// Thus if you say this:\n//    string a(\"hello\");\n//    string b(a);\n// the \"hello\" will be shared between a and b. If you then say this:\n//    a = \"world\";\n// then a will release its reference to \"hello\" and leave b with the only reference\n// to it. Normally this functionality is accomplished via reference counting and\n// with atomic operations or mutexes.\n//\n// The C++ standard does not say anything about basic_string and cow. However,\n// for a basic_string implementation to be standards-conforming, a number of\n// issues arise which dictate some things about how one would have to implement\n// a cow string. The discussion of these issues will not be rehashed here, as you\n// can read the references below for better detail than can be provided in the\n// space we have here. However, we can say that the C++ standard is sensible and\n// that anything we try to do here to allow for an efficient cow implementation\n// would result in a generally unacceptable string interface.\n//\n// The disadvantages of cow strings are:\n//    - A reference count needs to exist with the string, which increases string memory usage.\n//    - With thread safety, atomic operations and mutex locks are expensive, especially\n//      on weaker memory systems such as console gaming platforms.\n//    - All non-const string accessor functions need to do a sharing check then the\n//      first such check needs to detach the string. Similarly, all string assignments\n//      need to do a sharing check as well. If you access the string before doing an\n//      assignment, the assignment doesn't result in a shared string, because the string\n//      has already been detached.\n//    - String sharing doesn't happen the large majority of the time. In some cases,\n//      the total sum of the reference count memory can exceed any memory savings\n//      gained by the strings that share representations.\n//\n// The addition of a string_cow class is under consideration for this library.\n// There are conceivably some systems which have string usage patterns which would\n// benefit from cow sharing. Such functionality is best saved for a separate string\n// implementation so that the other string uses aren't penalized.\n//\n// References:\n//    This is a good starting HTML reference on the topic:\n//       http://www.gotw.ca/publications/optimizations.htm\n//    Here is a Usenet discussion on the topic:\n//       http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3dc6af5198d0bf7/886c8642cb06e03d\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_STRING_H\n#define EASTL_STRING_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/bonus/compressed_pair.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stddef.h>             // size_t, ptrdiff_t, etc.\n#include <stdarg.h>             // vararg functionality.\n\n#include <stdlib.h>             // malloc, free.\n#include <stdio.h>              // snprintf, etc.\n#include <ctype.h>              // toupper, etc.\n\nEA_DISABLE_GCC_WARNING(-Wtype-limits)\n#include <wchar.h>\nEA_RESTORE_GCC_WARNING()\n\n#include <string.h> // strlen, etc.\n\n#if EASTL_EXCEPTIONS_ENABLED\n\t#include <stdexcept> // std::out_of_range, std::length_error, std::logic_error.\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4480 - nonstandard extension used: specifying underlying type for enum\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\n// 4267 - 'argument' : conversion from 'size_t' to 'const uint32_t', possible loss of data. This is a bogus warning resulting from a bug in VC++.\n// 4702 - unreachable code\nEA_DISABLE_VC_WARNING(4530 4480 4571 4267 4702);\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n#include <EASTL/internal/char_traits.h>\n#include <EASTL/string_view.h>\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_STRING_EXPLICIT\n//\n// See EASTL_STRING_OPT_EXPLICIT_CTORS for documentation.\n//\n#if EASTL_STRING_OPT_EXPLICIT_CTORS\n\t#define EASTL_STRING_EXPLICIT explicit\n#else\n\t#define EASTL_STRING_EXPLICIT\n#endif\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Vsnprintf\n//\n// The user is expected to supply these functions one way or another. Note that\n// these functions are expected to accept parameters as per the C99 standard.\n// These functions can deal with C99 standard return values or Microsoft non-standard\n// return values but act more efficiently if implemented via the C99 style.\n//\n// In the case of EASTL_EASTDC_VSNPRINTF == 1, the user is expected to either\n// link EAStdC or provide the functions below that act the same. In the case of\n// EASTL_EASTDC_VSNPRINTF == 0, the user is expected to provide the function\n// implementations, and may simply use C vsnprintf if desired, though it's not\n// completely portable between compilers.\n//\n#if EASTL_EASTDC_VSNPRINTF\n\tnamespace EA\n\t{\n\t\tnamespace StdC\n\t\t{\n\t\t\t// Provided by the EAStdC package or by the user.\n\t\t\tEASTL_EASTDC_API int Vsnprintf(char*  EA_RESTRICT pDestination, size_t n, const char*  EA_RESTRICT pFormat, va_list arguments);\n\t\t\tEASTL_EASTDC_API int Vsnprintf(char16_t* EA_RESTRICT pDestination, size_t n, const char16_t* EA_RESTRICT pFormat, va_list arguments);\n\t\t\tEASTL_EASTDC_API int Vsnprintf(char32_t* EA_RESTRICT pDestination, size_t n, const char32_t* EA_RESTRICT pFormat, va_list arguments);\n\t\t\t#if EA_CHAR8_UNIQUE\n\t\t\t\tEASTL_EASTDC_API int Vsnprintf(char8_t*  EA_RESTRICT pDestination, size_t n, const char8_t*  EA_RESTRICT pFormat, va_list arguments);\n\t\t\t#endif\n\t\t\t#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\t\t\t\tEASTL_EASTDC_API int Vsnprintf(wchar_t* EA_RESTRICT pDestination, size_t n, const wchar_t* EA_RESTRICT pFormat, va_list arguments);\n\t\t\t#endif\n\t\t}\n\t}\n\n\tnamespace eastl\n\t{\n\t\tinline int Vsnprintf(char* EA_RESTRICT pDestination, size_t n, const char* EA_RESTRICT pFormat, va_list arguments)\n\t\t\t{ return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments); }\n\n\t\tinline int Vsnprintf(char16_t* EA_RESTRICT pDestination, size_t n, const char16_t* EA_RESTRICT pFormat, va_list arguments)\n\t\t\t{ return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments); }\n\n\t\tinline int Vsnprintf(char32_t* EA_RESTRICT pDestination, size_t n, const char32_t* EA_RESTRICT pFormat, va_list arguments)\n\t\t\t{ return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments); }\n\n\t\t#if EA_CHAR8_UNIQUE\n\t\t\tinline int Vsnprintf(char8_t* EA_RESTRICT pDestination, size_t n, const char8_t* EA_RESTRICT pFormat, va_list arguments)\n\t\t\t\t{ return EA::StdC::Vsnprintf((char*)pDestination, n, (const char*)pFormat, arguments); }\n\t\t#endif\n\n\t\t#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\t\t\tinline int Vsnprintf(wchar_t* EA_RESTRICT pDestination, size_t n, const wchar_t* EA_RESTRICT pFormat, va_list arguments)\n\t\t\t{ return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments); }\n\t\t#endif\n\t}\n#else\n\t// User-provided functions.\n\textern int Vsnprintf8 (char*  pDestination, size_t n, const char*  pFormat, va_list arguments);\n\textern int Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments);\n\textern int Vsnprintf32(char32_t* pDestination, size_t n, const char32_t* pFormat, va_list arguments);\n\t#if EA_CHAR8_UNIQUE\n\t\textern int Vsnprintf8 (char8_t*  pDestination, size_t n, const char8_t*  pFormat, va_list arguments);\n\t#endif\n\t#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\t\textern int VsnprintfW(wchar_t* pDestination, size_t n, const wchar_t* pFormat, va_list arguments);\n\t#endif\n\n\tnamespace eastl\n\t{\n\t\tinline int Vsnprintf(char* pDestination, size_t n, const char* pFormat, va_list arguments)\n\t\t\t{ return Vsnprintf8(pDestination, n, pFormat, arguments); }\n\n\t\tinline int Vsnprintf(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments)\n\t\t\t{ return Vsnprintf16(pDestination, n, pFormat, arguments); }\n\n\t\tinline int Vsnprintf(char32_t* pDestination, size_t n, const char32_t* pFormat, va_list arguments)\n\t\t\t{ return Vsnprintf32(pDestination, n, pFormat, arguments); }\n\n\t\t#if EA_CHAR8_UNIQUE\n\t\t\tinline int Vsnprintf(char8_t* pDestination, size_t n, const char8_t* pFormat, va_list arguments)\n\t\t\t\t{ return Vsnprintf8(pDestination, n, pFormat, arguments); }\n\t\t#endif\n\n\t\t#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\t\t\tinline int Vsnprintf(wchar_t* pDestination, size_t n, const wchar_t* pFormat, va_list arguments)\n\t\t\t\t{ return VsnprintfW(pDestination, n, pFormat, arguments); }\n\t\t#endif\n\t}\n#endif\n///////////////////////////////////////////////////////////////////////////////\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_BASIC_STRING_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_BASIC_STRING_DEFAULT_NAME\n\t\t#define EASTL_BASIC_STRING_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" basic_string\" // Unless the user overrides something, this is \"EASTL basic_string\".\n\t#endif\n\n\n\t/// EASTL_BASIC_STRING_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_BASIC_STRING_DEFAULT_ALLOCATOR\n\t\t#define EASTL_BASIC_STRING_DEFAULT_ALLOCATOR allocator_type(EASTL_BASIC_STRING_DEFAULT_NAME)\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t/// basic_string\n\t///\n\t/// Implements a templated string class, somewhat like C++ std::basic_string.\n\t///\n\t/// Notes:\n\t///     As of this writing, an insert of a string into itself necessarily\n\t///     triggers a reallocation, even if there is enough capacity in self\n\t///     to handle the increase in size. This is due to the slightly tricky\n\t///     nature of the operation of modifying one's self with one's self,\n\t///     and thus the source and destination are being modified during the\n\t///     operation. It might be useful to rectify this to the extent possible.\n\t///\n\t///     Our usage of noexcept specifiers is a little different from the\n\t///     requirements specified by std::basic_string in C++11. This is because\n\t///     our allocators are instances and not types and thus can be non-equal\n\t///     and result in exceptions during assignments that theoretically can't\n\t///     occur with std containers.\n\t///\n\ttemplate <typename T, typename Allocator = EASTLAllocatorType>\n\tclass basic_string\n\t{\n\tpublic:\n\t\ttypedef basic_string<T, Allocator>                      this_type;\n\t\ttypedef basic_string_view<T>                            view_type;\n\t\ttypedef T                                               value_type;\n\t\ttypedef T*                                              pointer;\n\t\ttypedef const T*                                        const_pointer;\n\t\ttypedef T&                                              reference;\n\t\ttypedef const T&                                        const_reference;\n\t\ttypedef T*                                              iterator;           // Maintainer note: We want to leave iterator defined as T* -- at least in release builds -- as this gives some algorithms an advantage that optimizers cannot get around.\n\t\ttypedef const T*                                        const_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator>               reverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator>         const_reverse_iterator;\n\t\ttypedef eastl_size_t                                    size_type;          // See config.h for the definition of eastl_size_t, which defaults to size_t.\n\t\ttypedef ptrdiff_t                                       difference_type;\n\t\ttypedef Allocator                                       allocator_type;\n\n\tstatic const EA_CONSTEXPR size_type npos     = (size_type)-1;      /// 'npos' means non-valid position or simply non-position.\n\n\tpublic:\n\t\t// CtorDoNotInitialize exists so that we can create a constructor that allocates but doesn't\n\t\t// initialize and also doesn't collide with any other constructor declaration.\n\t\tstruct CtorDoNotInitialize{};\n\n\t\t// CtorSprintf exists so that we can create a constructor that accepts printf-style\n\t\t// arguments but also doesn't collide with any other constructor declaration.\n\t\t#ifdef EA_PLATFORM_MINGW\n\t\t\t// Workaround for MinGW compiler bug: variadic arguments are corrupted if empty object is passed before it\n\t\t\tstruct CtorSprintf{ int dummy; };\n\t\t#else\n\t\t\tstruct CtorSprintf{};\n\t\t#endif\n\n\t\t// CtorConvert exists so that we can have a constructor that implements string encoding\n\t\t// conversion, such as between UCS2 char16_t and UTF8 char8_t.\n\t\tstruct CtorConvert{};\n\n\tprotected:\n\t\t// Masks used to determine if we are in SSO or Heap\n\t\t#ifdef EA_SYSTEM_BIG_ENDIAN\n\t\t\t// Big Endian use LSB, unless we want to reorder struct layouts on endianness, Bit is set when we are in Heap\n\t\t\tstatic EA_CONSTEXPR_OR_CONST size_type kHeapMask = 0x1;\n\t\t\tstatic EA_CONSTEXPR_OR_CONST size_type kSSOMask  = 0x1;\n\t\t#else\n\t\t\t// Little Endian use MSB\n\t\t\tstatic EA_CONSTEXPR_OR_CONST size_type kHeapMask = ~(size_type(~size_type(0)) >> 1);\n\t\t\tstatic EA_CONSTEXPR_OR_CONST size_type kSSOMask  = 0x80;\n\t\t#endif\n\n\tpublic:\n\t\t#ifdef EA_SYSTEM_BIG_ENDIAN\n\t\t\tstatic EA_CONSTEXPR_OR_CONST size_type kMaxSize = (~kHeapMask) >> 1;\n\t\t#else\n\t\t\tstatic EA_CONSTEXPR_OR_CONST size_type kMaxSize = ~kHeapMask;\n\t\t#endif\n\n\tprotected:\n\t\t// The view of memory when the string data is obtained from the allocator.\n\t\tstruct HeapLayout\n\t\t{\n\t\t\tvalue_type* mpBegin;  // Begin of string.\n\t\t\tsize_type mnSize;     // Size of the string. Number of characters currently in the string, not including the trailing '0'\n\t\t\tsize_type mnCapacity; // Capacity of the string. Number of characters string can hold, not including the trailing '0'\n\t\t};\n\n\t\ttemplate <typename CharT, size_t = sizeof(CharT)>\n\t\tstruct SSOPadding\n\t\t{\n\t\t\tchar padding[sizeof(CharT) - sizeof(char)];\n\t\t};\n\n\t\ttemplate <typename CharT>\n\t\tstruct SSOPadding<CharT, 1>\n\t\t{\n\t\t\t// template specialization to remove the padding structure to avoid warnings on zero length arrays\n\t\t\t// also, this allows us to take advantage of the empty-base-class optimization.\n\t\t};\n\n\t\t// The view of memory when the string data is able to store the string data locally (without a heap allocation).\n\t\tstruct SSOLayout\n\t\t{\n\t\t\tstatic EA_CONSTEXPR_OR_CONST size_type SSO_CAPACITY = (sizeof(HeapLayout) - sizeof(char)) / sizeof(value_type);\n\n\t\t\t// mnSize must correspond to the last byte of HeapLayout.mnCapacity, so we don't want the compiler to insert\n\t\t\t// padding after mnSize if sizeof(value_type) != 1; Also ensures both layouts are the same size.\n\t\t\tstruct SSOSize : SSOPadding<value_type>\n\t\t\t{\n\t\t\t\tchar mnRemainingSize;\n\t\t\t};\n\n\t\t\tvalue_type mData[SSO_CAPACITY]; // Local buffer for string data.\n\t\t\tSSOSize mRemainingSizeField;\n\t\t};\n\n\t\t// This view of memory is a utility structure for easy copying of the string data.\n\t\tstruct RawLayout\n\t\t{\n\t\t\tchar mBuffer[sizeof(HeapLayout)];\n\t\t};\n\n\t\tstatic_assert(sizeof(SSOLayout)  == sizeof(HeapLayout), \"heap and sso layout structures must be the same size\");\n\t\tstatic_assert(sizeof(HeapLayout) == sizeof(RawLayout),  \"heap and raw layout structures must be the same size\");\n\n\t\t// This implements the 'short string optimization' or SSO. SSO reuses the existing storage of string class to\n\t\t// hold string data short enough to fit therefore avoiding a heap allocation. The number of characters stored in\n\t\t// the string SSO buffer is variable and depends on the string character width. This implementation favors a\n\t\t// consistent string size than increasing the size of the string local data to accommodate a consistent number\n\t\t// of characters despite character width.\n\t\tstruct Layout\n\t\t{\n\t\t\tunion\n\t\t\t{\n\t\t\t\tHeapLayout heap;\n\t\t\t\tSSOLayout sso;\n\t\t\t\tRawLayout raw;\n\t\t\t};\n\n\t\t\tLayout()                                                  { ResetToSSO(); } // start as SSO by default\n\t\t\tLayout(const Layout& other)                               { Copy(*this, other); }\n\t\t\tLayout(Layout&& other)                                    { Move(*this, other); }\n\t\t\tLayout& operator=(const Layout& other)                    { Copy(*this, other); return *this; }\n\t\t\tLayout& operator=(Layout&& other)                         { Move(*this, other); return *this; }\n\n\t\t\t// We are using Heap when the bit is set, easier to conceptualize checking IsHeap instead of IsSSO\n\t\t\tinline bool IsHeap() const EA_NOEXCEPT                    { return !!(sso.mRemainingSizeField.mnRemainingSize & kSSOMask); }\n\t\t\tinline bool IsSSO() const EA_NOEXCEPT                     { return !IsHeap(); }\n\t\t\tinline value_type* SSOBufferPtr() EA_NOEXCEPT             { return sso.mData; }\n\t\t\tinline const value_type* SSOBufferPtr() const EA_NOEXCEPT { return sso.mData; }\n\n\t\t\t// Largest value for SSO.mnSize == 23, which has two LSB bits set, but on big-endian (BE)\n\t\t\t// use least significant bit (LSB) to denote heap so shift.\n\t\t\tinline size_type GetSSOSize() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\t#ifdef EA_SYSTEM_BIG_ENDIAN\n\t\t\t\t\treturn SSOLayout::SSO_CAPACITY - (sso.mRemainingSizeField.mnRemainingSize >> 2);\n\t\t\t\t#else\n\t\t\t\t\treturn (SSOLayout::SSO_CAPACITY - sso.mRemainingSizeField.mnRemainingSize);\n\t\t\t\t#endif\n\t\t\t}\n\t\t\tinline size_type GetHeapSize() const EA_NOEXCEPT { return heap.mnSize; }\n\t\t\tinline size_type GetSize() const EA_NOEXCEPT     { return IsHeap() ? GetHeapSize() : GetSSOSize(); }\n\n\t\t\tinline void SetSSOSize(size_type size) EA_NOEXCEPT\n\t\t\t{\n\t\t\t\t#ifdef EA_SYSTEM_BIG_ENDIAN\n\t\t\t\t\tsso.mRemainingSizeField.mnRemainingSize = (char)((SSOLayout::SSO_CAPACITY - size) << 2);\n\t\t\t\t#else\n\t\t\t\t\tsso.mRemainingSizeField.mnRemainingSize = (char)(SSOLayout::SSO_CAPACITY - size);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tinline void SetHeapSize(size_type size) EA_NOEXCEPT          { heap.mnSize = size; }\n\t\t\tinline void SetSize(size_type size) EA_NOEXCEPT              { IsHeap() ? SetHeapSize(size) : SetSSOSize(size); }\n\n\t\t\tinline size_type GetRemainingCapacity() const EA_NOEXCEPT    { return size_type(CapacityPtr() - EndPtr()); }\n\n\t\t\tinline value_type* HeapBeginPtr() EA_NOEXCEPT                { return heap.mpBegin; };\n\t\t\tinline const value_type* HeapBeginPtr() const EA_NOEXCEPT    { return heap.mpBegin; };\n\n\t\t\tinline value_type* SSOBeginPtr() EA_NOEXCEPT                 { return sso.mData; }\n\t\t\tinline const value_type* SSOBeginPtr() const EA_NOEXCEPT     { return sso.mData; }\n\n\t\t\tinline value_type* BeginPtr() EA_NOEXCEPT                    { return IsHeap() ? HeapBeginPtr() : SSOBeginPtr(); }\n\t\t\tinline const value_type* BeginPtr() const EA_NOEXCEPT        { return IsHeap() ? HeapBeginPtr() : SSOBeginPtr(); }\n\n\t\t\tinline value_type* HeapEndPtr() EA_NOEXCEPT                  { return heap.mpBegin + heap.mnSize; }\n\t\t\tinline const value_type* HeapEndPtr() const EA_NOEXCEPT      { return heap.mpBegin + heap.mnSize; }\n\n\t\t\tinline value_type* SSOEndPtr() EA_NOEXCEPT                   { return sso.mData + GetSSOSize(); }\n\t\t\tinline const value_type* SSOEndPtr() const EA_NOEXCEPT       { return sso.mData + GetSSOSize(); }\n\n\t\t\t// Points to end of character stream, *ptr == '0'\n\t\t\tinline value_type* EndPtr() EA_NOEXCEPT                      { return IsHeap() ? HeapEndPtr() : SSOEndPtr(); }\n\t\t\tinline const value_type* EndPtr() const EA_NOEXCEPT          { return IsHeap() ? HeapEndPtr() : SSOEndPtr(); }\n\n\t\t\tinline value_type* HeapCapacityPtr() EA_NOEXCEPT             { return heap.mpBegin + GetHeapCapacity(); }\n\t\t\tinline const value_type* HeapCapacityPtr() const EA_NOEXCEPT { return heap.mpBegin + GetHeapCapacity(); }\n\n\t\t\tinline value_type* SSOCapacityPtr() EA_NOEXCEPT               { return sso.mData + SSOLayout::SSO_CAPACITY; }\n\t\t\tinline const value_type* SSOCapacityPtr() const EA_NOEXCEPT   { return sso.mData + SSOLayout::SSO_CAPACITY; }\n\n\t\t\t// Points to end of the buffer at the terminating '0', *ptr == '0' <- only true when size() == capacity()\n\t\t\tinline value_type* CapacityPtr() EA_NOEXCEPT                 { return IsHeap() ? HeapCapacityPtr() : SSOCapacityPtr(); }\n\t\t\tinline const value_type* CapacityPtr() const EA_NOEXCEPT     { return IsHeap() ? HeapCapacityPtr() : SSOCapacityPtr(); }\n\n\t\t\tinline void SetHeapBeginPtr(value_type* pBegin) EA_NOEXCEPT  { heap.mpBegin = pBegin; }\n\n\t\t\tinline void SetHeapCapacity(size_type cap) EA_NOEXCEPT\n\t\t\t{\n\t\t\t#ifdef EA_SYSTEM_BIG_ENDIAN\n\t\t\t\theap.mnCapacity = (cap << 1) | kHeapMask;\n\t\t\t#else\n\t\t\t\theap.mnCapacity = (cap | kHeapMask);\n\t\t\t#endif\n\t\t\t}\n\n\t\t\tinline size_type GetHeapCapacity() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t#ifdef EA_SYSTEM_BIG_ENDIAN\n\t\t\t\treturn (heap.mnCapacity >> 1);\n\t\t\t#else\n\t\t\t\treturn (heap.mnCapacity & ~kHeapMask);\n\t\t\t#endif\n\t\t\t}\n\n\t\t\tinline void Copy(Layout& dst, const Layout& src) EA_NOEXCEPT { dst.raw = src.raw; }\n\t\t\tinline void Move(Layout& dst, Layout& src) EA_NOEXCEPT       { eastl::swap(dst.raw, src.raw); }\n\t\t\tinline void Swap(Layout& a, Layout& b) EA_NOEXCEPT           { eastl::swap(a.raw, b.raw); }\n\n\t\t\tinline void ResetToSSO() EA_NOEXCEPT { *SSOBeginPtr() = 0; SetSSOSize(0); }\n\t\t};\n\n\t\teastl::compressed_pair<Layout, allocator_type> mPair;\n\n\t\tinline Layout& internalLayout() EA_NOEXCEPT                        { return mPair.first(); }\n\t\tinline const Layout& internalLayout() const EA_NOEXCEPT            { return mPair.first(); }\n\t\tinline allocator_type& internalAllocator() EA_NOEXCEPT             { return mPair.second(); }\n\t\tinline const allocator_type& internalAllocator() const EA_NOEXCEPT { return mPair.second(); }\n\n\tpublic:\n\t\t// Constructor, destructor\n\t\tbasic_string() EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(EASTL_BASIC_STRING_DEFAULT_ALLOCATOR));\n\t\texplicit basic_string(const allocator_type& allocator) EA_NOEXCEPT;\n\t\tbasic_string(const this_type& x, size_type position, size_type n = npos);\n\t\tbasic_string(const value_type* p, size_type n, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t\tEASTL_STRING_EXPLICIT basic_string(const value_type* p, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t\tbasic_string(size_type n, value_type c, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t\tbasic_string(const this_type& x);\n\t    basic_string(const this_type& x, const allocator_type& allocator);\n\t\tbasic_string(const value_type* pBegin, const value_type* pEnd, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t\tbasic_string(CtorDoNotInitialize, size_type n, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t\tbasic_string(CtorSprintf, const value_type* pFormat, ...);\n\t\tbasic_string(std::initializer_list<value_type> init, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\n\t\tbasic_string(this_type&& x) EA_NOEXCEPT;\n\t\tbasic_string(this_type&& x, const allocator_type& allocator);\n\n\t\texplicit basic_string(const view_type& sv, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t\tbasic_string(const view_type& sv, size_type position, size_type n, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename OtherCharType>\n\t\tbasic_string(CtorConvert, const OtherCharType* p, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename OtherCharType>\n\t\tbasic_string(CtorConvert, const OtherCharType* p, size_type n, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename OtherStringType> // Unfortunately we need the CtorConvert here because otherwise this function would collide with the value_type* constructor.\n\t\tbasic_string(CtorConvert, const OtherStringType& x);\n\n\t   ~basic_string();\n\n\t\t// Allocator\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT;\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT;\n\t\tvoid                  set_allocator(const allocator_type& allocator);\n\n\t\t// Implicit conversion operator\n\t\toperator basic_string_view<T>() const EA_NOEXCEPT;\n\n\t\t// Operator=\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(const value_type* p);\n\t\tthis_type& operator=(value_type c);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(view_type v);\n\t\tthis_type& operator=(this_type&& x); // TODO(c++17): noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value);\n\n\t\t#if EASTL_OPERATOR_EQUALS_OTHER_ENABLED\n\t\t\tthis_type& operator=(value_type* p) { return operator=((const value_type*)p); } // We need this because otherwise the const value_type* version can collide with the const OtherStringType& version below.\n\n\t\t\ttemplate <typename OtherCharType>\n\t\t\tthis_type& operator=(const OtherCharType* p);\n\n\t\t\ttemplate <typename OtherStringType>\n\t\t\tthis_type& operator=(const OtherStringType& x);\n\t\t#endif\n\n\t\tvoid swap(this_type& x); // TODO(c++17): noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value);\n\n\t\t// Assignment operations\n\t\tthis_type& assign(const this_type& x);\n\t\tthis_type& assign(const this_type& x, size_type position, size_type n = npos);\n\t\tthis_type& assign(const value_type* p, size_type n);\n\t\tthis_type& assign(const value_type* p);\n\t\tthis_type& assign(size_type n, value_type c);\n\t\tthis_type& assign(const value_type* pBegin, const value_type* pEnd);\n\t\tthis_type& assign(this_type&& x); // TODO(c++17): noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value);\n\t\tthis_type& assign(std::initializer_list<value_type>);\n\n\t\ttemplate <typename OtherCharType>\n\t\tthis_type& assign_convert(const OtherCharType* p);\n\n\t\ttemplate <typename OtherCharType>\n\t\tthis_type& assign_convert(const OtherCharType* p, size_type n);\n\n\t\ttemplate <typename OtherStringType>\n\t\tthis_type& assign_convert(const OtherStringType& x);\n\n\t\t// Iterators.\n\t\titerator       begin() EA_NOEXCEPT;                 // Expanded in source code as: mpBegin\n\t\tconst_iterator begin() const EA_NOEXCEPT;           // Expanded in source code as: mpBegin\n\t\tconst_iterator cbegin() const EA_NOEXCEPT;\n\n\t\titerator       end() EA_NOEXCEPT;                   // Expanded in source code as: mpEnd\n\t\tconst_iterator end() const EA_NOEXCEPT;             // Expanded in source code as: mpEnd\n\t\tconst_iterator cend() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rbegin() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crbegin() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rend() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rend() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crend() const EA_NOEXCEPT;\n\n\n\t\t// Size-related functionality\n\t\tbool      empty() const EA_NOEXCEPT;\n\t\tsize_type size() const EA_NOEXCEPT;\n\t\tsize_type length() const EA_NOEXCEPT;\n\t\tsize_type max_size() const EA_NOEXCEPT;\n\t\tsize_type capacity() const EA_NOEXCEPT;\n\t\tvoid      resize(size_type n, value_type c);\n\t\tvoid      resize(size_type n);\n\t\tvoid      reserve(size_type = 0);\n\t\tvoid      set_capacity(size_type n = npos); // Revises the capacity to the user-specified value. Resizes the container to match the capacity if the requested capacity n is less than the current size. If n == npos then the capacity is reallocated (if necessary) such that capacity == size.\n\t\tvoid      force_size(size_type n);          // Unilaterally moves the string end position (mpEnd) to the given location. Useful for when the user writes into the string via some extenal means such as C strcpy or sprintf. This allows for more efficient use than using resize to achieve this.\n\t\tvoid shrink_to_fit();\n\n\t\t// Raw access\n\t\tconst value_type* data() const  EA_NOEXCEPT;\n\t\t      value_type* data()        EA_NOEXCEPT;\n\t\tconst value_type* c_str() const EA_NOEXCEPT;\n\n\t\t// Element access\n\t\treference       operator[](size_type n);\n\t\tconst_reference operator[](size_type n) const;\n\t\treference       at(size_type n);\n\t\tconst_reference at(size_type n) const;\n\t\treference       front();\n\t\tconst_reference front() const;\n\t\treference       back();\n\t\tconst_reference back() const;\n\n\t\t// Append operations\n\t\tthis_type& operator+=(const this_type& x);\n\t\tthis_type& operator+=(const value_type* p);\n\t\tthis_type& operator+=(value_type c);\n\n\t\tthis_type& append(const this_type& x);\n\t\tthis_type& append(const this_type& x,  size_type position, size_type n = npos);\n\t\tthis_type& append(const value_type* p, size_type n);\n\t\tthis_type& append(const value_type* p);\n\t\tthis_type& append(size_type n, value_type c);\n\t\tthis_type& append(const value_type* pBegin, const value_type* pEnd);\n\n\t\tthis_type& append_sprintf_va_list(const value_type* pFormat, va_list arguments);\n\t\tthis_type& append_sprintf(const value_type* pFormat, ...);\n\n\t\ttemplate <typename OtherCharType>\n\t\tthis_type& append_convert(const OtherCharType* p);\n\n\t\ttemplate <typename OtherCharType>\n\t\tthis_type& append_convert(const OtherCharType* p, size_type n);\n\n\t\ttemplate <typename OtherStringType>\n\t\tthis_type& append_convert(const OtherStringType& x);\n\n\t\tvoid push_back(value_type c);\n\t\tvoid pop_back();\n\n\t\t// Insertion operations\n\t\tthis_type& insert(size_type position, const this_type& x);\n\t\tthis_type& insert(size_type position, const this_type& x, size_type beg, size_type n);\n\t\tthis_type& insert(size_type position, const value_type* p, size_type n);\n\t\tthis_type& insert(size_type position, const value_type* p);\n\t\tthis_type& insert(size_type position, size_type n, value_type c);\n\t\titerator   insert(const_iterator p, value_type c);\n\t\titerator   insert(const_iterator p, size_type n, value_type c);\n\t\titerator   insert(const_iterator p, const value_type* pBegin, const value_type* pEnd);\n\t\titerator   insert(const_iterator p, std::initializer_list<value_type>);\n\n\t\t// Erase operations\n\t\tthis_type&       erase(size_type position = 0, size_type n = npos);\n\t\titerator         erase(const_iterator p);\n\t\titerator         erase(const_iterator pBegin, const_iterator pEnd);\n\t\treverse_iterator erase(reverse_iterator position);\n\t\treverse_iterator erase(reverse_iterator first, reverse_iterator last);\n\t\tvoid             clear() EA_NOEXCEPT;\n\n\t\t// Detach memory\n\t\tpointer detach() EA_NOEXCEPT;\n\n\t\t// Replacement operations\n\t\tthis_type&  replace(size_type position, size_type n,  const this_type& x);\n\t\tthis_type&  replace(size_type pos1,     size_type n1, const this_type& x,  size_type pos2, size_type n2 = npos);\n\t\tthis_type&  replace(size_type position, size_type n1, const value_type* p, size_type n2);\n\t\tthis_type&  replace(size_type position, size_type n1, const value_type* p);\n\t\tthis_type&  replace(size_type position, size_type n1, size_type n2, value_type c);\n\t\tthis_type&  replace(const_iterator first, const_iterator last, const this_type& x);\n\t\tthis_type&  replace(const_iterator first, const_iterator last, const value_type* p, size_type n);\n\t\tthis_type&  replace(const_iterator first, const_iterator last, const value_type* p);\n\t\tthis_type&  replace(const_iterator first, const_iterator last, size_type n, value_type c);\n\t\tthis_type&  replace(const_iterator first, const_iterator last, const value_type* pBegin, const value_type* pEnd);\n\t\tsize_type   copy(value_type* p, size_type n, size_type position = 0) const;\n\n\t\t// Find operations\n\t\tsize_type find(const this_type& x,  size_type position = 0) const EA_NOEXCEPT;\n\t\tsize_type find(const value_type* p, size_type position = 0) const;\n\t\tsize_type find(const value_type* p, size_type position, size_type n) const;\n\t\tsize_type find(value_type c, size_type position = 0) const EA_NOEXCEPT;\n\n\t\t// Reverse find operations\n\t\tsize_type rfind(const this_type& x,  size_type position = npos) const EA_NOEXCEPT;\n\t\tsize_type rfind(const value_type* p, size_type position = npos) const;\n\t\tsize_type rfind(const value_type* p, size_type position, size_type n) const;\n\t\tsize_type rfind(value_type c, size_type position = npos) const EA_NOEXCEPT;\n\n\t\t// Find first-of operations\n\t\tsize_type find_first_of(const this_type& x, size_type position = 0) const EA_NOEXCEPT;\n\t\tsize_type find_first_of(const value_type* p, size_type position = 0) const;\n\t\tsize_type find_first_of(const value_type* p, size_type position, size_type n) const;\n\t\tsize_type find_first_of(value_type c, size_type position = 0) const EA_NOEXCEPT;\n\n\t\t// Find last-of operations\n\t\tsize_type find_last_of(const this_type& x, size_type position = npos) const EA_NOEXCEPT;\n\t\tsize_type find_last_of(const value_type* p, size_type position = npos) const;\n\t\tsize_type find_last_of(const value_type* p, size_type position, size_type n) const;\n\t\tsize_type find_last_of(value_type c, size_type position = npos) const EA_NOEXCEPT;\n\n\t\t// Find first not-of operations\n\t\tsize_type find_first_not_of(const this_type& x, size_type position = 0) const EA_NOEXCEPT;\n\t\tsize_type find_first_not_of(const value_type* p, size_type position = 0) const;\n\t\tsize_type find_first_not_of(const value_type* p, size_type position, size_type n) const;\n\t\tsize_type find_first_not_of(value_type c, size_type position = 0) const EA_NOEXCEPT;\n\n\t\t// Find last not-of operations\n\t\tsize_type find_last_not_of(const this_type& x,  size_type position = npos) const EA_NOEXCEPT;\n\t\tsize_type find_last_not_of(const value_type* p, size_type position = npos) const;\n\t\tsize_type find_last_not_of(const value_type* p, size_type position, size_type n) const;\n\t\tsize_type find_last_not_of(value_type c, size_type position = npos) const EA_NOEXCEPT;\n\n\t\t// Substring functionality\n\t\tthis_type substr(size_type position = 0, size_type n = npos) const;\n\n\t\t// Comparison operations\n\t\tint        compare(const this_type& x) const EA_NOEXCEPT;\n\t\tint        compare(size_type pos1, size_type n1, const this_type& x) const;\n\t\tint        compare(size_type pos1, size_type n1, const this_type& x, size_type pos2, size_type n2) const;\n\t\tint        compare(const value_type* p) const;\n\t\tint        compare(size_type pos1, size_type n1, const value_type* p) const;\n\t\tint        compare(size_type pos1, size_type n1, const value_type* p, size_type n2) const;\n\t\tstatic int compare(const value_type* pBegin1, const value_type* pEnd1, const value_type* pBegin2, const value_type* pEnd2);\n\n\t\t// Case-insensitive comparison functions. Not part of C++ this_type. Only ASCII-level locale functionality is supported. Thus this is not suitable for localization purposes.\n\t\tint        comparei(const this_type& x) const EA_NOEXCEPT;\n\t\tint        comparei(const value_type* p) const;\n\t\tstatic int comparei(const value_type* pBegin1, const value_type* pEnd1, const value_type* pBegin2, const value_type* pEnd2);\n\n\t\t// Misc functionality, not part of C++ this_type.\n\t\tvoid         make_lower();\n\t\tvoid         make_upper();\n\t\tvoid         ltrim();\n\t\tvoid         rtrim();\n\t\tvoid         trim();\n\t\tvoid         ltrim(const value_type* p);\n\t\tvoid         rtrim(const value_type* p);\n\t\tvoid         trim(const value_type* p);\n\t\tthis_type    left(size_type n) const;\n\t\tthis_type    right(size_type n) const;\n\t\tthis_type&   sprintf_va_list(const value_type* pFormat, va_list arguments);\n\t\tthis_type&   sprintf(const value_type* pFormat, ...);\n\n\t\tbool validate() const EA_NOEXCEPT;\n\t\tint  validate_iterator(const_iterator i) const EA_NOEXCEPT;\n\n\n\tprotected:\n\t\t// Helper functions for initialization/insertion operations.\n\t\tvalue_type* DoAllocate(size_type n);\n\t\tvoid        DoFree(value_type* p, size_type n);\n\t\tsize_type   GetNewCapacity(size_type currentCapacity);\n\t\tsize_type   GetNewCapacity(size_type currentCapacity, size_type minimumGrowSize);\n\t\tvoid        AllocateSelf();\n\t\tvoid        AllocateSelf(size_type n);\n\t\tvoid        DeallocateSelf();\n\t\titerator    InsertInternal(const_iterator p, value_type c);\n\t\tvoid        RangeInitialize(const value_type* pBegin, const value_type* pEnd);\n\t\tvoid        RangeInitialize(const value_type* pBegin);\n\t\tvoid        SizeInitialize(size_type n, value_type c);\n\n\t\tbool        IsSSO() const EA_NOEXCEPT;\n\n\t\tvoid        ThrowLengthException() const;\n\t\tvoid        ThrowRangeException() const;\n\t\tvoid        ThrowInvalidArgumentException() const;\n\n\t\t#if EASTL_OPERATOR_EQUALS_OTHER_ENABLED\n\t\t\ttemplate <typename CharType>\n\t\t\tvoid DoAssignConvert(CharType c, true_type);\n\n\t\t\ttemplate <typename StringType>\n\t\t\tvoid DoAssignConvert(const StringType& x, false_type);\n\t\t#endif\n\t}; // basic_string\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// basic_string\n\t///////////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string() EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(EASTL_BASIC_STRING_DEFAULT_ALLOCATOR))\n\t    : mPair(allocator_type(EASTL_BASIC_STRING_DEFAULT_NAME))\n\t{\n\t\tAllocateSelf();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(const allocator_type& allocator) EA_NOEXCEPT\n\t    : mPair(allocator)\n\t{\n\t\tAllocateSelf();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(const this_type& x)\n\t    : mPair(x.get_allocator())\n\t{\n\t\tRangeInitialize(x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>::basic_string(const this_type& x, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tRangeInitialize(x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherStringType>\n\tinline basic_string<T, Allocator>::basic_string(CtorConvert, const OtherStringType& x)\n\t    : mPair(x.get_allocator())\n\t{\n\t\tAllocateSelf();\n\t\tappend_convert(x.c_str(), x.length());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>::basic_string(const this_type& x, size_type position, size_type n)\n\t\t: mPair(x.get_allocator())\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif (EASTL_UNLIKELY(position > x.internalLayout().GetSize())) // 21.4.2 p4\n\t\t\t{\n\t\t\t\tThrowRangeException();\n\t\t\t\tAllocateSelf();\n\t\t\t}\n\t\t\telse\n\t\t\t\tRangeInitialize(\n\t\t\t\t\tx.internalLayout().BeginPtr() + position,\n\t\t\t\t\tx.internalLayout().BeginPtr() + position + eastl::min_alt(n, x.internalLayout().GetSize() - position));\n        #else\n\t\t\tRangeInitialize(\n\t\t\t\tx.internalLayout().BeginPtr() + position,\n\t\t\t\tx.internalLayout().BeginPtr() + position + eastl::min_alt(n, x.internalLayout().GetSize() - position));\n        #endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(const value_type* p, size_type n, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tRangeInitialize(p, p + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(const view_type& sv, const allocator_type& allocator)\n\t    : basic_string(sv.data(), static_cast<size_type>(sv.size()), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(const view_type& sv, size_type position, size_type n, const allocator_type& allocator)\n\t    : basic_string(sv.substr(position, n), allocator)\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherCharType>\n\tinline basic_string<T, Allocator>::basic_string(CtorConvert, const OtherCharType* p, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tAllocateSelf();    // In this case we are converting from one string encoding to another, and we\n\t\tappend_convert(p); // implement this in the simplest way, by simply default-constructing and calling assign.\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherCharType>\n\tinline basic_string<T, Allocator>::basic_string(CtorConvert, const OtherCharType* p, size_type n, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tAllocateSelf();         // In this case we are converting from one string encoding to another, and we\n\t\tappend_convert(p, n);   // implement this in the simplest way, by simply default-constructing and calling assign.\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(const value_type* p, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tRangeInitialize(p);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(size_type n, value_type c, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tSizeInitialize(n, c);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::basic_string(const value_type* pBegin, const value_type* pEnd, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tRangeInitialize(pBegin, pEnd);\n\t}\n\n\n\t// CtorDoNotInitialize exists so that we can create a version that allocates but doesn't\n\t// initialize but also doesn't collide with any other constructor declaration.\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>::basic_string(CtorDoNotInitialize /*unused*/, size_type n, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\t// Note that we do not call SizeInitialize here.\n\t\tAllocateSelf(n);\n\t\tinternalLayout().SetSize(0);\n\t\t*internalLayout().EndPtr() = 0;\n\t}\n\n\n\t// CtorSprintf exists so that we can create a version that does a variable argument\n\t// sprintf but also doesn't collide with any other constructor declaration.\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>::basic_string(CtorSprintf /*unused*/, const value_type* pFormat, ...)\n\t\t: mPair()\n\t{\n\t\tconst size_type n = (size_type)CharStrlen(pFormat);\n\t\tAllocateSelf(n);\n\t\tinternalLayout().SetSize(0);\n\n\t\tva_list arguments;\n\t\tva_start(arguments, pFormat);\n\t\tappend_sprintf_va_list(pFormat, arguments);\n\t\tva_end(arguments);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>::basic_string(std::initializer_list<value_type> init, const allocator_type& allocator)\n\t\t: mPair(allocator)\n\t{\n\t\tRangeInitialize(init.begin(), init.end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>::basic_string(this_type&& x) EA_NOEXCEPT\n\t\t: mPair(x.get_allocator())\n\t{\n\t\tinternalLayout() = eastl::move(x.internalLayout());\n\t\tx.AllocateSelf();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>::basic_string(this_type&& x, const allocator_type& allocator)\n\t: mPair(allocator)\n\t{\n\t\tif(get_allocator() == x.get_allocator()) // If we can borrow from x...\n\t\t{\n\t\t\tinternalLayout() = eastl::move(x.internalLayout());\n\t\t\tx.AllocateSelf();\n\t\t}\n\t\telse if(x.internalLayout().BeginPtr())\n\t\t{\n\t\t\tRangeInitialize(x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t\t\t// Let x destruct its own items.\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>::~basic_string()\n\t{\n\t\tDeallocateSelf();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline const typename basic_string<T, Allocator>::allocator_type&\n\tbasic_string<T, Allocator>::get_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::allocator_type&\n\tbasic_string<T, Allocator>::get_allocator() EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::set_allocator(const allocator_type& allocator)\n\t{\n\t\tif(internalLayout().IsHeap() && get_allocator() != allocator)\n\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"basic_string::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\tget_allocator() = allocator;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline const typename basic_string<T, Allocator>::value_type*\n\tbasic_string<T, Allocator>::data()  const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().BeginPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline const typename basic_string<T, Allocator>::value_type*\n\tbasic_string<T, Allocator>::c_str() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().BeginPtr();\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::value_type*\n\tbasic_string<T, Allocator>::data() EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().BeginPtr();\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::begin() EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().BeginPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::end() EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().EndPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_iterator\n\tbasic_string<T, Allocator>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().BeginPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_iterator\n\tbasic_string<T, Allocator>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().BeginPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_iterator\n\tbasic_string<T, Allocator>::end() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().EndPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_iterator\n\tbasic_string<T, Allocator>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().EndPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::reverse_iterator\n\tbasic_string<T, Allocator>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::reverse_iterator\n\tbasic_string<T, Allocator>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(internalLayout().BeginPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reverse_iterator\n\tbasic_string<T, Allocator>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reverse_iterator\n\tbasic_string<T, Allocator>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reverse_iterator\n\tbasic_string<T, Allocator>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(internalLayout().BeginPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reverse_iterator\n\tbasic_string<T, Allocator>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(internalLayout().BeginPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool basic_string<T, Allocator>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn (internalLayout().GetSize() == 0);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool basic_string<T, Allocator>::IsSSO() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().IsSSO();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::size() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().GetSize();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::length() const EA_NOEXCEPT\n\t{\n\t\treturn internalLayout().GetSize();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::max_size() const EA_NOEXCEPT\n\t{\n\t\treturn kMaxSize;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::capacity() const EA_NOEXCEPT\n\t{\n\t\tif (internalLayout().IsHeap())\n\t\t{\n\t\t\treturn internalLayout().GetHeapCapacity();\n\t\t}\n\t\treturn SSOLayout::SSO_CAPACITY;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reference\n\tbasic_string<T, Allocator>::operator[](size_type n) const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED // We allow the user to reference the trailing 0 char without asserting. Perhaps we shouldn't.\n\t\t\tif(EASTL_UNLIKELY(n > internalLayout().GetSize()))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn internalLayout().BeginPtr()[n]; // Sometimes done as *(mpBegin + n)\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::reference\n\tbasic_string<T, Allocator>::operator[](size_type n)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED // We allow the user to reference the trailing 0 char without asserting. Perhaps we shouldn't.\n\t\t\tif(EASTL_UNLIKELY(n > internalLayout().GetSize()))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn internalLayout().BeginPtr()[n]; // Sometimes done as *(mpBegin + n)\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T,Allocator>::operator basic_string_view<T>() const EA_NOEXCEPT\n\t{\n\t\treturn basic_string_view<T>(data(), size());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(const this_type& x)\n\t{\n\t\tif(&x != this)\n\t\t{\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tbool bSlowerPathwayRequired = (get_allocator() != x.get_allocator());\n\t\t\t#else\n\t\t\t\tbool bSlowerPathwayRequired = false;\n\t\t\t#endif\n\n\t\t\tif(bSlowerPathwayRequired)\n\t\t\t{\n\t\t\t\tset_capacity(0); // Must use set_capacity instead of clear because set_capacity frees our memory, unlike clear.\n\n\t\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\t\tget_allocator() = x.get_allocator();\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tassign(x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\t#if EASTL_OPERATOR_EQUALS_OTHER_ENABLED\n\t\ttemplate <typename T, typename Allocator>\n\t\ttemplate <typename CharType>\n\t\tinline void basic_string<T, Allocator>::DoAssignConvert(CharType c, true_type)\n\t\t{\n\t\t\tassign_convert(&c, 1); // Call this version of append because it will result in the encoding-converting append being used.\n\t\t}\n\n\n\t\ttemplate <typename T, typename Allocator>\n\t\ttemplate <typename StringType>\n\t\tinline void basic_string<T, Allocator>::DoAssignConvert(const StringType& x, false_type)\n\t\t{\n\t\t\t//if(&x != this) // Unnecessary because &x cannot possibly equal this.\n\t\t\t{\n\t\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\t\tget_allocator() = x.get_allocator();\n\t\t\t\t#endif\n\n\t\t\t\tassign_convert(x.c_str(), x.length());\n\t\t\t}\n\t\t}\n\n\n\t\ttemplate <typename T, typename Allocator>\n\t\ttemplate <typename OtherStringType>\n\t\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(const OtherStringType& x)\n\t\t{\n\t\t\tclear();\n\t\t\tDoAssignConvert(x, is_integral<OtherStringType>());\n\t\t\treturn *this;\n\t\t}\n\n\n\t\ttemplate <typename T, typename Allocator>\n\t\ttemplate <typename OtherCharType>\n\t\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(const OtherCharType* p)\n\t\t{\n\t\t\treturn assign_convert(p);\n\t\t}\n\t#endif\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(const value_type* p)\n\t{\n\t\treturn assign(p, p + CharStrlen(p));\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(value_type c)\n\t{\n\t\treturn assign((size_type)1, c);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(this_type&& x)\n\t{\n\t\treturn assign(eastl::move(x));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\treturn assign(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::this_type& basic_string<T, Allocator>::operator=(view_type v)\n\t{\n\t\treturn assign(v.data(), static_cast<this_type::size_type>(v.size()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid basic_string<T, Allocator>::resize(size_type n, value_type c)\n\t{\n\t\tconst size_type s = internalLayout().GetSize();\n\n\t\tif(n < s)\n\t\t\terase(internalLayout().BeginPtr() + n, internalLayout().EndPtr());\n\t\telse if(n > s)\n\t\t\tappend(n - s, c);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid basic_string<T, Allocator>::resize(size_type n)\n\t{\n\t\t// C++ basic_string specifies that resize(n) is equivalent to resize(n, value_type()).\n\t\t// For built-in types, value_type() is the same as zero (value_type(0)).\n\t\t// We can improve the efficiency (especially for long strings) of this\n\t\t// string class by resizing without assigning to anything.\n\n\t\tconst size_type s = internalLayout().GetSize();\n\n\t\tif(n < s)\n\t\t\terase(internalLayout().BeginPtr() + n, internalLayout().EndPtr());\n\t\telse if(n > s)\n\t\t{\n\t\t\tappend(n - s, value_type());\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid basic_string<T, Allocator>::reserve(size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY(n > max_size()))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\t// C++20 says if the passed in capacity is less than the current capacity we do not shrink\n\t\t// If new_cap is less than or equal to the current capacity(), there is no effect.\n\t\t// http://en.cppreference.com/w/cpp/string/basic_string/reserve\n\n\t\tn = eastl::max_alt(n, internalLayout().GetSize()); // Calculate the new capacity, which needs to be >= container size.\n\n\t\tif(n > capacity())\n\t\t\tset_capacity(n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::shrink_to_fit()\n\t{\n\t\tset_capacity(internalLayout().GetSize());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::set_capacity(size_type n)\n\t{\n\t\tif(n == npos)\n\t\t\t// If the user wants to set the capacity to equal the current size...\n\t\t\t// '-1' because we pretend that we didn't allocate memory for the terminating 0.\n\t\t\tn = internalLayout().GetSize();\n\t\telse if(n < internalLayout().GetSize())\n\t\t{\n\t\t\tinternalLayout().SetSize(n);\n\t\t\t*internalLayout().EndPtr() = 0;\n\t\t}\n\n\t\tif((n < capacity() && internalLayout().IsHeap()) || (n > capacity()))\n\t\t{\n\t\t\t// In here the string is transition from heap->heap, heap->sso or sso->heap\n\n\t\t\tif(EASTL_LIKELY(n))\n\t\t\t{\n\n\t\t\t\tif(n <= SSOLayout::SSO_CAPACITY)\n\t\t\t\t{\n\t\t\t\t\t// heap->sso\n\t\t\t\t\t// A heap based layout wants to reduce its size to within sso capacity\n\t\t\t\t\t// An sso layout wanting to reduce its capacity will not get in here\n\t\t\t\t\tpointer pOldBegin = internalLayout().BeginPtr();\n\t\t\t\t\tconst size_type nOldCap = internalLayout().GetHeapCapacity();\n\n\t\t\t\t\tCharStringUninitializedCopy(pOldBegin, pOldBegin + n, internalLayout().SSOBeginPtr());\n\t\t\t\t\tinternalLayout().SetSSOSize(n);\n\t\t\t\t\t*internalLayout().SSOEndPtr() = 0;\n\n\t\t\t\t\tDoFree(pOldBegin, nOldCap + 1);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tpointer pNewBegin = DoAllocate(n + 1); // We need the + 1 to accomodate the trailing 0.\n\t\t\t\tsize_type nSavedSize = internalLayout().GetSize(); // save the size in case we transition from sso->heap\n\n\t\t\t\tpointer pNewEnd = CharStringUninitializedCopy(internalLayout().BeginPtr(), internalLayout().EndPtr(), pNewBegin);\n\t\t\t\t*pNewEnd = 0;\n\n\t\t\t\tDeallocateSelf();\n\n\t\t\t\tinternalLayout().SetHeapBeginPtr(pNewBegin);\n\t\t\t\tinternalLayout().SetHeapCapacity(n);\n\t\t\t\tinternalLayout().SetHeapSize(nSavedSize);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tDeallocateSelf();\n\t\t\t\tAllocateSelf();\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::force_size(size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(n > capacity()))\n\t\t\t\tThrowRangeException();\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n > capacity()))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::force_size -- out of range\");\n\t\t#endif\n\n\t\tinternalLayout().SetSize(n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::clear() EA_NOEXCEPT\n\t{\n\t\tinternalLayout().SetSize(0);\n\t\t*internalLayout().BeginPtr() = value_type(0);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::pointer\n\tbasic_string<T, Allocator>::detach() EA_NOEXCEPT\n\t{\n\t\t// The detach function is an extension function which simply forgets the\n\t\t// owned pointer. It doesn't free it but rather assumes that the user\n\t\t// does. If the string is utilizing the short-string-optimization when a\n\t\t// detach is requested, a copy of the string into a seperate memory\n\t\t// allocation occurs and the owning pointer is given to the user who is\n\t\t// responsible for freeing the memory.\n\n\t\tpointer pDetached = nullptr;\n\n\t\tif (internalLayout().IsSSO())\n\t\t{\n\t\t\tconst size_type n = internalLayout().GetSize() + 1; // +1' so that we have room for the terminating 0.\n\t\t\tpDetached = DoAllocate(n);\n\t\t\tpointer pNewEnd = CharStringUninitializedCopy(internalLayout().BeginPtr(), internalLayout().EndPtr(), pDetached);\n\t\t\t*pNewEnd = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpDetached = internalLayout().BeginPtr();\n\t\t}\n\n\t\tAllocateSelf(); // reset to string to empty\n\t\treturn pDetached;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reference\n\tbasic_string<T, Allocator>::at(size_type n) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(n >= internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#elif EASTL_ASSERT_ENABLED                  // We assert if the user references the trailing 0 char.\n\t\t\tif(EASTL_UNLIKELY(n >= internalLayout().GetSize()))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::at -- out of range\");\n\t\t#endif\n\n\t\treturn internalLayout().BeginPtr()[n];\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::reference\n\tbasic_string<T, Allocator>::at(size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(n >= internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#elif EASTL_ASSERT_ENABLED                  // We assert if the user references the trailing 0 char.\n\t\t\tif(EASTL_UNLIKELY(n >= internalLayout().GetSize()))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::at -- out of range\");\n\t\t#endif\n\n\t\treturn internalLayout().BeginPtr()[n];\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::reference\n\tbasic_string<T, Allocator>::front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(internalLayout().GetSize() == 0)) // We assert if the user references the trailing 0 char.\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::front -- empty string\");\n\t\t#else\n\t\t\t// We allow the user to reference the trailing 0 char without asserting.\n\t\t#endif\n\n\t\treturn *internalLayout().BeginPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reference\n\tbasic_string<T, Allocator>::front() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(internalLayout().GetSize() == 0)) // We assert if the user references the trailing 0 char.\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::front -- empty string\");\n\t\t#else\n\t\t\t// We allow the user to reference the trailing 0 char without asserting.\n\t\t#endif\n\n\t\treturn *internalLayout().BeginPtr();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::reference\n\tbasic_string<T, Allocator>::back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(internalLayout().GetSize() == 0)) // We assert if the user references the trailing 0 char.\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::back -- empty string\");\n\t\t#else\n\t\t\t// We allow the user to reference the trailing 0 char without asserting.\n\t\t#endif\n\n\t\treturn *(internalLayout().EndPtr() - 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::const_reference\n\tbasic_string<T, Allocator>::back() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(internalLayout().GetSize() == 0)) // We assert if the user references the trailing 0 char.\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::back -- empty string\");\n\t\t#else\n\t\t\t// We allow the user to reference the trailing 0 char without asserting.\n\t\t#endif\n\n\t\treturn *(internalLayout().EndPtr() - 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::operator+=(const this_type& x)\n\t{\n\t\treturn append(x);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::operator+=(const value_type* p)\n\t{\n\t\treturn append(p);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::operator+=(value_type c)\n\t{\n\t\tpush_back(c);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::append(const this_type& x)\n\t{\n\t\treturn append(x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::append(const this_type& x, size_type position, size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position >= x.internalLayout().GetSize())) // position must be < x.mpEnd, but position + n may be > mpEnd.\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\t    return append(x.internalLayout().BeginPtr() + position,\n\t\t\t\t          x.internalLayout().BeginPtr() + position + eastl::min_alt(n, x.internalLayout().GetSize() - position));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::append(const value_type* p, size_type n)\n\t{\n\t\treturn append(p, p + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::append(const value_type* p)\n\t{\n\t\treturn append(p, p + CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherCharType>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::append_convert(const OtherCharType* pOther)\n\t{\n\t\treturn append_convert(pOther, (size_type)CharStrlen(pOther));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherStringType>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::append_convert(const OtherStringType& x)\n\t{\n\t\treturn append_convert(x.c_str(), x.length());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherCharType>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::append_convert(const OtherCharType* pOther, size_type n)\n\t{\n\t\t// Question: What do we do in the case that we have an illegally encoded source string?\n\t\t// This can happen with UTF8 strings. Do we throw an exception or do we ignore the input?\n\t\t// One argument is that it's not a string class' job to handle the security aspects of a\n\t\t// program and the higher level application code should be verifying UTF8 string validity,\n\t\t// and thus we should do the friendly thing and ignore the invalid characters as opposed\n\t\t// to making the user of this function handle exceptions that are easily forgotten.\n\n\t\tconst size_t         kBufferSize = 512;\n\t\tvalue_type           selfBuffer[kBufferSize];   // This assumes that value_type is one of char8_t, char16_t, char32_t, or wchar_t. Or more importantly, a type with a trivial constructor and destructor.\n\t\tvalue_type* const    selfBufferEnd = selfBuffer + kBufferSize;\n\t\tconst OtherCharType* pOtherEnd = pOther + n;\n\n\t\twhile(pOther != pOtherEnd)\n\t\t{\n\t\t\tvalue_type* pSelfBufferCurrent = selfBuffer;\n\t\t\tDecodePart(pOther, pOtherEnd, pSelfBufferCurrent, selfBufferEnd);   // Write pOther to pSelfBuffer, converting encoding as we go. We currently ignore the return value, as we don't yet have a plan for handling encoding errors.\n\t\t\tappend(selfBuffer, pSelfBufferCurrent);\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::append(size_type n, value_type c)\n\t{\n\t\tif (n > 0)\n\t\t{\n\t\t\tconst size_type nSize = internalLayout().GetSize();\n\t\t\tconst size_type nCapacity = capacity();\n\n\t\t\tif((nSize + n) > nCapacity)\n\t\t\t\treserve(GetNewCapacity(nCapacity, (nSize + n) - nCapacity));\n\n\t\t\tpointer pNewEnd = CharStringUninitializedFillN(internalLayout().EndPtr(), n, c);\n\t\t\t*pNewEnd = 0;\n\t\t\tinternalLayout().SetSize(nSize + n);\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::append(const value_type* pBegin, const value_type* pEnd)\n\t{\n\t\tif(pBegin != pEnd)\n\t\t{\n\t\t\tconst size_type nOldSize  = internalLayout().GetSize();\n\t\t\tconst size_type n         = (size_type)(pEnd - pBegin);\n\t\t\tconst size_type nCapacity = capacity();\n\t\t\tconst size_type nNewSize = nOldSize + n;\n\n\t\t\tif(nNewSize > nCapacity)\n\t\t\t{\n\t\t\t\tconst size_type nLength = GetNewCapacity(nCapacity, nNewSize - nCapacity);\n\n\t\t\t\tpointer pNewBegin = DoAllocate(nLength + 1);\n\n\t\t\t\tpointer pNewEnd = CharStringUninitializedCopy(internalLayout().BeginPtr(), internalLayout().EndPtr(), pNewBegin);\n\t\t\t\tpNewEnd         = CharStringUninitializedCopy(pBegin,  pEnd,  pNewEnd);\n\t\t\t   *pNewEnd         = 0;\n\n\t\t\t\tDeallocateSelf();\n\t\t\t\tinternalLayout().SetHeapBeginPtr(pNewBegin);\n\t\t\t\tinternalLayout().SetHeapCapacity(nLength);\n\t\t\t\tinternalLayout().SetHeapSize(nNewSize);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpointer pNewEnd = CharStringUninitializedCopy(pBegin, pEnd, internalLayout().EndPtr());\n\t\t\t\t*pNewEnd = 0;\n\t\t\t\tinternalLayout().SetSize(nNewSize);\n\t\t\t}\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::append_sprintf_va_list(const value_type* pFormat, va_list arguments)\n\t{\n\t\t// From unofficial C89 extension documentation:\n\t\t// The vsnprintf returns the number of characters written into the array,\n\t\t// not counting the terminating null character, or a negative value\n\t\t// if count or more characters are requested to be generated.\n\t\t// An error can occur while converting a value for output.\n\n\t\t// From the C99 standard:\n\t\t// The vsnprintf function returns the number of characters that would have\n\t\t// been written had n been sufficiently large, not counting the terminating\n\t\t// null character, or a negative value if an encoding error occurred.\n\t\t// Thus, the null-terminated output has been completely written if and only\n\t\t// if the returned value is nonnegative and less than n.\n\n\t\t// https://www.freebsd.org/cgi/man.cgi?query=vswprintf&sektion=3&manpath=freebsd-release-ports\n\t\t// https://www.freebsd.org/cgi/man.cgi?query=snprintf&manpath=SuSE+Linux/i386+11.3\n\t\t// Well its time to go on an adventure...\n\t\t// C99 vsnprintf states that a buffer size of zero returns the number of characters that would\n\t\t// be written to the buffer irrelevant of whether the buffer is a nullptr\n\t\t// But C99 vswprintf for wchar_t changes the behaviour of the return to instead say that it\n\t\t// \"will fail if n or more wide characters were requested to be written\", so\n\t\t// calling vswprintf with a buffer size of zero always returns -1\n\t\t// unless... you are MSVC where they deviate from the std and say if the buffer is NULL\n\t\t// and the size is zero it will return the number of characters written or if we are using\n\t\t// EAStdC which also does the sane behaviour.\n\n#if !EASTL_OPENSOURCE || defined(EA_PLATFORM_MICROSOFT)\n\t\tsize_type nInitialSize = internalLayout().GetSize();\n\t\tint nReturnValue;\n\n\t\t#if EASTL_VA_COPY_ENABLED\n\t\t\tva_list argumentsSaved;\n\t\t\tva_copy(argumentsSaved, arguments);\n\t\t#endif\n\n\t\tnReturnValue = eastl::Vsnprintf(nullptr, 0, pFormat, arguments);\n\n\t\tif (nReturnValue > 0)\n\t\t{\n\t\t\tresize(nReturnValue + nInitialSize);\n\n\t\t#if EASTL_VA_COPY_ENABLED\n\t\t\tva_end(arguments);\n\t\t\tva_copy(arguments, argumentsSaved);\n\t\t#endif\n\n\t\t\tnReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, static_cast<size_t>(nReturnValue) + 1, pFormat, arguments);\n\t\t}\n\n\t\tif (nReturnValue >= 0)\n\t\t{\n\t\t\tinternalLayout().SetSize(nInitialSize + nReturnValue);\n\t\t}\n\n\t\t#if EASTL_VA_COPY_ENABLED\n\t\t\t// va_end for arguments will be called by the caller.\n\t\t\tva_end(argumentsSaved);\n\t\t#endif\n\n#else\n\t\tsize_type nInitialSize = internalLayout().GetSize();\n\t\tsize_type nInitialRemainingCapacity = internalLayout().GetRemainingCapacity();\n\t\tint       nReturnValue;\n\n\t\t#if EASTL_VA_COPY_ENABLED\n\t\t\tva_list argumentsSaved;\n\t\t\tva_copy(argumentsSaved, arguments);\n\t\t#endif\n\n\t\tnReturnValue = eastl::Vsnprintf(internalLayout().EndPtr(), (size_t)nInitialRemainingCapacity + 1,\n\t\t\t\t\t\t\t\t\t\tpFormat, arguments);\n\n\t\tif(nReturnValue >= (int)(nInitialRemainingCapacity + 1))  // If there wasn't enough capacity...\n\t\t{\n\t\t\t// In this case we definitely have C99 Vsnprintf behaviour.\n\t\t#if EASTL_VA_COPY_ENABLED\n\t\t\tva_end(arguments);\n\t\t\tva_copy(arguments, argumentsSaved);\n\t\t#endif\n\t\t\tresize(nInitialSize + nReturnValue);\n\t\t\tnReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, (size_t)(nReturnValue + 1),\n\t\t\t\t\t\t\t\t\t\t\tpFormat, arguments);\n\t\t}\n\t\telse if(nReturnValue < 0) // If vsnprintf is non-C99-standard\n\t\t{\n\t\t\t// In this case we either have C89 extension behaviour or C99 behaviour.\n\t\t\tsize_type n = eastl::max_alt((size_type)(SSOLayout::SSO_CAPACITY - 1), (size_type)(nInitialSize * 2));\n\n\t\t\tfor(; (nReturnValue < 0) && (n < 1000000); n *= 2)\n\t\t\t{\n\t\t\t#if EASTL_VA_COPY_ENABLED\n\t\t\t\tva_end(arguments);\n\t\t\t\tva_copy(arguments, argumentsSaved);\n\t\t\t#endif\n\t\t\t\tresize(n);\n\n\t\t\t\tconst size_t nCapacity = (size_t)(n - nInitialSize);\n\t\t\t\tnReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, nCapacity + 1, pFormat, arguments);\n\n\t\t\t\tif(nReturnValue == (int)(unsigned)nCapacity)\n\t\t\t\t{\n\t\t\t\t\tresize(++n);\n\t\t\t\t\tnReturnValue = eastl::Vsnprintf(internalLayout().BeginPtr() + nInitialSize, nCapacity + 2, pFormat, arguments);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(nReturnValue >= 0)\n\t\t{\n\t\t\tinternalLayout().SetSize(nInitialSize + nReturnValue);\n\t\t}\n\n\t\t#if EASTL_VA_COPY_ENABLED\n\t\t\t// va_end for arguments will be called by the caller.\n\t\t\tva_end(argumentsSaved);\n\t\t#endif\n\n#endif // EASTL_OPENSOURCE\n\n\t\treturn *this;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::append_sprintf(const value_type* pFormat, ...)\n\t{\n\t\tva_list arguments;\n\t\tva_start(arguments, pFormat);\n\t\tappend_sprintf_va_list(pFormat, arguments);\n\t\tva_end(arguments);\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::push_back(value_type c)\n\t{\n\t\tappend((size_type)1, c);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::pop_back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(internalLayout().GetSize() <= 0))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::pop_back -- empty string\");\n\t\t#endif\n\n\t\tinternalLayout().EndPtr()[-1] = value_type(0);\n\t\tinternalLayout().SetSize(internalLayout().GetSize() - 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::assign(const this_type& x)\n\t{\n\t\t// The C++11 Standard 21.4.6.3 p6 specifies that assign from this_type assigns contents only and not the allocator.\n\t\treturn assign(x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::assign(const this_type& x, size_type position, size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > x.internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\t// The C++11 Standard 21.4.6.3 p6 specifies that assign from this_type assigns contents only and not the allocator.\n\t\t    return assign(\n\t\t        x.internalLayout().BeginPtr() + position,\n\t\t        x.internalLayout().BeginPtr() + position + eastl::min_alt(n, x.internalLayout().GetSize() - position));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::assign(const value_type* p, size_type n)\n\t{\n\t\treturn assign(p, p + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::assign(const value_type* p)\n\t{\n\t\treturn assign(p, p + CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::assign(size_type n, value_type c)\n\t{\n\t\tif(n <= internalLayout().GetSize())\n\t\t{\n\t\t\tCharTypeAssignN(internalLayout().BeginPtr(), n, c);\n\t\t\terase(internalLayout().BeginPtr() + n, internalLayout().EndPtr());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tCharTypeAssignN(internalLayout().BeginPtr(), internalLayout().GetSize(), c);\n\t\t\tappend(n - internalLayout().GetSize(), c);\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::assign(const value_type* pBegin, const value_type* pEnd)\n\t{\n\t\tconst size_type n = (size_type)(pEnd - pBegin);\n\t\tif(n <= internalLayout().GetSize())\n\t\t{\n\t\t\tif(n)\n\t\t\t\tmemmove(internalLayout().BeginPtr(), pBegin, (size_t)n * sizeof(value_type));\n\t\t\terase(internalLayout().BeginPtr() + n, internalLayout().EndPtr());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmemmove(internalLayout().BeginPtr(), pBegin, (size_t)(internalLayout().GetSize()) * sizeof(value_type));\n\t\t\tappend(pBegin + internalLayout().GetSize(), pEnd);\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::assign(std::initializer_list<value_type> ilist)\n\t{\n\t\treturn assign(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::assign(this_type&& x)\n\t{\n\t\tif(get_allocator() == x.get_allocator())\n\t\t{\n\t\t\teastl::swap(internalLayout(), x.internalLayout());\n\t\t}\n\t\telse\n\t\t\tassign(x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherCharType>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::assign_convert(const OtherCharType* p)\n\t{\n\t\tclear();\n\t\tappend_convert(p);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherCharType>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::assign_convert(const OtherCharType* p, size_type n)\n\t{\n\t\tclear();\n\t\tappend_convert(p, n);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename OtherStringType>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::assign_convert(const OtherStringType& x)\n\t{\n\t\tclear();\n\t\tappend_convert(x.data(), x.length());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::insert(size_type position, const this_type& x)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY(internalLayout().GetSize() > (max_size() - x.internalLayout().GetSize())))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\tinsert(internalLayout().BeginPtr() + position, x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::insert(size_type position, const this_type& x, size_type beg, size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY((position > internalLayout().GetSize()) || (beg > x.internalLayout().GetSize())))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\tsize_type nLength = eastl::min_alt(n, x.internalLayout().GetSize() - beg);\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY(internalLayout().GetSize() > (max_size() - nLength)))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\tinsert(internalLayout().BeginPtr() + position, x.internalLayout().BeginPtr() + beg, x.internalLayout().BeginPtr() + beg + nLength);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::insert(size_type position, const value_type* p, size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY(internalLayout().GetSize() > (max_size() - n)))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\tinsert(internalLayout().BeginPtr() + position, p, p + n);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::insert(size_type position, const value_type* p)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\tsize_type nLength = (size_type)CharStrlen(p);\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY(internalLayout().GetSize() > (max_size() - nLength)))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\tinsert(internalLayout().BeginPtr() + position, p, p + nLength);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::insert(size_type position, size_type n, value_type c)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY(internalLayout().GetSize() > (max_size() - n)))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\tinsert(internalLayout().BeginPtr() + position, n, c);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::insert(const_iterator p, value_type c)\n\t{\n\t\tif(p == internalLayout().EndPtr())\n\t\t{\n\t\t\tpush_back(c);\n\t\t\treturn internalLayout().EndPtr() - 1;\n\t\t}\n\t\treturn InsertInternal(p, c);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::insert(const_iterator p, size_type n, value_type c)\n\t{\n\t\tconst difference_type nPosition = (p - internalLayout().BeginPtr()); // Save this because we might reallocate.\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((p < internalLayout().BeginPtr()) || (p > internalLayout().EndPtr())))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::insert -- invalid position\");\n\t\t#endif\n\n\t\tif(n) // If there is anything to insert...\n\t\t{\n\t\t\tif(internalLayout().GetRemainingCapacity() >= n) // If we have enough capacity...\n\t\t\t{\n\t\t\t\tconst size_type nElementsAfter = (size_type)(internalLayout().EndPtr() - p);\n\n\t\t\t\tif(nElementsAfter >= n) // If there's enough space for the new chars between the insert position and the end...\n\t\t\t\t{\n\t\t\t\t\t// Ensure we save the size before we do the copy, as we might overwrite the size field with the NULL\n\t\t\t\t\t// terminator in the edge case where we are inserting enough characters to equal our capacity\n\t\t\t\t\tconst size_type nSavedSize = internalLayout().GetSize();\n\t\t\t\t\tCharStringUninitializedCopy((internalLayout().EndPtr() - n) + 1, internalLayout().EndPtr() + 1, internalLayout().EndPtr() + 1);\n\t\t\t\t\tinternalLayout().SetSize(nSavedSize + n);\n\t\t\t\t\tmemmove(const_cast<value_type*>(p) + n, p, (size_t)((nElementsAfter - n) + 1) * sizeof(value_type));\n\t\t\t\t\tCharTypeAssignN(const_cast<value_type*>(p), n, c);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tpointer pOldEnd = internalLayout().EndPtr();\n\t\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t\tconst size_type nOldSize = internalLayout().GetSize();\n\t\t\t\t\t#endif\n\t\t\t\t\tCharStringUninitializedFillN(internalLayout().EndPtr() + 1, n - nElementsAfter - 1, c);\n\t\t\t\t\tinternalLayout().SetSize(internalLayout().GetSize() + (n - nElementsAfter));\n\n\t\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t#endif\n\t\t\t\t\t\t\t// See comment in if block above\n\t\t\t\t\t\t\tconst size_type nSavedSize = internalLayout().GetSize();\n\t\t\t\t\t\t\tCharStringUninitializedCopy(p, pOldEnd + 1, internalLayout().EndPtr());\n\t\t\t\t\t\t\tinternalLayout().SetSize(nSavedSize + nElementsAfter);\n\t\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(...)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinternalLayout().SetSize(nOldSize);\n\t\t\t\t\t\t\tthrow;\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n\n\t\t\t\t\tCharTypeAssignN(const_cast<value_type*>(p), nElementsAfter + 1, c);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconst size_type nOldSize = internalLayout().GetSize();\n\t\t\t\tconst size_type nOldCap  = capacity();\n\t\t\t\tconst size_type nLength  = GetNewCapacity(nOldCap, (nOldSize + n) - nOldCap);\n\n\t\t\t\titerator pNewBegin = DoAllocate(nLength + 1);\n\n\t\t\t\titerator pNewEnd = CharStringUninitializedCopy(internalLayout().BeginPtr(), p, pNewBegin);\n\t\t\t\tpNewEnd          = CharStringUninitializedFillN(pNewEnd, n, c);\n\t\t\t\tpNewEnd          = CharStringUninitializedCopy(p, internalLayout().EndPtr(), pNewEnd);\n\t\t\t   *pNewEnd          = 0;\n\n\t\t\t\tDeallocateSelf();\n\t\t\t\tinternalLayout().SetHeapBeginPtr(pNewBegin);\n\t\t\t\tinternalLayout().SetHeapCapacity(nLength);\n\t\t\t\tinternalLayout().SetHeapSize(nOldSize + n);\n\t\t\t}\n\t\t}\n\n\t\treturn internalLayout().BeginPtr() + nPosition;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::insert(const_iterator p, const value_type* pBegin, const value_type* pEnd)\n\t{\n\t\tconst difference_type nPosition = (p - internalLayout().BeginPtr()); // Save this because we might reallocate.\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((p < internalLayout().BeginPtr()) || (p > internalLayout().EndPtr())))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::insert -- invalid position\");\n\t\t#endif\n\n\t\tconst size_type n = (size_type)(pEnd - pBegin);\n\n\t\tif(n)\n\t\t{\n\t\t\tconst bool bCapacityIsSufficient = (internalLayout().GetRemainingCapacity() >= n);\n\t\t\tconst bool bSourceIsFromSelf     = ((pEnd >= internalLayout().BeginPtr()) && (pBegin <= internalLayout().EndPtr()));\n\n\t\t\tif(bSourceIsFromSelf && internalLayout().IsSSO())\n\t\t\t{\n\t\t\t\t// pBegin to pEnd will be <= this->GetSize(), so stackTemp will guaranteed be an SSO String\n\t\t\t\t// If we are inserting ourself into ourself and we are SSO, then on the recursive call we can\n\t\t\t\t// guarantee 0 or 1 allocation depending if we need to realloc\n\t\t\t\t// We don't do this for Heap strings as then this path may do 1 or 2 allocations instead of\n\t\t\t\t// only 1 allocation when we fall through to the last else case below\n\t\t\t\tconst this_type stackTemp(pBegin, pEnd, get_allocator());\n\t\t\t\treturn insert(p, stackTemp.data(), stackTemp.data() + stackTemp.size());\n\t\t\t}\n\n\t\t\t// If bSourceIsFromSelf is true, then we reallocate. This is because we are\n\t\t\t// inserting ourself into ourself and thus both the source and destination\n\t\t\t// be modified, making it rather tricky to attempt to do in place. The simplest\n\t\t\t// resolution is to reallocate. To consider: there may be a way to implement this\n\t\t\t// whereby we don't need to reallocate or can often avoid reallocating.\n\t\t\tif(bCapacityIsSufficient && !bSourceIsFromSelf)\n\t\t\t{\n\t\t\t\tconst size_type nElementsAfter = (size_type)(internalLayout().EndPtr() - p);\n\n\t\t\t\tif(nElementsAfter >= n) // If there are enough characters between insert pos and end\n\t\t\t\t{\n\t\t\t\t\t// Ensure we save the size before we do the copy, as we might overwrite the size field with the NULL\n\t\t\t\t\t// terminator in the edge case where we are inserting enough characters to equal our capacity\n\t\t\t\t\tconst size_type nSavedSize = internalLayout().GetSize();\n\t\t\t\t\tCharStringUninitializedCopy((internalLayout().EndPtr() - n) + 1, internalLayout().EndPtr() + 1, internalLayout().EndPtr() + 1);\n\t\t\t\t\tinternalLayout().SetSize(nSavedSize + n);\n\t\t\t\t\tmemmove(const_cast<value_type*>(p) + n, p, (size_t)((nElementsAfter - n) + 1) * sizeof(value_type));\n\t\t\t\t\tmemmove(const_cast<value_type*>(p), pBegin, (size_t)(n) * sizeof(value_type));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tpointer pOldEnd = internalLayout().EndPtr();\n\t\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t\tconst size_type nOldSize = internalLayout().GetSize();\n\t\t\t\t\t#endif\n\t\t\t\t\tconst value_type* const pMid = pBegin + (nElementsAfter + 1);\n\n\t\t\t\t\tCharStringUninitializedCopy(pMid, pEnd, internalLayout().EndPtr() + 1);\n\t\t\t\t\tinternalLayout().SetSize(internalLayout().GetSize() + (n - nElementsAfter));\n\n\t\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t#endif\n\t\t\t\t\t\t\t// See comment in if block above\n\t\t\t\t\t\t\tconst size_type nSavedSize = internalLayout().GetSize();\n\t\t\t\t\t\t\tCharStringUninitializedCopy(p, pOldEnd + 1, internalLayout().EndPtr());\n\t\t\t\t\t\t\tinternalLayout().SetSize(nSavedSize + nElementsAfter);\n\t\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(...)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinternalLayout().SetSize(nOldSize);\n\t\t\t\t\t\t\tthrow;\n\t\t\t\t\t\t}\n\t\t\t\t\t#endif\n\n\t\t\t\t\tCharStringUninitializedCopy(pBegin, pMid, const_cast<value_type*>(p));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse // Else we need to reallocate to implement this.\n\t\t\t{\n\t\t\t\tconst size_type nOldSize = internalLayout().GetSize();\n\t\t\t\tconst size_type nOldCap  = capacity();\n\t\t\t\tsize_type nLength;\n\n\t\t\t\tif(bCapacityIsSufficient) // If bCapacityIsSufficient is true, then bSourceIsFromSelf must be true.\n\t\t\t\t\tnLength = nOldSize + n;\n\t\t\t\telse\n\t\t\t\t\tnLength = GetNewCapacity(nOldCap, (nOldSize + n) - nOldCap);\n\n\t\t\t\tpointer pNewBegin = DoAllocate(nLength + 1);\n\n\t\t\t\tpointer pNewEnd = CharStringUninitializedCopy(internalLayout().BeginPtr(), p, pNewBegin);\n\t\t\t\tpNewEnd         = CharStringUninitializedCopy(pBegin, pEnd, pNewEnd);\n\t\t\t\tpNewEnd         = CharStringUninitializedCopy(p, internalLayout().EndPtr(), pNewEnd);\n\t\t\t   *pNewEnd         = 0;\n\n\t\t\t\tDeallocateSelf();\n\t\t\t\tinternalLayout().SetHeapBeginPtr(pNewBegin);\n\t\t\t\tinternalLayout().SetHeapCapacity(nLength);\n\t\t\t\tinternalLayout().SetHeapSize(nOldSize + n);\n\t\t\t}\n\t\t}\n\n\t\treturn internalLayout().BeginPtr() + nPosition;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::insert(const_iterator p, std::initializer_list<value_type> ilist)\n\t{\n\t\treturn insert(p, ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::erase(size_type position, size_type n)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::erase -- invalid position\");\n\t\t#endif\n\n\t\terase(internalLayout().BeginPtr() + position,\n\t\t\t  internalLayout().BeginPtr() + position + eastl::min_alt(n, internalLayout().GetSize() - position));\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::erase(const_iterator p)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((p < internalLayout().BeginPtr()) || (p >= internalLayout().EndPtr())))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::erase -- invalid position\");\n\t\t#endif\n\n\t\tmemmove(const_cast<value_type*>(p), p + 1, (size_t)(internalLayout().EndPtr() - p) * sizeof(value_type));\n\t\tinternalLayout().SetSize(internalLayout().GetSize() - 1);\n\t\treturn const_cast<value_type*>(p);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::erase(const_iterator pBegin, const_iterator pEnd)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY((pBegin < internalLayout().BeginPtr()) || (pBegin > internalLayout().EndPtr()) ||\n\t\t\t\t\t\t\t   (pEnd < internalLayout().BeginPtr()) || (pEnd > internalLayout().EndPtr()) || (pEnd < pBegin)))\n\t\t\t    EASTL_FAIL_MSG(\"basic_string::erase -- invalid position\");\n\t\t#endif\n\n\t\tif(pBegin != pEnd)\n\t\t{\n\t\t\tmemmove(const_cast<value_type*>(pBegin), pEnd, (size_t)((internalLayout().EndPtr() - pEnd) + 1) * sizeof(value_type));\n\t\t\tconst size_type n = (size_type)(pEnd - pBegin);\n\t\t\tinternalLayout().SetSize(internalLayout().GetSize() - n);\n\t\t}\n\t\treturn const_cast<value_type*>(pBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::reverse_iterator\n\tbasic_string<T, Allocator>::erase(reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::reverse_iterator\n\tbasic_string<T, Allocator>::erase(reverse_iterator first, reverse_iterator last)\n\t{\n\t\treturn reverse_iterator(erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::replace(size_type position, size_type n, const this_type& x)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\tconst size_type nLength = eastl::min_alt(n, internalLayout().GetSize() - position);\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY((internalLayout().GetSize() - nLength) >= (max_size() - x.internalLayout().GetSize())))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\treturn replace(internalLayout().BeginPtr() + position, internalLayout().BeginPtr() + position + nLength, x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::replace(size_type pos1, size_type n1, const this_type& x, size_type pos2, size_type n2)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\tif(EASTL_UNLIKELY((pos1 > internalLayout().GetSize()) || (pos2 > x.internalLayout().GetSize())))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\tconst size_type nLength1 = eastl::min_alt(n1, internalLayout().GetSize() - pos1);\n\t\tconst size_type nLength2 = eastl::min_alt(n2, x.internalLayout().GetSize() - pos2);\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY((internalLayout().GetSize() - nLength1) >= (max_size() - nLength2)))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\treturn replace(internalLayout().BeginPtr() + pos1, internalLayout().BeginPtr() + pos1 + nLength1, x.internalLayout().BeginPtr() + pos2, x.internalLayout().BeginPtr() + pos2 + nLength2);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::replace(size_type position, size_type n1, const value_type* p, size_type n2)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\tconst size_type nLength = eastl::min_alt(n1, internalLayout().GetSize() - position);\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY((n2 > max_size()) || ((internalLayout().GetSize() - nLength) >= (max_size() - n2))))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\treturn replace(internalLayout().BeginPtr() + position, internalLayout().BeginPtr() + position + nLength, p, p + n2);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::replace(size_type position, size_type n1, const value_type* p)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\tconst size_type nLength = eastl::min_alt(n1, internalLayout().GetSize() - position);\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tconst size_type n2 = (size_type)CharStrlen(p);\n\t\t\tif(EASTL_UNLIKELY((n2 > max_size()) || ((internalLayout().GetSize() - nLength) >= (max_size() - n2))))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\treturn replace(internalLayout().BeginPtr() + position, internalLayout().BeginPtr() + position + nLength, p, p + CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::replace(size_type position, size_type n1, size_type n2, value_type c)\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\tconst size_type nLength = eastl::min_alt(n1, internalLayout().GetSize() - position);\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY((n2 > max_size()) || (internalLayout().GetSize() - nLength) >= (max_size() - n2)))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\treturn replace(internalLayout().BeginPtr() + position, internalLayout().BeginPtr() + position + nLength, n2, c);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::replace(const_iterator pBegin, const_iterator pEnd, const this_type& x)\n\t{\n\t\treturn replace(pBegin, pEnd, x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::replace(const_iterator pBegin, const_iterator pEnd, const value_type* p, size_type n)\n\t{\n\t\treturn replace(pBegin, pEnd, p, p + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::replace(const_iterator pBegin, const_iterator pEnd, const value_type* p)\n\t{\n\t\treturn replace(pBegin, pEnd, p, p + CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::replace(const_iterator pBegin, const_iterator pEnd, size_type n, value_type c)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY((pBegin < internalLayout().BeginPtr()) || (pBegin > internalLayout().EndPtr()) ||\n\t\t\t\t\t\t\t   (pEnd < internalLayout().BeginPtr()) || (pEnd > internalLayout().EndPtr()) || (pEnd < pBegin)))\n\t\t\t    EASTL_FAIL_MSG(\"basic_string::replace -- invalid position\");\n\t\t#endif\n\n\t\tconst size_type nLength = static_cast<size_type>(pEnd - pBegin);\n\n\t\tif(nLength >= n)\n\t\t{\n\t\t\tCharTypeAssignN(const_cast<value_type*>(pBegin), n, c);\n\t\t\terase(pBegin + n, pEnd);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tCharTypeAssignN(const_cast<value_type*>(pBegin), nLength, c);\n\t\t\tinsert(pEnd, n - nLength, c);\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::replace(const_iterator pBegin1, const_iterator pEnd1, const value_type* pBegin2, const value_type* pEnd2)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY((pBegin1 < internalLayout().BeginPtr()) || (pBegin1 > internalLayout().EndPtr()) ||\n\t\t\t\t\t\t\t   (pEnd1 < internalLayout().BeginPtr()) || (pEnd1 > internalLayout().EndPtr()) || (pEnd1 < pBegin1)))\n\t\t\t    EASTL_FAIL_MSG(\"basic_string::replace -- invalid position\");\n\t\t#endif\n\n\t\tconst size_type nLength1 = (size_type)(pEnd1 - pBegin1);\n\t\tconst size_type nLength2 = (size_type)(pEnd2 - pBegin2);\n\n\t\tif(nLength1 >= nLength2) // If we have a non-expanding operation...\n\t\t{\n\t\t\tif((pBegin2 > pEnd1) || (pEnd2 <= pBegin1))  // If we have a non-overlapping operation...\n\t\t\t\tmemcpy(const_cast<value_type*>(pBegin1), pBegin2, (size_t)(pEnd2 - pBegin2) * sizeof(value_type));\n\t\t\telse\n\t\t\t\tmemmove(const_cast<value_type*>(pBegin1), pBegin2, (size_t)(pEnd2 - pBegin2) * sizeof(value_type));\n\t\t\terase(pBegin1 + nLength2, pEnd1);\n\t\t}\n\t\telse // Else we are expanding.\n\t\t{\n\t\t\tif((pBegin2 > pEnd1) || (pEnd2 <= pBegin1)) // If we have a non-overlapping operation...\n\t\t\t{\n\t\t\t\tconst value_type* const pMid2 = pBegin2 + nLength1;\n\n\t\t\t\tif((pEnd2 <= pBegin1) || (pBegin2 > pEnd1))\n\t\t\t\t\tmemcpy(const_cast<value_type*>(pBegin1), pBegin2, (size_t)(pMid2 - pBegin2) * sizeof(value_type));\n\t\t\t\telse\n\t\t\t\t\tmemmove(const_cast<value_type*>(pBegin1), pBegin2, (size_t)(pMid2 - pBegin2) * sizeof(value_type));\n\t\t\t\tinsert(pEnd1, pMid2, pEnd2);\n\t\t\t}\n\t\t\telse // else we have an overlapping operation.\n\t\t\t{\n\t\t\t\t// I can't think of any easy way of doing this without allocating temporary memory.\n\t\t\t\tconst size_type nOldSize     = internalLayout().GetSize();\n\t\t\t\tconst size_type nOldCap      = capacity();\n\t\t\t\tconst size_type nNewCapacity = GetNewCapacity(nOldCap, (nOldSize + (nLength2 - nLength1)) - nOldCap);\n\n\t\t\t\tpointer pNewBegin = DoAllocate(nNewCapacity + 1);\n\n\t\t\t\tpointer pNewEnd = CharStringUninitializedCopy(internalLayout().BeginPtr(), pBegin1, pNewBegin);\n\t\t\t\tpNewEnd         = CharStringUninitializedCopy(pBegin2, pEnd2,   pNewEnd);\n\t\t\t\tpNewEnd         = CharStringUninitializedCopy(pEnd1,   internalLayout().EndPtr(),   pNewEnd);\n\t\t\t   *pNewEnd         = 0;\n\n\t\t\t\tDeallocateSelf();\n\t\t\t\tinternalLayout().SetHeapBeginPtr(pNewBegin);\n\t\t\t\tinternalLayout().SetHeapCapacity(nNewCapacity);\n\t\t\t\tinternalLayout().SetHeapSize(nOldSize + (nLength2 - nLength1));\n\t\t\t}\n\t\t}\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::copy(value_type* p, size_type n, size_type position) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\t// C++ std says the effects of this function are as if calling char_traits::copy()\n\t\t// thus the 'p' must not overlap *this string, so we can use memcpy\n\t\tconst size_type nLength = eastl::min_alt(n, internalLayout().GetSize() - position);\n\t\tCharStringUninitializedCopy(internalLayout().BeginPtr() + position, internalLayout().BeginPtr() + position + nLength, p);\n\t\treturn nLength;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid basic_string<T, Allocator>::swap(this_type& x)\n\t{\n\t\tif(get_allocator() == x.get_allocator() || (internalLayout().IsSSO() && x.internalLayout().IsSSO())) // If allocators are equivalent...\n\t\t{\n\t\t\t// We leave mAllocator as-is.\n\t\t\teastl::swap(internalLayout(), x.internalLayout());\n\t\t}\n\t\telse // else swap the contents.\n\t\t{\n\t\t\tconst this_type temp(*this); // Can't call eastl::swap because that would\n\t\t\t*this = x;                   // itself call this member swap function.\n\t\t\tx     = temp;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find(const this_type& x, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn find(x.internalLayout().BeginPtr(), position, x.internalLayout().GetSize());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find(const value_type* p, size_type position) const\n\t{\n\t\treturn find(p, position, (size_type)CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find(const value_type* p, size_type position, size_type n) const\n\t{\n\t\t// It is not clear what the requirements are for position, but since the C++ standard\n\t\t// appears to be silent it is assumed for now that position can be any value.\n\t\t//#if EASTL_ASSERT_ENABLED\n\t\t//    if(EASTL_UNLIKELY(position > (size_type)(mpEnd - mpBegin)))\n\t\t//        EASTL_FAIL_MSG(\"basic_string::find -- invalid position\");\n\t\t//#endif\n\n\t\tif(EASTL_LIKELY(((npos - n) >= position) && (position + n) <= internalLayout().GetSize())) // If the range is valid...\n\t\t{\n\t\t\tconst value_type* const pTemp = eastl::search(internalLayout().BeginPtr() + position, internalLayout().EndPtr(), p, p + n);\n\n\t\t\tif((pTemp != internalLayout().EndPtr()) || (n == 0))\n\t\t\t\treturn (size_type)(pTemp - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find(value_type c, size_type position) const EA_NOEXCEPT\n\t{\n\t\t// It is not clear what the requirements are for position, but since the C++ standard\n\t\t// appears to be silent it is assumed for now that position can be any value.\n\t\t//#if EASTL_ASSERT_ENABLED\n\t\t//    if(EASTL_UNLIKELY(position > (size_type)(mpEnd - mpBegin)))\n\t\t//        EASTL_FAIL_MSG(\"basic_string::find -- invalid position\");\n\t\t//#endif\n\n\t\tif(EASTL_LIKELY(position < internalLayout().GetSize()))// If the position is valid...\n\t\t{\n\t\t\tconst const_iterator pResult = eastl::find(internalLayout().BeginPtr() + position, internalLayout().EndPtr(), c);\n\n\t\t\tif(pResult != internalLayout().EndPtr())\n\t\t\t\treturn (size_type)(pResult - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::rfind(const this_type& x, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn rfind(x.internalLayout().BeginPtr(), position, x.internalLayout().GetSize());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::rfind(const value_type* p, size_type position) const\n\t{\n\t\treturn rfind(p, position, (size_type)CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::rfind(const value_type* p, size_type position, size_type n) const\n\t{\n\t\t// Disabled because it's not clear what values are valid for position.\n\t\t// It is documented that npos is a valid value, though. We return npos and\n\t\t// don't crash if postion is any invalid value.\n\t\t//#if EASTL_ASSERT_ENABLED\n\t\t//    if(EASTL_UNLIKELY((position != npos) && (position > (size_type)(mpEnd - mpBegin))))\n\t\t//        EASTL_FAIL_MSG(\"basic_string::rfind -- invalid position\");\n\t\t//#endif\n\n\t\t// Note that a search for a zero length string starting at position = end() returns end() and not npos.\n\t\t// Note by Paul Pedriana: I am not sure how this should behave in the case of n == 0 and position > size.\n\t\t// The standard seems to suggest that rfind doesn't act exactly the same as find in that input position\n\t\t// can be > size and the return value can still be other than npos. Thus, if n == 0 then you can\n\t\t// never return npos, unlike the case with find.\n\t\tconst size_type nLength = internalLayout().GetSize();\n\n\t\tif(EASTL_LIKELY(n <= nLength))\n\t\t{\n\t\t\tif(EASTL_LIKELY(n))\n\t\t\t{\n\t\t\t\tconst const_iterator pEnd    = internalLayout().BeginPtr() + eastl::min_alt(nLength - n, position) + n;\n\t\t\t\tconst const_iterator pResult = CharTypeStringRSearch(internalLayout().BeginPtr(), pEnd, p, p + n);\n\n\t\t\t\tif(pResult != pEnd)\n\t\t\t\t\treturn (size_type)(pResult - internalLayout().BeginPtr());\n\t\t\t}\n\t\t\telse\n\t\t\t\treturn eastl::min_alt(nLength, position);\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::rfind(value_type c, size_type position) const EA_NOEXCEPT\n\t{\n\t\t// If n is zero or position is >= size, we return npos.\n\t\tconst size_type nLength = internalLayout().GetSize();\n\n\t\tif(EASTL_LIKELY(nLength))\n\t\t{\n\t\t\tconst value_type* const pEnd    = internalLayout().BeginPtr() + eastl::min_alt(nLength - 1, position) + 1;\n\t\t\tconst value_type* const pResult = CharTypeStringRFind(pEnd, internalLayout().BeginPtr(), c);\n\n\t\t\tif(pResult != internalLayout().BeginPtr())\n\t\t\t\treturn (size_type)((pResult - 1) - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_of(const this_type& x, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn find_first_of(x.internalLayout().BeginPtr(), position, x.internalLayout().GetSize());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_of(const value_type* p, size_type position) const\n\t{\n\t\treturn find_first_of(p, position, (size_type)CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_of(const value_type* p, size_type position, size_type n) const\n\t{\n\t\t// If position is >= size, we return npos.\n\t\tif(EASTL_LIKELY((position < internalLayout().GetSize())))\n\t\t{\n\t\t\tconst value_type* const pBegin = internalLayout().BeginPtr() + position;\n\t\t\tconst const_iterator pResult   = CharTypeStringFindFirstOf(pBegin, internalLayout().EndPtr(), p, p + n);\n\n\t\t\tif(pResult != internalLayout().EndPtr())\n\t\t\t\treturn (size_type)(pResult - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_of(value_type c, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn find(c, position);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_of(const this_type& x, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn find_last_of(x.internalLayout().BeginPtr(), position, x.internalLayout().GetSize());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_of(const value_type* p, size_type position) const\n\t{\n\t\treturn find_last_of(p, position, (size_type)CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_of(const value_type* p, size_type position, size_type n) const\n\t{\n\t\t// If n is zero or position is >= size, we return npos.\n\t\tconst size_type nLength = internalLayout().GetSize();\n\n\t\tif(EASTL_LIKELY(nLength))\n\t\t{\n\t\t\tconst value_type* const pEnd    = internalLayout().BeginPtr() + eastl::min_alt(nLength - 1, position) + 1;\n\t\t\tconst value_type* const pResult = CharTypeStringRFindFirstOf(pEnd, internalLayout().BeginPtr(), p, p + n);\n\n\t\t\tif(pResult != internalLayout().BeginPtr())\n\t\t\t\treturn (size_type)((pResult - 1) - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_of(value_type c, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn rfind(c, position);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_not_of(const this_type& x, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn find_first_not_of(x.internalLayout().BeginPtr(), position, x.internalLayout().GetSize());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_not_of(const value_type* p, size_type position) const\n\t{\n\t\treturn find_first_not_of(p, position, (size_type)CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_not_of(const value_type* p, size_type position, size_type n) const\n\t{\n\t\tif(EASTL_LIKELY(position <= internalLayout().GetSize()))\n\t\t{\n\t\t\tconst const_iterator pResult =\n\t\t\t    CharTypeStringFindFirstNotOf(internalLayout().BeginPtr() + position, internalLayout().EndPtr(), p, p + n);\n\n\t\t\tif(pResult != internalLayout().EndPtr())\n\t\t\t\treturn (size_type)(pResult - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_first_not_of(value_type c, size_type position) const EA_NOEXCEPT\n\t{\n\t\tif(EASTL_LIKELY(position <= internalLayout().GetSize()))\n\t\t{\n\t\t\t// Todo: Possibly make a specialized version of CharTypeStringFindFirstNotOf(pBegin, pEnd, c).\n\t\t\tconst const_iterator pResult =\n\t\t\t    CharTypeStringFindFirstNotOf(internalLayout().BeginPtr() + position, internalLayout().EndPtr(), &c, &c + 1);\n\n\t\t\tif(pResult != internalLayout().EndPtr())\n\t\t\t\treturn (size_type)(pResult - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_not_of(const this_type& x, size_type position) const EA_NOEXCEPT\n\t{\n\t\treturn find_last_not_of(x.internalLayout().BeginPtr(), position, x.internalLayout().GetSize());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_not_of(const value_type* p, size_type position) const\n\t{\n\t\treturn find_last_not_of(p, position, (size_type)CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_not_of(const value_type* p, size_type position, size_type n) const\n\t{\n\t\tconst size_type nLength = internalLayout().GetSize();\n\n\t\tif(EASTL_LIKELY(nLength))\n\t\t{\n\t\t\tconst value_type* const pEnd    = internalLayout().BeginPtr() + eastl::min_alt(nLength - 1, position) + 1;\n\t\t\tconst value_type* const pResult = CharTypeStringRFindFirstNotOf(pEnd, internalLayout().BeginPtr(), p, p + n);\n\n\t\t\tif(pResult != internalLayout().BeginPtr())\n\t\t\t\treturn (size_type)((pResult - 1) - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::find_last_not_of(value_type c, size_type position) const EA_NOEXCEPT\n\t{\n\t\tconst size_type nLength = internalLayout().GetSize();\n\n\t\tif(EASTL_LIKELY(nLength))\n\t\t{\n\t\t\t// Todo: Possibly make a specialized version of CharTypeStringRFindFirstNotOf(pBegin, pEnd, c).\n\t\t\tconst value_type* const pEnd    = internalLayout().BeginPtr() + eastl::min_alt(nLength - 1, position) + 1;\n\t\t\tconst value_type* const pResult = CharTypeStringRFindFirstNotOf(pEnd, internalLayout().BeginPtr(), &c, &c + 1);\n\n\t\t\tif(pResult != internalLayout().BeginPtr())\n\t\t\t\treturn (size_type)((pResult - 1) - internalLayout().BeginPtr());\n\t\t}\n\t\treturn npos;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator> basic_string<T, Allocator>::substr(size_type position, size_type n) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(position > internalLayout().GetSize()))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::substr -- invalid position\");\n\t\t#endif\n\n\t\t\t// C++ std says the return string allocator must be default constructed, not a copy of this->get_allocator()\n\t\t\treturn basic_string(\n\t\t\t\tinternalLayout().BeginPtr() + position,\n\t\t\t\tinternalLayout().BeginPtr() + position +\n\t\t\t\t\teastl::min_alt(n, internalLayout().GetSize() - position), get_allocator());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::compare(const this_type& x) const EA_NOEXCEPT\n\t{\n\t\treturn compare(internalLayout().BeginPtr(), internalLayout().EndPtr(), x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::compare(size_type pos1, size_type n1, const this_type& x) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(pos1 > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\treturn compare(\n\t\t\tinternalLayout().BeginPtr() + pos1,\n\t\t\tinternalLayout().BeginPtr() + pos1 + eastl::min_alt(n1, internalLayout().GetSize() - pos1),\n\t\t\tx.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::compare(size_type pos1, size_type n1, const this_type& x, size_type pos2, size_type n2) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY((pos1 > (size_type)(internalLayout().EndPtr() - internalLayout().BeginPtr())) ||\n\t\t\t                  (pos2 > (size_type)(x.internalLayout().EndPtr() - x.internalLayout().BeginPtr()))))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\treturn compare(internalLayout().BeginPtr() + pos1,\n\t\t\t\t\t   internalLayout().BeginPtr() + pos1 + eastl::min_alt(n1, internalLayout().GetSize() - pos1),\n\t\t\t\t\t   x.internalLayout().BeginPtr() + pos2,\n\t\t\t\t\t   x.internalLayout().BeginPtr() + pos2 + eastl::min_alt(n2, x.internalLayout().GetSize() - pos2));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::compare(const value_type* p) const\n\t{\n\t\treturn compare(internalLayout().BeginPtr(), internalLayout().EndPtr(), p, p + CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::compare(size_type pos1, size_type n1, const value_type* p) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(pos1 > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\treturn compare(internalLayout().BeginPtr() + pos1,\n\t\t\t\t\t   internalLayout().BeginPtr() + pos1 + eastl::min_alt(n1, internalLayout().GetSize() - pos1),\n\t\t\t\t\t   p,\n\t\t\t\t\t   p + CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::compare(size_type pos1, size_type n1, const value_type* p, size_type n2) const\n\t{\n\t\t#if EASTL_STRING_OPT_RANGE_ERRORS\n\t\t\tif(EASTL_UNLIKELY(pos1 > internalLayout().GetSize()))\n\t\t\t\tThrowRangeException();\n\t\t#endif\n\n\t\treturn compare(internalLayout().BeginPtr() + pos1,\n\t\t\t\t\t   internalLayout().BeginPtr() + pos1 + eastl::min_alt(n1, internalLayout().GetSize() - pos1),\n\t\t\t\t\t   p,\n\t\t\t\t\t   p + n2);\n\t}\n\n\n\t// make_lower\n\t// This is a very simple ASCII-only case conversion function\n\t// Anything more complicated should use a more powerful separate library.\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::make_lower()\n\t{\n\t\tfor(pointer p = internalLayout().BeginPtr(); p < internalLayout().EndPtr(); ++p)\n\t\t\t*p = (value_type)CharToLower(*p);\n\t}\n\n\n\t// make_upper\n\t// This is a very simple ASCII-only case conversion function\n\t// Anything more complicated should use a more powerful separate library.\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::make_upper()\n\t{\n\t\tfor(pointer p = internalLayout().BeginPtr(); p < internalLayout().EndPtr(); ++p)\n\t\t\t*p = (value_type)CharToUpper(*p);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::ltrim()\n\t{\n\t\tconst value_type array[] = { ' ', '\\t', 0 }; // This is a pretty simplistic view of whitespace.\n\t\terase(0, find_first_not_of(array));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::rtrim()\n\t{\n\t\tconst value_type array[] = { ' ', '\\t', 0 }; // This is a pretty simplistic view of whitespace.\n\t\terase(find_last_not_of(array) + 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::trim()\n\t{\n\t\tltrim();\n\t\trtrim();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::ltrim(const value_type* p)\n\t{\n\t\terase(0, find_first_not_of(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::rtrim(const value_type* p)\n\t{\n\t\terase(find_last_not_of(p) + 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::trim(const value_type* p)\n\t{\n\t\tltrim(p);\n\t\trtrim(p);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator> basic_string<T, Allocator>::left(size_type n) const\n\t{\n\t\tconst size_type nLength = length();\n\t\tif(n < nLength)\n\t\t\treturn substr(0, n);\n\t\t// C++ std says that substr must return default constructed allocated, but we do not.\n\t\t// Instead it is much more practical to provide the copy of the current allocator\n\t\treturn basic_string(*this, get_allocator());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator> basic_string<T, Allocator>::right(size_type n) const\n\t{\n\t\tconst size_type nLength = length();\n\t\tif(n < nLength)\n\t\t\treturn substr(nLength - n, n);\n\t\t// C++ std says that substr must return default constructed allocated, but we do not.\n\t\t// Instead it is much more practical to provide the copy of the current allocator\n\t\treturn basic_string(*this, get_allocator());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline basic_string<T, Allocator>& basic_string<T, Allocator>::sprintf(const value_type* pFormat, ...)\n\t{\n\t\tva_list arguments;\n\t\tva_start(arguments, pFormat);\n\t\tinternalLayout().SetSize(0); // Fast truncate to zero length.\n\t\tappend_sprintf_va_list(pFormat, arguments);\n\t\tva_end(arguments);\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator>& basic_string<T, Allocator>::sprintf_va_list(const value_type* pFormat, va_list arguments)\n\t{\n\t\tinternalLayout().SetSize(0); // Fast truncate to zero length.\n\n\t\treturn append_sprintf_va_list(pFormat, arguments);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tint basic_string<T, Allocator>::compare(const value_type* pBegin1, const value_type* pEnd1,\n\t\t\t\t\t\t\t\t\t\t\tconst value_type* pBegin2, const value_type* pEnd2)\n\t{\n\t\tconst difference_type n1   = pEnd1 - pBegin1;\n\t\tconst difference_type n2   = pEnd2 - pBegin2;\n\t\tconst difference_type nMin = eastl::min_alt(n1, n2);\n\t\tconst int       cmp  = Compare(pBegin1, pBegin2, (size_t)nMin);\n\n\t\treturn (cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0)));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tint basic_string<T, Allocator>::comparei(const value_type* pBegin1, const value_type* pEnd1,\n\t\t\t\t\t\t\t\t\t\t\t const value_type* pBegin2, const value_type* pEnd2)\n\t{\n\t\tconst difference_type n1   = pEnd1 - pBegin1;\n\t\tconst difference_type n2   = pEnd2 - pBegin2;\n\t\tconst difference_type nMin = eastl::min_alt(n1, n2);\n\t\tconst int       cmp  = CompareI(pBegin1, pBegin2, (size_t)nMin);\n\n\t\treturn (cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0)));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::comparei(const this_type& x) const EA_NOEXCEPT\n\t{\n\t\treturn comparei(internalLayout().BeginPtr(), internalLayout().EndPtr(), x.internalLayout().BeginPtr(), x.internalLayout().EndPtr());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::comparei(const value_type* p) const\n\t{\n\t\treturn comparei(internalLayout().BeginPtr(), internalLayout().EndPtr(), p, p + CharStrlen(p));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename basic_string<T, Allocator>::iterator\n\tbasic_string<T, Allocator>::InsertInternal(const_iterator p, value_type c)\n\t{\n\t\titerator pNewPosition = const_cast<value_type*>(p);\n\n\t\tif((internalLayout().EndPtr() + 1) <= internalLayout().CapacityPtr())\n\t\t{\n\t\t\tconst size_type nSavedSize = internalLayout().GetSize();\n\t\t\tmemmove(const_cast<value_type*>(p) + 1, p, (size_t)(internalLayout().EndPtr() - p) * sizeof(value_type));\n\t\t\t*(internalLayout().EndPtr() + 1) = 0;\n\t\t\t*pNewPosition = c;\n\t\t\tinternalLayout().SetSize(nSavedSize + 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconst size_type nOldSize = internalLayout().GetSize();\n\t\t\tconst size_type nOldCap  = capacity();\n\t\t\tconst size_type nLength = GetNewCapacity(nOldCap, 1);\n\n\t\t\titerator pNewBegin = DoAllocate(nLength + 1);\n\n\t\t\tpNewPosition = CharStringUninitializedCopy(internalLayout().BeginPtr(), p, pNewBegin);\n\t\t   *pNewPosition = c;\n\n\t\t\titerator pNewEnd = pNewPosition + 1;\n\t\t\tpNewEnd          = CharStringUninitializedCopy(p, internalLayout().EndPtr(), pNewEnd);\n\t\t   *pNewEnd          = 0;\n\n\t\t\tDeallocateSelf();\n\t\t\tinternalLayout().SetHeapBeginPtr(pNewBegin);\n\t\t\tinternalLayout().SetHeapCapacity(nLength);\n\t\t\tinternalLayout().SetHeapSize(nOldSize + 1);\n\t\t}\n\t\treturn pNewPosition;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid basic_string<T, Allocator>::SizeInitialize(size_type n, value_type c)\n\t{\n\t\tAllocateSelf(n);\n\n\t\tCharStringUninitializedFillN(internalLayout().BeginPtr(), n, c);\n\t\t*internalLayout().EndPtr() = 0;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid basic_string<T, Allocator>::RangeInitialize(const value_type* pBegin, const value_type* pEnd)\n\t{\n\t\t#if EASTL_STRING_OPT_ARGUMENT_ERRORS\n\t\t\tif(EASTL_UNLIKELY(!pBegin && (pEnd < pBegin))) // 21.4.2 p7\n\t\t\t\tThrowInvalidArgumentException();\n\t\t#endif\n\n\t\tconst size_type n = (size_type)(pEnd - pBegin);\n\n\t\tAllocateSelf(n);\n\n\t\tCharStringUninitializedCopy(pBegin, pEnd, internalLayout().BeginPtr());\n\t\t*internalLayout().EndPtr() = 0;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::RangeInitialize(const value_type* pBegin)\n\t{\n\t\t#if EASTL_STRING_OPT_ARGUMENT_ERRORS\n\t\t\tif(EASTL_UNLIKELY(!pBegin))\n\t\t\t\tThrowInvalidArgumentException();\n\t\t#endif\n\n\t\tRangeInitialize(pBegin, pBegin + CharStrlen(pBegin));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::value_type*\n\tbasic_string<T, Allocator>::DoAllocate(size_type n)\n\t{\n\t\treturn (value_type*)EASTLAlloc(get_allocator(), n * sizeof(value_type));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::DoFree(value_type* p, size_type n)\n\t{\n\t\tif(p)\n\t\t\tEASTLFree(get_allocator(), p, n * sizeof(value_type));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::GetNewCapacity(size_type currentCapacity)\n\t{\n\t\treturn GetNewCapacity(currentCapacity, 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename basic_string<T, Allocator>::size_type\n\tbasic_string<T, Allocator>::GetNewCapacity(size_type currentCapacity, size_type minimumGrowSize)\n\t{\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tconst size_type nRemainingSize = max_size() - currentCapacity;\n\t\t\tif(EASTL_UNLIKELY((minimumGrowSize > nRemainingSize)))\n\t\t\t{\n\t\t\t\tThrowLengthException();\n\t\t\t}\n\t\t#endif\n\n\t\tconst size_type nNewCapacity = eastl::max_alt(currentCapacity + minimumGrowSize, currentCapacity * 2);\n\n\t\treturn nNewCapacity;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::AllocateSelf()\n\t{\n\t\tinternalLayout().ResetToSSO();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid basic_string<T, Allocator>::AllocateSelf(size_type n)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= 0x40000000))\n\t\t\t\tEASTL_FAIL_MSG(\"basic_string::AllocateSelf -- improbably large request.\");\n\t\t#endif\n\n\t\t#if EASTL_STRING_OPT_LENGTH_ERRORS\n\t\t\tif(EASTL_UNLIKELY(n > max_size()))\n\t\t\t\tThrowLengthException();\n\t\t#endif\n\n\t\tif(n > SSOLayout::SSO_CAPACITY)\n\t\t{\n\t\t\tpointer pBegin = DoAllocate(n + 1);\n\t\t\tinternalLayout().SetHeapBeginPtr(pBegin);\n\t\t\tinternalLayout().SetHeapCapacity(n);\n\t\t\tinternalLayout().SetHeapSize(n);\n\t\t}\n\t\telse\n\t\t\tinternalLayout().SetSSOSize(n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::DeallocateSelf()\n\t{\n\t\tif(internalLayout().IsHeap())\n\t\t{\n\t\t\tDoFree(internalLayout().BeginPtr(), internalLayout().GetHeapCapacity() + 1);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::ThrowLengthException() const\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tthrow std::length_error(\"basic_string -- length_error\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tEASTL_FAIL_MSG(\"basic_string -- length_error\");\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::ThrowRangeException() const\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tthrow std::out_of_range(\"basic_string -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tEASTL_FAIL_MSG(\"basic_string -- out of range\");\n\t\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void basic_string<T, Allocator>::ThrowInvalidArgumentException() const\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tthrow std::invalid_argument(\"basic_string -- invalid argument\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tEASTL_FAIL_MSG(\"basic_string -- invalid argument\");\n\t\t#endif\n\t}\n\n\t// iterator operators\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator==(const typename basic_string<T, Allocator>::reverse_iterator& r1,\n\t\t\t\t\t\t   const typename basic_string<T, Allocator>::reverse_iterator& r2)\n\t{\n\t\treturn r1.mpCurrent == r2.mpCurrent;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const typename basic_string<T, Allocator>::reverse_iterator& r1,\n\t\t\t\t\t\t   const typename basic_string<T, Allocator>::reverse_iterator& r2)\n\t{\n\t\treturn r1.mpCurrent != r2.mpCurrent;\n\t}\n\n\n\t// Operator +\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::CtorDoNotInitialize CtorDoNotInitialize;\n\t\tCtorDoNotInitialize cDNI; // GCC 2.x forces us to declare a named temporary like this.\n\t\tbasic_string<T, Allocator> result(cDNI, a.size() + b.size(), const_cast<basic_string<T, Allocator>&>(a).get_allocator()); // Note that we choose to assign a's allocator.\n\t\tresult.append(a);\n\t\tresult.append(b);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(const typename basic_string<T, Allocator>::value_type* p, const basic_string<T, Allocator>& b)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::CtorDoNotInitialize CtorDoNotInitialize;\n\t\tCtorDoNotInitialize cDNI; // GCC 2.x forces us to declare a named temporary like this.\n\t\tconst typename basic_string<T, Allocator>::size_type n = (typename basic_string<T, Allocator>::size_type)CharStrlen(p);\n\t\tbasic_string<T, Allocator> result(cDNI, n + b.size(), const_cast<basic_string<T, Allocator>&>(b).get_allocator());\n\t\tresult.append(p, p + n);\n\t\tresult.append(b);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(typename basic_string<T, Allocator>::value_type c, const basic_string<T, Allocator>& b)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::CtorDoNotInitialize CtorDoNotInitialize;\n\t\tCtorDoNotInitialize cDNI; // GCC 2.x forces us to declare a named temporary like this.\n\t\tbasic_string<T, Allocator> result(cDNI, 1 + b.size(), const_cast<basic_string<T, Allocator>&>(b).get_allocator());\n\t\tresult.push_back(c);\n\t\tresult.append(b);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::CtorDoNotInitialize CtorDoNotInitialize;\n\t\tCtorDoNotInitialize cDNI; // GCC 2.x forces us to declare a named temporary like this.\n\t\tconst typename basic_string<T, Allocator>::size_type n = (typename basic_string<T, Allocator>::size_type)CharStrlen(p);\n\t\tbasic_string<T, Allocator> result(cDNI, a.size() + n, const_cast<basic_string<T, Allocator>&>(a).get_allocator());\n\t\tresult.append(a);\n\t\tresult.append(p, p + n);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(const basic_string<T, Allocator>& a, typename basic_string<T, Allocator>::value_type c)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::CtorDoNotInitialize CtorDoNotInitialize;\n\t\tCtorDoNotInitialize cDNI; // GCC 2.x forces us to declare a named temporary like this.\n\t\tbasic_string<T, Allocator> result(cDNI, a.size() + 1, const_cast<basic_string<T, Allocator>&>(a).get_allocator());\n\t\tresult.append(a);\n\t\tresult.push_back(c);\n\t\treturn result;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(basic_string<T, Allocator>&& a, basic_string<T, Allocator>&& b)\n\t{\n\t\ta.append(b); // Using an rvalue by name results in it becoming an lvalue.\n\t\treturn eastl::move(a);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(basic_string<T, Allocator>&& a, const basic_string<T, Allocator>& b)\n\t{\n\t\ta.append(b);\n\t\treturn eastl::move(a);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(const typename basic_string<T, Allocator>::value_type* p, basic_string<T, Allocator>&& b)\n\t{\n\t\tb.insert(0, p);\n\t\treturn eastl::move(b);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(basic_string<T, Allocator>&& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\ta.append(p);\n\t\treturn eastl::move(a);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tbasic_string<T, Allocator> operator+(basic_string<T, Allocator>&& a, typename basic_string<T, Allocator>::value_type c)\n\t{\n\t\ta.push_back(c);\n\t\treturn eastl::move(a);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool basic_string<T, Allocator>::validate() const EA_NOEXCEPT\n\t{\n\t\tif((internalLayout().BeginPtr() == nullptr) || (internalLayout().EndPtr() == nullptr))\n\t\t\treturn false;\n\t\tif(internalLayout().EndPtr() < internalLayout().BeginPtr())\n\t\t\treturn false;\n\t\tif(internalLayout().CapacityPtr() < internalLayout().EndPtr())\n\t\t\treturn false;\n\t\tif(*internalLayout().EndPtr() != 0)\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int basic_string<T, Allocator>::validate_iterator(const_iterator i) const EA_NOEXCEPT\n\t{\n\t\tif(i >= internalLayout().BeginPtr())\n\t\t{\n\t\t\tif(i < internalLayout().EndPtr())\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\n\t\t\tif(i <= internalLayout().EndPtr())\n\t\t\t\treturn (isf_valid | isf_current);\n\t\t}\n\n\t\treturn isf_none;\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\t// Operator== and operator!=\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator==(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn ((a.size() == b.size()) && (Compare(a.data(), b.data(), (size_t)a.size()) == 0));\n\t}\n\n#if !defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator==(const typename basic_string<T, Allocator>::value_type* p, const basic_string<T, Allocator>& b)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::size_type string_size_type;\n\t\tconst string_size_type n = (string_size_type)CharStrlen(p);\n\t\treturn ((n == b.size()) && (Compare(p, b.data(), (size_t)n) == 0));\n\t}\n#endif\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator==(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::size_type string_size_type;\n\t\tconst string_size_type n = (string_size_type)CharStrlen(p);\n\t\treturn ((a.size() == n) && (Compare(a.data(), p, (size_t)n) == 0));\n\t}\n\t\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Allocator>\n\tinline auto operator<=>(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn basic_string<T, Allocator>::compare(a.begin(), a.end(), b.begin(), b.end()) <=> 0;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline auto operator<=>(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::size_type string_size_type;\n\t\tconst string_size_type n = (string_size_type)CharStrlen(p);\n\t\treturn basic_string<T, Allocator>::compare(a.begin(), a.end(), p, p + n) <=> 0;\n\t}\n\t\n\ttemplate <typename T, typename Allocator>\n\tinline auto operator<=>(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::view_type v)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::view_type view_type;\n\t\treturn static_cast<view_type>(a) <=> v;\n\t}\n\n#else\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator==(const typename basic_string<T, Allocator>::view_type v, const basic_string<T, Allocator>& b)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\ttypedef typename basic_string<T, Allocator>::view_type view_type;\n\t\treturn v == static_cast<view_type>(b);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator==(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::view_type v)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\ttypedef typename basic_string<T, Allocator>::view_type view_type;\n\t\treturn static_cast<view_type>(a) == v;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const typename basic_string<T, Allocator>::value_type* p, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn !(p == b);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\treturn !(a == p);\n\t}\n\t\n\t\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const typename basic_string<T, Allocator>::view_type v, const basic_string<T, Allocator>& b)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn !(v == b);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::view_type v)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn !(a == v);\n\t}\n\n\n\t// Operator< (and also >, <=, and >=).\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn basic_string<T, Allocator>::compare(a.begin(), a.end(), b.begin(), b.end()) < 0; }\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<(const typename basic_string<T, Allocator>::value_type* p, const basic_string<T, Allocator>& b)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::size_type string_size_type;\n\t\tconst string_size_type n = (string_size_type)CharStrlen(p);\n\t\treturn basic_string<T, Allocator>::compare(p, p + n, b.begin(), b.end()) < 0;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\ttypedef typename basic_string<T, Allocator>::size_type string_size_type;\n\t\tconst string_size_type n = (string_size_type)CharStrlen(p);\n\t\treturn basic_string<T, Allocator>::compare(a.begin(), a.end(), p, p + n) < 0;\n\t}\n\t\n\t\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<(const typename basic_string<T, Allocator>::view_type v, const basic_string<T, Allocator>& b)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n \n\t\ttypedef typename basic_string<T, Allocator>::view_type view_type;\n\t\treturn v < static_cast<view_type>(b);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::view_type v)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\ttypedef typename basic_string<T, Allocator>::view_type view_type;\n\t\treturn static_cast<view_type>(a) < v;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>(const typename basic_string<T, Allocator>::value_type* p, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn b < p;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\treturn p < a;\n\t}\n\t\n\t\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>(const typename basic_string<T, Allocator>::view_type v, const basic_string<T, Allocator>& b)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn b < v;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::view_type v)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn v < a;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<=(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<=(const typename basic_string<T, Allocator>::value_type* p, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn !(b < p);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<=(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\treturn !(p < a);\n\t}\n\t\n\t\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<=(const typename basic_string<T, Allocator>::view_type v, const basic_string<T, Allocator>& b)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn !(b < v);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<=(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::view_type v)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn !(v < a);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>=(const basic_string<T, Allocator>& a, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>=(const typename basic_string<T, Allocator>::value_type* p, const basic_string<T, Allocator>& b)\n\t{\n\t\treturn !(p < b);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>=(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::value_type* p)\n\t{\n\t\treturn !(a < p);\n\t}\n\t\n\t\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>=(const typename basic_string<T, Allocator>::view_type v, const basic_string<T, Allocator>& b)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn !(v < b);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>=(const basic_string<T, Allocator>& a, const typename basic_string<T, Allocator>::view_type v)\n\t{\n\t\t// Workaround for basic_string_view comparisons that require conversions,\n\t\t// since they are causing an internal compiler error when compiled using\n\t\t// MSVC when certain flags are enabled (/Zi /O2 /Zc:inline).\n\n\t\treturn !(a < v);\n\t}\n#endif\n\n\ttemplate <typename T, typename Allocator>\n\tinline void swap(basic_string<T, Allocator>& a, basic_string<T, Allocator>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n\t/// string / wstring\n\ttypedef basic_string<char>    string;\n\ttypedef basic_string<wchar_t> wstring;\n\n\t/// custom string8 / string16 / string32\n\ttypedef basic_string<char>     string8;\n\ttypedef basic_string<char16_t> string16;\n\ttypedef basic_string<char32_t> string32;\n\n\t/// ISO mandated string types\n\ttypedef basic_string<char8_t>  u8string;    // Actually not a C++11 type, but added for consistency.\n\ttypedef basic_string<char16_t> u16string;\n\ttypedef basic_string<char32_t> u32string;\n\n\n\t/// hash<string>\n\t///\n\t/// We provide EASTL hash function objects for use in hash table containers.\n\t///\n\t/// Example usage:\n\t///    #include <EASTL/hash_set.h>\n\t///    hash_set<string> stringHashSet;\n\t///\n\ttemplate <typename T> struct hash;\n\n\ttemplate <typename Allocator>\n\tstruct hash<basic_string<char, Allocator>>\n\t{\n\t\tsize_t operator()(const basic_string<char, Allocator>& x) const\n\t\t{\n\t\t\tconst unsigned char* p = (const unsigned char*)x.c_str(); // To consider: limit p to at most 256 chars.\n\t\t\tunsigned int c, result = 2166136261U; // We implement an FNV-like string hash.\n\t\t\twhile((c = *p++) != 0) // Using '!=' disables compiler warnings.\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\t\ttemplate <typename Allocator>\n\t\tstruct hash<basic_string<char8_t, Allocator>>\n\t\t{\n\t\t\tsize_t operator()(const basic_string<char8_t, Allocator>& x) const\n\t\t\t{\n\t\t\t\tconst char8_t* p = (const char8_t*)x.c_str();\n\t\t\t\tunsigned int c, result = 2166136261U;\n\t\t\t\twhile((c = *p++) != 0)\n\t\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\t\treturn (size_t)result;\n\t\t\t}\n\t\t};\n\t#endif\n\n\ttemplate <typename Allocator>\n\tstruct hash<basic_string<char16_t, Allocator>>\n\t{\n\t\tsize_t operator()(const basic_string<char16_t, Allocator>& x) const\n\t\t{\n\t\t\tconst char16_t* p = x.c_str();\n\t\t\tunsigned int c, result = 2166136261U;\n\t\t\twhile((c = *p++) != 0)\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate <typename Allocator>\n\tstruct hash<basic_string<char32_t, Allocator>>\n\t{\n\t\tsize_t operator()(const basic_string<char32_t, Allocator>& x) const\n\t\t{\n\t\t\tconst char32_t* p = x.c_str();\n\t\t\tunsigned int c, result = 2166136261U;\n\t\t\twhile((c = (unsigned int)*p++) != 0)\n\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\t#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\t\ttemplate <typename Allocator>\n\t\tstruct hash<basic_string<wchar_t, Allocator>>\n\t\t{\n\t\t\tsize_t operator()(const basic_string<wchar_t, Allocator>& x) const\n\t\t\t{\n\t\t\t\tconst wchar_t* p = x.c_str();\n\t\t\t\tunsigned int c, result = 2166136261U;\n\t\t\t\twhile((c = (unsigned int)*p++) != 0)\n\t\t\t\t\tresult = (result * 16777619) ^ c;\n\t\t\t\treturn (size_t)result;\n\t\t\t}\n\t\t};\n\t#endif\n\n\tnamespace internal {\n\ttemplate<typename T>\n\tstruct transparent_string_hash {\n\t\tsize_t operator()(T* s) const { return hash<T*>()(s); }\n\n\t\tsize_t operator()(const T* s) const { return hash<const T*>()(s); }\n\n\t\ttemplate <typename Allocator>\n\t\tsize_t operator()(const basic_string<T, Allocator>& s) const { return hash<basic_string<T, Allocator>>()(s); }\n\n\t\tsize_t operator()(const basic_string_view<T>& s) const { return hash<basic_string_view<T>>()(s); }\n\t};\n\t} // namespace internal\n\n\t// extension to the standard.\n\t// transparent hash objects for string types.\n\tstruct transparent_string_hash\n\t\t: public internal::transparent_string_hash<char>\n#if EA_CHAR8_UNIQUE\n\t\t, public internal::transparent_string_hash<char8_t>\n#endif\n\t{\n\t\tusing is_transparent = int;\n\t\tusing internal::transparent_string_hash<char>::operator();\n#if EA_CHAR8_UNIQUE\n\t\tusing internal::transparent_string_hash<char8_t>::operator();\n#endif\n\t};\n\n\tstruct transparent_string16_hash\n\t\t: public internal::transparent_string_hash<char16_t>\n#if EA_WCHAR_UNIQUE == 1 && EA_WCHAR_SIZE == 2\n\t\t, public internal::transparent_string_hash<wchar_t>\n#endif\n\t{\n\t\tusing is_transparent = int;\n\t\tusing internal::transparent_string_hash<char16_t>::operator();\n#if EA_WCHAR_UNIQUE == 1 && EA_WCHAR_SIZE == 2\n\t\tusing internal::transparent_string_hash<wchar_t>::operator();\n#endif\n\t};\n\n\tstruct transparent_string32_hash\n\t\t: public internal::transparent_string_hash<char32_t>\n#if EA_WCHAR_UNIQUE == 1 && EA_WCHAR_SIZE == 4\n\t\t, public internal::transparent_string_hash<wchar_t>\n#endif\n\t{\n\t\tusing is_transparent = int;\n\t\tusing internal::transparent_string_hash<char32_t>::operator();\n#if EA_WCHAR_UNIQUE == 1 && EA_WCHAR_SIZE == 4\n\t\tusing internal::transparent_string_hash<wchar_t>::operator();\n#endif\n\t};\n\n\tstruct transparent_wstring_hash\n\t\t: public internal::transparent_string_hash<wchar_t>\n#if EA_WCHAR_UNIQUE == 1\n#if EA_WCHAR_SIZE == 2\n\t\t, public internal::transparent_string_hash<char16_t>\n#elif EA_WCHAR_SIZE == 4\n\t\t, public internal::transparent_string_hash<char32_t>\n#endif\n#endif\n\t{\n\t\tusing is_transparent = int;\n\t\tusing internal::transparent_string_hash<wchar_t>::operator();\n#if EA_WCHAR_UNIQUE == 1\n#if EA_WCHAR_SIZE == 2\n\t\tusing internal::transparent_string_hash<char16_t>::operator();\n#elif EA_WCHAR_SIZE == 4\n\t\tusing internal::transparent_string_hash<char32_t>::operator();\n#endif\n#endif\n\t};\n\n\t/// to_string\n\t///\n\t/// Converts integral types to an eastl::string with the same content that sprintf produces.  The following\n\t/// implementation provides a type safe conversion mechanism which avoids the common bugs associated with sprintf\n\t/// style format strings.\n\t///\n\t/// http://en.cppreference.com/w/cpp/string/basic_string/to_string\n\t///\n\tinline string to_string(int value)\n\t\t{ return string(string::CtorSprintf(), \"%d\", value); }\n\tinline string to_string(long value)\n\t\t{ return string(string::CtorSprintf(), \"%ld\", value); }\n\tinline string to_string(long long value)\n\t\t{ return string(string::CtorSprintf(), \"%lld\", value); }\n\tinline string to_string(unsigned value)\n\t\t{ return string(string::CtorSprintf(), \"%u\", value); }\n\tinline string to_string(unsigned long value)\n\t\t{ return string(string::CtorSprintf(), \"%lu\", value); }\n\tinline string to_string(unsigned long long value)\n\t\t{ return string(string::CtorSprintf(), \"%llu\", value); }\n\tinline string to_string(float value)\n\t\t{ return string(string::CtorSprintf(), \"%f\", value); }\n\tinline string to_string(double value)\n\t\t{ return string(string::CtorSprintf(), \"%f\", value); }\n\tinline string to_string(long double value)\n\t\t{ return string(string::CtorSprintf(), \"%Lf\", value); }\n\n\n\t/// to_wstring\n\t///\n\t/// Converts integral types to an eastl::wstring with the same content that sprintf produces.  The following\n\t/// implementation provides a type safe conversion mechanism which avoids the common bugs associated with sprintf\n\t/// style format strings.\n\t///\n\t/// http://en.cppreference.com/w/cpp/string/basic_string/to_wstring\n\t///\n\tinline wstring to_wstring(int value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%d\", value); }\n\tinline wstring to_wstring(long value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%ld\", value); }\n\tinline wstring to_wstring(long long value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%lld\", value); }\n\tinline wstring to_wstring(unsigned value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%u\", value); }\n\tinline wstring to_wstring(unsigned long value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%lu\", value); }\n\tinline wstring to_wstring(unsigned long long value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%llu\", value); }\n\tinline wstring to_wstring(float value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%f\", value); }\n\tinline wstring to_wstring(double value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%f\", value); }\n\tinline wstring to_wstring(long double value)\n\t\t{ return wstring(wstring::CtorSprintf(), L\"%Lf\", value); }\n\n\n\t/// user defined literals\n\t///\n\t/// Converts a character array literal to a basic_string.\n\t///\n\t/// Example:\n\t///   string s = \"abcdef\"s;\n\t///\n\t/// http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s\n\t///\n\t#if EASTL_USER_LITERALS_ENABLED && EASTL_INLINE_NAMESPACES_ENABLED\n\t\t// Disabling the Clang/GCC/MSVC warning about using user\n\t\t// defined literals without a leading '_' as they are reserved\n\t\t// for standard libary usage.\n\t\tEA_DISABLE_VC_WARNING(4455)\n\t\tEA_DISABLE_CLANG_WARNING(-Wuser-defined-literals)\n\t\tEA_DISABLE_GCC_WARNING(-Wliteral-suffix)\n\t    inline namespace literals\n\t    {\n\t\t    inline namespace string_literals\n\t\t    {\n\t\t\t\tinline string operator\"\" s(const char* str, size_t len) EA_NOEXCEPT { return {str, string::size_type(len)}; }\n\t\t\t\tinline u16string operator\"\" s(const char16_t* str, size_t len) EA_NOEXCEPT { return {str, u16string::size_type(len)}; }\n\t\t\t\tinline u32string operator\"\" s(const char32_t* str, size_t len) EA_NOEXCEPT { return {str, u32string::size_type(len)}; }\n\t\t\t\tinline wstring operator\"\" s(const wchar_t* str, size_t len) EA_NOEXCEPT { return {str, wstring::size_type(len)}; }\n\n\t\t\t\t// C++20 char8_t support.\n\t\t\t\t#if EA_CHAR8_UNIQUE\n\t\t\t\t\tinline u8string operator\"\" s(const char8_t* str, size_t len) EA_NOEXCEPT { return {str, u8string::size_type(len)}; }\n\t\t\t\t#endif\n\t\t    }\n\t    }\n\t\tEA_RESTORE_GCC_WARNING()\t// -Wliteral-suffix\n\t\tEA_RESTORE_CLANG_WARNING()\t// -Wuser-defined-literals\n\t\tEA_RESTORE_VC_WARNING()\t\t// warning: 4455\n\t#endif\n\n\n\t/// erase / erase_if\n\t///\n\t/// https://en.cppreference.com/w/cpp/string/basic_string/erase2\n\ttemplate <class CharT, class Allocator, class U>\n\ttypename basic_string<CharT, Allocator>::size_type erase(basic_string<CharT, Allocator>& c, const U& value)\n\t{\n\t\t// Erases all elements that compare equal to value from the container.\n\t\tauto origEnd = c.end();\n\t\tauto newEnd = eastl::remove(c.begin(), origEnd, value);\n\t\tauto numRemoved = eastl::distance(newEnd, origEnd);\n\t\tc.erase(newEnd, origEnd);\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the\n\t\t// string should not have more characters than fit in a\n\t\t// uint32_t and so the distance here should fit in a\n\t\t// size_type.\n\t\treturn static_cast<typename basic_string<CharT, Allocator>::size_type>(numRemoved);\n\t}\n\n\ttemplate <class CharT, class Allocator, class Predicate>\n\ttypename basic_string<CharT, Allocator>::size_type erase_if(basic_string<CharT, Allocator>& c, Predicate predicate)\n\t{\n\t\t// Erases all elements that satisfy the predicate pred from the container.\n\t\tauto origEnd = c.end();\n\t\tauto newEnd = eastl::remove_if(c.begin(), origEnd, predicate);\n\t\tauto numRemoved = eastl::distance(newEnd, origEnd);\n\t\tc.erase(newEnd, origEnd);\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the\n\t\t// string should not have more characters than fit in a\n\t\t// uint32_t and so the distance here should fit in a\n\t\t// size_type.\n\t\treturn static_cast<typename basic_string<CharT, Allocator>::size_type>(numRemoved);\n\t}\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/string_hash_map.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_STRING_HASH_MAP_H\n#define EASTL_STRING_HASH_MAP_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once \n#endif\n\n#include <EASTL/hash_map.h>\n#include <EASTL/string.h>\n\nnamespace eastl\n{\n\n\n// Note: this class creates a copy of the key on insertion and manages it in its own internal\n// buffer this has side effects like:\n//\n//     const char* p = \"X\";\n//     string_hash_map<int> map;\n//     auto x = map.insert(p, 1);\n//     const char* the_key = x.first->first;\n//     the_key != p; <<<< This is true, since we copied the key internally.\n//\n//\n// TODO: This publically inherits from hash_map but really shouldn't since it deliberately uses\n// name hiding to change the behaviour of some of its methods in a way that's incompatible with\n// what hash_map does. e.g:\n//\n//     void foo(hash_map<const char*, int, hash<const char*>, str_equal_to<const char*>>& map)\n//     {\n//         map[\"a\"] = 1;\n//     }\n//\n//     string_hash_map<int> strMap;\n//\n//     // This is very bad! foo() will use hash_map's implementation of operator[], which\n//     // doesn't copy the char* but strMap assumes it owns all its key pointers, this\n//     // will cause a crash when strMap is destructed.\n//     foo(strMap);\n//\ntemplate<typename T, typename Hash = hash<const char*>, typename Predicate = str_equal_to<const char*>, typename Allocator = EASTLAllocatorType>\nclass string_hash_map : public eastl::hash_map<const char*, T, Hash, Predicate, Allocator>\n{\npublic:\n\ttypedef eastl::hash_map<const char*, T, Hash, Predicate, Allocator> base;\n\ttypedef string_hash_map<T, Hash, Predicate, Allocator> this_type;\n\ttypedef typename base::base_type::allocator_type allocator_type;\n\ttypedef typename base::base_type::insert_return_type insert_return_type;\n\ttypedef typename base::base_type::iterator iterator;\n//  typedef typename base::base_type::reverse_iterator reverse_iterator;\n\ttypedef typename base::base_type::const_iterator const_iterator;\n\ttypedef typename base::base_type::size_type size_type;\n\ttypedef typename base::base_type::value_type value_type;\n\ttypedef typename base::mapped_type mapped_type;\n\n\tstring_hash_map(const allocator_type& allocator = allocator_type()) : base(allocator) {}\n\n\t// Note/warning: the copy constructor does not copy the underlying allocator instance. This\n\t// is different from what hash_map does.\n\tstring_hash_map(const string_hash_map& src, const allocator_type& allocator = allocator_type());\n\t\t\t\t\t\t~string_hash_map();\n\n\tvoid\t\t\t\tclear();\n    void\t\t\t\tclear(bool clearBuckets);\n\n\tthis_type&\t\t\toperator=(const this_type& x);\n\n\tinsert_return_type\t insert(const char* key, const T& value);\n\tinsert_return_type\t insert(const char* key);\n\tpair<iterator, bool> insert_or_assign(const char* key, const T& value);\n\titerator\t\t\t erase(const_iterator position);\n\tsize_type\t\t\t erase(const char* key);\n\tmapped_type&\t\t operator[](const char* key);\n\n\t// Note: the `emplace` methods are restricted to take the key directly as a first\n\t// parameter, and the value will be constructed from the template arguments in-place.\n\t// This choice makes emplace literally equivalent to `try_emplace`.\n\ttemplate <class... Args>\n\tinsert_return_type emplace(const char* key, Args&&... valArgs);\n\n\ttemplate <class... Args>\n\titerator emplace_hint(const_iterator position, const char* key, Args&&... valArgs);\n\n\ttemplate <class... Args>\n\tinline insert_return_type try_emplace(const char* k, Args&&... valArgs);\n\n\ttemplate <class... Args>\n\tinline iterator try_emplace(const_iterator, const char* k, Args&&... valArgs);\n\nprivate:\n\tchar*\t\t\t\tstrduplicate(const char* str);\n\tvoid\t\t\t\tfree(const char* str);\n\n\t// Not implemented right now\n\t// insert_return_type\tinsert(const value_type& value);\n\t// iterator\t\t\t\tinsert(iterator position, const value_type& value);\n    // reverse_iterator\t\terase(reverse_iterator position);\n    // reverse_iterator\t\terase(reverse_iterator first, reverse_iterator last);\n};\n\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\nstring_hash_map<T, Hash, Predicate, Allocator>::string_hash_map(const string_hash_map& src, const allocator_type& allocator) : base(allocator)\n{\n\tfor (const_iterator i=src.begin(), e=src.end(); i!=e; ++i)\n\t\tbase::base_type::insert(eastl::make_pair(strduplicate(i->first), i->second));\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\nstring_hash_map<T, Hash, Predicate, Allocator>::~string_hash_map()\n{\n\tclear();\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\nvoid string_hash_map<T, Hash, Predicate, Allocator>::clear()\n{\n\tfor (const_iterator i=base::base_type::begin(), e=base::base_type::end(); i!=e; ++i)\n\t\tfree(i->first);\n\tbase::base_type::clear();\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\nvoid string_hash_map<T, Hash, Predicate, Allocator>::clear(bool clearBuckets)\n{\n\tfor (const_iterator i=base::base_type::begin(), e=base::base_type::end(); i!=e; ++i)\n\t\tfree(i->first);\n\tbase::base_type::clear(clearBuckets);\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::this_type&\nstring_hash_map<T, Hash, Predicate, Allocator>::operator=(const this_type& x)\n{\n\tallocator_type allocator = base::base_type::get_allocator();\n\tthis->~this_type();\n\tnew (this) this_type(x, allocator);\n\treturn *this;\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::insert_return_type\nstring_hash_map<T, Hash, Predicate, Allocator>::insert(const char* key)\n{\n\treturn insert(key, mapped_type());\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::insert_return_type\nstring_hash_map<T, Hash, Predicate, Allocator>::insert(const char* key, const T& value)\n{\n\tEASTL_ASSERT(key);\n\titerator i = base::base_type::find(key);\n\tif (i != base::base_type::end())\n\t{\n\t\tinsert_return_type ret;\n\t\tret.first = i;\n\t\tret.second = false;\n\t\treturn ret;\n\t}\n\treturn base::base_type::insert(eastl::make_pair(strduplicate(key), value));\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\neastl::pair<typename string_hash_map<T, Hash, Predicate, Allocator>::iterator, bool>\nstring_hash_map<T, Hash, Predicate, Allocator>::insert_or_assign(const char* key, const T& value)\n{\n\titerator i = base::base_type::find(key);\n\tif (i != base::base_type::end())\n\t{\n\t\treturn base::base_type::insert_or_assign(i->first, value);\n\t}\n\telse\n\t{\n\t\treturn base::base_type::insert_or_assign(strduplicate(key), value);\n\t}\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::iterator\nstring_hash_map<T, Hash, Predicate, Allocator>::erase(const_iterator position)\n{\n\tconst char* key = position->first;\n\titerator result = base::base_type::erase(position);\n\tfree(key);\n\treturn result;\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::size_type\nstring_hash_map<T, Hash, Predicate, Allocator>::erase(const char* key)\n{\n    const iterator it(base::base_type::find(key));\n\n    if(it != base::base_type::end())\n    {\n        erase(it);\n        return 1;\n    }\n    return 0;\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::mapped_type&\nstring_hash_map<T, Hash, Predicate, Allocator>::operator[](const char* key)\n{\n\tusing base_value_type = typename base::base_type::value_type;\n\n\tEASTL_ASSERT(key);\n\titerator i = base::base_type::find(key);\n\tif (i != base::base_type::end())\n\t\treturn i->second;\n\treturn base::base_type::insert(base_value_type(pair_first_construct, strduplicate(key))).first->second;\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntemplate <class... Args>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::insert_return_type\nstring_hash_map<T, Hash, Predicate, Allocator>::emplace(const char* key, Args&&...valArgs)\n{\n\treturn try_emplace(key, eastl::forward<Args>(valArgs)...);\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntemplate <class... Args>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::iterator\nstring_hash_map<T, Hash, Predicate, Allocator>::emplace_hint(typename string_hash_map<T, Hash, Predicate, Allocator>::const_iterator hint, const char* key, Args&&...valArgs)\n{\n\treturn try_emplace(hint, key, eastl::forward<Args>(valArgs)...);\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntemplate <class... Args>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::insert_return_type\nstring_hash_map<T, Hash, Predicate, Allocator>::try_emplace(const char* k, Args&&...valArgs)\n{\n\t// This is lifted from hash_map::try_emplace_forwarding.  The point is that we don't want to\n\t// allocate space for a copy of `k` unless we know we're going to insert it.\n\tusing hashtable_type = typename base::base_type;\n\tconst auto key_data = hashtable_type::DoFindKeyData(k);\n\tif (key_data.node)\n\t{\n\t\t// Node exists, no insertion needed.\n\t\treturn eastl::pair<iterator, bool>(\n\t\t\titerator(key_data.node, hashtable_type::mpBucketArray + key_data.bucket_index), false);\n\t}\n\telse\n\t{\n\t\t// We're adding a new node, copy the key.\n\t\tconst char* keyCopy = strduplicate(k);\n\t\ttypename base::node_type* const pNodeNew = hashtable_type::DoAllocateNode(\n\t\t\tpiecewise_construct, eastl::forward_as_tuple(keyCopy), forward_as_tuple(eastl::forward<Args>(valArgs)...));\n\t\treturn hashtable_type::template DoInsertUniqueNode<true>(keyCopy, key_data.code, key_data.bucket_index,\n\t\t\t                                                     pNodeNew);\n\t}\n}\n\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\ntemplate <class... Args>\ntypename string_hash_map<T, Hash, Predicate, Allocator>::iterator\nstring_hash_map<T, Hash, Predicate, Allocator>::try_emplace(typename string_hash_map<T, Hash, Predicate, Allocator>::const_iterator hint, const char* key, Args&&...valArgs)\n{\n\tEA_UNUSED(hint);\n\t// The hint is currently ignored in all our implementations :(\n\tauto ret = try_emplace(key, eastl::forward<Args>(valArgs)...);\n\treturn base::base_type::DoGetResultIterator(true_type(), ret);\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\nchar*\nstring_hash_map<T, Hash, Predicate, Allocator>::strduplicate(const char* str)\n{\n\tsize_t len = strlen(str);\n\tchar* result = (char*)EASTLAlloc(base::base_type::get_allocator(), (len + 1));\n\tmemcpy(result, str, len+1);\n\treturn result;\n}\n\ntemplate<typename T, typename Hash, typename Predicate, typename Allocator>\nvoid\nstring_hash_map<T, Hash, Predicate, Allocator>::free(const char* str)\n{\n\tEASTLFree(base::base_type::get_allocator(), (void*)str, 0);\n}\n\n\n}\n\n#endif\n"
  },
  {
    "path": "include/EASTL/string_map.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_STRING_MAP_H\n#define EASTL_STRING_MAP_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once \n#endif\n\n#include <EASTL/map.h>\n#include <EASTL/string.h>\n\nnamespace eastl\n{\n\n\ntemplate<typename T, typename Predicate = str_less<const char*>, typename Allocator = EASTLAllocatorType>\nclass string_map : public eastl::map<const char*, T, Predicate, Allocator>\n{\npublic:\n\ttypedef eastl::map<const char*, T, Predicate, Allocator> base;\n\ttypedef string_map<T, Predicate, Allocator>              this_type;\n\ttypedef typename base::base_type::allocator_type         allocator_type;\n\ttypedef typename base::base_type::insert_return_type     insert_return_type;\n\ttypedef typename base::base_type::iterator               iterator;\n\ttypedef typename base::base_type::reverse_iterator       reverse_iterator;\n\ttypedef typename base::base_type::const_iterator         const_iterator;\n\ttypedef typename base::base_type::size_type              size_type;\n\ttypedef typename base::base_type::key_type               key_type;\n\ttypedef typename base::base_type::value_type             value_type;\n\ttypedef typename base::mapped_type                       mapped_type;\n\n\t\t                string_map(const allocator_type& allocator = allocator_type()) : base(allocator) {}\n\t\t\t\t\t\tstring_map(const string_map& src, const allocator_type& allocator = allocator_type());\n\t\t\t\t\t\t~string_map();\n\tvoid\t\t\t\tclear();\n\t\n\tthis_type&\t\t\toperator=(const this_type& x);\n\n\tinsert_return_type\tinsert(const char* key, const T& value);\n\tinsert_return_type\tinsert(const char* key);\n\titerator\t\t\terase(iterator position);\n\tsize_type\t\t\terase(const char* key);\n\tmapped_type&\t\toperator[](const char* key);\n\nprivate:\n\tchar*\t\t\t\tstrduplicate(const char* str);\n\n\t// Not implemented right now\n\t// insert_return_type\tinsert(const value_type& value);\n\t// iterator\t\t\t    insert(iterator position, const value_type& value);\n    // reverse_iterator\t    erase(reverse_iterator position);\n    // reverse_iterator\t    erase(reverse_iterator first, reverse_iterator last);\n    // void\t\t\t\t    erase(const key_type* first, const key_type* last);\n};\n\n\n\ntemplate<typename T, typename Predicate, typename Allocator>\nstring_map<T, Predicate, Allocator>::string_map(const string_map& src, const allocator_type& allocator) : base(allocator)\n{\n\tfor (const_iterator i=src.begin(), e=src.end(); i!=e; ++i)\n\t\tbase::base_type::insert(eastl::make_pair(strduplicate(i->first), i->second));\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\nstring_map<T, Predicate, Allocator>::~string_map()\n{\n\tclear();\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\nvoid\nstring_map<T, Predicate, Allocator>::clear()\n{\n\tallocator_type& allocator = base::base_type::get_allocator();\n\tfor (const_iterator i=base::base_type::begin(), e=base::base_type::end(); i!=e; ++i)\n\t\tallocator.deallocate((void*)i->first, 0);\n\tbase::base_type::clear();\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\ntypename string_map<T, Predicate, Allocator>::this_type&\nstring_map<T, Predicate, Allocator>::operator=(const this_type& x)\n{\n\tallocator_type allocator = base::base_type::get_allocator();\n\tthis->~this_type();\n\tnew (this) this_type(x, allocator);\n\treturn *this;\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\ntypename string_map<T, Predicate, Allocator>::insert_return_type\nstring_map<T, Predicate, Allocator>::insert(const char* key)\n{\n\treturn insert(key, mapped_type());\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\ntypename string_map<T, Predicate, Allocator>::insert_return_type\nstring_map<T, Predicate, Allocator>::insert(const char* key, const T& value)\n{\n\tEASTL_ASSERT(key);\n\titerator i = base::base_type::find(key);\n\tif (i != base::base_type::end())\n\t{\n\t\tinsert_return_type ret;\n\t\tret.first = i;\n\t\tret.second = false;\n\t\treturn ret;\n\t}\n\treturn base::base_type::insert(eastl::make_pair(strduplicate(key), value));\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\ntypename string_map<T, Predicate, Allocator>::iterator\nstring_map<T, Predicate, Allocator>::erase(iterator position)\n{\n\tconst char* key = position->first;\n\titerator result = base::base_type::erase(position);\n\tbase::base_type::get_allocator().deallocate((void*)key, 0);\n\treturn result;\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\ntypename string_map<T, Predicate, Allocator>::size_type\nstring_map<T, Predicate, Allocator>::erase(const char* key)\n{\n\tconst iterator it(base::base_type::find(key));\n\n    if(it != base::base_type::end())\n    {\n        erase(it);\n        return 1;\n    }\n    return 0;\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\ntypename string_map<T, Predicate, Allocator>::mapped_type&\nstring_map<T, Predicate, Allocator>::operator[](const char* key)\n{\n\tusing base_value_type = typename base::base_type::value_type;\n\n\tEASTL_ASSERT(key);\n\titerator i = base::base_type::find(key);\n\tif (i != base::base_type::end())\n\t\treturn i->second;\n\treturn base::base_type::insert(base_value_type(pair_first_construct, strduplicate(key))).first->second;\n}\n\ntemplate<typename T, typename Predicate, typename Allocator>\nchar*\nstring_map<T, Predicate, Allocator>::strduplicate(const char* str)\n{\n\tsize_t len = strlen(str);\n\tchar* result = (char*)base::base_type::get_allocator().allocate(len + 1);\n\tmemcpy(result, str, len+1);\n\treturn result;\n}\n\n\n}\n\n#endif\n"
  },
  {
    "path": "include/EASTL/string_view.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements the eastl::string_view which is part of the C++ standard\n// STL library specification.\n//\n// http://en.cppreference.com/w/cpp/header/string_view\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_STRING_VIEW_H\n#define EASTL_STRING_VIEW_H\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/char_traits.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/iterator.h>\n#include <EASTL/numeric_limits.h>\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <stdexcept> // std::out_of_range.\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\nEA_DISABLE_VC_WARNING(4814)\n\nnamespace eastl\n{\n\ttemplate <typename T>\n\tclass basic_string_view\n\t{\n\tpublic:\n\t\ttypedef basic_string_view<T>\t\t\t\t\t\tthis_type;\n\t\ttypedef T \t\t\t\t\t\t\t\t\t\t\tvalue_type;\n\t\ttypedef T* \t\t\t\t\t\t\t\t\t\t\tpointer;\n\t\ttypedef const T* \t\t\t\t\t\t\t\t\tconst_pointer;\n\t\ttypedef T& \t\t\t\t\t\t\t\t\t\t\treference;\n\t\ttypedef const T& \t\t\t\t\t\t\t\t\tconst_reference;\n\t\ttypedef T* \t\t\t\t\t\t\t\t\t\t\titerator;\n\t\ttypedef const T* \t\t\t\t\t\t\t\t\tconst_iterator;\n\t\ttypedef eastl::reverse_iterator<iterator> \t\t\treverse_iterator;\n\t\ttypedef eastl::reverse_iterator<const_iterator> \tconst_reverse_iterator;\n\t\ttypedef size_t \t\t\t\t\t\t\t\t\t\tsize_type;\n\t\ttypedef ptrdiff_t \t\t\t\t\t\t\t\t\tdifference_type;\n\n\t\tstatic const EA_CONSTEXPR size_type npos = size_type(-1);\n\n\tprotected:\n\t\tconst_pointer mpBegin = nullptr;\n\t\tsize_type mnCount = 0;\n\n\tpublic:\n\t\t// 21.4.2.1, construction and assignment\n\t\tEA_CONSTEXPR basic_string_view() EA_NOEXCEPT : mpBegin(nullptr), mnCount(0) {}\n\t\tEA_CONSTEXPR basic_string_view(const basic_string_view& other) EA_NOEXCEPT = default;\n\t\tEA_CONSTEXPR basic_string_view(const T* s, size_type count) : mpBegin(s), mnCount(count) {}\n\t\tEA_CONSTEXPR basic_string_view(const T* s) : mpBegin(s), mnCount(s != nullptr ? CharStrlen(s) : 0) {}\n\t\tbasic_string_view& operator=(const basic_string_view& view) = default;\n\n\t\t// 21.4.2.2, iterator support\n\t\tEA_CONSTEXPR const_iterator begin() const EA_NOEXCEPT { return mpBegin; }\n\t\tEA_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT { return mpBegin; }\n\t\tEA_CONSTEXPR const_iterator end() const EA_NOEXCEPT { return mpBegin + mnCount; }\n\t\tEA_CONSTEXPR const_iterator cend() const EA_NOEXCEPT { return mpBegin + mnCount; }\n\t\tEA_CONSTEXPR const_reverse_iterator rbegin() const EA_NOEXCEPT { return const_reverse_iterator(mpBegin + mnCount); }\n\t\tEA_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT { return const_reverse_iterator(mpBegin + mnCount); }\n\t\tEA_CONSTEXPR const_reverse_iterator rend() const EA_NOEXCEPT { return const_reverse_iterator(mpBegin); }\n\t\tEA_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT { return const_reverse_iterator(mpBegin); }\n\n\n\t\t// 21.4.2.4, element access\n\t\tEA_CONSTEXPR const_pointer data() const { return mpBegin; }\n\t\tEA_CONSTEXPR const_reference front() const\n\t\t{\n\t\t\treturn [&] { EASTL_ASSERT_MSG(!empty(), \"behavior is undefined if string_view is empty\"); }(), mpBegin[0];\n\t\t}\n\n\t\tEA_CONSTEXPR const_reference back() const\n\t\t{\n\t\t\treturn [&] { EASTL_ASSERT_MSG(!empty(), \"behavior is undefined if string_view is empty\"); }(), mpBegin[mnCount - 1];\n\t\t}\n\n\t\tEA_CONSTEXPR const_reference operator[](size_type pos) const\n\t\t{\n\t\t\t// As per the standard spec: No bounds checking is performed: the behavior is undefined if pos >= size().\n\t\t\treturn mpBegin[pos];\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR const_reference at(size_type pos) const\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(pos >= mnCount))\n\t\t\t\t\tthrow std::out_of_range(\"string_view::at -- out of range\");\n\t\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(pos >= mnCount))\n\t\t\t\t\tEASTL_FAIL_MSG(\"string_view::at -- out of range\");\n\t\t\t#endif\n\n\t\t\treturn mpBegin[pos];\n\t\t}\n\n\n\t\t// 21.4.2.3, capacity\n\t\tEA_CONSTEXPR size_type size() const EA_NOEXCEPT { return mnCount; }\n\t\tEA_CONSTEXPR size_type length() const EA_NOEXCEPT { return mnCount; }\n\n\t\t// avoid macro expansion of max(...) from windows headers (potentially included before this file)\n\t\t// by wrapping function name in brackets\n\t\tEA_CONSTEXPR size_type max_size() const EA_NOEXCEPT { return (numeric_limits<size_type>::max)(); }\n\t\tEA_CONSTEXPR bool empty() const EA_NOEXCEPT { return mnCount == 0; }\n\n\n\t\t// 21.4.2.5, modifiers\n\t\tEA_CPP14_CONSTEXPR void swap(basic_string_view& v)\n\t\t{\n\t\t\teastl::swap(mpBegin, v.mpBegin);\n\t\t\teastl::swap(mnCount, v.mnCount);\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR void remove_prefix(size_type n)\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(n <= mnCount, \"behavior is undefined if moving past the end of the string\");\n\t\t\tmpBegin += n;\n\t\t\tmnCount -= n;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR void remove_suffix(size_type n)\n\t\t{\n\t\t\tEASTL_ASSERT_MSG(n <= mnCount, \"behavior is undefined if moving past the beginning of the string\");\n\t\t\tmnCount -= n;\n\t\t}\n\n\n\t\t// 21.4.2.6, string operations\n\t\tsize_type copy(T* pDestination, size_type count, size_type pos = 0) const\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(pos > mnCount))\n\t\t\t\t\tthrow std::out_of_range(\"string_view::copy -- out of range\");\n\t\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(pos > mnCount))\n\t\t\t\t\tEASTL_FAIL_MSG(\"string_view::copy -- out of range\");\n\t\t\t#endif\n\n\t\t\tcount = eastl::min<size_type>(count, mnCount - pos);\n\t\t\tauto* pResult = CharStringUninitializedCopy(mpBegin + pos, mpBegin + pos + count, pDestination);\n\t\t\t// *pResult = 0; // don't write the null-terminator\n\t\t\treturn pResult - pDestination;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR basic_string_view substr(size_type pos = 0, size_type count = npos) const\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(pos > mnCount))\n\t\t\t\t\tthrow std::out_of_range(\"string_view::substr -- out of range\");\n\t\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t\tif(EASTL_UNLIKELY(pos > mnCount))\n\t\t\t\t\tEASTL_FAIL_MSG(\"string_view::substr -- out of range\");\n\t\t\t#endif\n\n\t\t\tcount = eastl::min<size_type>(count, mnCount - pos);\n\t\t\treturn this_type(mpBegin + pos, count);\n\t\t}\n\n\t\tstatic EA_CPP14_CONSTEXPR int compare(const T* pBegin1, const T* pEnd1, const T* pBegin2, const T* pEnd2)\n\t\t{\n\t\t\tconst ptrdiff_t n1   = pEnd1 - pBegin1;\n\t\t\tconst ptrdiff_t n2   = pEnd2 - pBegin2;\n\t\t\tconst ptrdiff_t nMin = eastl::min_alt(n1, n2);\n\t\t\tconst int       cmp  = Compare(pBegin1, pBegin2, (size_type)nMin);\n\n\t\t\treturn (cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0)));\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR int compare(basic_string_view sw) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn compare(mpBegin, mpBegin + mnCount, sw.mpBegin, sw.mpBegin + sw.mnCount);\n\t\t}\n\n\t\tEA_CONSTEXPR int compare(size_type pos1, size_type count1, basic_string_view sw) const\n\t\t{\n\t\t\treturn substr(pos1, count1).compare(sw);\n\t\t}\n\n\t\tEA_CONSTEXPR int compare(size_type pos1,\n\t\t                         size_type count1,\n\t\t                         basic_string_view sw,\n\t\t                         size_type pos2,\n\t\t                         size_type count2) const\n\t\t{\n\t\t\treturn substr(pos1, count1).compare(sw.substr(pos2, count2));\n\t\t}\n\n\t\tEA_CONSTEXPR int compare(const T* s) const { return compare(basic_string_view(s)); }\n\n\t\tEA_CONSTEXPR int compare(size_type pos1, size_type count1, const T* s) const\n\t\t{\n\t\t\treturn substr(pos1, count1).compare(basic_string_view(s));\n\t\t}\n\n\t\tEA_CONSTEXPR int compare(size_type pos1, size_type count1, const T* s, size_type count2) const\n\t\t{\n\t\t\treturn substr(pos1, count1).compare(basic_string_view(s, count2));\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR size_type find(basic_string_view sw, size_type pos = 0) const EA_NOEXCEPT\n\t\t{\n\t\t\tauto* pEnd = mpBegin + mnCount;\n\t\t\tif (EASTL_LIKELY(((npos - sw.size()) >= pos) && (pos + sw.size()) <= mnCount))\n\t\t\t{\n\t\t\t\tconst value_type* const pTemp = eastl::search(mpBegin + pos, pEnd, sw.data(), sw.data() + sw.size());\n\n\t\t\t\tif ((pTemp != pEnd) || (sw.size() == 0))\n\t\t\t\t\treturn (size_type)(pTemp - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find(T c, size_type pos = 0) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn find(basic_string_view(&c, 1), pos);\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find(const T* s, size_type pos, size_type count) const\n\t\t{\n\t\t\treturn find(basic_string_view(s, count), pos);\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find(const T* s, size_type pos = 0) const { return find(basic_string_view(s), pos); }\n\n\t\tEA_CONSTEXPR size_type rfind(basic_string_view sw, size_type pos = npos) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn rfind(sw.mpBegin, pos, sw.mnCount);\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR size_type rfind(T c, size_type pos = npos) const EA_NOEXCEPT\n\t\t{\n\t\t\tif (EASTL_LIKELY(mnCount))\n\t\t\t{\n\t\t\t\tconst value_type* const pEnd = mpBegin + eastl::min_alt(mnCount - 1, pos) + 1;\n\t\t\t\tconst value_type* const pResult = CharTypeStringRFind(pEnd, mpBegin, c);\n\n\t\t\t\tif (pResult != mpBegin)\n\t\t\t\t\treturn (size_type)((pResult - 1) - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR size_type rfind(const T* s, size_type pos, size_type n) const\n\t\t{\n\t\t\t// Disabled because it's not clear what values are valid for position.\n\t\t\t// It is documented that npos is a valid value, though. We return npos and\n\t\t\t// don't crash if postion is any invalid value.\n\t\t\t//#if EASTL_ASSERT_ENABLED\n\t\t\t//    if(EASTL_UNLIKELY((position != npos) && (position > (size_type)(mpEnd - mpBegin))))\n\t\t\t//        EASTL_FAIL_MSG(\"basic_string::rfind -- invalid position\");\n\t\t\t//#endif\n\n\t\t\t// Note that a search for a zero length string starting at position = end() returns end() and not npos.\n\t\t\t// Note by Paul Pedriana: I am not sure how this should behave in the case of n == 0 and position > size.\n\t\t\t// The standard seems to suggest that rfind doesn't act exactly the same as find in that input position\n\t\t\t// can be > size and the return value can still be other than npos. Thus, if n == 0 then you can\n\t\t\t// never return npos, unlike the case with find.\n\t\t\tif (EASTL_LIKELY(n <= mnCount))\n\t\t\t{\n\t\t\t\tif (EASTL_LIKELY(n))\n\t\t\t\t{\n\t\t\t\t\tconst const_iterator pEnd = mpBegin + eastl::min_alt(mnCount - n, pos) + n;\n\t\t\t\t\tconst const_iterator pResult = CharTypeStringRSearch(mpBegin, pEnd, s, s + n);\n\n\t\t\t\t\tif (pResult != pEnd)\n\t\t\t\t\t\treturn (size_type)(pResult - mpBegin);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\treturn eastl::min_alt(mnCount, pos);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CONSTEXPR size_type rfind(const T* s, size_type pos = npos) const\n\t\t{\n\t\t\treturn rfind(s, pos, (size_type)CharStrlen(s));\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_first_of(basic_string_view sw, size_type pos = 0) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn find_first_of(sw.mpBegin, pos, sw.mnCount);\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_first_of(T c, size_type pos = 0) const EA_NOEXCEPT { return find(c, pos); }\n\n\t\tEA_CPP14_CONSTEXPR size_type find_first_of(const T* s, size_type pos, size_type n) const\n\t\t{\n\t\t\t// If position is >= size, we return npos.\n\t\t\tif (EASTL_LIKELY((pos < mnCount)))\n\t\t\t{\n\t\t\t\tconst value_type* const pBegin = mpBegin + pos;\n\t\t\t\tconst value_type* const pEnd = mpBegin + mnCount;\n\t\t\t\tconst const_iterator pResult = CharTypeStringFindFirstOf(pBegin, pEnd, s, s + n);\n\n\t\t\t\tif (pResult != pEnd)\n\t\t\t\t\treturn (size_type)(pResult - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_first_of(const T* s, size_type pos = 0) const\n\t\t{\n\t\t\treturn find_first_of(s, pos, (size_type)CharStrlen(s));\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_last_of(basic_string_view sw, size_type pos = npos) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn find_last_of(sw.mpBegin, pos, sw.mnCount);\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_last_of(T c, size_type pos = npos) const EA_NOEXCEPT { return rfind(c, pos); }\n\n\t\tEA_CPP14_CONSTEXPR size_type find_last_of(const T* s, size_type pos, size_type n) const\n\t\t{\n\t\t\t// If n is zero or position is >= size, we return npos.\n\t\t\tif (EASTL_LIKELY(mnCount))\n\t\t\t{\n\t\t\t\tconst value_type* const pEnd = mpBegin + eastl::min_alt(mnCount - 1, pos) + 1;\n\t\t\t\tconst value_type* const pResult = CharTypeStringRFindFirstOf(pEnd, mpBegin, s, s + n);\n\n\t\t\t\tif (pResult != mpBegin)\n\t\t\t\t\treturn (size_type)((pResult - 1) - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_last_of(const T* s, size_type pos = npos) const\n\t\t{\n\t\t\treturn find_last_of(s, pos, (size_type)CharStrlen(s));\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_first_not_of(basic_string_view sw, size_type pos = 0) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn find_first_not_of(sw.mpBegin, pos, sw.mnCount);\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR size_type find_first_not_of(T c, size_type pos = 0) const EA_NOEXCEPT\n\t\t{\n\t\t\tif (EASTL_LIKELY(pos <= mnCount))\n\t\t\t{\n\t\t\t\tconst auto pEnd = mpBegin + mnCount;\n\t\t\t\t// Todo: Possibly make a specialized version of CharTypeStringFindFirstNotOf(pBegin, pEnd, c).\n\t\t\t\tconst const_iterator pResult = CharTypeStringFindFirstNotOf(mpBegin + pos, pEnd, &c, &c + 1);\n\n\t\t\t\tif (pResult != pEnd)\n\t\t\t\t\treturn (size_type)(pResult - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR size_type find_first_not_of(const T* s, size_type pos, size_type n) const\n\t\t{\n\t\t\tif (EASTL_LIKELY(pos <= mnCount))\n\t\t\t{\n\t\t\t\tconst auto pEnd = mpBegin + mnCount;\n\t\t\t\tconst const_iterator pResult = CharTypeStringFindFirstNotOf(mpBegin + pos, pEnd, s, s + n);\n\n\t\t\t\tif (pResult != pEnd)\n\t\t\t\t\treturn (size_type)(pResult - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_first_not_of(const T* s, size_type pos = 0) const\n\t\t{\n\t\t\treturn find_first_not_of(s, pos, (size_type)CharStrlen(s));\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_last_not_of(basic_string_view sw, size_type pos = npos) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn find_last_not_of(sw.mpBegin, pos, sw.mnCount);\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR size_type find_last_not_of(T c, size_type pos = npos) const EA_NOEXCEPT\n\t\t{\n\t\t\tif (EASTL_LIKELY(mnCount))\n\t\t\t{\n\t\t\t\t// Todo: Possibly make a specialized version of CharTypeStringRFindFirstNotOf(pBegin, pEnd, c).\n\t\t\t\tconst value_type* const pEnd = mpBegin + eastl::min_alt(mnCount - 1, pos) + 1;\n\t\t\t\tconst value_type* const pResult = CharTypeStringRFindFirstNotOf(pEnd, mpBegin, &c, &c + 1);\n\n\t\t\t\tif (pResult != mpBegin)\n\t\t\t\t\treturn (size_type)((pResult - 1) - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR size_type find_last_not_of(const T* s, size_type pos, size_type n) const\n\t\t{\n\t\t\tif (EASTL_LIKELY(mnCount))\n\t\t\t{\n\t\t\t\tconst value_type* const pEnd = mpBegin + eastl::min_alt(mnCount - 1, pos) + 1;\n\t\t\t\tconst value_type* const pResult = CharTypeStringRFindFirstNotOf(pEnd, mpBegin, s, s + n);\n\n\t\t\t\tif (pResult != mpBegin)\n\t\t\t\t\treturn (size_type)((pResult - 1) - mpBegin);\n\t\t\t}\n\t\t\treturn npos;\n\t\t}\n\n\t\tEA_CONSTEXPR size_type find_last_not_of(const T* s, size_type pos = npos) const\n\t\t{\n\t\t\treturn find_last_not_of(s, pos, (size_type)CharStrlen(s));\n\t\t}\n\n\t\t// starts_with\n\t\tEA_CONSTEXPR bool starts_with(basic_string_view x) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (size() >= x.size()) && (compare(0, x.size(), x) == 0);\n\t\t}\n\n\t\tEA_CONSTEXPR bool starts_with(T x) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn starts_with(basic_string_view(&x, 1));\n\t\t}\n\n\t\tEA_CONSTEXPR bool starts_with(const T* s) const\n\t\t{\n\t\t\treturn starts_with(basic_string_view(s));\n\t\t}\n\n\t\t// ends_with\n\t\tEA_CONSTEXPR bool ends_with(basic_string_view x) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn (size() >= x.size()) && (compare(size() - x.size(), npos, x) == 0);\n\t\t}\n\n\t\tEA_CONSTEXPR bool ends_with(T x) const EA_NOEXCEPT\n\t\t{\n\t\t\treturn ends_with(basic_string_view(&x, 1));\n\t\t}\n\n\t\tEA_CONSTEXPR bool ends_with(const T* s) const\n\t\t{\n\t\t\treturn ends_with(basic_string_view(s));\n\t\t}\n\t};\n\n\n\t// global operators\n\n\t// Extra template parameter is to get around a known limitation in MSVC's ABI (name decoration)\n\ttemplate <class CharT, int = 0>\n\tinline EA_CONSTEXPR bool operator==(basic_string_view<CharT> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn (lhs.size() == rhs.size()) && (lhs.compare(rhs) == 0);\n\t}\n\t\n\t// type_identity_t is used in this context to forcefully trigger conversion operators towards basic_string_view.\n\t// Mostly we want basic_string::operator basic_string_view() to kick-in to be able to compare strings and string_views.\n\ttemplate <class CharT, int = 1>\n\tinline EA_CONSTEXPR bool operator==(type_identity_t<basic_string_view<CharT>> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn (lhs.size() == rhs.size()) && (lhs.compare(rhs) == 0);\n\t}\n\n\ttemplate <class CharT, int = 2>\n\tinline EA_CONSTEXPR bool operator==(basic_string_view<CharT> lhs, type_identity_t<basic_string_view<CharT>> rhs) EA_NOEXCEPT\n\t{\n\t\treturn (lhs.size() == rhs.size()) && (lhs.compare(rhs) == 0);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <class CharT>\n\tinline EA_CONSTEXPR auto operator<=>(basic_string_view<CharT> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<std::weak_ordering>(lhs.compare(rhs) <=> 0);\n\t}\n\n\ttemplate <class CharT>\n\tinline EA_CONSTEXPR auto operator<=>(basic_string_view<CharT> lhs, typename basic_string_view<CharT>::const_pointer rhs) EA_NOEXCEPT\n\t{\n\t\ttypedef basic_string_view<CharT> view_type;\n\t\treturn static_cast<std::weak_ordering>(lhs <=> static_cast<view_type>(rhs));\n\t}\n\n#else\n\t// Extra template parameter is to get around a known limitation in MSVC's ABI (name decoration)\n\ttemplate <class CharT, int = 0>\n\tinline EA_CONSTEXPR bool operator!=(basic_string_view<CharT> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(lhs == rhs);\n\t}\n\t\n\ttemplate <class CharT, int = 1>\n\tinline EA_CONSTEXPR bool operator!=(type_identity_t<basic_string_view<CharT>> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(lhs == rhs);\n\t}\n\n\ttemplate <class CharT>\n\tinline EA_CONSTEXPR bool operator!=(basic_string_view<CharT> lhs, type_identity_t<basic_string_view<CharT>> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(lhs == rhs);\n\t}\n\n\t// Extra template parameter is to get around a known limitation in MSVC's ABI (name decoration)\n\ttemplate <class CharT, int = 0>\n\tinline EA_CONSTEXPR bool operator<(basic_string_view<CharT> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn lhs.compare(rhs) < 0;\n\t}\n\t\n\ttemplate <class CharT, int = 1>\n\tinline EA_CONSTEXPR bool operator<(type_identity_t<basic_string_view<CharT>> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn lhs.compare(rhs) < 0;\n\t}\n\n\ttemplate <class CharT>\n\tinline EA_CONSTEXPR bool operator<(basic_string_view<CharT> lhs, type_identity_t<basic_string_view<CharT>> rhs) EA_NOEXCEPT\n\t{\n\t\treturn lhs.compare(rhs) < 0;\n\t}\n\n\t// Extra template parameter is to get around a known limitation in MSVC's ABI (name decoration)\n\ttemplate <class CharT, int = 0>\n\tinline EA_CONSTEXPR bool operator<=(basic_string_view<CharT> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(rhs < lhs);\n\t}\n\t\n\ttemplate <class CharT, int = 1>\n\tinline EA_CONSTEXPR bool operator<=(type_identity_t<basic_string_view<CharT>> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(rhs < lhs);\n\t}\n\n\ttemplate <class CharT>\n\tinline EA_CONSTEXPR bool operator<=(basic_string_view<CharT> lhs, type_identity_t<basic_string_view<CharT>> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(rhs < lhs);\n\t}\n\n\t// Extra template parameter is to get around a known limitation in MSVC's ABI (name decoration)\n\ttemplate <class CharT, int = 0>\n\tinline EA_CONSTEXPR bool operator>(basic_string_view<CharT> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn rhs < lhs;\n\t}\n\t\n\ttemplate <class CharT, int = 1>\n\tinline EA_CONSTEXPR bool operator>(type_identity_t<basic_string_view<CharT>> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn rhs < lhs;\n\t}\n\n\ttemplate <class CharT>\n\tinline EA_CONSTEXPR bool operator>(basic_string_view<CharT> lhs, type_identity_t<basic_string_view<CharT>> rhs) EA_NOEXCEPT\n\t{\n\t\treturn rhs < lhs;\n\t}\n\n\t// Extra template parameter is to get around a known limitation in MSVC's ABI (name decoration)\n\ttemplate <class CharT, int = 0>\n\tinline EA_CONSTEXPR bool operator>=(basic_string_view<CharT> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(lhs < rhs);\n\t}\n\t\n\ttemplate <class CharT, int = 1>\n\tinline EA_CONSTEXPR bool operator>=(type_identity_t<basic_string_view<CharT>> lhs, basic_string_view<CharT> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(lhs < rhs);\n\t}\n\n\ttemplate <class CharT>\n\tinline EA_CONSTEXPR bool operator>=(basic_string_view<CharT> lhs, type_identity_t<basic_string_view<CharT>> rhs) EA_NOEXCEPT\n\t{\n\t\treturn !(lhs < rhs);\n\t}\n#endif\n\t// string_view / wstring_view \n\ttypedef basic_string_view<char>    string_view;\n\ttypedef basic_string_view<wchar_t> wstring_view;\n\n\t// C++17 string types\n\ttypedef basic_string_view<char8_t>  u8string_view;  // C++20 feature, but always present for consistency.\n\ttypedef basic_string_view<char16_t> u16string_view;\n\ttypedef basic_string_view<char32_t> u32string_view;\n\n\n\t/// hash<string_view>\n\t///\n\t/// We provide EASTL hash function objects for use in hash table containers.\n\t///\n\t/// Example usage:\n\t///    #include <EASTL/hash_set.h>\n\t///    hash_set<string_view> stringHashSet;\n\t///\n\ttemplate <typename T> struct hash;\n\n\ttemplate<> struct hash<string_view>\n\t{\n\t\tsize_t operator()(const string_view& x) const\n\t\t{\n\t\t\tstring_view::const_iterator p = x.cbegin();\n\t\t\tstring_view::const_iterator end = x.cend();\n\t\t\tuint32_t result = 2166136261U; // We implement an FNV-like string hash.\n\t\t\twhile (p != end)\n\t\t\t\tresult = (result * 16777619) ^ (uint8_t)*p++;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\t\ttemplate<> struct hash<u8string_view>\n\t\t{\n\t\t\tsize_t operator()(const u8string_view& x) const\n\t\t\t{\n\t\t\t\tu8string_view::const_iterator p = x.cbegin();\n\t\t\t\tu8string_view::const_iterator end = x.cend();\n\t\t\t\tuint32_t result = 2166136261U;\n\t\t\t\twhile (p != end)\n\t\t\t\t\tresult = (result * 16777619) ^ (uint8_t)*p++;\n\t\t\t\treturn (size_t)result;\n\t\t\t}\n\t\t};\n\t#endif\n\n\ttemplate<> struct hash<u16string_view>\n\t{\n\t\tsize_t operator()(const u16string_view& x) const\n\t\t{\n\t\t\tu16string_view::const_iterator p = x.cbegin();\n\t\t\tu16string_view::const_iterator end = x.cend();\n\t\t\tuint32_t result = 2166136261U;\n\t\t\twhile (p != end)\n\t\t\t\tresult = (result * 16777619) ^ (uint16_t)*p++;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\ttemplate<> struct hash<u32string_view>\n\t{\n\t\tsize_t operator()(const u32string_view& x) const\n\t\t{\n\t\t\tu32string_view::const_iterator p = x.cbegin();\n\t\t\tu32string_view::const_iterator end = x.cend();\n\t\t\tuint32_t result = 2166136261U;\n\t\t\twhile (p != end)\n\t\t\t\tresult = (result * 16777619) ^ (uint32_t)*p++;\n\t\t\treturn (size_t)result;\n\t\t}\n\t};\n\n\t#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\t\ttemplate<> struct hash<wstring_view>\n\t\t{\n\t\t\tsize_t operator()(const wstring_view& x) const\n\t\t\t{\n\t\t\t\twstring_view::const_iterator p = x.cbegin();\n\t\t\t\twstring_view::const_iterator end = x.cend();\n\t\t\t\tuint32_t result = 2166136261U;\n\t\t\t\twhile (p != end)\n\t\t\t\t\tresult = (result * 16777619) ^ (uint32_t)*p++;\n\t\t\t\treturn (size_t)result;\n\t\t\t}\n\t\t};\n\t#endif\n\n\n\t#if EASTL_USER_LITERALS_ENABLED && EASTL_INLINE_NAMESPACES_ENABLED\n\t\t// Disabling the Clang/GCC/MSVC warning about using user\n\t\t// defined literals without a leading '_' as they are reserved\n\t\t// for standard libary usage.\n\t\tEA_DISABLE_VC_WARNING(4455)\n\t\tEA_DISABLE_CLANG_WARNING(-Wuser-defined-literals)\n\t\tEA_DISABLE_GCC_WARNING(-Wliteral-suffix)\n\n\t    inline namespace literals\n\t    {\n\t\t    inline namespace string_view_literals\n\t\t    {\n\t\t\t    EA_CONSTEXPR inline string_view operator \"\" sv(const char* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t    EA_CONSTEXPR inline u16string_view operator \"\" sv(const char16_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t    EA_CONSTEXPR inline u32string_view operator \"\" sv(const char32_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t    EA_CONSTEXPR inline wstring_view operator \"\" sv(const wchar_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\n\t\t\t\t// We've seen _sv trigger the following warning on clang:\n\t\t\t\t// identifier '_sv' is reserved because it starts with '_' at global scope [-Wreserved-identifier]\n\t\t\t\t// Temporarily disable the warning until we figure out why it thinks _sv is \"at global scope\".\n\t\t\t\tEA_DISABLE_CLANG_WARNING(-Wreserved-identifier)\n\t\t\t\t// Backwards compatibility.\n\t\t\t    EA_CONSTEXPR inline string_view operator \"\" _sv(const char* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t    EA_CONSTEXPR inline u16string_view operator \"\" _sv(const char16_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t    EA_CONSTEXPR inline u32string_view operator \"\" _sv(const char32_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t    EA_CONSTEXPR inline wstring_view operator \"\" _sv(const wchar_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t\tEA_RESTORE_CLANG_WARNING()\t// -Wreserved-identifier\n\n\t\t\t\t// C++20 char8_t support.\n\t\t\t\t#if EA_CHAR8_UNIQUE\n\t\t\t\t\tEA_CONSTEXPR inline u8string_view operator \"\" sv(const char8_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t\t\tEA_CONSTEXPR inline u8string_view operator \"\" _sv(const char8_t* str, size_t len) EA_NOEXCEPT { return {str, len}; }\n\t\t\t\t#endif\n\t\t    }\n\t    }\n\n\t\tEA_RESTORE_GCC_WARNING()\t// -Wliteral-suffix\n\t\tEA_RESTORE_CLANG_WARNING()\t// -Wuser-defined-literals\n\t\tEA_RESTORE_VC_WARNING()\t\t// warning: 4455\n\t#endif\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING()\n#endif // EASTL_STRING_VIEW_H\n"
  },
  {
    "path": "include/EASTL/tuple.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_TUPLE_H\n#define EASTL_TUPLE_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/compare.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/utility.h>\n\n#include <EASTL/internal/tuple_fwd_decls.h>\n\nEA_DISABLE_VC_WARNING(4623) // warning C4623: default constructor was implicitly defined as deleted\nEA_DISABLE_VC_WARNING(4625) // warning C4625: copy constructor was implicitly defined as deleted\nEA_DISABLE_VC_WARNING(4510) // warning C4510: default constructor could not be generated\n\n#if EASTL_TUPLE_ENABLED\n\nnamespace eastl\n{\n// non-recursive tuple implementation based on libc++ tuple implementation and description at\n// http://mitchnull.blogspot.ca/2012/06/c11-tuple-implementation-details-part-1.html\n\n// TupleTypes helper\ntemplate <typename... Ts> struct TupleTypes {};\n\n// tuple_size helper\ntemplate <typename T> struct tuple_size {};\ntemplate <typename T> struct tuple_size<const T>          : public tuple_size<T> {};\ntemplate <typename T> struct tuple_size<volatile T>       : public tuple_size<T> {};\ntemplate <typename T> struct tuple_size<const volatile T> : public tuple_size<T> {};\n\ntemplate <typename... Ts> struct tuple_size<TupleTypes<Ts...>> : public integral_constant<size_t, sizeof...(Ts)> {};\ntemplate <typename... Ts> struct tuple_size<tuple<Ts...>>      : public integral_constant<size_t, sizeof...(Ts)> {};\n\nnamespace Internal\n{\n\ttemplate <typename TupleIndices, typename... Ts>\n\tstruct TupleImpl;\n} // namespace Internal\n\ntemplate <typename Indices, typename... Ts>\nstruct tuple_size<Internal::TupleImpl<Indices, Ts...>> : public integral_constant<size_t, sizeof...(Ts)>\n{\n};\n\n// tuple_element helper to be able to isolate a type given an index\ntemplate <size_t I, typename T>\nstruct tuple_element\n{\n};\n\ntemplate <size_t I>\nstruct tuple_element<I, TupleTypes<>>\n{\npublic:\n\tstatic_assert(I != I, \"tuple_element index out of range\");\n};\n\ntemplate <typename H, typename... Ts>\nstruct tuple_element<0, TupleTypes<H, Ts...>>\n{\npublic:\n\ttypedef H type;\n};\n\ntemplate <size_t I, typename H, typename... Ts>\nstruct tuple_element<I, TupleTypes<H, Ts...>>\n{\npublic:\n\ttypedef tuple_element_t<I - 1, TupleTypes<Ts...>> type;\n};\n\n// specialization for tuple\ntemplate <size_t I, typename... Ts>\nstruct tuple_element<I, tuple<Ts...>>\n{\npublic:\n\ttypedef tuple_element_t<I, TupleTypes<Ts...>> type;\n};\n\ntemplate <size_t I, typename T>\nstruct tuple_element<I, const T>\n{\npublic:\n\ttypedef add_const_t<tuple_element_t<I, T>> type;\n};\n\ntemplate <size_t I, typename... Ts>\nstruct EA_REMOVE_AT_2026_APRIL tuple_element<I, volatile tuple<Ts...>>\n{\npublic:\n\ttypedef typename add_volatile<tuple_element_t<I, TupleTypes<Ts...>>>::type type;\n};\n\ntemplate <size_t I, typename... Ts>\nstruct EA_REMOVE_AT_2026_APRIL tuple_element<I, const volatile tuple<Ts...>>\n{\npublic:\n\ttypedef typename add_cv<tuple_element_t<I, TupleTypes<Ts...>>>::type type;\n};\n\n// specialization for TupleImpl\ntemplate <size_t I, typename Indices, typename... Ts>\nstruct tuple_element<I, Internal::TupleImpl<Indices, Ts...>> : public tuple_element<I, tuple<Ts...>>\n{\n};\n\ntemplate <size_t I, typename Indices, typename... Ts>\nstruct tuple_element<I, const Internal::TupleImpl<Indices, Ts...>> : public tuple_element<I, const tuple<Ts...>>\n{\n};\n\ntemplate <size_t I, typename Indices, typename... Ts>\nstruct tuple_element<I, volatile Internal::TupleImpl<Indices, Ts...>> : public tuple_element<I, volatile tuple<Ts...>>\n{\n};\n\ntemplate <size_t I, typename Indices, typename... Ts>\nstruct tuple_element<I, const volatile Internal::TupleImpl<Indices, Ts...>> : public tuple_element<\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t I, const volatile tuple<Ts...>>\n{\n};\n\n// attempt to isolate index given a type\ntemplate <typename T, typename Tuple>\nstruct tuple_index\n{\n};\n\ntemplate <typename T>\nstruct tuple_index<T, TupleTypes<>>\n{\n\ttypedef void DuplicateTypeCheck;\n\ttuple_index() = delete; // tuple_index should only be used for compile-time assistance, and never be instantiated\n\tstatic const size_t index = 0;\n};\n\ntemplate <typename T, typename... TsRest>\nstruct tuple_index<T, TupleTypes<T, TsRest...>>\n{\n\ttypedef int DuplicateTypeCheck;\n\t// after finding type T in the list of types, try to find type T in TsRest.\n\t// If we stumble back into this version of tuple_index, i.e. type T appears twice in the list of types, then DuplicateTypeCheck will be of type int, and the static_assert will fail.\n\t// If we don't, then we'll go through the version of tuple_index above, where all of the types have been exhausted, and DuplicateTypeCheck will be void.\n\tstatic_assert(is_void<typename tuple_index<T, TupleTypes<TsRest...>>::DuplicateTypeCheck>::value, \"duplicate type T in tuple_vector::get<T>(); unique types must be provided in declaration, or only use get<size_t>()\");\n\n\tstatic const size_t index = 0;\n};\n\ntemplate <typename T, typename TsHead, typename... TsRest>\nstruct tuple_index<T, TupleTypes<TsHead, TsRest...>>\n{\n\ttypedef typename tuple_index<T, TupleTypes<TsRest...>>::DuplicateTypeCheck DuplicateTypeCheck;\n\tstatic const size_t index = tuple_index<T, TupleTypes<TsRest...>>::index + 1;\n};\n\ntemplate <typename T, typename Indices, typename... Ts>\nstruct tuple_index<T, Internal::TupleImpl<Indices, Ts...>> : public tuple_index<T, TupleTypes<Ts...>>\n{\n};\n\n\nnamespace Internal\n{\n\t// swallow\n\t//\n\t// Provides a vessel to expand variadic packs.\n\t//\n\ttemplate <typename... Ts>\n\tvoid swallow(Ts&&...) {}\n\n\n\t// TupleLeaf\n\t//\n\ttemplate <size_t I, typename ValueType, bool IsEmpty = is_empty_v<ValueType>>\n\tclass TupleLeaf;\n\n\ttemplate <size_t I, typename ValueType, bool IsEmpty>\n\tinline void swap(TupleLeaf<I, ValueType, IsEmpty>& a, TupleLeaf<I, ValueType, IsEmpty>& b)\n\t{\n\t\teastl::swap(a.getInternal(), b.getInternal());\n\t}\n\n\ttemplate <size_t I, typename ValueType, bool IsEmpty>\n\tclass TupleLeaf\n\t{\n\tpublic:\n\t\tTupleLeaf() : mValue() {}\n\n\t\t// We shouldn't need this explicit constructor as it should be handled by the template below but OSX clang\n\t\t// is_constructible type trait incorrectly gives false for is_constructible<T&&, T&&>::value\n\t\texplicit TupleLeaf(ValueType&& v) : mValue(eastl::forward<ValueType>(v)) {}\n\n\t\ttemplate <typename T, typename = typename enable_if<is_constructible<ValueType, T&&>::value>::type>\n\t\texplicit TupleLeaf(T&& t)\n\t\t\t: mValue(eastl::forward<T>(t))\n\t\t{\n\t\t}\n\t\t\n\t\tTupleLeaf(const TupleLeaf&) = default;\n\t\tTupleLeaf(TupleLeaf&&) noexcept = default;\n\n\t\t// The standard requires the assignment for tuples to assign each element of the tuple,\n\t\t// in particular this should work for tuple<T&>. If we default the assignment(s) here,\n\t\t// TupleLeaf would have its assignment deleted when ValueType is a reference type\n\t\t// because it has a member of that type, then TupleImpl has the assignment deleted due\n\t\t// to the inheritance and then so does tuple<T&> because it has a member of type\n\t\t// TupleImpl. So we explicitly implement the assignment so it isn't deleted in tuple<T&>.\n\t\tTupleLeaf& operator=(const TupleLeaf& t)\n\t\t{\n\t\t\tmValue = t.getInternal();\n\t\t\treturn *this;\n\t\t}\n\t\tTupleLeaf& operator=(TupleLeaf&& t) noexcept\n\t\t{\n\t\t\tmValue = eastl::move(t.getInternal());\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename T>\n\t\tTupleLeaf& operator=(T&& t)\n\t\t{\n\t\t\tmValue = eastl::forward<T>(t);\n\t\t\treturn *this;\n\t\t}\n\n\t\tint swap(TupleLeaf& t)\n\t\t{\n\t\t\teastl::Internal::swap(*this, t);\n\t\t\treturn 0;\n\t\t}\n\n\t\tValueType& getInternal() { return mValue; }\n\t\tconst ValueType& getInternal() const { return mValue; }\n\n\tprivate:\n\t\tValueType mValue;  \n\t};\n\n\t// TupleLeaf: partial specialization for when we can use the Empty Base Class Optimization\n\ttemplate <size_t I, typename ValueType>\n\tclass TupleLeaf<I, ValueType, true> : private ValueType\n\t{\n\tpublic:\n\t\tTupleLeaf() = default;\n\n\t\t// We shouldn't need this explicit constructor as it should be handled by the template below but OSX clang\n\t\t// is_constructible type trait incorrectly gives false for is_constructible<T&&, T&&>::value\n\t\texplicit TupleLeaf(ValueType&& v) : ValueType(eastl::forward<ValueType>(v)) {}\n\n\t\ttemplate <typename T, typename = typename enable_if<is_constructible<ValueType, T&&>::value>::type>\n\t\texplicit TupleLeaf(T&& t)\n\t\t\t: ValueType(eastl::forward<T>(t))\n\t\t{\n\t\t}\n\n\t\tTupleLeaf(const TupleLeaf&) = default;\n\t\tTupleLeaf(TupleLeaf&&) noexcept = default;\n\t\tTupleLeaf& operator=(const TupleLeaf&) = default;\n\t\tTupleLeaf& operator=(TupleLeaf&&) noexcept = default;\n\n\t\ttemplate <typename T>\n\t\tTupleLeaf& operator=(T&& t)\n\t\t{\n\t\t\tValueType::operator=(eastl::forward<T>(t));\n\t\t\treturn *this;\n\t\t}\n\n\t\tint swap(TupleLeaf& t)\n\t\t{\n\t\t\teastl::Internal::swap(*this, t);\n\t\t\treturn 0;\n\t\t}\n\n\t\tValueType& getInternal() { return static_cast<ValueType&>(*this); }\n\t\tconst ValueType& getInternal() const { return static_cast<const ValueType&>(*this); }\n\t};\n\n\n\n\t// MakeTupleTypes\n\t//\n\t//\n\ttemplate <typename TupleTypes, typename Tuple, size_t Start, size_t End>\n\tstruct MakeTupleTypesImpl;\n\n\ttemplate <typename... Types, typename Tuple, size_t Start, size_t End>\n\tstruct MakeTupleTypesImpl<TupleTypes<Types...>, Tuple, Start, End>\n\t{\n\t\ttypedef typename remove_reference<Tuple>::type TupleType;\n\t\ttypedef typename MakeTupleTypesImpl<\n\t\t\tTupleTypes<Types..., typename conditional<is_lvalue_reference<Tuple>::value,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  // append ref if Tuple is ref\n\t\t\t\t\t\t\t\t\t\t\t\t\t  tuple_element_t<Start, TupleType>&,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  // append non-ref otherwise\n\t\t\t\t\t\t\t\t\t\t\t\t\t  tuple_element_t<Start, TupleType>>::type>,\n\t\t\tTuple, Start + 1, End>::type type;\n\t};\n\n\ttemplate <typename... Types, typename Tuple, size_t End>\n\tstruct MakeTupleTypesImpl<TupleTypes<Types...>, Tuple, End, End>\n\t{\n\t\ttypedef TupleTypes<Types...> type;\n\t};\n\n\ttemplate <typename Tuple>\n\tusing MakeTupleTypes_t = typename MakeTupleTypesImpl<TupleTypes<>, Tuple, 0,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t tuple_size<typename remove_reference<Tuple>::type>::value>::type;\n\n\n\t// TupleImpl\n\t//\n\t//\n\n\ttemplate <size_t... Indices, typename... Ts>\n\tstruct TupleImpl<integer_sequence<size_t, Indices...>, Ts...> : public TupleLeaf<Indices, Ts>...\n\t{\n\t\tEA_CONSTEXPR TupleImpl() = default;\n\n\t\t// index_sequence changed to integer_sequence due to issues described below in VS2015 CTP 6. \n\t\t// https://connect.microsoft.com/VisualStudio/feedback/details/1126958/error-in-template-parameter-pack-expansion-of-std-index-sequence\n\t\t// \n\t\ttemplate <typename... Us, typename... ValueTypes>\n\t\texplicit TupleImpl(integer_sequence<size_t, Indices...>, TupleTypes<Us...>, ValueTypes&&... values)\n\t\t\t: TupleLeaf<Indices, Ts>(eastl::forward<ValueTypes>(values))...\n\t\t{\n\t\t}\n\n\t\tTupleImpl(const TupleImpl&) = default;\n\t\tTupleImpl(TupleImpl&&) noexcept = default;\n\t\tTupleImpl& operator=(const TupleImpl&) = default;\n\t\tTupleImpl& operator=(TupleImpl&&) noexcept = default;\n\n\t\ttemplate <typename OtherTuple>\n\t\tTupleImpl(OtherTuple&& t)\n\t\t\t: TupleLeaf<Indices, Ts>(eastl::forward<tuple_element_t<Indices, MakeTupleTypes_t<OtherTuple>>>(get<Indices>(t)))...\n\t\t{\n\t\t}\n\n\t\ttemplate <typename OtherTuple>\n\t\tTupleImpl& operator=(OtherTuple&& t)\n\t\t{\n\t\t\tswallow(TupleLeaf<Indices, Ts>::operator=(\n\t\t\t\t\t\teastl::forward<tuple_element_t<Indices, MakeTupleTypes_t<OtherTuple>>>(get<Indices>(t)))...);\n\t\t\treturn *this;\n\t\t}\n\n\t\tvoid swap(TupleImpl& t) { swallow(TupleLeaf<Indices, Ts>::swap(static_cast<TupleLeaf<Indices, Ts>&>(t))...); }\n\t};\n\n\ttemplate <size_t I, typename Indices, typename... Ts>\n\tinline tuple_element_t<I, TupleImpl<Indices, Ts...>>& getImpl(TupleImpl<Indices, Ts...>& t)\n\t{\n\t\ttypedef tuple_element_t<I, TupleImpl<Indices, Ts...>> Type;\n\t\treturn static_cast<TupleLeaf<I, Type>&>(t).getInternal();\n\t}\n\n\ttemplate <size_t I, typename Indices, typename... Ts>\n\tinline const_tuple_element_t<I, TupleImpl<Indices, Ts...>>& getImpl(const TupleImpl<Indices, Ts...>& t)\n\t{\n\t\ttypedef tuple_element_t<I, TupleImpl<Indices, Ts...>> Type;\n\t\treturn static_cast<const TupleLeaf<I, Type>&>(t).getInternal();\n\t}\n\n\ttemplate <size_t I, typename Indices, typename... Ts>\n\tinline tuple_element_t<I, TupleImpl<Indices, Ts...>>&& getImpl(TupleImpl<Indices, Ts...>&& t)\n\t{\n\t\ttypedef tuple_element_t<I, TupleImpl<Indices, Ts...>> Type;\n\t\treturn static_cast<Type&&>(static_cast<TupleLeaf<I, Type>&>(t).getInternal());\n\t}\n\n\ttemplate <typename T, typename Indices, typename... Ts>\n\tinline T& getImpl(TupleImpl<Indices, Ts...>& t)\n\t{\n\t\ttypedef tuple_index<T, TupleImpl<Indices, Ts...>> Index;\n\t\treturn static_cast<TupleLeaf<Index::index, T>&>(t).getInternal();\n\t}\n\n\ttemplate <typename T, typename Indices, typename... Ts>\n\tinline const T& getImpl(const TupleImpl<Indices, Ts...>& t)\n\t{\n\t\ttypedef tuple_index<T, TupleImpl<Indices, Ts...>> Index;\n\t\treturn static_cast<const TupleLeaf<Index::index, T>&>(t).getInternal();\n\t}\n\n\ttemplate <typename T, typename Indices, typename... Ts>\n\tinline T&& getImpl(TupleImpl<Indices, Ts...>&& t)\n\t{\n\t\ttypedef tuple_index<T, TupleImpl<Indices, Ts...>> Index;\n\t\treturn static_cast<T&&>(static_cast<TupleLeaf<Index::index, T>&>(t).getInternal());\n\t}\n\n\n\t// TupleLike\n\t//\n\t// type-trait that determines if a type is an eastl::tuple or an eastl::pair.\n\t//\n\ttemplate <typename T> struct TupleLike                   : public false_type {};\n\ttemplate <typename T> struct TupleLike<const T>          : public TupleLike<T> {};\n\ttemplate <typename T> struct TupleLike<volatile T>       : public TupleLike<T> {};\n\ttemplate <typename T> struct TupleLike<const volatile T> : public TupleLike<T> {};\n\n\ttemplate <typename... Ts>\n\tstruct TupleLike<tuple<Ts...>> : public true_type {};\n\n\ttemplate <typename First, typename Second>\n\tstruct TupleLike<eastl::pair<First, Second>> : public true_type {};\n\n\n\t// TupleConvertible\n\t//\n\t//\n\t//\n\ttemplate <bool IsSameSize, typename From, typename To>\n\tstruct TupleConvertibleImpl : public false_type\n\t{\n\t};\n\n\ttemplate <typename... FromTypes, typename... ToTypes>\n\tstruct TupleConvertibleImpl<true, TupleTypes<FromTypes...>,\tTupleTypes<ToTypes...>>\n\t\t: public integral_constant<bool, conjunction<is_convertible<FromTypes, ToTypes>...>::value>\n\t{\n\t};\n\n\ttemplate <typename From, typename To,\n\t\t\t  bool = TupleLike<typename remove_reference<From>::type>::value,\n\t\t\t  bool = TupleLike<typename remove_reference<To>::type>::value>\n\tstruct TupleConvertible : public false_type\n\t{\n\t};\n\n\ttemplate <typename From, typename To>\n\tstruct TupleConvertible<From, To, true, true>\n\t\t: public TupleConvertibleImpl<tuple_size<typename remove_reference<From>::type>::value ==\n\t\t\t\ttuple_size<typename remove_reference<To>::type>::value,\n\t\t\t\tMakeTupleTypes_t<From>, MakeTupleTypes_t<To>>\n\t{\n\t};\n\n\n\t// TupleAssignable\n\t//\n\t//\n\t//\n\ttemplate <bool IsSameSize, typename Target, typename From>\n\tstruct TupleAssignableImpl : public false_type\n\t{\n\t};\n\n\ttemplate <typename... TargetTypes, typename... FromTypes>\n\tstruct TupleAssignableImpl<true, TupleTypes<TargetTypes...>, TupleTypes<FromTypes...>>\n\t\t: public bool_constant<conjunction<is_assignable<TargetTypes, FromTypes>...>::value>\n\t{\n\t};\n\n\ttemplate <typename Target, typename From,\n\t\t\t  bool = TupleLike<typename remove_reference<Target>::type>::value,\n\t\t\t  bool = TupleLike<typename remove_reference<From>::type>::value>\n\tstruct TupleAssignable : public false_type\n\t{\n\t};\n\n\ttemplate <typename Target, typename From>\n\tstruct TupleAssignable<Target, From, true, true>\n\t\t: public TupleAssignableImpl<\n\t\t\ttuple_size<typename remove_reference<Target>::type>::value ==\n\t\t\ttuple_size<typename remove_reference<From>::type>::value,\n\t\t\tMakeTupleTypes_t<Target>, MakeTupleTypes_t<From>>\n\t{\n\t};\n\n\n\t// TupleImplicitlyConvertible and TupleExplicitlyConvertible \n\t//\n\t// helpers for constraining conditionally-explicit ctors\n\t//\n\ttemplate <bool IsSameSize, typename TargetType, typename... FromTypes>\n\tstruct TupleImplicitlyConvertibleImpl : public false_type\n\t{\n\t};\n\n\n\ttemplate <typename... TargetTypes, typename... FromTypes>\n\tstruct TupleImplicitlyConvertibleImpl<true, TupleTypes<TargetTypes...>, FromTypes...>\n\t\t: public conjunction<\n\t\tis_constructible<TargetTypes, FromTypes>...,\n\t\tis_convertible<FromTypes, TargetTypes>...>\n\t{\n\t};\n\n\ttemplate <typename TargetTupleType, typename... FromTypes>\n\tstruct TupleImplicitlyConvertible\n\t\t: public TupleImplicitlyConvertibleImpl<\n\t\ttuple_size<TargetTupleType>::value == sizeof...(FromTypes),\n\t\tMakeTupleTypes_t<TargetTupleType>, FromTypes...>::type\n\t{\n\t};\n\n\ttemplate<typename TargetTupleType, typename... FromTypes>\n\tusing TupleImplicitlyConvertible_t = enable_if_t<TupleImplicitlyConvertible<TargetTupleType, FromTypes...>::value, bool>;\n\n\ttemplate <bool IsSameSize, typename TargetType, typename... FromTypes>\n\tstruct TupleExplicitlyConvertibleImpl : public false_type\n\t{\n\t};\n\n\ttemplate <typename... TargetTypes, typename... FromTypes>\n\tstruct TupleExplicitlyConvertibleImpl<true, TupleTypes<TargetTypes...>, FromTypes...>\n\t\t: public conjunction<\n\t\t\tis_constructible<TargetTypes, FromTypes>...,\n\t\t\tnegation<conjunction<is_convertible<FromTypes, TargetTypes>...>>>\n\t{\n\t};\n\n\ttemplate <typename TargetTupleType, typename... FromTypes>\n\tstruct TupleExplicitlyConvertible\n\t\t: public TupleExplicitlyConvertibleImpl<\n\t\ttuple_size<TargetTupleType>::value == sizeof...(FromTypes),\n\t\tMakeTupleTypes_t<TargetTupleType>, FromTypes...>::type\n\t{\n\t};\n\n\ttemplate<typename TargetTupleType, typename... FromTypes>\n\tusing TupleExplicitlyConvertible_t = enable_if_t<TupleExplicitlyConvertible<TargetTupleType, FromTypes...>::value, bool>;\n\n\n\t// TupleEqual\n\t//\n\t//\n\t//\n\ttemplate <size_t I>\n\tstruct TupleEqual\n\t{\n\t\ttemplate <typename Tuple1, typename Tuple2>\n\t\tbool operator()(const Tuple1& t1, const Tuple2& t2)\n\t\t{\n\t\t\tstatic_assert(tuple_size<Tuple1>::value == tuple_size<Tuple2>::value, \"comparing tuples of different sizes.\");\n\t\t\treturn TupleEqual<I - 1>()(t1, t2) && get<I - 1>(t1) == get<I - 1>(t2);\n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct TupleEqual<0>\n\t{\n\t\ttemplate <typename Tuple1, typename Tuple2>\n\t\tbool operator()(const Tuple1&, const Tuple2&)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t};\n\n\t// TupleLess\n\t//\n\t//\n\t//\n\ttemplate <size_t I>\n\tstruct TupleLess\n\t{\n\t\ttemplate <typename Tuple1, typename Tuple2>\n\t\tbool operator()(const Tuple1& t1, const Tuple2& t2)\n\t\t{\n\t\t\tstatic_assert(tuple_size<Tuple1>::value == tuple_size<Tuple2>::value, \"comparing tuples of different sizes.\");\n\t\t\treturn TupleLess<I - 1>()(t1, t2) || (!TupleLess<I - 1>()(t2, t1) && get<I - 1>(t1) < get<I - 1>(t2));\n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct TupleLess<0>\n\t{\n\t\ttemplate <typename Tuple1, typename Tuple2>\n\t\tbool operator()(const Tuple1&, const Tuple2&)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t};\n\n\n\t// MakeTupleReturnImpl\n\t//\n\t//\n\t//\n\ttemplate <typename T> struct MakeTupleReturnImpl                       { typedef T type; };\n\ttemplate <typename T> struct MakeTupleReturnImpl<reference_wrapper<T>> { typedef T& type; };\n\n\ttemplate <typename T>\n\tusing MakeTupleReturn_t = typename MakeTupleReturnImpl<decay_t<T>>::type;\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename... T1s, typename... T2s, size_t... Is>\n\tconstexpr auto TupleThreeWay(const tuple<T1s...>& t1, const tuple<T2s...>& t2, index_sequence<Is...> is)\n\t{\n\t\tstd::common_comparison_category_t<synth_three_way_result<T1s, T2s>...> result = std::strong_ordering::equal;\n\t\t((result = synth_three_way{}(get<Is>(t1), get<Is>(t2)), result != 0) || ...);\n\t\treturn result;\n\t}\n#endif\n}  // namespace Internal\n\n\n\n// tuple\n//\n// eastl::tuple is a fixed-size container of heterogeneous values. It is a\n// generalization of eastl::pair which hold only two heterogeneous values.\n//\n// https://en.cppreference.com/w/cpp/utility/tuple\n//\ntemplate <typename... Ts>\nclass tuple;\n\ntemplate <typename T, typename... Ts>\nclass tuple<T, Ts...>\n{\npublic:\n\tEA_CONSTEXPR tuple() = default;\n\t\n\ttemplate <typename T2 = T, \n\t\tInternal::TupleImplicitlyConvertible_t<tuple, const T2&, const Ts&...> = 0>\n\tEA_CONSTEXPR tuple(const T& t, const Ts&... ts)\n\t\t: mImpl(make_index_sequence<sizeof...(Ts) + 1>{}, Internal::MakeTupleTypes_t<tuple>{}, t, ts...)\n\t{\n\t}\n\n\ttemplate <typename T2 = T, \n\t\tInternal::TupleExplicitlyConvertible_t<tuple, const T2&, const Ts&...> = 0>\n\texplicit EA_CONSTEXPR tuple(const T& t, const Ts&... ts)\n\t\t: mImpl(make_index_sequence<sizeof...(Ts) + 1>{}, Internal::MakeTupleTypes_t<tuple>{}, t, ts...)\n\t{\n\t}\n\n\ttemplate <typename U, typename... Us,\n\t\tInternal::TupleImplicitlyConvertible_t<tuple, U, Us...> = 0>\n\t\tEA_CONSTEXPR tuple(U&& u, Us&&... us)\n\t\t\t: mImpl(make_index_sequence<sizeof...(Us) + 1>{}, Internal::MakeTupleTypes_t<tuple>{}, eastl::forward<U>(u),\n\t\t\t\t\teastl::forward<Us>(us)...)\n\t{\n\t}\n\n\ttemplate <typename U, typename... Us,\n\t\tInternal::TupleExplicitlyConvertible_t<tuple, U, Us...> = 0>\n\t\texplicit EA_CONSTEXPR tuple(U&& u, Us&&... us)\n\t\t\t: mImpl(make_index_sequence<sizeof...(Us) + 1>{}, Internal::MakeTupleTypes_t<tuple>{}, eastl::forward<U>(u),\n\t\t\t\t\teastl::forward<Us>(us)...)\n\t{\n\t}\n\n\ttemplate <typename OtherTuple,\n\t\t\t  typename enable_if<Internal::TupleConvertible<OtherTuple, tuple>::value, bool>::type = false>\n\ttuple(OtherTuple&& t)\n\t\t: mImpl(eastl::forward<OtherTuple>(t))\n\t{\n\t}\n\n\ttemplate <typename OtherTuple,\n\t\t\t  typename enable_if<Internal::TupleAssignable<tuple, OtherTuple>::value, bool>::type = false>\n\ttuple& operator=(OtherTuple&& t)\n\t{\n\t\tmImpl.operator=(eastl::forward<OtherTuple>(t));\n\t\treturn *this;\n\t}\n\n\tvoid swap(tuple& t) { mImpl.swap(t.mImpl); }\n\nprivate:\n\ttypedef Internal::TupleImpl<make_index_sequence<sizeof...(Ts) + 1>, T, Ts...> Impl;\n\tImpl mImpl;\n\n\ttemplate <size_t I, typename... Ts_>\n\tfriend tuple_element_t<I, tuple<Ts_...>>& get(tuple<Ts_...>& t);\n\n\ttemplate <size_t I, typename... Ts_>\n\tfriend const_tuple_element_t<I, tuple<Ts_...>>& get(const tuple<Ts_...>& t);\n\n\ttemplate <size_t I, typename... Ts_>\n\tfriend tuple_element_t<I, tuple<Ts_...>>&& get(tuple<Ts_...>&& t);\n\n\ttemplate <typename T_, typename... ts_>\n\tfriend T_& get(tuple<ts_...>& t);\n\n\ttemplate <typename T_, typename... ts_>\n\tfriend const T_& get(const tuple<ts_...>& t);\n\n\ttemplate <typename T_, typename... ts_>\n\tfriend T_&& get(tuple<ts_...>&& t);\n};\n\n// template specialization for an empty tuple\ntemplate <>\nclass tuple<>\n{\npublic:\n\tvoid swap(tuple&) {}\n};\n\ntemplate <size_t I, typename... Ts>\ninline tuple_element_t<I, tuple<Ts...>>& get(tuple<Ts...>& t)\n{\n\treturn Internal::getImpl<I>(t.mImpl);\n}\n\ntemplate <size_t I, typename... Ts>\ninline const_tuple_element_t<I, tuple<Ts...>>& get(const tuple<Ts...>& t)\n{\n\treturn Internal::getImpl<I>(t.mImpl);\n}\n\ntemplate <size_t I, typename... Ts>\ninline tuple_element_t<I, tuple<Ts...>>&& get(tuple<Ts...>&& t)\n{\n\treturn Internal::getImpl<I>(eastl::move(t.mImpl));\n}\n\ntemplate <typename T, typename... Ts>\ninline T& get(tuple<Ts...>& t)\n{\n\treturn Internal::getImpl<T>(t.mImpl);\n}\n\ntemplate <typename T, typename... Ts>\ninline const T& get(const tuple<Ts...>& t)\n{\n\treturn Internal::getImpl<T>(t.mImpl);\n}\n\ntemplate <typename T, typename... Ts>\ninline T&& get(tuple<Ts...>&& t)\n{\n\treturn Internal::getImpl<T>(eastl::move(t.mImpl));\n}\n\ntemplate <typename... Ts>\ninline void swap(tuple<Ts...>& a, tuple<Ts...>& b)\n{\n\ta.swap(b);\n}\n\n\n// tuple operators\n//\n//\ntemplate <typename... T1s, typename... T2s>\ninline bool operator==(const tuple<T1s...>& t1, const tuple<T2s...>& t2)\n{\n\treturn Internal::TupleEqual<sizeof...(T1s)>()(t1, t2);\n}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\ntemplate <typename... T1s, typename... T2s>\ninline constexpr std::common_comparison_category_t<synth_three_way_result<T1s, T2s>...> operator<=>(const tuple<T1s...>& t1, const tuple<T2s...>& t2)\n{\n\treturn Internal::TupleThreeWay(t1, t2, make_index_sequence<sizeof...(T1s)>{});\n}\n#else\ntemplate <typename... T1s, typename... T2s>\ninline bool operator<(const tuple<T1s...>& t1, const tuple<T2s...>& t2)\n{\n\treturn Internal::TupleLess<sizeof...(T1s)>()(t1, t2);\n}\n\ntemplate <typename... T1s, typename... T2s> inline bool operator!=(const tuple<T1s...>& t1, const tuple<T2s...>& t2) { return !(t1 == t2); }\ntemplate <typename... T1s, typename... T2s> inline bool operator> (const tuple<T1s...>& t1, const tuple<T2s...>& t2) { return t2 < t1; }\ntemplate <typename... T1s, typename... T2s> inline bool operator<=(const tuple<T1s...>& t1, const tuple<T2s...>& t2) { return !(t2 < t1); }\ntemplate <typename... T1s, typename... T2s> inline bool operator>=(const tuple<T1s...>& t1, const tuple<T2s...>& t2) { return !(t1 < t2); }\n#endif\n\nnamespace Internal\n{\n\t// tuple_cat helpers\n\t//\n\t//\n\t//\n\n\t// TupleCat2Impl\n\ttemplate <typename Tuple1, typename Is1, typename Tuple2, typename Is2>\n\tstruct TupleCat2Impl;\n\n\ttemplate <typename... T1s, size_t... I1s, typename... T2s, size_t... I2s>\n\tstruct TupleCat2Impl<tuple<T1s...>, index_sequence<I1s...>, tuple<T2s...>, index_sequence<I2s...>>\n\t{\n\t\tusing ResultType = tuple<T1s..., T2s...>;\n\n\t\ttemplate <typename Tuple1, typename Tuple2>\n\t\tstatic inline ResultType DoCat2(Tuple1&& t1, Tuple2&& t2)\n\t\t{\n\t\t\treturn ResultType(get<I1s>(eastl::forward<Tuple1>(t1))..., get<I2s>(eastl::forward<Tuple2>(t2))...);\n\t\t}\n\t};\n\n\t// TupleCat2\n\ttemplate <typename Tuple1, typename Tuple2>\n\tstruct TupleCat2;\n\n\ttemplate <typename... T1s, typename... T2s>\n\tstruct TupleCat2<tuple<T1s...>, tuple<T2s...>>\n\t{\n\t\tusing Is1        = make_index_sequence<sizeof...(T1s)>;\n\t\tusing Is2        = make_index_sequence<sizeof...(T2s)>;\n\t\tusing TCI        = TupleCat2Impl<tuple<T1s...>, Is1, tuple<T2s...>, Is2>;\n\t\tusing ResultType = typename TCI::ResultType;\n\n\t\ttemplate <typename Tuple1, typename Tuple2>\n\t\tstatic inline ResultType DoCat2(Tuple1&& t1, Tuple2&& t2)\n\t\t{\n\t\t\treturn TCI::DoCat2(eastl::forward<Tuple1>(t1), eastl::forward<Tuple2>(t2));\n\t\t}\n\t};\n\n\t// TupleCat\n\ttemplate <typename... Tuples>\n\tstruct TupleCat;\n\n\ttemplate <typename Tuple1, typename Tuple2, typename... TuplesRest>\n\tstruct TupleCat<Tuple1, Tuple2, TuplesRest...>\n\t{\n\t\tusing TC2             = TupleCat2<Tuple1, Tuple2>;\n\t\tusing FirstResultType = typename TupleCat2<Tuple1, Tuple2>::ResultType;\n\t\tusing ResultType      = typename TupleCat<FirstResultType, TuplesRest...>::ResultType;\n\n\t\ttemplate <typename TupleArg1, typename TupleArg2, typename... TupleArgsRest>\n\t\tstatic inline ResultType DoCat(TupleArg1&& t1, TupleArg2&& t2, TupleArgsRest&&... ts)\n\t\t{\n\t\t\treturn TupleCat<FirstResultType, TuplesRest...>::DoCat(\n\t\t\t\tTC2::DoCat2(eastl::forward<TupleArg1>(t1), eastl::forward<TupleArg2>(t2)),\n\t\t\t\teastl::forward<TupleArgsRest>(ts)...);\n\t\t}\n\t};\n\n\ttemplate <typename Tuple1, typename Tuple2>\n\tstruct TupleCat<Tuple1, Tuple2>\n\t{\n\t\tusing TC2 = TupleCat2<Tuple1, Tuple2>;\n\t\tusing ResultType = typename TC2::ResultType;\n\n\t\ttemplate <typename TupleArg1, typename TupleArg2>\n\t\tstatic inline ResultType DoCat(TupleArg1&& t1, TupleArg2&& t2)\n\t\t{\n\t\t\treturn TC2::DoCat2(eastl::forward<TupleArg1>(t1), eastl::forward<TupleArg2>(t2));\n\t\t}\n\t};\n\n\ttemplate <typename... Ts>\n\tstruct TupleCat<tuple<Ts...>>\n\t{\n\t\tusing ResultType = tuple<Ts...>;\n\t\t\n\t\ttemplate <typename TupleArg>\n\t\tstatic inline tuple<Ts...> DoCat(TupleArg&& t)\n\t\t{\n\t\t\treturn eastl::forward<TupleArg>(t);\n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct TupleCat<>\n\t{\n\t\tusing ResultType = tuple<>;\n\t\t\n\t\tstatic inline tuple<> DoCat()\n\t\t{\n\t\t\treturn {};\n\t\t}\n\t};\n}\n\t\n// tuple_cat \n//\n//\ntemplate <typename... Tuples>\ninline typename Internal::TupleCat<eastl::remove_cvref_t<Tuples>...>::ResultType tuple_cat(Tuples&&... ts)\n{\n\treturn Internal::TupleCat<eastl::remove_cvref_t<Tuples>...>::DoCat(eastl::forward<Tuples>(ts)...);\n}\n\n\n// make_tuple \n//\n//\ntemplate <typename... Ts>\ninline EA_CONSTEXPR tuple<Internal::MakeTupleReturn_t<Ts>...> make_tuple(Ts&&... values)\n{\n\treturn tuple<Internal::MakeTupleReturn_t<Ts>...>(eastl::forward<Ts>(values)...);\n}\n\n\n// forward_as_tuple \n//\n//\ntemplate <typename... Ts>\ninline EA_CONSTEXPR tuple<Ts&&...> forward_as_tuple(Ts&&... ts) EA_NOEXCEPT\n{\n\treturn tuple<Ts&&...>(eastl::forward<Ts&&>(ts)...);\n}\n\n\n// ignore \n//\n// An object of unspecified type such that any value can be assigned to it with no effect.\n//\n// https://en.cppreference.com/w/cpp/utility/tuple/ignore\n//\nnamespace Internal \n{\n\tstruct ignore_t\n\t{\n\t\tignore_t() = default;\n\n\t\ttemplate <typename T>\n\t\tconst ignore_t& operator=(const T&) const\n\t\t{\n\t\t\treturn *this;\n\t\t}\n\t};\n}// namespace Internal\n\nstatic const Internal::ignore_t ignore;\n\n\n// tie \n//\n// Creates a tuple of lvalue references to its arguments or instances of eastl::ignore.\n//\n// https://en.cppreference.com/w/cpp/utility/tuple/tie\n//\ntemplate <typename... Ts>\ninline EA_CONSTEXPR tuple<Ts&...> tie(Ts&... ts) EA_NOEXCEPT\n{\n\treturn tuple<Ts&...>(ts...);\n}\n\n\n// apply\n//\n// Invoke a callable object using a tuple to supply the arguments. \n//\n// http://en.cppreference.com/w/cpp/utility/apply\n//\nnamespace detail\n{\n\ttemplate <class F, class Tuple, size_t... I>\n\tEA_CONSTEXPR decltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>)\n\t{\n\t\treturn eastl::invoke(eastl::forward<F>(f), get<I>(eastl::forward<Tuple>(t))...);\n\t}\n} // namespace detail\n\ntemplate <class F, class Tuple>\nEA_CONSTEXPR decltype(auto) apply(F&& f, Tuple&& t)\n{\n\treturn detail::apply_impl(eastl::forward<F>(f), eastl::forward<Tuple>(t),\n\t\t                      make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});\n}\n\n\n// make_from_tuple\n//\n// Construct an object of type T, using the elements of the tuple as the arguments to the constructor.\n//\n// https://en.cppreference.com/w/cpp/utility/make_from_tuple\n//\nnamespace detail\n{\ntemplate <typename T, typename Tuple, size_t... I>\nconstexpr eastl::enable_if_t<eastl::is_constructible_v<T, decltype(eastl::get<I>(eastl::declval<Tuple>()))...>, T> make_from_tuple_impl(Tuple&& t, eastl::index_sequence<I...>)\n{\n\treturn T(eastl::get<I>(eastl::forward<Tuple>(t))...);\n}\n}  // namespace detail\n\ntemplate <typename T, typename Tuple>\nconstexpr T make_from_tuple(Tuple&& t)\n{\n\treturn detail::make_from_tuple_impl<T>(eastl::forward<Tuple>(t), eastl::make_index_sequence<eastl::tuple_size_v<eastl::remove_reference_t<Tuple>>>{});\n}\n\n}  // namespace eastl\n\n///////////////////////////////////////////////////////////////\n// C++17 structured bindings support for eastl::tuple\n//\n#ifndef EA_COMPILER_NO_STRUCTURED_BINDING\n// we can't forward declare tuple_size and tuple_element because some std implementations\n// don't declare it in the std namespace, but instead alias it.\n#include <tuple>\n\n\tnamespace std\n\t{\n\t\ttemplate <class... Ts>\n\t\tstruct tuple_size<::eastl::tuple<Ts...>> : public ::eastl::integral_constant<size_t, sizeof...(Ts)>\n\t\t{\n\t\t};\n\n\t\ttemplate <size_t I, class... Ts>\n\t\tstruct tuple_element<I, ::eastl::tuple<Ts...>> : public ::eastl::tuple_element<I, ::eastl::tuple<Ts...>>\n\t\t{\n\t\t};\n\t}\n#endif\n\n\n#endif  // EASTL_TUPLE_ENABLED\nEA_RESTORE_VC_WARNING()\nEA_RESTORE_VC_WARNING()\nEA_RESTORE_VC_WARNING()\n#endif  // EASTL_TUPLE_H\n"
  },
  {
    "path": "include/EASTL/type_traits.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Specification\n//\n// This file implements C++ type traits as proposed by the emerging C++ update\n// as of May, 2005. This update is known as \"Proposed Draft Technical Report\n// on C++ Library Extensions\" and is document number n1745. It can be found\n// on the Internet as n1745.pdf and as of this writing it is updated every\n// couple months to reflect current thinking.\n//////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Description\n//\n// EASTL includes a fairly serious type traits library that is on par with the\n// one found in Boost but offers some additional performance-enhancing help as well.\n// The type_traits library provides information about class types, as opposed to\n// class instances. For example, the is_integral type trait tells if a type is\n// one of int, short, long, char, uint64_t, etc.\n//\n// There are three primary uses of type traits:\n//     * Allowing for optimized operations on some data types.\n//     * Allowing for different logic pathways based on data types.\n//     * Allowing for compile-type assertions about data type expectations.\n//\n// Here is an example of using type traits to tell if a value is a floating point\n// value or not:\n//\n//    template <typename T>\n//    DoSomething(T t) {\n//        assert(is_floating_point<T>::value);\n//    }\n//\n// In this example, if Widget is trivally copyable.\n//    vector<Widget> wVector;\n//    .. add elements ...\n//    wVector.erase(wVector.begin());\n// The vector::erase() operation will optimize the moving of [begin() + 1, end()) to [begin(), end())\n// by using memcpy instead of explicitly calling the copy constructor of each element.\n//\n// The following is a full list of the currently recognized type traits. Most of these\n// are implemented as of this writing, but if there is one that is missing, feel free\n// to contact the maintainer of this library and request that it be completed.\n// As of this writing all C++11 type traits are supported, as well as some additional ones.\n// http://en.cppreference.com/w/cpp/types\n//\n//    Trait                                 Description\n// ------------------------------------------------------------------------------\n//    is_void                               T is void or a cv-qualified (const/void-qualified) void.\n//    is_null_pointer\n//    is_integral                           T is an integral type.\n//    is_floating_point                     T is a floating point type.\n//    is_array                              T is an array type. The templated array container is not an array type.\n//    is_enum                               T is an enumeration type.\n//    is_union                              T is a union type.\n//    is_class                              T is a class type but not a union type.\n//    is_function                           T is a function type.\n//    is_pointer                            T is a pointer type. Includes function pointers, but not pointers to (data or function) members.\n//    is_rvalue_reference\n//    is_lvalue_reference\n//    is_member_object_pointer              T is a pointer to data member.\n//    is_member_function_pointer            T is a pointer to member function.\n//\n//    is_fundamental                        T is a fundamental type (void, integral, or floating point).\n//    is_arithmetic                         T is an arithmetic type (integral or floating point).\n//    is_scalar                             T is a scalar type (arithmetic, enum, pointer, member_pointer)\n//    is_object                             T is an object type.\n//    is_compound                           T is a compound type (anything but fundamental).\n//    is_reference                          T is a reference type. Includes references to functions.\n//    is_member_pointer                     T is a pointer to a member or member function.\n//\n//    is_const                              T is const-qualified.\n//    is_volatile                           T is volatile-qualified.\n//    is_trivial\n//    is_trivially_copyable\n//    is_standard_layout\n//    is_pod                                T is a POD type.\n//    is_empty                              T is an empty class.\n//    is_polymorphic                        T is a polymorphic class.\n//    is_abstract                           T is an abstract class.\n//    is_signed                             T is a signed integral type.\n//    is_unsigned                           T is an unsigned integral type.\n//    is_bounded_array                      T is a type is an array type of known bound\n//    is_unbounded_array                    T is a type is an array type of unknown bound\n//\n//    is_constructible\n//    is_trivially_constructible\n//    is_nothrow_constructible\n//    is_default_constructible\n//    is_trivially_default_constructible\n//    is_nothrow_default_constructible\n//    is_copy_constructible\n//    is_trivially_copy_constructible\n//    is_nothrow_copy_constructible\n//    is_move_constructible\n//    is_trivially_move_constructible\n//    is_nothrow_move_constructible\n//    is_assignable\n//    is_trivially_assignable\n//    is_nothrow_assignable\n//    is_copy_assignable\n//    is_trivially_copy_assignable\n//    is_nothrow_copy_assignable\n//    is_move_assignable\n//    is_trivially_move_assignable\n//    is_nothrow_move_assignable\n//    is_destructible\n//    is_trivially_destructible\n//    is_nothrow_destructible\n//    has_virtual_destructor                T has a virtual destructor.\n//\n//    alignment_of                          An integer value representing the number of bytes of the alignment of objects of type T; an object of type T may be allocated at an address that is a multiple of its alignment.\n//    rank                                  An integer value representing the rank of objects of type T. The term 'rank' here is used to describe the number of dimensions of an array type.\n//    extent                                An integer value representing the extent (dimension) of the I'th bound of objects of type T. If the type T is not an array type, has rank of less than I, or if I == 0 and T is of type 'array of unknown bound of U,' then value shall evaluate to zero; otherwise value shall evaluate to the number of elements in the I'th array bound of T. The term 'extent' here is used to describe the number of elements in an array type.\n//\n//    is_same                               T and U name the same type.\n//    is_base_of                            Base is a base class of Derived or Base and Derived name the same type.\n//    is_convertible                        An imaginary lvalue of type From is implicitly convertible to type To. Special conversions involving string-literals and null-pointer constants are not considered. No function-parameter adjustments are made to type To when determining whether From is convertible to To; this implies that if type To is a function type or an array type, then the condition is false.\n//\n//    remove_cv\n//    remove_const                          The member typedef type shall be the same as T except that any top level const-qualifier has been removed. remove_const<const volatile int>::type evaluates to volatile int, whereas remove_const<const int*> is const int*.\n//    remove_volatile\n//    remove_cvref\n//    add_cv\n//    add_const\n//    add_volatile\n//\n//    remove_reference\n//    add_lvalue_reference\n//    add_rvalue_reference\n//\n//    remove_pointer\n//    add_pointer\n//\n//    make_signed\n//    make_unsigned\n//\n//    remove_extent\n//    remove_all_extents\n//\n//    aligned_storage\n//    aligned_union\n//    decay\n//    enable_if\n//    conditional\n//    common_type\n//    underlying_type\n//\n//    integral_constant\n//    bool_constant\n//    true_type\n//    false_type\n//\n// EASTL extension type traits\n//    is_aligned                            Defined as true if the type has alignment requirements greater than default alignment, which is taken to be 8. is_aligned is not found in Boost nor C++11, though alignment_of is.\n//    union_cast                            Allows for easy-to-read casting between types that are unrelated but have binary equivalence. The classic use case is converting between float and int32_t bit representations.\n//    yes_type\n//    no_type\n//    is_swappable                          Found in <EASTL/utility.h>\n//    is_nothrow_swappable                  \"\n//    is_reference_wrapper                  Found in <EASTL/functional.h>\n//    remove_reference_wrapper              \"\n//    is_detected                           Checks if some supplied arguments (Args) respect a constraint (Op).\n//    detected_t                            Check which type we obtain after expanding some arguments (Args) over a constraint (Op).\n//    detected_or                           Checks if some supplied arguments (Args) respect a constraint (Op) and allow to overwrite return type.\n//    detected_or_t                         Equivalent to detected_or<Default, Op, Args...>::type.\n//    is_detected_exact                     Check that the type we obtain after expanding some arguments (Args) over a constraint (Op) is equivalent to Expected.\n//    is_detected_convertible               Check that the type we obtain after expanding some arguments (Args) over a constraint (Op) is convertible to Expected.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Requirements\n//\n// As of this writing (5/2005), type_traits here requires a well-conforming\n// C++ compiler with respect to template metaprogramming. To use this library\n// you need to have at least one of the following:\n//     MSVC++ 7.1       (includes Win32, Win64, and WinCE platforms)\n//     GCC 3.2          (includes MacOSX, and Linux platforms)\n//     Metrowerks 8.0   (incluees MacOSX, Windows, and other platforms)\n//     EDG              (includes any compiler with EDG as a back-end, such as the Intel compiler)\n//     Comeau           (this is a C++ to C generator)\n//\n// It may be useful to list the compilers/platforms the current version of\n// type_traits doesn't support:\n//     Borland C++      (it simply has too many bugs with respect to templates).\n//     GCC 2.96         We used to have a separate set of type traits for this compiler, but removed it due to lack of necessity.\n//////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Implementation\n//\n// The implementation here is almost entirely based on template metaprogramming.\n// This is whereby you use the compiler's template functionality to define types\n// and values and make compilation decisions based on template declarations.\n// Many of the algorithms here are similar to those found in books such as\n// \"Modern C++ Design\" and C++ libraries such as Boost. The implementations here\n// are simpler and more straightforward than those found in some libraries, due\n// largely to our assumption that the compiler is good at doing template programming.\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef EASTL_TYPE_TRAITS_H\n#define EASTL_TYPE_TRAITS_H\n\n\n\n#include <EASTL/internal/config.h>\n#include <stddef.h>                 // Is needed for size_t usage by some traits.\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t///////////////////////////////////////////////////////////////////////\n\t// integral_constant\n\t//\n\t// This is the base class for various type traits, as defined by C++11.\n\t// This is essentially a utility base class for defining properties\n\t// as both class constants (value) and as types (type).\n\t//\n\ttemplate <typename T, T v>\n\tstruct integral_constant\n\t{\n\t\tstatic EA_CONSTEXPR T value = v;\n\t\ttypedef T value_type;\n\t\ttypedef integral_constant<T, v> type;\n\n\t\tEA_CONSTEXPR operator value_type() const EA_NOEXCEPT { return value; }\n\t\tEA_CONSTEXPR value_type operator()() const EA_NOEXCEPT { return value; }\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// true_type / false_type\n\t//\n\t// These are commonly used types in the implementation of type_traits.\n\t// Other integral constant types can be defined, such as those based on int.\n\t//\n\ttypedef integral_constant<bool, true>  true_type;\n\ttypedef integral_constant<bool, false> false_type;\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// bool_constant\n\t//\n\t// This is a convenience helper for the often used integral_constant<bool, value>.\n\t//\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <bool B>\n\t\tstruct bool_constant : public integral_constant<bool, B> {};\n\t#else\n\t\ttemplate <bool B>\n\t\tusing bool_constant = integral_constant<bool, B>;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// yes_type / no_type\n\t//\n\t// These are used as a utility to differentiate between two things.\n\t//\n\ttypedef char yes_type;                      // sizeof(yes_type) == 1\n\tstruct       no_type { char padding[8]; };  // sizeof(no_type)  != 1\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// unused\n\t//\n\t// Used internally to denote a special template argument that means\n\t// it's an unused argument.\n\t//\n\tstruct unused { };\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// argument_sink\n\t//\n\t// Used as a type which constructs from anything.\n\t//\n\t// For compilers that support variadic templates we provide an\n\t// alternative argument_sink which provides a constructor overload of\n\t// the variadic pack of arguments by reference.  This avoids issues of\n\t// object alignment not being respected in Microsoft compilers.  Seen\n\t// in VS2015 preview.  In general, since arguments are consumed and\n\t// ignored its cheaper to consume references than passing by value\n\t// which incurs a construction cost.\n\tstruct argument_sink\n\t{\n\t\ttemplate<typename... Args>\n\t\targument_sink(Args&&...) {}\n\t};\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// first_type_select\n\t//\n\t//  Similar to conditional<> but unilaterally selects the first type.\n\t//\n\ttemplate <typename T, typename = eastl::unused, typename = eastl::unused>\n\tstruct first_type_select { typedef T type; };\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// enable_if, disable_if\n\t//\n\t// template <bool B, typename T = void> struct enable_if;\n\t// template <bool B, typename T = void> struct disable_if;\n\n\ttemplate<bool B, typename T = void>\n\tstruct enable_if {};\n\n\ttemplate <typename T>\n\tstruct enable_if<true, T> { typedef T type; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <bool B, class T = void>\n\t\tusing enable_if_t = typename enable_if<B, T>::type;\n\t#endif\n\n\n\ttemplate<bool B, typename T = void>\n\tstruct disable_if {};\n\n\ttemplate <typename T>\n\tstruct disable_if<false, T> { typedef T type; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <bool B, class T = void>\n\t\tusing disable_if_t = typename disable_if<B, T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// conditional\n\t//\n\t// Provides member typedef type which is defined as T if B is true at\n\t// compile time, or as F if B is false.\n\t//\n\ttemplate<bool B, typename T, typename F>\n\tstruct conditional { typedef T type; };\n\n\ttemplate <typename T, typename F>\n\tstruct conditional<false, T, F> { typedef F type; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <bool B, class T, class F>\n\t\tusing conditional_t = typename conditional<B, T, F>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// conjunction\n\t//\n\t// This is a C++17 standard utility class that performs a short-circuiting\n\t// logical AND on a sequence of type traits.\n\t//\n\t// http://en.cppreference.com/w/cpp/types/conjunction\n\t//\n\ttemplate <class...>\n\tstruct conjunction : eastl::true_type {};\n\n\ttemplate <class B>\n\tstruct conjunction<B> : B {};\n\n\ttemplate <class B, class... Bn>\n\tstruct conjunction<B, Bn...> : conditional<bool(B::value), conjunction<Bn...>, B>::type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <typename... Bn>\n\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool conjunction_v = conjunction<Bn...>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// disjunction\n\t//\n\t// This is a C++17 standard utility class that performs a short-circuiting\n\t// logical OR on a sequence of type traits.\n\t//\n\t// http://en.cppreference.com/w/cpp/types/disjunction\n\t//\n\ttemplate <class...>\n\tstruct disjunction : eastl::false_type {};\n\n\ttemplate <class B>\n\tstruct disjunction<B> : B {};\n\n\ttemplate <class B, class... Bn>\n\tstruct disjunction<B, Bn...> : conditional<bool(B::value), B, disjunction<Bn...>>::type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <typename... B>\n\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool disjunction_v = disjunction<B...>::value;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// negation\n\t//\n\t// This is a C++17 standard utility class that performs a logical NOT on a\n\t// single type trait.\n\t//\n\t// http://en.cppreference.com/w/cpp/types/negation\n\t//\n\ttemplate <class B>\n\tstruct negation : eastl::bool_constant<!bool(B::value)> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <typename B>\n\t\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR bool negation_v = negation<B>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// type_identity\n\t//\n\t// The purpose of this is typically to deal with non-deduced template\n\t// contexts. See the C++11 Standard, 14.8.2.5 p5.\n\t// Also: http://cppquiz.org/quiz/question/109?result=CE&answer=&did_answer=Answer\n\t//\n\t// https://en.cppreference.com/w/cpp/types/type_identity\n\t//\n\ttemplate <typename T>\n\tstruct type_identity { using type = T; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <typename T>\n\t\tusing type_identity_t = typename type_identity<T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_same\n\t//\n\t// Given two (possibly identical) types T and U, is_same<T, U>::value == true\n\t// if and only if T and U are the same type.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_same_CONFORMANCE 1    // is_same is conforming; doesn't make mistakes.\n\n\ttemplate <typename T, typename U>\n\tstruct is_same : public eastl::false_type { };\n\n\ttemplate <typename T>\n\tstruct is_same<T, T> : public eastl::true_type { };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T, class U>\n\t\tEA_CONSTEXPR bool is_same_v = is_same<T, U>::value;\n\t#endif\n\n\n    ///////////////////////////////////////////////////////////////////////\n\t// is_const\n\t//\n\t// is_const<T>::value == true if and only if T has const-qualification.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_const_CONFORMANCE 1    // is_const is conforming.\n\n\ttemplate <typename T> struct is_const : public eastl::false_type {};\n\ttemplate <typename T> struct is_const<const T> : public eastl::true_type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_const_v = is_const<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_volatile\n\t//\n\t// is_volatile<T>::value == true  if and only if T has volatile-qualification.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_volatile_CONFORMANCE 1    // is_volatile is conforming.\n\n\ttemplate <typename T> struct is_volatile : public eastl::false_type {};\n\ttemplate <typename T> struct is_volatile<volatile T> : public eastl::true_type {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate <class T>\n\t\tEA_CONSTEXPR bool is_volatile_v = is_volatile<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_reference\n\t//\n\t// is_reference<T>::value == true if and only if T is a reference type (l-value reference or r-value reference).\n\t// This category includes reference to function types.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_reference_CONFORMANCE 1    // is_reference is conforming; doesn't make mistakes.\n\n\ttemplate <typename T> struct is_reference      : public eastl::false_type{};\n\ttemplate <typename T> struct is_reference<T&>  : public eastl::true_type{};\n\ttemplate <typename T> struct is_reference<T&&> : public eastl::true_type{};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_reference_v = is_reference<T>::value;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// is_function\n\t//\n\t// is_function<T>::value == true  if and only if T is a function type.\n\t// A function type here does not include a member function type.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_is_function_CONFORMANCE 1    // is_function is conforming.\n\n\t// afaik, original credit is to Walter Brown who described this implementation at CppCon 2019.\n\t// libc++, libstdc++ and MS STL all use similar implementations.\n\t// This relies on the fact that only function and reference types can't be const qualified.\n\t// Rather than listing an obscene number of specializations for const, volatile, l- and r-value reference,\n\t// noexcept and all relevant combinations we take advantage of this fact.\n#ifdef _MSC_VER\n\t#pragma warning(push)\n\t#pragma warning(disable: 4180)  // qualifier applied to function type has no meaning; ignored\n#endif\n\ttemplate <typename T>\n\tstruct is_function\n\t\t: public eastl::bool_constant<!eastl::is_reference<T>::value && !eastl::is_const<const T>::value>::type {};\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tEA_CONSTEXPR bool is_function_v = is_function<T>::value;\n\t#endif\n\n\n\t// The following remove utilities are defined here instead of in the headers\n\t// below because they are core utilits that many other type traits need.\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_const\n\t//\n\t// Remove const from a type.\n\t//\n\t// The remove_const transformation trait removes top-level const\n\t// qualification (if any) from the type to which it is applied. For a\n\t// given type T, remove_const<T const>::type is equivalent to the type T.\n\t// For example, remove_const<char*>::type is equivalent to char* while\n\t// remove_const<const char*>::type is equivalent to const char*.\n\t// In the latter case, the const qualifier modifies char, not *, and is\n\t// therefore not at the top level.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_const_CONFORMANCE 1    // remove_const is conforming.\n\n\ttemplate <typename T>           struct remove_const             { typedef T type;    };\n\ttemplate <typename T>           struct remove_const<const T>    { typedef T type;    };\n\ttemplate <typename T>           struct remove_const<const T[]>  { typedef T type[];  };\n\ttemplate <typename T, size_t N> struct remove_const<const T[N]> { typedef T type[N]; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tusing remove_const_t = typename remove_const<T>::type;\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_volatile\n\t//\n\t// Remove volatile from a type.\n\t//\n\t// The remove_volatile transformation trait removes top-level volatile\n\t// qualification (if any) from the type to which it is applied.\n\t// For a given type T, the type remove_volatile <T volatile>::T is equivalent\n\t// to the type T. For example, remove_volatile <char* volatile>::type is\n\t// equivalent to char* while remove_volatile <volatile char*>::type is\n\t// equivalent to volatile char*. In the latter case, the volatile qualifier\n\t// modifies char, not *, and is therefore not at the top level.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_volatile_CONFORMANCE 1    // remove_volatile is conforming.\n\n\ttemplate <typename T>           struct remove_volatile                { typedef T type;    };\n\ttemplate <typename T>           struct remove_volatile<volatile T>    { typedef T type;    };\n\ttemplate <typename T>           struct remove_volatile<volatile T[]>  { typedef T type[];  };\n\ttemplate <typename T, size_t N> struct remove_volatile<volatile T[N]> { typedef T type[N]; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tusing remove_volatile_t = typename remove_volatile<T>::type;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_cv\n\t//\n\t// Remove const and volatile from a type.\n\t//\n\t// The remove_cv transformation trait removes top-level const and/or volatile\n\t// qualification (if any) from the type to which it is applied. For a given type T,\n\t// remove_cv<T const volatile>::type is equivalent to T. For example,\n\t// remove_cv<char* volatile>::type is equivalent to char*, while remove_cv<const char*>::type\n\t// is equivalent to const char*. In the latter case, the const qualifier modifies\n\t// char, not *, and is therefore not at the top level.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_cv_CONFORMANCE 1    // remove_cv is conforming.\n\n\ttemplate <typename T>\n\tstruct remove_cv { typedef typename eastl::remove_volatile<typename eastl::remove_const<T>::type>::type type; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tusing remove_cv_t = typename remove_cv<T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_reference\n\t//\n\t// Remove reference from a type.\n\t//\n\t// The remove_reference transformation trait removes top-level of\n\t// indirection by reference (if any) from the type to which it is applied.\n\t// For a given type T, remove_reference<T&>::type is equivalent to T.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_reference_CONFORMANCE 1\n\n\ttemplate <typename T> struct remove_reference     { typedef T type; };\n\ttemplate <typename T> struct remove_reference<T&> { typedef T type; };\n\ttemplate <typename T> struct remove_reference<T&&>{ typedef T type; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tusing remove_reference_t = typename remove_reference<T>::type;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// remove_cvref\n\t//\n\t// Remove const and volatile from a reference type.\n\t//\n\t// The remove_cvref transformation trait removes top-level const and/or volatile\n\t// qualification (if any) from the reference type to which it is applied. For a given type T&,\n\t// remove_cvref<T& const volatile>::type is equivalent to T. For example,\n\t// remove_cv<int& volatile>::type is equivalent to int.\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_remove_cvref_CONFORMANCE 1    // remove_cvref is conforming.\n\n\ttemplate <typename T>\n\tstruct remove_cvref { typedef typename eastl::remove_volatile<typename eastl::remove_const<typename eastl::remove_reference<T>::type>::type>::type type; };\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\ttemplate<typename T>\n\t\tusing remove_cvref_t = typename remove_cvref<T>::type;\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// add_lvalue_reference\n\t//\n\t// C++11 Standard, section 20.9.7.2\n\t// If T names an object or function type then the member typedef type\n\t// shall name T&; otherwise, if T names a type 'rvalue reference to T1' then\n\t// the member typedef type shall name T1&; otherwise, type shall name T.\n\t//\n\t// Rules (8.3.2 p6):\n\t//      void + &  -> void\n\t//      T    + &  -> T&\n\t//      T&   + &  -> T&\n\t//      T&&  + &  -> T&\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_add_lvalue_reference_CONFORMANCE 1    // add_lvalue_reference is conforming.\n\n\tnamespace internal\n\t{\n\t\ttemplate <typename T>\n\t\tauto try_add_lvalue_reference(int)->type_identity<T&>;\n\n\t\ttemplate <typename T>\n\t\tauto try_add_lvalue_reference(...)->type_identity<T>;\n\t}\n\n\ttemplate <typename T> struct add_lvalue_reference : decltype(internal::try_add_lvalue_reference<T>(0)) {};\n\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t// To do: define macro.\n\t#else\n\t\ttemplate <typename T>\n\t\tusing add_lvalue_reference_t = typename add_lvalue_reference<T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// add_rvalue_reference\n\t//\n\t// C++11 Standard, section 20.9.7.2\n\t// If T names an object or function type then the member typedef type\n\t// shall name T&&; otherwise, type shall name T. [ Note: This rule reflects\n\t// the semantics of reference collapsing (8.3.2). For example, when a type T\n\t// names a type T1&, the type add_rvalue_reference<T>::type is not an\n\t// rvalue reference. end note ]\n\t//\n\t// Rules (8.3.2 p6):\n\t//      void + &&  -> void\n\t//      T    + &&  -> T&&\n\t//      T&   + &&  -> T&\n\t//      T&&  + &&  -> T&&\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_add_rvalue_reference_CONFORMANCE 1\n\n\tnamespace internal\n\t{\n\t\ttemplate <typename T>\n\t\tauto try_add_rvalue_reference(int)->type_identity<T&&>;\n\n\t\ttemplate <typename T>\n\t\tauto try_add_rvalue_reference(...)->type_identity<T>;\n\t}\n\n\ttemplate <typename T> struct add_rvalue_reference : decltype(internal::try_add_rvalue_reference<T>(0)) {};\n\n\t#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t// To do: define macro.\n\t#else\n\t\ttemplate <typename T>\n\t\tusing add_rvalue_reference_t = typename add_rvalue_reference<T>::type;\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// declval\n\t//\n\t// declval is normally found in <utility.h> but type traits need it and utility #includes this.\n\t//\n\t// Converts any type T to a reference type, making it possible to use member functions in\n\t// decltype expressions without specifying constructors. It has no use outside decltype expressions.\n\t// By design there is no implementation, as it's never executed but rather is used only in decltype expressions.\n\t// The C++11 Standard section 20.2.4 states that we must declare this.\n\t// http://en.cppreference.com/w/cpp/utility/declval\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\n\t#define EASTL_TYPE_TRAIT_declval_CONFORMANCE 1\n\n\ttemplate <typename T>\n\ttypename eastl::add_rvalue_reference<T>::type declval() EA_NOEXCEPT;\n\n\t#if !defined(EA_COMPILER_NO_DECLTYPE) && !EASTL_TYPE_TRAIT_declval_CONFORMANCE\n\t\t#error decltype is supported by the compiler but declval is not. A lot of our type trait code assumes that if the compiler supports decltype then it supports rvalue references.\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// static_min / static_max\n\t//\n\t// These are primarily useful in templated code for meta programming.\n\t// Currently we are limited to size_t, as C++ doesn't allow integral\n\t// template parameters to be generic. We can expand the supported types\n\t// to include additional integers if needed.\n\t//\n\t// These are not in the C++ Standard.\n\t//\n\t// Example usage:\n\t//     Printf(\"%zu\", static_max<3, 7, 1, 5>::value); // prints \"7\"\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\t#define EASTL_TYPE_TRAIT_static_min_CONFORMANCE 1\n\t#define EASTL_TYPE_TRAIT_static_max_CONFORMANCE 1\n\n\ttemplate <size_t I0, size_t ...in>\n\tstruct static_min;\n\n\ttemplate <size_t I0>\n\tstruct static_min<I0>\n\t\t{ static const size_t value = I0; };\n\n\ttemplate <size_t I0, size_t I1, size_t ...in>\n\tstruct static_min<I0, I1, in...>\n\t\t{ static const size_t value = ((I0 <= I1) ? static_min<I0, in...>::value : static_min<I1, in...>::value); };\n\n\ttemplate <size_t I0, size_t ...in>\n\tstruct static_max;\n\n\ttemplate <size_t I0>\n\tstruct static_max<I0>\n\t\t{ static const size_t value = I0; };\n\n\ttemplate <size_t I0, size_t I1, size_t ...in>\n\tstruct static_max<I0, I1, in...>\n\t\t{ static const size_t value = ((I0 >= I1) ? static_max<I0, in...>::value : static_max<I1, in...>::value); };\n\n\t///////////////////////////////////////////////////////////////////////\n\t/// This enum class is useful for detecting whether a system is little\n\t/// or big endian. Mixed or middle endian is not modeled here as described\n\t/// by the C++20 spec.\n\t///////////////////////////////////////////////////////////////////////\n\tEA_DISABLE_VC_WARNING(4472) // 'endian' is a native enum: add an access specifier (private/public) to declare a managed enum\n\tenum class endian\n\t{\n\t\t#ifdef EA_SYSTEM_LITTLE_ENDIAN\n\t\t\tlittle = 1,\n\t\t\tbig = 0,\n\t\t\tnative = little\n\t\t#else\n\t\t\tlittle = 0,\n\t\t\tbig = 1,\n\t\t\tnative = big\n\t\t#endif\n\t};\n\tEA_RESTORE_VC_WARNING();\n\n} // namespace eastl\n\n\n// The following files implement the type traits themselves.\n#include <EASTL/internal/type_fundamental.h>\n#include <EASTL/internal/type_transformations.h>\n#include <EASTL/internal/type_void_t.h>\n#include <EASTL/internal/type_properties.h>\n#include <EASTL/internal/type_compound.h>\n#include <EASTL/internal/type_pod.h>\n#include <EASTL/internal/type_detected.h>\n\nnamespace eastl\n{\n\tnamespace detail\n\t{\n\t\ttemplate<typename, typename = void>\n\t\tstruct is_transparent_comparison : eastl::false_type {};\n\n\t\ttemplate<typename T>\n\t\tstruct is_transparent_comparison<T, eastl::void_t<typename T::is_transparent>> : eastl::true_type {};\n\n\t\ttemplate <typename T>\n\t\tEA_CONSTEXPR bool is_transparent_comparison_v = is_transparent_comparison<T>::value;\n\n\t} // namespace detail\n\n} // namespace eastl\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/unique_ptr.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_UNIQUE_PTR_H\n#define EASTL_UNIQUE_PTR_H\n\n\n#include <EABase/nullptr.h>\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/smart_ptr.h>   // Defines smart_ptr_deleter\n#include <EASTL/internal/move_help.h>   // Defines EASTL_MOVE\n#include <EASTL/type_traits.h>\n#include <EASTL/utility.h>\n#include <EASTL/functional.h>\n#include <EASTL/bonus/compressed_pair.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\nnamespace eastl\n{\n\t/// class unique_ptr\n\t///\n\t/// This class implements a unique_ptr template. This is a class which is \n\t/// similar to the C++ auto_ptr template, except that it prohibits copying \n\t/// of itself, for safety.\n\t///\n\t/// More specifically, the unique_ptr class template stores a pointer to a \n\t/// dynamically allocated object.  The object pointed to is automatically \n\t/// deleted on destructor of unique_ptr or can be manually deleted via the \n\t/// unique_ptr::reset function. \n\t///\n\t/// Memory allocation notes:\n\t/// unique_ptr doesn't allocate memory; all allocated pointers are externally \n\t/// derived. unique_ptr does deallocate memory, though always through the \n\t/// user-provided deleter. You need to make sure you are consistent in providing \n\t/// a deleter which frees memory in a way that matches how it was originally allocated.\n\t/// Deleters have instance information and are moved between containers the same way \n\t/// the allocated pointers are. Thus you can allocate memory via some heap and \n\t/// provide a deleter which contains a pointer to that same heap, and regardless\n\t/// of what you do with the unique_ptr, including moving it to another unique_ptr,\n\t/// the deletion will use the originally provided heap.\n\t///\n\t/// Example usage:\n\t///     unique_ptr<int> p(new int);\n\t///     *p = 4;\n\t///\n\t///     unique_ptr<int[]> pArray(new int[4]);\n\t///     p[0] = 4;\n\t///\n\t/// Type completeness requirements\n\t/// http://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-know-the-full-definition-of-t/6089065#6089065\n\t/// Here is a table which documents several members of shared_ptr and unique_ptr with respect to completeness requirements. \n\t/// If the member requires a complete type, the entry has a \"C\", otherwise the table entry is filled with \"I\".\n\t/// \n\t///                                 unique_ptr       shared_ptr\n\t///     +------------------------+---------------+---------------+\n\t///     |          P()           |      I        |      I        |\n\t///     |  default constructor   |               |               |\n\t///     +------------------------+---------------+---------------+\n\t///     |      P(const P&)       |     N/A       |      I        |\n\t///     |    copy constructor    |               |               |\n\t///     +------------------------+---------------+---------------+\n\t///     |         P(P&&)         |      I        |      I        |\n\t///     |    move constructor    |               |               |\n\t///     +------------------------+---------------+---------------+\n\t///     |         ~P()           |      C        |      I        |\n\t///     |       destructor       |               |               |\n\t///     +------------------------+---------------+---------------+\n\t///     |         P(A*)          |      I        |      C        |\n\t///     +------------------------+---------------+---------------+\n\t///     |  operator=(const P&)   |     N/A       |      I        |\n\t///     |    copy assignment     |               |               |\n\t///     +------------------------+---------------+---------------+\n\t///     |    operator=(P&&)      |      C        |      I        |\n\t///     |    move assignment     |               |               |\n\t///     +------------------------+---------------+---------------+\n\t///     |        reset()         |      C        |      I        |\n\t///     +------------------------+---------------+---------------+\n\t///     |       reset(A*)        |      C        |      C        |\n\t///     +------------------------+---------------+---------------+\n\t///\n\ttemplate <typename T, typename Deleter = eastl::default_delete<T> > \n\tclass unique_ptr\n\t{\n\t\tstatic_assert(!is_rvalue_reference<Deleter>::value, \"The supplied Deleter cannot be a r-value reference.\");\n\tpublic:\n\t\ttypedef Deleter                                                                  deleter_type;\n\t\ttypedef T                                                                        element_type;\n\t\ttypedef unique_ptr<element_type, deleter_type>                                   this_type;\n\t\ttypedef typename Internal::unique_pointer_type<element_type, deleter_type>::type pointer;\n\n\tpublic:\n\t\t/// unique_ptr\n\t\t/// Construct a unique_ptr from a pointer allocated via new.\n\t\t/// Example usage:\n\t\t///    unique_ptr<int> ptr;\n\t\tEA_CPP14_CONSTEXPR unique_ptr() EA_NOEXCEPT\n\t\t\t: mPair(pointer())\n\t\t{\n\t\t\tstatic_assert(!eastl::is_pointer<deleter_type>::value, \"unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class.\");\n\t\t}\n\n\t\t/// unique_ptr\n\t\t/// Construct a unique_ptr from a null pointer.\n\t\t/// Example usage:\n\t\t///    unique_ptr<int> ptr(nullptr);\n\t\tEA_CPP14_CONSTEXPR unique_ptr(std::nullptr_t) EA_NOEXCEPT\n\t\t\t: mPair(pointer())\n\t\t{\n\t\t\tstatic_assert(!eastl::is_pointer<deleter_type>::value, \"unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class.\");\n\t\t}\n\n\t\t/// unique_ptr\n\t\t/// Construct a unique_ptr from a pointer allocated via new.\n\t\t/// Example usage:\n\t\t///    unique_ptr<int> ptr(new int(3));\n\t\texplicit unique_ptr(pointer pValue) EA_NOEXCEPT\n\t\t\t: mPair(pValue)\n\t\t{\n\t\t\tstatic_assert(!eastl::is_pointer<deleter_type>::value, \"unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class.\");\n\t\t}\n\n\t\t/// unique_ptr\n\t\t/// Constructs a unique_ptr with the owner pointer and deleter specified\n\t\t/// Example usage:\n\t\t///     eastl::smart_ptr_deleter<int> del;\n\t\t///     unique_ptr<int> ptr(new int(3), del);\n\t\tunique_ptr(pointer pValue, typename eastl::conditional<eastl::is_lvalue_reference<deleter_type>::value, deleter_type, typename eastl::add_lvalue_reference<const deleter_type>::type>::type deleter) EA_NOEXCEPT\n\t\t\t: mPair(pValue, deleter) {}\n\n\t\t/// unique_ptr\n\t\t/// Constructs a unique_ptr with the owned pointer and deleter specified (rvalue)\n\t\t/// Example usage:\n\t\t///     unique_ptr<int> ptr(new int(3), eastl::smart_ptr_deleter<int>());\n\t\tunique_ptr(pointer pValue, typename eastl::remove_reference<deleter_type>::type&& deleter) EA_NOEXCEPT\n\t\t\t: mPair(pValue, eastl::move(deleter))\n\t\t{\n\t\t\tstatic_assert(!eastl::is_lvalue_reference<deleter_type>::value, \"deleter_type reference refers to an rvalue deleter. The reference will probably become invalid before used. Change the deleter_type to not be a reference or construct with permanent deleter.\");\n\t\t}\n\n\t\t/// unique_ptr\n\t\t/// Move constructor\n\t\t/// Example usage:\n\t\t///     unique_ptr<int> ptr(new int(3));\n\t\t///     unique_ptr<int> newPtr = eastl::move(ptr);\n\t\tunique_ptr(this_type&& x) EA_NOEXCEPT\n\t\t\t: mPair(x.release(), eastl::forward<deleter_type>(x.get_deleter())) {}\n\n\t\t/// unique_ptr\n\t\t/// Move constructor\n\t\t/// Example usage:\n\t\t///     unique_ptr<int> ptr(new int(3));\n\t\t///     unique_ptr<int> newPtr = eastl::move(ptr);\n\t\ttemplate <typename U, typename E>\n\t\tunique_ptr(unique_ptr<U, E>&& u, typename enable_if<!is_array<U>::value && is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value && is_convertible<E, deleter_type>::value && (is_same<deleter_type, E>::value || !is_lvalue_reference<deleter_type>::value)>::type* = 0) EA_NOEXCEPT\n\t\t\t: mPair(u.release(), eastl::forward<E>(u.get_deleter())) {}\n\n\t\t/// unique_ptr\n\t\t/// Move assignment\n\t\t/// Example usage:\n\t\t///     unique_ptr<int> ptr(new int(3));\n\t\t///     unique_ptr<int> newPtr(new int(4));\n\t\t///     ptr = eastl::move(newPtr);  // Deletes int(3) and assigns mpValue to int(4)\n\t\tthis_type& operator=(this_type&& x) EA_NOEXCEPT\n\t\t{\n\t\t\treset(x.release());\n\t\t\tmPair.second() = eastl::move(eastl::forward<deleter_type>(x.get_deleter()));\n\t\t\treturn *this;\n\t\t}\n\n\t\t/// unique_ptr\n\t\t/// Move assignment\n\t\ttemplate <typename U, typename E>\n\t\ttypename enable_if<!is_array<U>::value && is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value && is_assignable<deleter_type&, E&&>::value, this_type&>::type\n\t\toperator=(unique_ptr<U, E>&& u) EA_NOEXCEPT\n\t\t{\n\t\t\treset(u.release());\n\t\t\tmPair.second() = eastl::move(eastl::forward<E>(u.get_deleter()));\n\t\t\treturn *this;\n\t\t}\n\n\t\t/// operator=(nullptr_t)\n\t\tthis_type& operator=(std::nullptr_t) EA_NOEXCEPT\n\t\t{\n\t\t\treset();\n\t\t\treturn *this;\n\t\t}\n\n\t\t/// ~unique_ptr\n\t\t/// Destroys the owned pointer. The destructor for the object\n\t\t/// referred to by the owned pointer will be called.\n\t\t~unique_ptr() EA_NOEXCEPT\n\t\t{\n\t\t\treset();\n\t\t}\n\n\t\t/// reset\n\t\t/// Deletes the owned pointer and takes ownership of the \n\t\t/// passed in pointer. If the passed in pointer is the same\n\t\t/// as the owned pointer, nothing is done.\n\t\t/// Example usage:\n\t\t///    unique_ptr<int> ptr(new int(3));\n\t\t///    ptr.reset(new int(4));  // deletes int(3)\n\t\t///    ptr.reset(NULL);        // deletes int(4)\n\t\tvoid reset(pointer pValue = pointer()) EA_NOEXCEPT\n\t\t{\n\t\t\tif (pValue != mPair.first())\n\t\t\t{\n\t\t\t\tif (auto first = eastl::exchange(mPair.first(), pValue))\n\t\t\t\t\tget_deleter()(first);\n\t\t\t}\n\t\t}\n\n\t\t/// release\n\t\t/// This simply forgets the owned pointer. It doesn't \n\t\t/// free it but rather assumes that the user does.\n\t\t/// Example usage:\n\t\t///    unique_ptr<int> ptr(new int(3));\n\t\t///    int* pInt = ptr.release();\n\t\t///    delete pInt;\n\t\tpointer release() EA_NOEXCEPT\n\t\t{\n\t\t\tpointer const pTemp = mPair.first();\n\t\t\tmPair.first() = pointer();\n\t\t\treturn pTemp;\n\t\t}\n\n\t\t/// detach\n\t\t/// For backwards-compatibility with pre-C++11 code.\n\t\tpointer detach() EA_NOEXCEPT { return release(); } \n\n\t\t/// swap\n\t\t/// Exchanges the owned pointer beween two unique_ptr objects. \n\t\tvoid swap(this_type& x) EA_NOEXCEPT\n\t\t{\n\t\t\tmPair.swap(x.mPair);\n\t\t}\n\n\t\t/// operator*\n\t\t/// Returns the owner pointer dereferenced.\n\t\t/// Example usage:\n\t\t///    unique_ptr<int> ptr(new int(3));\n\t\t///    int x = *ptr;\n\t\ttypename add_lvalue_reference<T>::type operator*() const // Not noexcept, because the pointer may be NULL.\n\t\t{\n\t\t\treturn *mPair.first();\n\t\t}\n\n\t\t/// operator->\n\t\t/// Allows access to the owned pointer via operator->()\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    unique_ptr<int> ptr(new X);\n\t\t///    ptr->DoSomething();\n\t\tpointer operator->() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPair.first();\n\t\t}\n\n\t\t/// get\n\t\t/// Returns the owned pointer. Note that this class does \n\t\t/// not provide an operator T() function. This is because such\n\t\t/// a thing (automatic conversion) is deemed unsafe.\n\t\t/// Example usage:\n\t\t///    struct X{ void DoSomething(); }; \n\t\t///    unique_ptr<int> ptr(new X);\n\t\t///    X* pX = ptr.get();\n\t\t///    pX->DoSomething();\n\t\tpointer get() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPair.first();\n\t\t}\n\n\t\t/// get_deleter\n\t\t/// Returns the deleter used to delete the owned pointer\n\t\t/// Example usage:\n\t\t/// unique_ptr<int> ptr(new int(3));\n\t\t/// eastl::smart_ptr_deleter<int>& del = ptr.get_deleter();\n\t\tdeleter_type& get_deleter() EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPair.second();\n\t\t}\n\n\t\t/// get_deleter\n\t\t/// Const version for getting the deleter\n\t\tconst deleter_type& get_deleter() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPair.second();\n\t\t}\n\n\t\t#ifdef EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS\n\t\t\t/// Note that below we do not use operator bool(). The reason for this\n\t\t\t/// is that booleans automatically convert up to short, int, float, etc.\n\t\t\t/// The result is that this: if(uniquePtr == 1) would yield true (bad).\n\t\t\ttypedef T* (this_type::*bool_)() const;\n\t\t\toperator bool_() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tif(mPair.first())\n\t\t\t\t\treturn &this_type::get;\n\t\t\t\treturn NULL;\n\t\t\t}\n\n\t\t\tbool operator!() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn (mPair.first() == pointer());\n\t\t\t}\n\t\t#else\n\t\t\t/// operator bool\n\t\t\t/// Allows for using a unique_ptr as a boolean. \n\t\t\t/// Example usage:\n\t\t\t///    unique_ptr<int> ptr(new int(3));\n\t\t\t///    if(ptr)\n\t\t\t///        ++*ptr;\n\t\t\t///\n\t\t\texplicit operator bool() const EA_NOEXCEPT\n\t\t\t{ \n\t\t\t\treturn (mPair.first() != pointer());\n\t\t\t}\n\t\t#endif\n\n\t\t/// These functions are deleted in order to prevent copying, for safety.\n\t\tunique_ptr(const this_type&) = delete;\n\t\tunique_ptr& operator=(const this_type&) = delete;\n\t\tunique_ptr& operator=(pointer pValue) = delete;\n\n\tprotected:\n\t\teastl::compressed_pair<pointer, deleter_type> mPair;\n\t}; // class unique_ptr\n\n\n\n\t/// unique_ptr specialization for unbounded arrays.\n\t///\n\t/// Differences from unique_ptr<T>:\n\t///     - Conversions between different types of unique_ptr<T[], D> or to or \n\t///       from the non-array forms of unique_ptr produce an ill-formed program.\n\t///     - Pointers to types derived from T are rejected by the constructors, and by reset.\n\t///     - The observers operator* and operator-> are not provided.\n\t///     - The indexing observer operator[] is provided.\n\t///     - The default deleter will call delete[].\n\t/// \n\t/// It's not possible to create a unique_ptr for arrays of a known bound (e.g. int[4] as opposed to int[]).\n\t///\n\t/// Example usage:\n\t///     unique_ptr<int[]> ptr(new int[10]);\n\t///     ptr[4] = 4;\n\t///\n\ttemplate <typename T, typename Deleter>\n\tclass unique_ptr<T[], Deleter>\n\t{\n\tpublic:\n\t\ttypedef Deleter                                                                  deleter_type;\n\t\ttypedef T                                                                        element_type;\n\t\ttypedef unique_ptr<element_type[], deleter_type>                                 this_type;\n\t\ttypedef typename Internal::unique_pointer_type<element_type, deleter_type>::type pointer;\n\n\tpublic:\n\t\tEA_CPP14_CONSTEXPR unique_ptr() EA_NOEXCEPT\n\t\t\t: mPair(pointer())\n\t\t{\n\t\t\tstatic_assert(!eastl::is_pointer<deleter_type>::value, \"unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class.\");\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR unique_ptr(std::nullptr_t) EA_NOEXCEPT\n\t\t\t: mPair(pointer())\n\t\t{\n\t\t\tstatic_assert(!eastl::is_pointer<deleter_type>::value, \"unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class.\");\n\t\t}\n\n\t\ttemplate <typename P,\n\t\t          typename = eastl::enable_if_t<Internal::is_array_cv_convertible<P, pointer>::value>> // Pointers to types derived from T are rejected by the constructors, and by reset.\n\t\t explicit unique_ptr(P pArray) EA_NOEXCEPT\n\t\t    : mPair(pArray)\n\t\t{\n\t\t\tstatic_assert(!eastl::is_pointer<deleter_type>::value,\n\t\t\t              \"unique_ptr deleter default-constructed with null pointer. Use a different constructor or \"\n\t\t\t              \"change your deleter to a class.\");\n\t\t}\n\n\t\ttemplate <typename P>\n\t\tunique_ptr(P pArray, typename eastl::conditional<eastl::is_lvalue_reference<deleter_type>::value, deleter_type,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttypename eastl::add_lvalue_reference<const deleter_type>::type>::type deleter,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttypename eastl::enable_if<Internal::is_array_cv_convertible<P, pointer>::value>::type* = 0) EA_NOEXCEPT\n\t\t\t: mPair(pArray, deleter) {}\n\n\t\ttemplate <typename P>\n\t\tunique_ptr(P pArray, typename eastl::remove_reference<deleter_type>::type&& deleter, eastl::enable_if_t<Internal::is_array_cv_convertible<P, pointer>::value>* = 0) EA_NOEXCEPT\n\t\t\t: mPair(pArray, eastl::move(deleter))\n\t\t{\n\t\t\tstatic_assert(!eastl::is_lvalue_reference<deleter_type>::value, \"deleter_type reference refers to an rvalue deleter. The reference will probably become invalid before used. Change the deleter_type to not be a reference or construct with permanent deleter.\");\n\t\t}\n\n\t\tunique_ptr(this_type&& x) EA_NOEXCEPT\n\t\t\t: mPair(x.release(), eastl::forward<deleter_type>(x.get_deleter())) {}\n\n\t\ttemplate <typename U, typename E>\n\t\tunique_ptr(unique_ptr<U, E>&& u, typename enable_if<Internal::is_safe_array_conversion<T, pointer, U, typename unique_ptr<U, E>::pointer>::value && \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\teastl::is_convertible<E, deleter_type>::value &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   (!eastl::is_lvalue_reference<deleter_type>::value || eastl::is_same<E, deleter_type>::value)>::type* = 0) EA_NOEXCEPT\n\t\t\t: mPair(u.release(), eastl::forward<E>(u.get_deleter())) {}\n\n\t\tthis_type& operator=(this_type&& x) EA_NOEXCEPT\n\t\t{\n\t\t\treset(x.release());\n\t\t\tmPair.second() = eastl::move(eastl::forward<deleter_type>(x.get_deleter()));\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename U, typename E>\n\t\ttypename enable_if<Internal::is_safe_array_conversion<T, pointer, U, typename unique_ptr<U, E>::pointer>::value && is_assignable<deleter_type&, E&&>::value, this_type&>::type\n\t\toperator=(unique_ptr<U, E>&& u) EA_NOEXCEPT\n\t\t{\n\t\t\treset(u.release());\n\t\t\tmPair.second() = eastl::move(eastl::forward<E>(u.get_deleter()));\n\t\t\treturn *this;\n\t\t}\n\n\t\tthis_type& operator=(std::nullptr_t) EA_NOEXCEPT\n\t\t{\n\t\t\treset();\n\t\t\treturn *this;\n\t\t}\n\n\t\t~unique_ptr() EA_NOEXCEPT\n\t\t{\n\t\t\treset();\n\t\t}\n\n\t\tvoid reset(pointer pArray = pointer()) EA_NOEXCEPT\n\t\t{\n\t\t\tif(pArray != mPair.first())\n\t\t\t{\n\t\t\t\tif (auto first = eastl::exchange(mPair.first(), pArray))\n\t\t\t\t\tget_deleter()(first);\n\t\t\t}\n\t\t}\n\n\t\tpointer release() EA_NOEXCEPT\n\t\t{\n\t\t\tpointer const pTemp = mPair.first();\n\t\t\tmPair.first() = pointer();\n\t\t\treturn pTemp;\n\t\t}\n\n\t\t/// detach\n\t\t/// For backwards-compatibility with pre-C++11 code.\n\t\tpointer detach() EA_NOEXCEPT { return release(); }\n\n\t\tvoid swap(this_type& x) EA_NOEXCEPT\n\t\t{\n\t\t\tmPair.swap(x.mPair);\n\t\t}\n\n\t\t/// operator[]\n\t\t/// Returns a reference to the specified item in the owned pointer\n\t\t/// array. \n\t\t/// Example usage:\n\t\t///    unique_ptr<int> ptr(new int[6]);\n\t\t///    int x = ptr[2];\n\t\ttypename add_lvalue_reference<T>::type operator[](ptrdiff_t i) const\n\t\t{\n\t\t\t// assert(mpArray && (i >= 0));\n\t\t\treturn mPair.first()[i];\n\t\t}\n\n\t\tpointer get() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPair.first();\n\t\t}\n\n\t\tdeleter_type& get_deleter() EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPair.second();\n\t\t}\n\n\t\tconst deleter_type& get_deleter() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn mPair.second();\n\t\t}\n\n\t\t#ifdef EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS\n\t\t\ttypedef T* (this_type::*bool_)() const;\n\t\t\toperator bool_() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tif(mPair.first())\n\t\t\t\t\treturn &this_type::get;\n\t\t\t\treturn NULL;\n\t\t\t}\n\n\t\t\tbool operator!() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\treturn (mPair.first() == pointer());\n\t\t\t}\n\t\t#else\n\t\t\texplicit operator bool() const EA_NOEXCEPT\n\t\t\t{ \n\t\t\t\treturn (mPair.first() != pointer());\n\t\t\t}\n\t\t#endif\n\n\t\t/// These functions are deleted in order to prevent copying, for safety.\n\t\tunique_ptr(const this_type&) = delete;\n\t\tunique_ptr& operator=(const this_type&) = delete;\n\t\tunique_ptr& operator=(pointer pArray) = delete;\n\n\tprotected:\n\t\teastl::compressed_pair<pointer, deleter_type> mPair;\n\t};\n\n\n\n\t/// make_unique\n\t///\n\t/// The C++11 Standard doesn't have make_unique, but there's no agreed reason as to why.\n\t/// http://stackoverflow.com/questions/12580432/why-does-c11-have-make-shared-but-not-make-unique\n\t/// http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/\n\t/// Herb's solution is OK but doesn't support unique_ptr<[]> (array version). We do the same\n\t/// thing libc++ does and make a specialization of make_unique for arrays.\n\t///\n\t/// make_unique has two cases where you can't use it and need to directly use unique_ptr:\n\t///     - You need to construct the unique_ptr with a raw pointer.\n\t///     - You need to specify a custom deleter.\n\t///\n\t/// Note: This function uses global new T by default to create the ptr instance, as per \n\t/// the C++11 Standard make_shared_ptr.\n\t///\n\t/// Example usage:\n\t///     struct Test{ Test(int, int){} };\n\t///     auto p = make_unique<Test>(1, 2);\n\t///\n\t///     auto pArray = make_unique<Test[]>(4);\n\t///\n\ttemplate <typename T, typename... Args>\n\tinline typename eastl::enable_if<!eastl::is_array<T>::value, eastl::unique_ptr<T>>::type make_unique(Args&&... args)\n\t\t{ return unique_ptr<T>(new T(eastl::forward<Args>(args)...)); }\n\n\ttemplate <typename T>\n\tinline typename eastl::enable_if<eastl::is_unbounded_array<T>::value, eastl::unique_ptr<T>>::type make_unique(size_t n)\n\t{\n\t\ttypedef typename eastl::remove_extent<T>::type TBase;\n\t\treturn unique_ptr<T>(new TBase[n]);\n\t}\n\n\t// It's not possible to create a unique_ptr for arrays of a known bound (e.g. int[4] as opposed to int[]).\n\ttemplate <typename T, typename... Args>\n\ttypename eastl::enable_if<eastl::is_bounded_array<T>::value>::type\n\tmake_unique(Args&&...) = delete;\n\n\n\n\n\t/// hash specialization for unique_ptr.\n\t/// It simply returns eastl::hash(x.get()). If your unique_ptr pointer type (the return value of unique_ptr<T>::get) is \n\t/// a custom type and not a built-in pointer type then you will need to independently define eastl::hash for that type.\n\ttemplate <typename T, typename D>\n\tstruct hash< unique_ptr<T, D> >\n\t{\n\t\tsize_t operator()(const unique_ptr<T, D>& x) const EA_NOEXCEPT\n\t\t\t{ return eastl::hash<typename unique_ptr<T, D>::pointer>()(x.get()); }\n\t};\n\n\t/// swap\n\t/// Exchanges the owned pointer beween two unique_ptr objects.\n\t/// This non-member version is useful for compatibility of unique_ptr\n\t/// objects with the C++ Standard Library and other libraries.\n\ttemplate <typename T, typename D>\n\tinline void swap(unique_ptr<T, D>& a, unique_ptr<T, D>& b) EA_NOEXCEPT\n\t{\n\t\ta.swap(b);\n\t}\n\n\n\ttemplate <typename T1, typename D1, typename T2, typename D2>\n\tinline bool operator==(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b)\n\t{\n\t\treturn (a.get() == b.get());\n\t}\n\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T1, typename D1, typename T2, typename D2>\n\trequires std::three_way_comparable_with<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>\n\tinline std::compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> operator<=>(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b)\n\t{\n\t\treturn a.get() <=> b.get();\n\t}\n\t#else\n\ttemplate <typename T1, typename D1, typename T2, typename D2>\n\tinline bool operator!=(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b)\n\t{\n\t\treturn !(a.get() == b.get());\n\t}\n\t#endif\n\n\t/// Returns which unique_ptr is 'less' than the other. Useful when storing\n\t/// sorted containers of unique_ptr objects.\n\ttemplate <typename T1, typename D1, typename T2, typename D2>\n\tinline bool operator<(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b)\n\t{\n\t\t//typedef typename eastl::unique_ptr<T1, D1>::pointer P1;       // We currently need to make these temporary variables, as otherwise clang complains about CPointer being int*&&&.\n\t\t//typedef typename eastl::unique_ptr<T2, D2>::pointer P2;       // I think there's something wrong with our common_type type trait implementation.\n\t\t//typedef typename eastl::common_type<P1, P2>::type   PCommon;  // \"in instantiation of function template specialization 'eastl::operator<<int, int>, no known conversion from 'element_type *' (aka 'int *') to 'int *&&&' for 1st argument\"\n\t\t//return less<PCommon>()(a.get(), b.get());                     // It looks like common_type is making CPointer be (e.g.) int*&& instead of int*, though the problem may be in how less<> deals with that.\n\n\t\ttypedef typename eastl::unique_ptr<T1, D1>::pointer P1;\n\t\ttypedef typename eastl::unique_ptr<T2, D2>::pointer P2;\n\t\ttypedef typename eastl::common_type<P1, P2>::type   PCommon;\n\t\tPCommon pT1 = a.get();\n\t\tPCommon pT2 = b.get();\n\t\treturn less<PCommon>()(pT1, pT2);\n\t}\n\n\ttemplate <typename T1, typename D1, typename T2, typename D2>\n\tinline bool operator>(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) \n\t{\n\t\treturn (b < a);\n\t}\n\n\ttemplate <typename T1, typename D1, typename T2, typename D2>\n\tinline bool operator<=(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) \n\t{\n\t\treturn !(b < a);\n\t}\n\n\ttemplate <typename T1, typename D1, typename T2, typename D2>\n\tinline bool operator>=(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) \n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename T, typename D>\n\tinline bool operator==(const unique_ptr<T, D>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn !a;\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename D>\n\trequires std::three_way_comparable_with<typename unique_ptr<T, D>::pointer, std::nullptr_t>\n\tinline std::compare_three_way_result_t<typename unique_ptr<T, D>::pointer, std::nullptr_t> operator<=>(const unique_ptr<T, D>& a, std::nullptr_t)\n\t{\n\t\treturn a.get() <=> nullptr;\n\t}\n#else\n\ttemplate <typename T, typename D>\n\tinline bool operator==(std::nullptr_t, const unique_ptr<T, D>& a) EA_NOEXCEPT\n\t{\n\t\treturn !a;\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator!=(const unique_ptr<T, D>& a, std::nullptr_t) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<bool>(a);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator!=(std::nullptr_t, const unique_ptr<T, D>& a) EA_NOEXCEPT\n\t{\n\t\treturn static_cast<bool>(a);\n\t}\n#endif\n\n\ttemplate <typename T, typename D>\n\tinline bool operator<(const unique_ptr<T, D>& a, std::nullptr_t)\n\t{\n\t\ttypedef typename unique_ptr<T, D>::pointer pointer;\n\t\treturn less<pointer>()(a.get(), nullptr);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator<(std::nullptr_t, const unique_ptr<T, D>& b)\n\t{\n\t\ttypedef typename unique_ptr<T, D>::pointer pointer;\n\t\tpointer pT = b.get();\n\t\treturn less<pointer>()(nullptr, pT);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator>(const unique_ptr<T, D>& a, std::nullptr_t)\n\t{\n\t\treturn (nullptr < a);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator>(std::nullptr_t, const unique_ptr<T, D>& b)\n\t{\n\t\treturn (b < nullptr);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator<=(const unique_ptr<T, D>& a, std::nullptr_t)\n\t{\n\t\treturn !(nullptr < a);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator<=(std::nullptr_t, const unique_ptr<T, D>& b)\n\t{\n\t\treturn !(b < nullptr);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator>=(const unique_ptr<T, D>& a, std::nullptr_t)\n\t{\n\t\treturn !(a < nullptr);\n\t}\n\n\ttemplate <typename T, typename D>\n\tinline bool operator>=(std::nullptr_t, const unique_ptr<T, D>& b)\n\t{\n\t\treturn !(nullptr < b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/unordered_map.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_UNORDERED_MAP_H\n#define EASTL_UNORDERED_MAP_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/hash_map.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\nnamespace eastl\n{\n\t/// unordered_map \n\t///\n\t/// The original TR1 (technical report 1) used \"hash_map\" to name a hash\n\t/// table backed associative container of unique key-value pairs.  When the\n\t/// container was added to the C++11 standard the committee chose the name\n\t/// \"unordered_map\" to clarify that internally the elements are NOT sorted in\n\t/// any particular order.  We provide a template alias here to ensure feature\n\t/// parity with the original eastl::hash_map.\n\t///\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename Key,\n\t\t\t\t  typename T,\n\t\t\t\t  typename Hash = eastl::hash<Key>,\n\t\t\t\t  typename Predicate = eastl::equal_to<Key>,\n\t\t\t\t  typename Allocator = EASTLAllocatorType,\n\t\t\t\t  bool bCacheHashCode = false>\n\t\tusing unordered_map = hash_map<Key, T, Hash, Predicate, Allocator, bCacheHashCode>;\n    #endif\n\n\n    /// unordered_multimap\n\t///\n\t/// Similar template alias as \"unordered_map\" except the contained elements\n\t/// need not be unique. See \"hash_multimap\" for more details.\n\t///\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename Key,\n\t\t\t\t  typename T,\n\t\t\t\t  typename Hash = eastl::hash<Key>,\n\t\t\t\t  typename Predicate = eastl::equal_to<Key>,\n\t\t\t\t  typename Allocator = EASTLAllocatorType,\n\t\t\t\t  bool bCacheHashCode = false>\n\t\tusing unordered_multimap = hash_multimap<Key, T, Hash, Predicate, Allocator, bCacheHashCode>;\n    #endif\n\n} // namespace eastl\n\n#endif // Header include guard\n\n"
  },
  {
    "path": "include/EASTL/unordered_set.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_UNORDERED_SET_H\n#define EASTL_UNORDERED_SET_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/hash_set.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\nnamespace eastl\n{\n\n\t/// unordered_set \n\t///\n\t/// The original TR1 (technical report 1) used \"hash_set\" to name a hash\n\t/// table backed associative container of unique \"Key\" type objects.  When\n\t/// the container was added to the C++11 standard the committee chose the\n\t/// name \"unordered_set\" to clarify that internally the elements are NOT\n\t/// sorted in any particular order.  We provide a template alias here to\n\t/// ensure feature parity with the original eastl::hash_set.\n\t///\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename Value,\n\t\t\t\t  typename Hash = eastl::hash<Value>,\n\t\t\t\t  typename Predicate = eastl::equal_to<Value>,\n\t\t\t\t  typename Allocator = EASTLAllocatorType,\n\t\t\t\t  bool bCacheHashCode = false>\n\t\tusing unordered_set = hash_set<Value, Hash, Predicate, Allocator, bCacheHashCode>;\n\t#endif\n\n    /// unordered_multiset \n\t///\n\t/// Similar template alias as \"unordered_set\" except the contained elements\n\t/// need not be unique. See \"hash_multiset\" for more details. \n\t///\n\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\ttemplate <typename Value,\n\t\t\t\t  typename Hash = eastl::hash<Value>,\n\t\t\t\t  typename Predicate = eastl::equal_to<Value>,\n\t\t\t\t  typename Allocator = EASTLAllocatorType,\n\t\t\t\t  bool bCacheHashCode = false>\n\t\tusing unordered_multiset = hash_multiset<Value, Hash, Predicate, Allocator, bCacheHashCode>;\n\t#endif\n\n} // namespace eastl\n\n#endif // Header include guard\n\n"
  },
  {
    "path": "include/EASTL/utility.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_UTILITY_H\n#define EASTL_UTILITY_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/numeric_limits.h>\n#include <EASTL/compare.h>\n#include <EASTL/internal/functional_base.h>\n#include <EASTL/internal/move_help.h>\n#include <EASTL/meta.h>\n#include <EABase/eahave.h>\n\n#include <EASTL/internal/integer_sequence.h>\n#include <EASTL/internal/tuple_fwd_decls.h>\n#include <EASTL/internal/in_place_t.h>\n#include <EASTL/internal/piecewise_construct_t.h>\n\n\n// 4619 - There is no warning number 'number'.\n// 4217 - Member template functions cannot be used for copy-assignment or copy-construction.\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4619 4217 4512 4626);\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// swap\n\t///\n\t/// Assigns the contents of a to b and the contents of b to a. \n\t/// A temporary instance of type T is created and destroyed\n\t/// in the process.\n\t///\n\t/// This function is used by numerous other algorithms, and as \n\t/// such it may in some cases be feasible and useful for the user \n\t/// to implement an override version of this function which is \n\t/// more efficient in some way. \n\t///\n\n\ttemplate <typename T> \n\tinline void swap(T& a, T& b) EA_NOEXCEPT_IF(eastl::is_nothrow_move_constructible<T>::value && eastl::is_nothrow_move_assignable<T>::value)\n\t{\n\t\tT temp(EASTL_MOVE(a));  // EASTL_MOVE uses EASTL::move when available, else is a no-op.\n\t\ta = EASTL_MOVE(b);\n\t\tb = EASTL_MOVE(temp);\n\t}\n\n\n\t/// is_swappable\n\t///\n\t/// Determines if two types can be swapped via the swap function. This determines\n\t/// only if there is a swap function that matches the types and not if the assignments\n\t/// within the swap implementation are valid.\n\t/// Returns false for pre-C++11 compilers that don't support decltype.\n\t///\n\t/// This is a type trait, but it's not currently found within <type_traits.h>,\n\t/// as it's dependent on the swap algorithm, which is at a higher level than\n\t/// type traits.\n\t///\n\t/// Example usage:\n\t///     static_assert(is_swappable<int>::value, \"int should be swappable\");\n\t///\n\t#if defined(EA_COMPILER_NO_DECLTYPE)\n\t\t#define EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE 0\n\n\t\ttemplate <typename>\n\t\tstruct is_swappable\n\t\t\t: public eastl::false_type {};\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE 1\n\n\t\t// We declare this version of 'eastl::swap' to make compile-time existance checks for swap functions possible.  \n\t\t//\n\t\t#if EASTL_VARIADIC_TEMPLATES_ENABLED\n\t\t\teastl::unused swap(eastl::argument_sink, eastl::argument_sink);\n\t\t#else\n\t\t\t// Compilers that do not support variadic templates suffer from a bug with variable arguments list that\n\t\t\t// causes the construction of aligned types in unaligned memory. To prevent the aligned type construction we\n\t\t\t// accept the parameters by reference.\n\t\t\teastl::unused swap(eastl::argument_sink&, eastl::argument_sink&);\n\t\t#endif\n\n\t\ttemplate <typename T>\n\t\tstruct is_swappable\n\t\t\t: public integral_constant<bool, !eastl::is_same<decltype(swap(eastl::declval<T&>(), eastl::declval<T&>())), eastl::unused>::value> {}; // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.\n\t#endif\n\t\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n        template <class T>\n        EA_CONSTEXPR bool is_swappable_v = is_swappable<T>::value;\n    #endif\n\n\n\n\t/// is_nothrow_swappable\n\t///\n\t/// Evaluates to true if is_swappable, and swap is a nothrow function.\n\t/// returns false for pre-C++11 compilers that don't support nothrow.\n\t///\n\t/// This is a type trait, but it's not currently found within <type_traits.h>,\n\t/// as it's dependent on the swap algorithm, which is at a higher level than\n\t/// type traits.\n\t///\n\t#define EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE\n\n\ttemplate <typename T>\n\tstruct is_nothrow_swappable_helper_noexcept_wrapper\n\t\t{ const static bool value = noexcept(swap(eastl::declval<T&>(), eastl::declval<T&>())); };\n\n\ttemplate <typename T, bool>\n\tstruct is_nothrow_swappable_helper\n\t\t: public eastl::integral_constant<bool, is_nothrow_swappable_helper_noexcept_wrapper<T>::value> {}; // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.\n\n\ttemplate <typename T>\n\tstruct is_nothrow_swappable_helper<T, false>\n\t\t: public eastl::false_type {};\n\n\ttemplate <typename T>\n\tstruct is_nothrow_swappable\n\t\t: public eastl::is_nothrow_swappable_helper<T, eastl::is_swappable<T>::value> {};\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n        template <class T>\n        EA_CONSTEXPR bool is_nothrow_swappable_v = is_nothrow_swappable<T>::value;\n    #endif\n\n\n\t\n\t/// is_swappable_with\n\t///\n\t///\n\ttemplate <typename T, typename U, bool OneTypeIsVoid = (eastl::is_void<T>::value || eastl::is_void<U>::value)>\n\tstruct is_swappable_with_helper\n\t{\n\t\t// Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.\n\t    static const bool value =\n\t        !eastl::is_same<decltype(swap(eastl::declval<T>(), eastl::declval<U>())), eastl::unused>::value &&\n\t        !eastl::is_same<decltype(swap(eastl::declval<U>(), eastl::declval<T>())), eastl::unused>::value;\n    };\n\n\ttemplate <typename T, typename U>\n\tstruct is_swappable_with_helper<T,U, true> { static const bool value = false; };\n\n    template<typename T, typename U>\n\tstruct is_swappable_with \n\t\t\t: public eastl::bool_constant<is_swappable_with_helper<T, U>::value> {}; \n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n        template <class T, class U>\n        EA_CONSTEXPR bool is_swappable_with_v = is_swappable_with<T, U>::value;\n    #endif\n\n\n\t\n\t/// is_nothrow_swappable_with\n\t///\n\t///\n\t#if defined(EA_COMPILER_NO_DECLTYPE) || defined(EA_COMPILER_NO_NOEXCEPT) \n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_swappable_with_CONFORMANCE 0\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_nothrow_swappable_with_helper { static const bool value = false; };\n\t#else\n\t\t#define EASTL_TYPE_TRAIT_is_nothrow_swappable_with_CONFORMANCE 1\n\t\ttemplate <typename T, typename U, bool OneTypeIsVoid = (eastl::is_void<T>::value || eastl::is_void<U>::value)>\n\t\tstruct is_nothrow_swappable_with_helper\n\t\t{\n\t        // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.\n\t        static const bool value = noexcept(swap(eastl::declval<T>(), eastl::declval<U>())) &&\n\t                                  noexcept(swap(eastl::declval<U>(), eastl::declval<T>()));\n        };\n\n\t\ttemplate <typename T, typename U>\n\t\tstruct is_nothrow_swappable_with_helper<T,U, true> { static const bool value = false; };\n\t#endif\n\n    template <typename T, typename U>\n    struct is_nothrow_swappable_with : public eastl::bool_constant<is_nothrow_swappable_with_helper<T, U>::value> {};\n\n    #if EASTL_VARIABLE_TEMPLATES_ENABLED\n        template <class T, class U>\n        EA_CONSTEXPR bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<T, U>::value;\n    #endif\n\t\n\n\n\t// iter_swap helper functions\n\t//\n\ttemplate <bool bTypesAreEqual>\n\tstruct iter_swap_impl\n\t{\n\t\t// Handles the false case, where *a and *b are different types.\n\t\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\t\tstatic void iter_swap(ForwardIterator1 a, ForwardIterator2 b)\n\t\t{\n\t\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::value_type value_type_a;\n\n\t\t\tvalue_type_a temp(EASTL_MOVE(*a)); // EASTL_MOVE uses EASTL::move when available, else is a no-op.\n\t\t\t*a = EASTL_MOVE(*b);\n\t\t\t*b = EASTL_MOVE(temp); \n\t\t}\n\t};\n\n\ttemplate <>\n\tstruct iter_swap_impl<true>\n\t{\n\t\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\t\tstatic void iter_swap(ForwardIterator1 a, ForwardIterator2 b)\n\t\t{\n\t\t\tswap(*a, *b);  // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.\n\t\t}\n\t};\n\n\n\t/// iter_swap\n\t///\n\t/// Swaps the values of the elements the given iterators are pointing to. \n\t///\n\t/// Equivalent to swap(*a, *b), though the user can provide an override to\n\t/// iter_swap that is independent of an override which may exist for swap.\n\t///\n\t/// We provide a version of iter_swap which uses swap when the swapped types \n\t/// are equal but a manual implementation otherwise. We do this because the \n\t/// C++ standard defect report says that iter_swap(a, b) must be implemented \n\t/// as swap(*a, *b) when possible.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\tinline void iter_swap(ForwardIterator1 a, ForwardIterator2 b)\n\t{\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::value_type value_type_a;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator2>::value_type value_type_b;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator1>::reference  reference_a;\n\t\ttypedef typename eastl::iterator_traits<ForwardIterator2>::reference  reference_b;\n\n\t\teastl::iter_swap_impl<eastl::conjunction<eastl::is_same<value_type_a, value_type_b>, eastl::is_same<value_type_a&, reference_a>, eastl::is_same<value_type_b&, reference_b>>::value >::iter_swap(a, b);\n\t}\n\n\n\n\t/// swap_ranges\n\t///\n\t/// Swaps each of the elements in the range [first1, last1) with the \n\t/// corresponding element in the range [first2, first2 + (last1 - first1)). \n\t///\n\t/// Effects: For each nonnegative integer n < (last1 - first1),\n\t/// performs: swap(*(first1 + n), *(first2 + n)).\n\t///\n\t/// Requires: The two ranges [first1, last1) and [first2, first2 + (last1 - first1))\n\t/// shall not overlap.\n\t///\n\t/// Returns: first2 + (last1 - first1). That is, returns the end of the second range.\n\t///\n\t/// Complexity: Exactly 'last1 - first1' swaps.\n\t///\n\ttemplate <typename ForwardIterator1, typename ForwardIterator2>\n\tinline ForwardIterator2\n\tswap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)\n\t{\n\t\tfor(; first1 != last1; ++first1, ++first2)\n\t\t\titer_swap(first1, first2); // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.\n\t\treturn first2;\n\t}\n\n\n\t/// swap\n\t///\n\t/// C++11 array swap\n\t/// http://en.cppreference.com/w/cpp/algorithm/swap\n\t///\n\ttemplate <typename T, size_t N>\n\tinline void\n\tswap(T (&a)[N], T (&b)[N]) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<T>::value)\n\t{\n\t\teastl::swap_ranges(a, a + N, b);\n\t}\n\n\n\t/// exchange\n\t///\n\t/// Replaces the value of the first argument with the new value provided.  \n\t/// The return value is the previous value of first argument.\n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/exchange\n\t///\n\ttemplate <typename T, typename U = T>\n\tinline T exchange(T& obj, U&& new_value)\n\t{\n\t\tT old_value = eastl::move(obj);\n\t\tobj = eastl::forward<U>(new_value);\n\t\treturn old_value;\n\t}\n\n\n\t/// as_const\n\t///\n\t/// Converts a 'T&' into a 'const T&' which simplifies calling const functions on non-const objects. \n\t///\n\t/// http://en.cppreference.com/w/cpp/utility/as_const\n\t///\n\t/// C++ proposal paper:\n\t/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4380.html\n\t///\n\ttemplate <class T>\n\tEA_CONSTEXPR typename eastl::add_const<T>::type& as_const(T& t) EA_NOEXCEPT\n\t\t{ return t; }\n\n\t// The C++17 forbids 'eastl::as_const' from accepting rvalues.  Passing an rvalue reference to 'eastl::as_const'\n\t// generates an 'const T&' or const lvalue reference to a temporary object. \n\ttemplate <class T>\n\tvoid as_const(const T&&) = delete;\n\n\n    ///////////////////////////////////////////////////////////////////////\n\t/// rel_ops\n\t///\n\t/// rel_ops allow the automatic generation of operators !=, >, <=, >= from\n\t/// just operators == and <. These are intentionally in the rel_ops namespace\n\t/// so that they don't conflict with other similar operators. To use these \n\t/// operators, add \"using namespace std::rel_ops;\" to an appropriate place in \n\t/// your code, usually right in the function that you need them to work.\n\t/// In fact, you will very likely have collision problems if you put such\n\t/// using statements anywhere other than in the .cpp file like so and may \n\t/// also have collisions when you do, as the using statement will affect all\n\t/// code in the module. You need to be careful about use of rel_ops.\n\t///\n\tnamespace rel_ops\n\t{\n\t\ttemplate <typename T>\n\t\tinline bool operator!=(const T& x, const T& y)\n\t\t\t{ return !(x == y); }\n\n\t\ttemplate <typename T>\n\t\tinline bool operator>(const T& x, const T& y)\n\t\t\t{ return (y < x); }\n\n\t\ttemplate <typename T>\n\t\tinline bool operator<=(const T& x, const T& y)\n\t\t\t{ return !(y < x); }\n\n\t\ttemplate <typename T>\n\t\tinline bool operator>=(const T& x, const T& y)\n\t\t\t{ return !(x < y); }\n\t}\n\n\n\t#if defined(EA_COMPILER_CPP17_ENABLED)\n\t///////////////////////////////////////////////////////////////////////\n\t/// Safe Integral Comparisons\n\t///\n\ttemplate <typename T, typename U>\n\tEA_CONSTEXPR bool cmp_equal(const T x, const U y) EA_NOEXCEPT\n\t{\n\t\t// Assert types are not chars, bools, etc.\n\t\tstatic_assert(eastl::is_integral_v<T> && !eastl::is_same_v<eastl::remove_cv_t<T>, bool> && !eastl::is_same_v<eastl::remove_cv_t<T>, char>);\n\t\tstatic_assert(eastl::is_integral_v<U> && !eastl::is_same_v<eastl::remove_cv_t<U>, bool> && !eastl::is_same_v<eastl::remove_cv_t<U>, char>);\n\n\t\tusing UT = eastl::make_unsigned_t<T>;\n\t\tusing UU = eastl::make_unsigned_t<U>;\n\n\t\tif constexpr (eastl::is_signed_v<T> == eastl::is_signed_v<U>)\n\t\t{\n\t\t\treturn x == y;\n\t\t}\n\t\telse if constexpr (eastl::is_signed_v<T>)\n\t\t{\n\t\t\treturn (x < 0) ? false : UT(x) == y;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn (y < 0) ? false : x == UU(y);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename U>\n\tEA_CONSTEXPR bool cmp_not_equal(const T x, const U y) EA_NOEXCEPT\n\t\t{ return !eastl::cmp_equal(x, y); }\n\n\n\ttemplate <typename T, typename U>\n\tEA_CONSTEXPR bool cmp_less(const T x, const U y) EA_NOEXCEPT\n\t{\n\t\tstatic_assert(eastl::is_integral_v<T> && !eastl::is_same_v<eastl::remove_cv_t<T>, bool> && !eastl::is_same_v<eastl::remove_cv_t<T>, char>);\n\t\tstatic_assert(eastl::is_integral_v<U> && !eastl::is_same_v<eastl::remove_cv_t<U>, bool> && !eastl::is_same_v<eastl::remove_cv_t<U>, char>);\n\n\t\tusing UT = eastl::make_unsigned_t<T>;\n\t\tusing UU = eastl::make_unsigned_t<U>;\n\n\t\tif constexpr (eastl::is_signed_v<T> == eastl::is_signed_v<U>)\n\t\t{\n\t\t\treturn x < y;\n\t\t}\n\t\telse if constexpr (eastl::is_signed_v<T>)\n\t\t{\n\t\t\treturn (x < 0) ? true : UT(x) < y;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn (y < 0) ? false : x < UU(y);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename U>\n\tEA_CONSTEXPR bool cmp_greater(const T x, const U y) EA_NOEXCEPT\n\t\t{ return eastl::cmp_less(y, x); }\n\n\n\ttemplate <typename T, typename U>\n\tEA_CONSTEXPR bool cmp_less_equal(const T x, const U y) EA_NOEXCEPT\n\t\t{ return !eastl::cmp_greater(x, y); }\n\n\n\ttemplate <typename T, typename U>\n\tEA_CONSTEXPR bool cmp_greater_equal(const T x, const U y) EA_NOEXCEPT\n\t\t{ return !eastl::cmp_less(x, y); }\n\n\n\ttemplate <typename T, typename U>\n\tEA_CONSTEXPR bool in_range(const U x) EA_NOEXCEPT\n\t{\n\t\tstatic_assert(eastl::is_integral_v<T> && !eastl::is_same_v<eastl::remove_cv_t<T>, bool> && !eastl::is_same_v<eastl::remove_cv_t<T>, char>);\n\t\tstatic_assert(eastl::is_integral_v<U> && !eastl::is_same_v<eastl::remove_cv_t<U>, bool> && !eastl::is_same_v<eastl::remove_cv_t<U>, char>);\n\n\t\treturn eastl::cmp_greater_equal(x, eastl::numeric_limits<T>::min()) && eastl::cmp_less_equal(x, eastl::numeric_limits<T>::max());\n\t}\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t/// pair_first_construct\n\t///\n\t/// Disambiguates when a user is requesting the 'single first element' pair constructor.\n\t///\n\tstruct pair_first_construct_t {};\n\tEA_CONSTEXPR pair_first_construct_t pair_first_construct = pair_first_construct_t();\n\n\t\n\t///////////////////////////////////////////////////////////////////////\n\t/// pair\n\t///\n\t/// Implements a simple pair, just like the C++ std::pair.\n\t///\n\ttemplate <typename T1, typename T2>\n\tstruct pair\n\t{\n\t\ttypedef T1           first_type;\n\t\ttypedef T2           second_type;\n\t\ttypedef pair<T1, T2> this_type;\n\n\t\tT1 first;\n\t\tT2 second;\n\n\t\ttemplate <typename TT1 = T1,\n\t\t          typename TT2 = T2,\n\t\t          class = eastl::enable_if_t<eastl::is_default_constructible_v<TT1> &&\n\t\t                                     eastl::is_default_constructible_v<TT2>>>\n\t\tEA_CONSTEXPR pair()\n\t\t    : first(), second()\n\t\t{\n\t\t}\n\n\t#if EASTL_ENABLE_PAIR_FIRST_ELEMENT_CONSTRUCTOR\n\t\ttemplate <typename TT1 = T1, typename TT2 = T2, typename = eastl::enable_if_t<eastl::is_default_constructible_v<TT2>>>\n\t\tEA_CPP14_CONSTEXPR pair(const TT1& x)\n\t\t    : first(x), second()\n\t\t{\n\t\t}\n\n\t\t// GCC has a bug with overloading rvalue and lvalue function templates.\t\n\t\t// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425\t\n\t\t//\t\n\t\t// error: 'eastl::pair<T1, T2>::pair(T1&&) [with T1 = const int&; T2 = const int&]' cannot be overloaded\t\n\t\t// error: with 'eastl::pair<T1, T2>::pair(const T1&) [with T1 = const int&; T2 = const int&]'\n\t\t#if !defined(EA_COMPILER_GNUC)\n\t\t\ttemplate <typename TT2 = T2, typename = eastl::enable_if_t<eastl::is_default_constructible_v<TT2>>>\n\t\t\tEA_CPP14_CONSTEXPR pair(T1&& x)\n\t\t\t\t: first(eastl::move(x)), second()\n\t\t\t{\n\t\t\t}\n\t\t#endif\n\t#endif\n\n\t\n\t// NOTE(rparolin): \n\t// This is a workaround to a compiler intrinic bug which fails to correctly identify a nested class using\n\t// non-static data member initialization as default constructible.  \n\t//\n\t// See bug submitted to LLVM for more details.\n\t// https://bugs.llvm.org/show_bug.cgi?id=38374\n\t#if !defined(__clang__)\n\t\ttemplate<typename T>\n\t\tusing single_pair_ctor_sfinae = eastl::enable_if_t<eastl::is_default_constructible_v<T>>;\n\t#else\n\t\ttemplate<typename>\n\t\tusing single_pair_ctor_sfinae = void;\n\t#endif\n\n\t\ttemplate <typename TT1 = T1, typename TT2 = T2, typename = single_pair_ctor_sfinae<TT2>>\n\t\tEA_CPP14_CONSTEXPR pair(pair_first_construct_t, const TT1& x)\n\t\t    : first(x), second()\n\t\t{\n\t\t}\n\n\t\t// GCC has a bug with overloading rvalue and lvalue function templates.\t\n\t\t// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425\t\n\t\t//\t\n\t\t// error: 'eastl::pair<T1, T2>::pair(T1&&) [with T1 = const int&; T2 = const int&]' cannot be overloaded\t\n\t\t// error: with 'eastl::pair<T1, T2>::pair(const T1&) [with T1 = const int&; T2 = const int&]'\n\t\t#if !defined(EA_COMPILER_GNUC)\n\t\t\ttemplate <typename TT2 = T2, typename = single_pair_ctor_sfinae<TT2>>\n\t\t\tEA_CPP14_CONSTEXPR pair(pair_first_construct_t, T1&& x)\n\t\t\t\t: first(eastl::move(x)), second()\n\t\t\t{\n\t\t\t}\n\t\t#endif\n\n\t\ttemplate <\n\t\t    typename TT1 = T1,\n\t\t    typename TT2 = T2,\n\t\t    class = eastl::enable_if_t<eastl::is_copy_constructible_v<TT1> && eastl::is_copy_constructible_v<TT2>>>\n\t\tEA_CPP14_CONSTEXPR pair(const T1& x, const T2& y)\n\t\t    : first(x), second(y)\n\t\t{\n\t\t}\n\n\t\tEA_CPP14_CONSTEXPR pair(pair&& p) = default;\n\t\tEA_CPP14_CONSTEXPR pair(const pair&) = default;\n\t\tEA_CPP14_CONSTEXPR pair& operator=(const pair&) = default;\n\t\tEA_CPP14_CONSTEXPR pair& operator=(pair&&) = default;\n\n\t\ttemplate <\n\t\t    typename U,\n\t\t    typename V,\n\t\t    class = eastl::enable_if_t<eastl::is_constructible_v<T1, const U&> && eastl::is_constructible_v<T2, const V&>>>\n\t\tEA_CPP14_CONSTEXPR pair(const pair<U, V>& p)\n\t\t    : first(p.first), second(p.second)\n\t\t{\n\t\t}\n\n\t\ttemplate <typename U,\n\t\t          typename V,\n\t\t          typename = eastl::enable_if_t<eastl::is_constructible_v<T1, U> && eastl::is_constructible_v<T2, V>>>\n\t\tEA_CPP14_CONSTEXPR pair(U&& u, V&& v)\n\t\t    : first(eastl::forward<U>(u)), second(eastl::forward<V>(v))\n\t\t{\n\t\t}\n\n\t\ttemplate <typename U, typename = eastl::enable_if_t<eastl::is_constructible_v<T1, U>>>\n\t\tEA_CPP14_CONSTEXPR pair(U&& x, const T2& y)\n\t\t\t: first(eastl::forward<U>(x)), second(y)\n\t\t{\n\t\t}\n\n\t\ttemplate <typename V, typename = eastl::enable_if_t<eastl::is_constructible_v<T2, V>>>\n\t\tEA_CPP14_CONSTEXPR pair(const T1& x, V&& y)\n\t\t\t: first(x), second(eastl::forward<V>(y))\n\t\t{\n\t\t}\n\n\t\ttemplate <typename U,\n\t\t          typename V,\n\t\t          typename = eastl::enable_if_t<eastl::is_constructible_v<T1, U>&& eastl::is_constructible_v<T2, V>>>\n\t\tEA_CPP14_CONSTEXPR pair(pair<U, V>&& p)\n\t\t    : first(eastl::forward<U>(p.first)), second(eastl::forward<V>(p.second))\n\t\t{\n\t\t}\n\n\t\t// Initializes first with arguments of types Args1... obtained by forwarding the elements of first_args and\n\t\t// initializes second with arguments of types Args2... obtained by forwarding the elements of second_args.\n\t\ttemplate <class... Args1,\n\t\t          class... Args2,\n\t\t          typename = eastl::enable_if_t<eastl::is_constructible_v<first_type, Args1&&...> &&\n\t\t                                        eastl::is_constructible_v<second_type, Args2&&...>>>\n\t\tpair(eastl::piecewise_construct_t pwc, eastl::tuple<Args1...> first_args, eastl::tuple<Args2...> second_args)\n\t\t    : pair(pwc,\n\t\t           eastl::move(first_args),\n\t\t           eastl::move(second_args),\n\t\t           eastl::make_index_sequence<sizeof...(Args1)>(),\n\t\t           eastl::make_index_sequence<sizeof...(Args2)>())\n\t\t{\n\t\t}\n\n\tprivate:\n\t\t// NOTE(rparolin): Internal constructor used to expand the index_sequence required to expand the tuple elements.\n\t\ttemplate <class... Args1, class... Args2, size_t... I1, size_t... I2>\n\t\tpair(eastl::piecewise_construct_t,\n\t\t\t eastl::tuple<Args1...> first_args,\n\t\t\t eastl::tuple<Args2...> second_args,\n\t\t\t eastl::index_sequence<I1...>,\n\t\t\t eastl::index_sequence<I2...>)\n\t\t\t: first(eastl::forward<Args1>(eastl::get<I1>(first_args))...)\n\t\t\t, second(eastl::forward<Args2>(eastl::get<I2>(second_args))...)\n\t\t{\n\t\t}\n\n\tpublic:\n\t\ttemplate <typename U,\n\t\t          typename V,\n\t\t          typename = eastl::enable_if_t<eastl::is_assignable_v<T1&, const U&> && eastl::is_assignable_v<T2&, const V&>>>\n\t\tpair& operator=(const pair<U, V>& p)\n\t\t{\n\t\t\tfirst = p.first;\n\t\t\tsecond = p.second;\n\t\t\treturn *this;\n\t\t}\n\n\t\ttemplate <typename U,\n\t\t          typename V,\n\t\t          typename = eastl::enable_if_t<eastl::is_assignable_v<T1&, U> && eastl::is_assignable_v<T2&, V>>>\n\t\tpair& operator=(pair<U, V>&& p)\n\t\t{\n\t\t\tfirst = eastl::forward<U>(p.first);\n\t\t\tsecond = eastl::forward<V>(p.second);\n\t\t\treturn *this;\n\t\t}\n\n\t\tvoid swap(pair& p) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable_v<T1>&& eastl::is_nothrow_swappable_v<T2>)\n\t\t{\n\t\t\teastl::iter_swap(&first, &p.first);\n\t\t\teastl::iter_swap(&second, &p.second);\n\t\t}\n\t};\n\n\t#define EASTL_PAIR_CONFORMANCE 1\n\n\n\n\t/// use_self\n\t///\n\t/// operator()(x) simply returns x. Used in sets, as opposed to maps.\n\t/// This is a template policy implementation; it is an alternative to \n\t/// the use_first template implementation.\n\t///\n\t/// The existance of use_self may seem odd, given that it does nothing,\n\t/// but these kinds of things are useful, virtually required, for optimal \n\t/// generic programming.\n\t///\n\ttemplate <typename T>\n\tstruct use_self\n\t{\n\t\ttypedef T result_type;\n\n\t\tconst T& operator()(const T& x) const\n\t\t\t{ return x; }\n\t};\n\n\t/// use_first\n\t///\n\t/// operator()(x) simply returns x.first. Used in maps, as opposed to sets.\n\t/// This is a template policy implementation; it is an alternative to \n\t/// the use_self template implementation. This is the same thing as the\n\t/// SGI SGL select1st utility.\n\t///\n\ttemplate <typename Pair>\n\tstruct use_first\n\t{\n\t\ttypedef Pair argument_type;\n\t\ttypedef typename Pair::first_type result_type;\n\n\t\tconst result_type& operator()(const Pair& x) const\n\t\t\t{ return x.first; }\n\t};\n\n\t/// use_second\n\t///\n\t/// operator()(x) simply returns x.second. \n\t/// This is the same thing as the SGI SGL select2nd utility\n\t///\n\ttemplate <typename Pair>\n\tstruct use_second\n\t{\n\t\ttypedef Pair argument_type;\n\t\ttypedef typename Pair::second_type result_type;\n\n\t\tconst result_type& operator()(const Pair& x) const\n\t\t\t{ return x.second; }\n\t};\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T1, typename T2>\n\tEA_CPP14_CONSTEXPR inline bool operator==(const pair<T1, T2>& a, const pair<T1, T2>& b)\n\t{\n\t\treturn ((a.first == b.first) && (a.second == b.second));\n\t}\n\n\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T1, typename T2>\n\tEA_CONSTEXPR inline std::common_comparison_category_t<synth_three_way_result<T1>, synth_three_way_result<T2>> operator<=>(const pair<T1, T2>& a, const pair<T1, T2>& b)\n\t{\n\t\tif (auto result = synth_three_way{}(a.first, b.first); result != 0)\n\t\t{\n\t\t\treturn result;\n\t\t}\n\t\treturn synth_three_way{}(a.second, b.second);\n\t}\n\t#else\n\ttemplate <typename T1, typename T2>\n\tEA_CPP14_CONSTEXPR inline bool operator<(const pair<T1, T2>& a, const pair<T1, T2>& b)\n\t{\n\t\t// Note that we use only operator < in this expression. Otherwise we could\n\t\t// use the simpler: return (a.m1 == b.m1) ? (a.m2 < b.m2) : (a.m1 < b.m1);\n\t\t// The user can write a specialization for this operator to get around this\n\t\t// in cases where the highest performance is required.\n\t\treturn ((a.first < b.first) || (!(b.first < a.first) && (a.second < b.second)));\n\t}\n\n\n\ttemplate <typename T1, typename T2>\n\tEA_CPP14_CONSTEXPR inline bool operator!=(const pair<T1, T2>& a, const pair<T1, T2>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename T1, typename T2>\n\tEA_CPP14_CONSTEXPR inline bool operator>(const pair<T1, T2>& a, const pair<T1, T2>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename T1, typename T2>\n\tEA_CPP14_CONSTEXPR inline bool operator>=(const pair<T1, T2>& a, const pair<T1, T2>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename T1, typename T2>\n\tEA_CPP14_CONSTEXPR inline bool operator<=(const pair<T1, T2>& a, const pair<T1, T2>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\t#endif\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t/// make_pair\n\t///\n\t/// Create a pair, deducing the element types from the types of arguments.\n\t/// \n\t/// Note: You don't need to use make_pair in order to make a pair, it's a convenience for deducing the element types. \n\t/// C++17's class template argument deduction (https://en.cppreference.com/w/cpp/language/class_template_argument_deduction)\n\t/// performs the same purpose as make_unique, make_tuple and similar.\n\t/// \n\t/// The following code all declare pairs of the same type:\n\t///     pair<char*, char*> p1(1, \"explicit\");\n\t///     auto p2 = make_pair(2, \"deduce types\");\n\t///     pair p3(3, \"language feature\"); // requires C++17\n\t///\n\ttemplate <typename T1, typename T2>\n\tEA_CPP14_CONSTEXPR inline pair<typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type, \n\t\t\t\t\t\t\t\t   typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type>\n\tmake_pair(T1&& a, T2&& b)\n\t{\n\t\ttypedef typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type T1Type;\n\t\ttypedef typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type T2Type;\n\n\t\treturn eastl::pair<T1Type, T2Type>(eastl::forward<T1>(a), eastl::forward<T2>(b));\n\t}\n\n\n\t// Note: DO NOT pass type parameters to make_pair().\n\t// eg.\n\t//   const int myInt = 0;\n\t//   const char* myCStr = \"example\";\n\t//   auto pair1 = eastl::make_pair<int, eastl::string>(myInt, myCStr);\n\t//                                ^^^^^^^^^^^^^^^^^^^^--- wrong.\n\t// \n\t// use one of the following, depending on the intended pair type: \n\t//   eastl::pair<int, const char*> pair2 = eastl::make_pair(myInt, myCStr);\n\t//   eastl::pair<int, eastl::string> pair3(myInt, myCStr);\n\t//\n#if defined(_MSC_VER)\n\ttemplate <typename T1, typename T2, typename DeduceT1, typename DeduceT2>\n\tEASTL_REMOVE_AT_2024_SEPT EA_CPP14_CONSTEXPR inline pair<T1, T2> make_pair(\n\t\tconst DeduceT1& a,\n\t\tconst DeduceT2& b,\n\t\ttypename eastl::enable_if<!eastl::is_array<T1>::value && !eastl::is_array<T2>::value>::type* = 0)\n\t{\n\t\treturn eastl::pair<T1, T2>(a, b);\n\t}\n#endif\n\n\t// use make_pair() instead. they are equivalent.\n\ttemplate <typename T1, typename T2>\n\tEASTL_REMOVE_AT_2024_SEPT\n\tEA_CPP14_CONSTEXPR inline pair<typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type, \n\t\t\t\t\t\t\t\t   typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type>\n\tmake_pair_ref(T1&& a, T2&& b)\n\t{\n\t\ttypedef typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type T1Type;\n\t\ttypedef typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type T2Type;\n\n\t\treturn eastl::pair<T1Type, T2Type>(eastl::forward<T1>(a), eastl::forward<T2>(b));\n\t}\n\n#if EASTL_TUPLE_ENABLED\n\n\t\ttemplate <typename T1, typename T2>\n\t\tstruct tuple_size<pair<T1, T2>> : public integral_constant<size_t, 2>\n\t\t{\n\t\t};\n\n\t\ttemplate <typename T1, typename T2>\n\t\tstruct tuple_size<const pair<T1, T2>> : public integral_constant<size_t, 2>\n\t\t{\n\t\t};\n\n\t\ttemplate <typename T1, typename T2>\n\t\tstruct tuple_element<0, pair<T1, T2>>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef T1 type;\n\t\t};\n\n\t\ttemplate <typename T1, typename T2>\n\t\tstruct tuple_element<1, pair<T1, T2>>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef T2 type;\n\t\t};\n\n\t\ttemplate <typename T1, typename T2>\n\t\tstruct tuple_element<0, const pair<T1, T2>>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef const T1 type;\n\t\t};\n\n\t\ttemplate <typename T1, typename T2>\n\t\tstruct tuple_element<1, const pair<T1, T2>>\n\t\t{\n\t\tpublic:\n\t\t\ttypedef const T2 type;\n\t\t};\n\n\t\tnamespace internal\n\t\t{\n\t\t\ttemplate <size_t I>\n\t\t\tstruct GetPair;\n\n\t\t\ttemplate <>\n\t\t\tstruct GetPair<0>\n\t\t\t{\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR T1& get(pair<T1, T2>& p)\n\t\t\t\t{\n\t\t\t\t\treturn p.first;\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR const T1& get(const pair<T1, T2>& p)\n\t\t\t\t{\n\t\t\t\t\treturn p.first;\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR T1&& get(pair<T1, T2>&& p)\n\t\t\t\t{\n\t\t\t\t\treturn eastl::forward<T1>(p.first);\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR const T1&& get(const pair<T1, T2>&& p)\n\t\t\t\t{\n\t\t\t\t\treturn eastl::forward<const T1>(p.first);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttemplate <>\n\t\t\tstruct GetPair<1>\n\t\t\t{\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR T2& get(pair<T1, T2>& p)\n\t\t\t\t{\n\t\t\t\t\treturn p.second;\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR const T2& get(const pair<T1, T2>& p)\n\t\t\t\t{\n\t\t\t\t\treturn p.second;\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR T2&& get(pair<T1, T2>&& p)\n\t\t\t\t{\n\t\t\t\t\treturn eastl::forward<T2>(p.second);\n\t\t\t\t}\n\n\t\t\t\ttemplate <typename T1, typename T2>\n\t\t\t\tstatic EA_CONSTEXPR const T2&& get(const pair<T1, T2>&& p)\n\t\t\t\t{\n\t\t\t\t\treturn eastl::forward<const T2>(p.second);\n\t\t\t\t}\n\t\t\t};\n\t\t} // namespace internal\n\n\t\ttemplate <size_t I, typename T1, typename T2>\n\t\tEA_CPP14_CONSTEXPR tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p)\n\t\t{\n\t\t\treturn internal::GetPair<I>::get(p);\n\t\t}\n\n\t\ttemplate <size_t I, typename T1, typename T2>\n\t\tEA_CPP14_CONSTEXPR const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p)\n\t\t{\n\t\t\treturn internal::GetPair<I>::get(p);\n\t\t}\n\n\t\ttemplate <size_t I, typename T1, typename T2>\n\t\tEA_CPP14_CONSTEXPR tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p)\n\t\t{\n\t\t\treturn internal::GetPair<I>::get(eastl::move(p));\n\t\t}\n\n\t\ttemplate <size_t I, typename T1, typename T2>\n\t\tEA_CPP14_CONSTEXPR const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&& p)\n\t\t{\n\t\t\treturn internal::GetPair<I>::get(eastl::move(p));\n\t\t}\n\n\t\ttemplate <typename T1, typename T2>\n\t\tEA_CONSTEXPR T1& get(pair<T1, T2>& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<0>::get(p);\n\t\t}\n\n\t\ttemplate <typename T2, typename T1>\n\t\tEA_CONSTEXPR T2& get(pair<T1, T2>& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<1>::get(p);\n\t\t}\n\n\t\ttemplate <typename T1, typename T2>\n\t\tEA_CONSTEXPR const T1& get(const pair<T1, T2>& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<0>::get(p);\n\t\t}\n\n\t\ttemplate <typename T2, typename T1>\n\t\tEA_CONSTEXPR const T2& get(const pair<T1, T2>& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<1>::get(p);\n\t\t}\n\n\t\ttemplate <typename T1, typename T2>\n\t\tEA_CONSTEXPR T1&& get(pair<T1, T2>&& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<0>::get(eastl::move(p));\n\t\t}\n\n\t\ttemplate <typename T2, typename T1>\n\t\tEA_CONSTEXPR T2&& get(pair<T1, T2>&& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<1>::get(eastl::move(p));\n\t\t}\n\n\t\ttemplate <typename T1, typename T2>\n\t\tEA_CONSTEXPR const T1&& get(const pair<T1, T2>&& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<0>::get(eastl::move(p));\n\t\t}\n\n\t\ttemplate <typename T2, typename T1>\n\t\tEA_CONSTEXPR const T2&& get(const pair<T1, T2>&& p) EA_NOEXCEPT\n\t\t{\n\t\t\treturn internal::GetPair<1>::get(eastl::move(p));\n\t\t}\n\n#endif  // EASTL_TUPLE_ENABLED\n\n\n}  // namespace eastl\n\n///////////////////////////////////////////////////////////////\n// C++17 structured bindings support for eastl::pair\n//\n#ifndef EA_COMPILER_NO_STRUCTURED_BINDING\n// we can't forward declare tuple_size and tuple_element because some std implementations\n// don't declare it in the std namespace, but instead alias it.\n#include <utility>\n\n\tnamespace std\n\t{\n\t\ttemplate <class... Ts>\n\t\tstruct tuple_size<::eastl::pair<Ts...>> : public ::eastl::integral_constant<size_t, sizeof...(Ts)>\n\t\t{\n\t\t};\n\n\t\ttemplate <size_t I, class... Ts>\n\t\tstruct tuple_element<I, ::eastl::pair<Ts...>> : public ::eastl::tuple_element<I, ::eastl::pair<Ts...>>\n\t\t{\n\t\t};\n\t}\n#endif\n\n\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/variant.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////\n// Implements the class template variant represents a type-safe union. An\n// instance of variant at any given time either holds a value of one of its\n// alternative types, or it holds no value.\n//\n// As with unions, if a variant holds a value of some object type T, the object\n// representation of T is allocated directly within the object representation of\n// the variant itself.\n//\n// Variant is not allowed to allocate additional (dynamic) memory.\n//\n// A variant is not permitted to hold references, arrays, or the type void.\n// Empty variants are also ill-formed (variant<monostate> can be used instead).\n//\n// A variant is permitted to hold the same type more than once, and to hold\n// differently cv-qualified versions of the same type.  As with unions, the\n// default-initialized variant holds a value of its first alternative, unless\n// that alternative is not default-constructible (in which case default\n// constructor won't compile: the helper class monostate can be used to make\n// such variants default-constructible)\n//\n// Given defect 2901, the eastl::variant implementation does not provide the\n// specified allocator-aware functions.  This will be re-evaluated when the LWG\n// addresses this issue in future standardization updates.\n// LWG Defect 2901: https://cplusplus.github.io/LWG/issue2901\n//\n// Allocator-extended constructors\n// template <class Alloc> variant(allocator_arg_t, const Alloc&);\n// template <class Alloc> variant(allocator_arg_t, const Alloc&, const variant&);\n// template <class Alloc> variant(allocator_arg_t, const Alloc&, variant&&);\n// template <class Alloc, class T> variant(allocator_arg_t, const Alloc&, T&&);\n// template <class Alloc, class T, class... Args> variant(allocator_arg_t, const Alloc&, in_place_type_t<T>, Args&&...);\n// template <class Alloc, class T, class U, class... Args> variant(allocator_arg_t, const Alloc&, in_place_type_t<T>, initializer_list<U>, Args&&...);\n// template <class Alloc, size_t I, class... Args> variant(allocator_arg_t, const Alloc&, in_place_index_t<I>, Args&&...);\n// template <class Alloc, size_t I, class U, class... Args> variant(allocator_arg_t, const Alloc&, in_place_index_t<I>, initializer_list<U>, Args&&...);\n//\n// 20.7.12, allocator-related traits\n// template <class T, class Alloc>        struct uses_allocator;\n// template <class... Types, class Alloc> struct uses_allocator<variant<Types...>, Alloc>;\n//\n// eastl::variant doesn't support:\n//  * recursive variant support\n//  * strong exception guarantees as specified (we punted on the assignment problem).\n//    if an exception is thrown during assignment its undefined behaviour in our implementation.\n//\n// Reference:\n// \t* http://en.cppreference.com/w/cpp/utility/variant\n// \t* https://thenewcpp.wordpress.com/2012/02/15/variadic-templates-part-3-or-how-i-wrote-a-variant-class/\n///////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_VARIANT_H\n#define EASTL_VARIANT_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/in_place_t.h>\n#include <EASTL/internal/integer_sequence.h>\n#include <EASTL/internal/special_member_functions_variant_optional.h>\n#include <EASTL/meta.h>\n#include <EASTL/utility.h>\n#include <EASTL/functional.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/tuple.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/array.h>\n\n#if EASTL_EXCEPTIONS_ENABLED\n\t#include <stdexcept>\n\t#include <exception>\n#endif\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n#ifndef EA_COMPILER_CPP14_ENABLED\n\tstatic_assert(false, \"eastl::variant requires a C++14 compatible compiler (at least) \");\n#endif\n\nEA_DISABLE_VC_WARNING(4625) // copy constructor was implicitly defined as deleted\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.3, variant_npos\n\t//\n\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR size_t variant_npos = size_t(-1);\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.10, class bad_variant_access\n\t//\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\tstruct bad_variant_access : public std::logic_error\n\t\t{\n\t\t\tbad_variant_access() : std::logic_error(\"eastl::bad_variant_access exception\") {}\n\t\t\tvirtual ~bad_variant_access() EA_NOEXCEPT {}\n\t\t};\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.7, class monostate\n\t//\n\t// Unit type intended for use as a well-behaved empty alternative in\n\t// variant. A variant of non-default-constructible types may list monostate\n\t// as its first alternative: this makes the variant itself default-contructible.\n\t//\n\tstruct monostate {};\n\n\t// 20.7.8, monostate relational operators\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\tEA_CONSTEXPR std::strong_ordering operator<=>(monostate, monostate) EA_NOEXCEPT { return std::strong_ordering::equal; }\n#else\n\tEA_CONSTEXPR bool operator> (monostate, monostate) EA_NOEXCEPT { return false; }\n\tEA_CONSTEXPR bool operator< (monostate, monostate) EA_NOEXCEPT { return false; }\n\tEA_CONSTEXPR bool operator!=(monostate, monostate) EA_NOEXCEPT { return false; }\n\tEA_CONSTEXPR bool operator<=(monostate, monostate) EA_NOEXCEPT { return true; }\n\tEA_CONSTEXPR bool operator>=(monostate, monostate) EA_NOEXCEPT { return true; }\n#endif\n\tEA_CONSTEXPR bool operator==(monostate, monostate) EA_NOEXCEPT { return true; }\n\n\t// 20.7.11, hash support\n\ttemplate <class T> struct hash;\n\ttemplate <> struct hash<monostate>\n\t\t{ size_t operator()(monostate) const { return static_cast<size_t>(-0x42); } };\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.2, forward-declaration for types that depend on the variant\n\t//\n\ttemplate <class... Types>\n\tclass variant;\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.3, variant_size, variant_size_v helper classes\n\t//\n\ttemplate <class T>        struct variant_size;\n\ttemplate <class T>        struct variant_size<const T>           : integral_constant<size_t, variant_size<T>::value>  {};\n\ttemplate <class T>        struct variant_size<volatile T>        : integral_constant<size_t, variant_size<T>::value>  {};\n\ttemplate <class T>        struct variant_size<const volatile T>  : integral_constant<size_t, variant_size<T>::value>  {};\n\ttemplate <class... Types> struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> {};\n\n\t// variant_size_v template alias\n\ttemplate <typename T>\n\tEASTL_CPP17_INLINE_VARIABLE EA_CONSTEXPR size_t variant_size_v = variant_size<T>::value;\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// variant_alternative_helper\n\t//\n\t// This helper does the heavy lifting of traversing the variadic type list\n\t// and retrieving the type at the user provided index.\n\t//\n\ttemplate <size_t I, typename... Ts>\n\tstruct variant_alternative_helper;\n\n\ttemplate <size_t I, typename Head, typename... Tail>\n\tstruct variant_alternative_helper<I, Head, Tail...>\n\t\t{ typedef typename variant_alternative_helper<I - 1, Tail...>::type type; };\n\n\ttemplate <typename Head, typename... Tail>\n\tstruct variant_alternative_helper<0, Head, Tail...>\n\t\t{ typedef Head type; };\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.4, variant_alternative\n\t//\n\ttemplate <size_t I, class T> struct variant_alternative;\n\ttemplate <size_t I, class... Types> struct variant_alternative<I, variant<Types...>> : variant_alternative_helper<I, Types...> {};\n\n\t// ISO required cv-qualifer specializations\n\ttemplate <size_t I, class T> struct variant_alternative<I, const T>          : add_const<typename variant_alternative<I, T>::type> {};\n\ttemplate <size_t I, class T> struct variant_alternative<I, volatile T>       : add_volatile<typename variant_alternative<I, T>::type> {};\n\ttemplate <size_t I, class T> struct variant_alternative<I, const volatile T> : add_cv<typename variant_alternative<I, T>::type> {};\n\n\t// variant_alternative_t template alias\n\ttemplate <size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type;\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.11, hash support\n\t//\n\tnamespace internal {\n\ttemplate<class Variant, bool enabled>\n\tstruct variant_hash {};\n\n\ttemplate<class Variant>\n\tstruct variant_hash<Variant, true>\n\t{\n\t\tsize_t operator()(const Variant& obj) const\n\t\t{\n\t\t\tif (obj.valueless_by_exception())\n\t\t\t\treturn 0;\n\n\t\t\tauto genericVisitor = [](const auto& thisAlternative)\n\t\t\t{\n\t\t\t\tusing alternative_t = remove_const_t<remove_reference_t<decltype(thisAlternative)>>;\n\t\t\t\treturn hash<alternative_t>{}(thisAlternative);\n\t\t\t};\n\n\t\t\tconst size_t alternativeHash = visit(genericVisitor, obj);\n\n\t\t\treturn (alternativeHash * 16777619) ^ obj.index();\n\t\t}\n\t};\n\n\ttemplate<class, class, class = void>\n\tstruct is_hasher_for : public false_type {};\n\n\ttemplate<class Hash, class Key>\n\tstruct is_hasher_for <Hash, Key, void_t<\n\t\tdecltype(Hash()) // default constructible\n\t\t, decltype(Hash(declval<Hash>())) // copy constructible\n\t\t, decltype(declval<Hash>() = declval<const Hash&>()) // copy assignable\n\t\t, decltype(swap(declval<Hash>(), declval<Hash>())) // swappable\n\t\t, decltype(size_t(declval<const Hash>()(declval<const Key&>()))) // function object\n\t\t>> : public true_type {};\n\n\ttemplate <class Hash, class Key>\n\tconstexpr bool is_hasher_for_v = is_hasher_for<Hash, Key>::value;\n\t} // namespace internal\n\n\ttemplate <class... Types>\n\tstruct hash<variant<Types...>>\n\t\t: public internal::variant_hash<variant<Types...>, conjunction_v<internal::is_hasher_for<hash<remove_const_t<Types>>, Types>...>> {};\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// get_if\n\t//\n\ttemplate <size_t I, class... Types, enable_if_t<I < sizeof...(Types), bool> = true>\n\tEA_CONSTEXPR add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>* pv) EA_NOEXCEPT\n\t{\n\t\tusing return_type = add_pointer_t<variant_alternative_t<I, variant<Types...>>>;\n\n\t\treturn (!pv || pv->index() != I) ? nullptr : pv->template get_as<return_type>();\n\t}\n\n\ttemplate <size_t I, class... Types, enable_if_t<I < sizeof...(Types), bool> = true>\n\tEA_CONSTEXPR add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>* pv) EA_NOEXCEPT\n\t{\n\t\tusing return_type = add_pointer_t<variant_alternative_t<I, variant<Types...>>>;\n\n\t\treturn (!pv || pv->index() != I) ? nullptr : pv->template get_as<return_type>();\n\t}\n\n\ttemplate <class T, class... Types, size_t I = meta::get_type_index_v<T, Types...>, enable_if_t<I < sizeof...(Types) && meta::duplicate_type_check_v<T, Types...>, bool> = true>\n\tEA_CONSTEXPR add_pointer_t<T> get_if(variant<Types...>* pv) EA_NOEXCEPT\n\t{\n\t\treturn get_if<I>(pv);\n\t}\n\n\ttemplate <class T, class... Types, size_t I = meta::get_type_index_v<T, Types...>, enable_if_t<I < sizeof...(Types) && meta::duplicate_type_check_v<T, Types...>, bool> = true>\n\tEA_CONSTEXPR add_pointer_t<const T> get_if(const variant<Types...>* pv) EA_NOEXCEPT\n\t{\n\t\treturn get_if<I>(pv);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// get\n\t//\n\ttemplate <size_t I, class... Types, enable_if_t<I < sizeof...(Types), bool> = true>\n\tEA_CONSTEXPR variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v)\n\t{\n\t\tusing return_type = add_pointer_t<variant_alternative_t<I, variant<Types...>>>;\n\n\t\tif (v.index() != I)\n\t\t\tEASTL_THROW_OR_ASSERT(bad_variant_access, \"get -- bad_variant_access\");\n\n\t\treturn *v.template get_as<return_type>();\n\t}\n\n\ttemplate <size_t I, class... Types, enable_if_t<I < sizeof...(Types), bool> = true>\n\tEA_CONSTEXPR variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v)\n\t{\n\t\tusing return_type = add_pointer_t<variant_alternative_t<I, variant<Types...>>>;\n\n\t\tif (v.index() != I)\n\t\t\tEASTL_THROW_OR_ASSERT(bad_variant_access, \"get -- bad_variant_access\");\n\n\t\treturn eastl::move(*v.template get_as<return_type>());\n\t}\n\n\ttemplate <size_t I, class... Types, enable_if_t<I < sizeof...(Types), bool> = true>\n\tEA_CONSTEXPR const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v)\n\t{\n\t\tusing return_type = add_pointer_t<variant_alternative_t<I, variant<Types...>>>;\n\n\t\tif (v.index() != I)\n\t\t\tEASTL_THROW_OR_ASSERT(bad_variant_access, \"get -- bad_variant_access\");\n\n\t\treturn *v.template get_as<return_type>();\n\t}\n\n\ttemplate <size_t I, class... Types, enable_if_t<I < sizeof...(Types), bool> = true>\n\tEA_CONSTEXPR const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v)\n\t{\n\t\tusing return_type = add_pointer_t<variant_alternative_t<I, variant<Types...>>>;\n\n\t\tif (v.index() != I)\n\t\t\tEASTL_THROW_OR_ASSERT(bad_variant_access, \"get -- bad_variant_access\");\n\n\t\treturn eastl::move(*v.template get_as<return_type>());\n\t}\n\n\ttemplate <class T, class... Types, size_t I = meta::get_type_index_v<T, Types...>, enable_if_t<I < sizeof...(Types) && meta::duplicate_type_check_v<T, Types...>, bool> = true>\n\tEA_CONSTEXPR T& get(variant<Types...>& v)\n\t{\n\t\treturn get<I>(v);\n\t}\n\n\ttemplate <class T, class... Types, size_t I = meta::get_type_index_v<T, Types...>, enable_if_t<I < sizeof...(Types) && meta::duplicate_type_check_v<T, Types...>, bool> = true>\n\tEA_CONSTEXPR T&& get(variant<Types...>&& v)\n\t{\n\t\treturn get<I>(eastl::move(v));\n\t}\n\n\ttemplate <class T, class... Types, size_t I = meta::get_type_index_v<T, Types...>, enable_if_t<I < sizeof...(Types) && meta::duplicate_type_check_v<T, Types...>, bool> = true>\n\tEA_CONSTEXPR const T& get(const variant<Types...>& v)\n\t{\n\t\treturn get<I>(v);\n\t}\n\n\ttemplate <class T, class... Types, size_t I = meta::get_type_index_v<T, Types...>, enable_if_t<I < sizeof...(Types) && meta::duplicate_type_check_v<T, Types...>, bool> = true>\n\tEA_CONSTEXPR const T&& get(const variant<Types...>&& v)\n\t{\n\t\treturn get<I>(eastl::move(v));\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.4, value access\n\t//\n\ttemplate <class T, class... Types, size_t I = meta::get_type_index_v<T, Types...>, enable_if_t<I < sizeof...(Types) && meta::duplicate_type_check_v<T, Types...>, bool> = true>\n\tEA_CONSTEXPR bool holds_alternative(const variant<Types...>& v) EA_NOEXCEPT\n\t{\n\t\treturn I == variant_npos ? false : (v.index() == I);\n\t}\n\n\n\tnamespace internal {\n\ttemplate<typename T, bool = eastl::is_nothrow_copy_constructible_v<T> || !eastl::is_nothrow_move_constructible_v<T>>\n\tstruct emplace_or_move_assign\n\t{\n\t\ttemplate<size_t I, typename... Types>\n\t\tstatic void call(variant<Types...>& obj, const T& rhs)\n\t\t{\n\t\t\tobj.template emplace<I>(rhs);\n\t\t}\n\t};\n\n\ttemplate<typename T>\n\tstruct emplace_or_move_assign<T, false>\n\t{\n\t\ttemplate<size_t I, typename... Types>\n\t\tstatic void call(variant<Types...>& obj, const T& rhs)\n\t\t{\n\t\t\tobj = variant<Types...>(rhs);\n\t\t}\n\t};\n\n\ttemplate<typename T_j, typename T, bool = eastl::is_nothrow_constructible_v<T_j, T> || !eastl::is_nothrow_move_constructible_v<T_j>>\n\tstruct converting_emplace\n\t{\n\t\ttemplate<size_t I, typename... Types>\n\t\tstatic void call(variant<Types...>& obj, T&& rhs)\n\t\t{\n\t\t\tobj.template emplace<I>(eastl::forward<T>(rhs));\n\t\t}\n\t};\n\n\ttemplate<typename T_j, typename T>\n\tstruct converting_emplace<T_j, T, false>\n\t{\n\t\ttemplate<size_t I, typename... Types>\n\t\tstatic void call(variant<Types...>& obj, T&& rhs)\n\t\t{\n\t\t\tobj.template emplace<I>(T_j(eastl::forward<T>(rhs)));\n\t\t}\n\t};\n\n\ttemplate <typename Visitor, typename Variant>\n\tEA_CPP14_CONSTEXPR decltype(auto) visit_with_index(Visitor&& visitor, Variant&& variant);\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// variant_storage\n\t//\n\t// This is a utility class to simplify the implementation of a storage type\n\t// for a distriminted union.  This utility handles the alignment, size\n\t// requirements, and data access required by the variant type.\n\t//\n\ttemplate<bool IsTriviallyDestructible, class... Types>\n\tstruct variant_storage;\n\n\t// reinterpret_cast used between related classes: 'variant_storage' and 'variant'\n\t// MSVC incorrectly raises this warning - the warning can be surpressed by using a static_cast, but Clang correctly catches this as an error;\n\t// variant_storage is a *private* base class.\n\tEA_DISABLE_VC_WARNING(4946)\n\n\t// variant_storage\n\t//\n\t// specialization for non-trivially destructible types\n\t//\n\ttemplate<class... Types>\n\tstruct variant_storage<false, Types...>\n\t{\n\t\tusing aligned_storage_impl_t = aligned_union_t<1, Types...>;\n\n\t\tsize_t mIndex;\n\t\taligned_storage_impl_t mBuffer;\n\n\t\t~variant_storage()\n\t\t{\n\t\t\tif (!this->valueless_by_exception())\n\t\t\t\tdestroy();\n\t\t}\n\n\t\t// precondition:\n\t\t//\t!this->valueless_by_exception()\n\t\tvoid destroy()\n\t\t{\n\t\t\tauto genericVisitor = [](auto& thisAlternative)\n\t\t\t{\n\t\t\t\tusing alternative_t = remove_reference_t<decltype(thisAlternative)>;\n\t\t\t\tthisAlternative.~alternative_t();\n\t\t\t};\n\n\t\t\tvisit(genericVisitor, reinterpret_cast<variant<Types...>&>(*this));\n\t\t}\n\n\t\tEA_CONSTEXPR size_t index() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn this->mIndex;\n\t\t}\n\n\t\tEA_CONSTEXPR bool valueless_by_exception() const EA_NOEXCEPT\n\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\treturn this->mIndex == variant_npos;\n#else\n\t\t\treturn false;\n#endif\n\t\t}\n\t};\n\n\n\t// variant_storage\n\t//\n\t// specialization for trivially destructible types\n\t//\n\ttemplate<class... Types>\n\tstruct variant_storage<true, Types...>\n\t{\n\t\tusing aligned_storage_impl_t = aligned_union_t<1, Types...>;\n\n\t\tsize_t mIndex;\n\t\taligned_storage_impl_t mBuffer;\n\n\t\tvoid destroy()\n\t\t{\n\t\t\t// trivially destructible, no op.\n\t\t}\n\n\t\tEA_CONSTEXPR size_t index() const EA_NOEXCEPT\n\t\t{\n\t\t\treturn this->mIndex;\n\t\t}\n\n\t\tEA_CONSTEXPR bool valueless_by_exception() const EA_NOEXCEPT\n\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\treturn this->mIndex == variant_npos;\n#else\n\t\t\treturn false;\n#endif\n\t\t}\n\t};\n\n\ttemplate<class... Types>\n\tstruct variant_base : protected variant_storage<conjunction_v<is_trivially_destructible<Types>...>, Types...>\n\t{\n\t\tusing variant_storage_t = variant_storage<conjunction_v<is_trivially_destructible<Types>...>, Types...>;\n\t\tusing aligned_storage_impl_t = typename variant_storage_t::aligned_storage_impl_t;\n\n\t\tEA_DISABLE_VC_WARNING(4702) // unreachable code: suppress warning because construct_as<I>() may always throw\n\t\t\t                        // (because alternative_type(args...) throws).\n\t\ttemplate <size_t I, typename... Args>\n\t\tvoid construct_as(Args&&... args)\n\t\t{\n\t\t\tusing alternative_type = variant_alternative_t<I, variant<Types...>>;\n\n\t\t\t// NOTE(rparolin): If this assert fires there is an EASTL problem picking the size of the local buffer which\n\t\t\t// variant_storage used to store types. The size selected should be large enough to hold the largest type in\n\t\t\t// the user provided variant type-list.\n\t\t\tstatic_assert(sizeof(aligned_storage_impl_t) >= sizeof(alternative_type), \"alternative_type is larger than local buffer size\");\n\n\t\t\tnew (&this->mBuffer) alternative_type(eastl::forward<Args>(args)...);\n\t\t\tthis->mIndex = I;\n\t\t}\n\n\t\ttemplate <size_t I, typename U, typename... Args>\n\t\tvoid construct_as(std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\tusing alternative_type = variant_alternative_t<I, variant<Types...>>;\n\n\t\t\t// NOTE(rparolin): If this assert fires there is an EASTL problem picking the size of the local buffer which\n\t\t\t// variant_storage used to store types. The size selected should be large enough to hold the largest type in\n\t\t\t// the user provided variant type-list.\n\t\t\tstatic_assert(sizeof(aligned_storage_impl_t) >= sizeof(alternative_type), \"alternative_type is larger than local buffer size\");\n\n\t\t\tnew (&this->mBuffer) alternative_type(il, eastl::forward<Args>(args)...);\n\t\t\tthis->mIndex = I;\n\t\t}\n\t\tEA_RESTORE_VC_WARNING()\n\n\t\ttemplate<typename T>\n\t\tT get_as()\n\t\t{\n\t\t\tstatic_assert(eastl::is_pointer_v<T>, \"T must be a pointer type\");\n\t\t\treturn reinterpret_cast<T>(&this->mBuffer);\n\t\t}\n\n\t\ttemplate<typename T>\n\t\tconst T get_as() const\n\t\t{\n\t\t\tstatic_assert(eastl::is_pointer_v<T>, \"T must be a pointer type\");\n\t\t\treturn reinterpret_cast<const T>(reinterpret_cast<uintptr_t>(&this->mBuffer));\n\t\t}\n\n#if !EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tvariant_base() = default;\n#endif\n\n\t\t// copy constructor\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tvoid ConstructFrom(const variant_base& rhs)\n#else\n\t\tvariant_base(const variant_base& rhs)\n#endif\n\t\t{\n\t\t\tthis->mIndex = rhs.mIndex;\n\n\t\t\tauto genericVisitor = [&rhs](auto& thisAlternative)\n\t\t\t{\n\t\t\t\tusing alternative_t = remove_reference_t<decltype(thisAlternative)>;\n\t\t\t\tnew (&thisAlternative) alternative_t(*rhs.template get_as<const alternative_t*>());\n\t\t\t};\n\n\t\t\tif(!rhs.valueless_by_exception())\n\t\t\t\tvisit(genericVisitor, reinterpret_cast<variant<Types...>&>(*this));\n\t\t}\n\n\t\t// move constructor\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tEA_CONSTEXPR void ConstructFrom(variant_base&& rhs) EA_NOEXCEPT(conjunction_v<is_nothrow_move_constructible<Types>...>)\n#else\n\t\tvariant_base(variant_base&& rhs)\n#endif\n\t\t{\n\t\t\tthis->mIndex = rhs.mIndex;\n\n\t\t\tauto genericVisitor = [&rhs](auto& thisAlternative)\n\t\t\t{\n\t\t\t\tusing alternative_t = remove_reference_t<decltype(thisAlternative)>;\n\t\t\t\tnew (&thisAlternative) alternative_t(eastl::move(*rhs.template get_as<alternative_t*>()));\n\t\t\t};\n\n\t\t\tif (!rhs.valueless_by_exception())\n\t\t\t\tvisit(genericVisitor, reinterpret_cast<variant<Types...>&>(*this));\n\t\t}\n\n\t\t// copy assignment\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tvoid AssignFrom(const variant_base& rhs)\n\t\t\tEA_NOEXCEPT(conjunction_v<conjunction<is_nothrow_copy_constructible<Types>...>,\n\t\t\t\tconjunction<is_nothrow_copy_assignable<Types>...>>)\n#else\n\t\tvariant_base& operator=(const variant_base& rhs)\n#endif\n\t\t{\n\t\t\tif (this->valueless_by_exception() && rhs.valueless_by_exception())\n\t\t\t{\n\t\t\t\t// no op\n\t\t\t}\n\t\t\telse if (!this->valueless_by_exception() && rhs.valueless_by_exception())\n\t\t\t{\n\t\t\t\tthis->destroy();\n\t\t\t\tthis->mIndex = variant_npos;\n\t\t\t}\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\telse if (!this->valueless_by_exception() && this->mIndex == rhs.mIndex)\n\t\t\t{\n\t\t\t\tauto genericVisitor = [&rhs](auto& thisAlternative)\n\t\t\t\t{\n\t\t\t\t\tusing alternative_t = remove_reference_t<decltype(thisAlternative)>;\n\t\t\t\t\tthisAlternative = *rhs.template get_as<alternative_t*>();\n\t\t\t\t};\n\n\t\t\t\tvisit(genericVisitor, reinterpret_cast<variant<Types...>&>(*this));\n\t\t\t}\n#endif\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto genericVisitor = [this](auto idxConstant, const auto& rhsAlternative)\n\t\t\t\t{\n\t\t\t\t\tconstexpr size_t I = idxConstant();\n\t\t\t\t\tusing alternative_t = remove_cvref_t<decltype(rhsAlternative)>;\n\t\t\t\t\templace_or_move_assign<alternative_t>::template call<I>(reinterpret_cast<variant<Types...>&>(*this), rhsAlternative);\n\t\t\t\t};\n\n\t\t\t\tvisit_with_index(genericVisitor, reinterpret_cast<const variant<Types...>&>(rhs));\n\t\t\t}\n\n#if !EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\treturn *this;\n#endif\n\t\t}\n\n\t\t// move assignment\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tvoid AssignFrom(variant_base&& rhs)\n\t\t\tEA_NOEXCEPT(conjunction_v<conjunction<is_nothrow_move_constructible<Types>...>,\n\t\t\t\tconjunction<is_nothrow_move_assignable<Types>...>>)\n#else\n\t\tvariant_base& operator=(variant_base&& rhs)\n#endif\n\t\t{\n\t\t\tif (this->valueless_by_exception() && rhs.valueless_by_exception())\n\t\t\t{\n\t\t\t\t// no op\n\t\t\t}\n\t\t\telse if (!this->valueless_by_exception() && rhs.valueless_by_exception())\n\t\t\t{\n\t\t\t\tthis->destroy();\n\t\t\t\tthis->mIndex = variant_npos;\n\t\t\t}\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\telse if (!this->valueless_by_exception() && this->mIndex == rhs.mIndex)\n\t\t\t{\n\t\t\t\tauto genericVisitor = [&rhs](auto& thisAlternative)\n\t\t\t\t{\n\t\t\t\t\tusing alternative_t = remove_reference_t<decltype(thisAlternative)>;\n\t\t\t\t\tthisAlternative = eastl::move(*rhs.template get_as<alternative_t*>());\n\t\t\t\t};\n\n\t\t\t\tvisit(genericVisitor, reinterpret_cast<variant<Types...>&>(*this));\n\t\t\t}\n#endif\n\t\t\telse\n\t\t\t{\n\t\t\t\tauto genericVisitor = [this](auto idxConstant, auto& rhsAlternative)\n\t\t\t\t{\n\t\t\t\t\tconstexpr size_t I = idxConstant();\n\t\t\t\t\treinterpret_cast<variant<Types...>&>(*this).template emplace<I>(eastl::move(rhsAlternative));\n\t\t\t\t};\n\n\t\t\t\tvisit_with_index(genericVisitor, reinterpret_cast<variant<Types...>&>(rhs));\n\t\t\t}\n\n#if !EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\treturn *this;\n#endif\n\t\t}\n\t};\n\n\tEA_RESTORE_VC_WARNING() // 4946\n\n\ttemplate<typename>\n\tconstexpr bool is_in_place_type_specialization_v = false;\n\n\ttemplate<typename T>\n\tconstexpr bool is_in_place_type_specialization_v<in_place_type_t<T>> = true;\n\n\ttemplate<typename>\n\tconstexpr bool is_in_place_index_specialization_v = false;\n\n\ttemplate<size_t Idx>\n\tconstexpr bool is_in_place_index_specialization_v<in_place_index_t<Idx>> = true;\n\n\t// this could be a generic lambda, except that MSVC and Clang disagree with whether constants need to be in the capture list and MSVC (circa 2024) doesn't\n\t// recognize constants passed in the capture list as constant in the lambda body.\n\ttemplate<typename LhsAlternative, size_t LhsAlternativeIndex, typename... Types>\n\tstruct swap_visitor\n\t{\n\t\tvariant<Types...>& lhs;\n\t\tvariant<Types...>& rhs;\n\t\tLhsAlternative& lhsAlternative;\n\n\t\ttemplate<typename IntConstant, typename RhsAlternative>\n\t\tvoid operator()(IntConstant rhsIdxConstant, RhsAlternative& rhsAlternative)\n\t\t{\n\t\t\tconstexpr size_t RhsAlternativeIndex = rhsIdxConstant();\n\n\t\t\tLhsAlternative temp(eastl::move(lhsAlternative));\n\t\t\tlhs.template emplace<RhsAlternativeIndex>(eastl::move(rhsAlternative));\n\t\t\trhs.template emplace<LhsAlternativeIndex>(eastl::move(temp));\n\t\t};\n\t};\n\t} // namespace internal\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.2, variant\n\t//\n\ttemplate <class... Types>\n\tclass variant\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t: private internal::EnableVariantOptionalSpecialMemberFunctions<internal::variant_base<Types...>, Types...>\n\t{\n\t\tusing base_type = internal::EnableVariantOptionalSpecialMemberFunctions<internal::variant_base<Types...>, Types...>;\n#else\n\t\t: private internal::variant_base<Types...>\n\t{\n\t\tusing base_type = internal::variant_base<Types...>;\n#endif\n\n\t\tusing T_0 = variant_alternative_t<0, variant>;  // alias for the 1st type in the variadic pack\n\n\t\tstatic_assert(sizeof...(Types) > 0,                           \"variant must have at least 1 type (empty variants are ill-formed)\");\n\t\tstatic_assert(disjunction_v<is_reference<Types>...> == false, \"variant alternative types must be destructible (non-reference)\");\n\t\tstatic_assert(disjunction_v<is_array<Types>...> == false,     \"variant alternative types must be destructible (non-array)\");\n\t\tstatic_assert(conjunction_v<is_destructible<Types>...>,\t\t  \"variant alternative types must be destructible\");\n\n\t\tusing variant_storage_t = typename base_type::variant_storage_t;\n\n\tpublic:\n\n\t\t///////////////////////////////////////////////////////////////////////////\n\t\t// 20.7.2.1, constructors\n\t\t//\n\n\t\t// Only participates in overload resolution when the first alternative is default constructible\n\t\ttemplate <typename TT0 = T_0, enable_if_t<is_default_constructible_v<TT0>, bool> = true>\n\t\tEA_CONSTEXPR variant() EA_NOEXCEPT(eastl::is_nothrow_default_constructible_v<TT0>)\n\t\t{\n\t\t\tthis->template construct_as<0>();\n\t\t}\n\n\t\t// implemented by EnableVariantOptionalSpecialMemberFunctions<...>\n\t\tvariant(const variant&) = default;\n\t\tvariant(variant&&) = default;\n\n\t\t// Conversion constructor\n\t\ttemplate <typename T,\n\t\t\ttypename T_j = meta::overload_resolution_t<T, meta::overload_set<Types...>>,\n\t\t\tsize_t I = meta::get_type_index_v<remove_cvref_t<T_j>, Types...>,\n\t\t\tenable_if_t<(sizeof...(Types) > 0) &&\n\t\t\t\tI < sizeof...(Types) &&\n\t\t\t\t!is_same_v<remove_cvref_t<T>, variant> &&\n\t\t\t\t!internal::is_in_place_type_specialization_v<remove_cvref_t<T>> &&\n\t\t\t\t!internal::is_in_place_index_specialization_v<remove_cvref_t<T>> &&\n\t\t\t\teastl::is_constructible_v<T_j, T>, bool> = true>\n\t\t\tEA_CONSTEXPR variant(T&& t) EA_NOEXCEPT(is_nothrow_constructible_v<T_j, T>)\n\t\t{\n\t\t\tthis->template construct_as<I>(eastl::forward<T>(t));\n\t\t}\n\n\t\t///////////////////////////////////////////////////////////////////////////\n\t\t// 20.7.2.1, in_place_t constructors\n\t\t//\n\t\ttemplate <\n\t\t\tclass T,\n\t\t\tclass... Args,\n\t\t\tenable_if_t<conjunction_v<meta::duplicate_type_check<T, Types...>, is_constructible<T, Args...>>, bool> = true>\n\t\t\tEA_CPP14_CONSTEXPR explicit variant(in_place_type_t<T>, Args&&... args)\n\t\t\t: variant(in_place_index<meta::get_type_index_v<T, Types...>>, eastl::forward<Args>(args)...)\n\t\t{}\n\n\t\ttemplate <\n\t\t\tclass T,\n\t\t\tclass U,\n\t\t\tclass... Args,\n\t\t\tenable_if_t<conjunction_v<meta::duplicate_type_check<T, Types...>, is_constructible<T, Args...>>, bool> = true>\n\t\t\tEA_CPP14_CONSTEXPR explicit variant(in_place_type_t<T>, std::initializer_list<U> il, Args&&... args)\n\t\t\t: variant(in_place_index<meta::get_type_index_v<T, Types...>>, il, eastl::forward<Args>(args)...)\n\t\t{}\n\n\t\ttemplate <size_t I,\n\t\t\tclass... Args,\n\t\t\tenable_if_t<conjunction_v<integral_constant<bool, (I < sizeof...(Types))>,\n\t\t\tis_constructible<meta::get_type_at_t<I, Types...>, Args...>>, bool> = true>\n\t\t\tEA_CPP14_CONSTEXPR explicit variant(in_place_index_t<I>, Args&&... args)\n\t\t{\n\t\t\tthis->template construct_as<I>(eastl::forward<Args>(args)...);\n\t\t}\n\n\t\ttemplate <size_t I,\n\t\t\tclass U,\n\t\t\tclass... Args,\n\t\t\tenable_if_t<conjunction_v<integral_constant<bool, (I < sizeof...(Types))>,\n\t\t\tis_constructible<meta::get_type_at_t<I, Types...>, Args...>>, bool> = true>\n\t\t\tEA_CPP14_CONSTEXPR explicit variant(in_place_index_t<I>, std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\tthis->template construct_as<I>(il, eastl::forward<Args>(args)...);\n\t\t}\n\n\t\t///////////////////////////////////////////////////////////////////////////\n\t\t// 20.7.2.2, destructor\n\t\t//\n\t\t// implemented by EnableVariantOptionalSpecialMemberFunctions<...>\n\t\t~variant() = default;\n\n\n\t\t///////////////////////////////////////////////////////////////////////////\n\t\t// 20.7.2.4, modifiers\n\t\t//\n\n\t\t// Equivalent to emplace<I>(std::forward<Args>(args)...), where I is the zero-based index of T in Types....\n\t\t// This overload only participates in overload resolution if std::is_constructible_v<T, Args...> is true, and T\n\t\t// occurs exactly once in Types...\n\t\ttemplate <\n\t\t    class T,\n\t\t    class... Args,\n\t\t    size_t I = meta::get_type_index_v<T, Types...>,\n\t\t    enable_if_t<conjunction_v<is_constructible<T, Args...>, meta::duplicate_type_check<T, Types...>>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR decltype(auto) emplace(Args&&... args)\n\t\t{\n\t\t\treturn emplace<I>(eastl::forward<Args>(args)...);\n\t\t}\n\n\t\t// Equivalent to emplace<I>(il, std::forward<Args>(args)...), where I is the zero-based index of T in Types....\n\t\t// This overload only participates in overload resolution if std::is_constructible_v<T,\n\t\t// std::initializer_list<U>&, Args...> is true, and T occurs exactly once in Types...\n\t\ttemplate <class T,\n\t\t          class U,\n\t\t          class... Args,\n\t\t          size_t I = meta::get_type_index_v<T, Types...>,\n\t\t          enable_if_t<conjunction_v<is_constructible<T, std::initializer_list<U>&, Args...>,\n\t\t                                               meta::duplicate_type_check<T, Types...>>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR decltype(auto) emplace(std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\treturn emplace<I>(il, eastl::forward<T>(args)...);\n\t\t}\n\n\t\t// First, destroys the currently contained value (if any). Then direct-initializes the contained value as if\n\t\t// constructing a value of type T_I with the arguments std::forward<Args>(args).... If an exception is thrown,\n\t\t// *this may become valueless_by_exception. This overload only participates in overload resolution if\n\t\t// std::is_constructible_v<T_I, Args...> is true. The behavior is undefined if I is not less than\n\t\t// sizeof...(Types).\n\t\t//\n\t\tEA_DISABLE_VC_WARNING(4702) // unreachable code: suppress warning because construct_as<I>() may always throws (because T(args...) throws).\n\t\ttemplate <size_t I,\n\t\t          class... Args,\n\t\t          typename T = meta::get_type_at_t<I, Types...>,\n\t\t          enable_if_t<is_constructible_v<T, Args...>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR variant_alternative_t<I, variant>& emplace(Args&&... args)\n\t\t{\n\t\t\tif (!valueless_by_exception())\n\t\t\t{\n\t\t\t\tthis->destroy();\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tthis->mIndex = static_cast<size_t>(variant_npos);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tthis->template construct_as<I>(eastl::forward<Args>(args)...);\n\t\t\treturn *reinterpret_cast<T*>(&this->mBuffer);\n\t\t}\n\t\tEA_RESTORE_VC_WARNING()\n\n\t\t// First, destroys the currently contained value (if any). Then direct-initializes the contained value as if\n\t\t// constructing a value of type T_I with the arguments il, std::forward<Args>(args).... If an exception is\n\t\t// thrown, *this may become valueless_by_exception. This overload only participates in overload resolution if\n\t\t// std::is_constructible_v<T_I, initializer_list<U>&, Args...> is true. The behavior is undefined if I is not\n\t\t// less than sizeof...(Types).\n\t\t//\n\t\tEA_DISABLE_VC_WARNING(4702) // unreachable code: suppress warning because construct_as<I>() may always throws (because T(args...) throws).\n\t\ttemplate <size_t I,\n\t\t          class U,\n\t\t          class... Args,\n\t\t          typename T = meta::get_type_at_t<I, Types...>,\n\t\t          enable_if_t<is_constructible_v<T, std::initializer_list<U>&, Args...>, bool> = true>\n\t\tEA_CPP20_CONSTEXPR variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il, Args&&... args)\n\t\t{\n\t\t\tif (!valueless_by_exception())\n\t\t\t{\n\t\t\t\tthis->destroy();\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tthis->mIndex = static_cast<size_t>(variant_npos);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tthis->template construct_as<I>(il, eastl::forward<Args>(args)...);\n\t\t\treturn *reinterpret_cast<T*>(&this->mBuffer);\n\t\t}\n\t\tEA_RESTORE_VC_WARNING()\n\n\n\t\t///////////////////////////////////////////////////////////////////////////\n\t\t// 20.7.2.3, assignment\n\t\t//\n\n\t\t// implemented by EnableVariantOptionalSpecialMemberFunctions<...>\n\t\tvariant& operator=(const variant&) = default;\n\t\tvariant& operator=(variant&&) = default;\n\n\t\ttemplate <class T,\n\t\t          typename T_j = meta::overload_resolution_t<T, meta::overload_set<Types...>>,\n\t\t          size_t I = meta::get_type_index_v<decay_t<T_j>, Types...>,\n\t\t          enable_if_t<!eastl::is_same_v<eastl::remove_cvref_t<T>, variant> && eastl::is_assignable_v<T_j&, T> &&\n\t\t              eastl::is_constructible_v<T_j, T>, bool> = true>\n\t\tEA_CPP14_CONSTEXPR variant& operator=(T&& t)\n\t\t    EA_NOEXCEPT(conjunction_v<is_nothrow_assignable<T_j&, T>, is_nothrow_constructible<T_j, T>>)\n\t\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\tif (this->mIndex == I) // already holds a T_j\n\t\t\t{\n\t\t\t\t*this->template get_as<T_j*>() = eastl::forward<T>(t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tinternal::converting_emplace<T_j, T>::template call<I>(*this, eastl::forward<T>(t));\n\t\t\t}\n#else\n\t\t\tif (!valueless_by_exception())\n\t\t\t\tthis->destroy();\n\n\t\t\tthis->template construct_as<I>(eastl::forward<T>(t));\n#endif\n\t\t\treturn *this;\n\t\t}\n\n\n\t\t///////////////////////////////////////////////////////////////////////////\n\t\t// 20.7.2.5, value status\n\t\t//\n\t\tusing base_type::index;\n\t\tusing base_type::valueless_by_exception;\n\n\n\t\t///////////////////////////////////////////////////////////////////////////\n\t\t// 20.7.2.6, swap\n\t\t//\n\t\tvoid swap(variant& other)\n\t\t\tEA_NOEXCEPT(conjunction_v<is_nothrow_move_constructible<Types>..., is_nothrow_swappable<Types>...>)\n\t\t{\n\t\t\tif (this->valueless_by_exception() && other.valueless_by_exception())\n\t\t\t{\n\t\t\t\t// no op\n\t\t\t}\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\telse if (this->mIndex == other.mIndex)\n\t\t\t{\n\t\t\t\tauto genericVisitor = [&other](auto& thisAlternative)\n\t\t\t\t{\n\t\t\t\t\tusing alternative_t = remove_reference_t<decltype(thisAlternative)>;\n\n\t\t\t\t\tusing eastl::swap;\n\t\t\t\t\tswap(thisAlternative, *other.template get_as<alternative_t*>());\n\t\t\t\t};\n\n\t\t\t\tvisit(genericVisitor, *this);\n\t\t\t}\n#endif\n\t\t\telse if (this->valueless_by_exception() && !other.valueless_by_exception())\n\t\t\t{\n\t\t\t\tauto genericVisitor = [this](auto idxConstant, auto&& otherAlternative)\n\t\t\t\t{\n\t\t\t\t\tconstexpr size_t I = idxConstant();\n\t\t\t\t\tthis->template construct_as<I>(eastl::move(otherAlternative));\n\t\t\t\t};\n\n\t\t\t\tinternal::visit_with_index(genericVisitor, eastl::move(other));\n\t\t\t\tother.destroy(); // moved variant still contains an object.\n\t\t\t\tother.mIndex = variant_npos;\n\t\t\t}\n\t\t\telse if (!this->valueless_by_exception() && other.valueless_by_exception())\n\t\t\t{\n\t\t\t\tauto genericVisitor = [&other](auto idxConstant, auto&& thisAlternative)\n\t\t\t\t{\n\t\t\t\t\tconstexpr size_t I = idxConstant();\n\t\t\t\t\tother.template construct_as<I>(eastl::move(thisAlternative));\n\t\t\t\t};\n\n\t\t\t\tinternal::visit_with_index(genericVisitor, eastl::move(*this));\n\t\t\t\tthis->destroy(); // moved variant still contains an object.\n\t\t\t\tthis->mIndex = variant_npos;\n\t\t\t}\n\t\t\telse // if (!this->valueless_by_exception() && !other.valueless_by_exception() && this->mIndex != other.mIndex)\n\t\t\t{\n\t\t\t\t// the standard specifies swap() only requires that alternative types are swappable and move constructible.\n\t\t\t\t// therefore we can't use the assignment operator.\n\n\t\t\t\tauto thisVisitor = [this, &other](auto thisIdxConstant, auto& thisAlternative)\n\t\t\t\t{\n\t\t\t\t\tconstexpr size_t ThisAlternativeIndex = thisIdxConstant();\n\t\t\t\t\tusing this_alternative_t = remove_reference_t<decltype(thisAlternative)>;\n\n\t\t\t\t\tinternal::swap_visitor<this_alternative_t, ThisAlternativeIndex, Types...> swapVisitor{ *this, other, thisAlternative };\n\t\t\t\t\tinternal::visit_with_index(swapVisitor, other);\n\t\t\t\t};\n\n\t\t\t\tinternal::visit_with_index(thisVisitor, *this);\n\t\t\t}\n\t\t}\n\n\tprivate:\n\t\t// NOTE(rparolin): get_if accessors require internal access to the variant storage class\n\t\ttemplate <size_t I, class... Types2, enable_if_t<I < sizeof...(Types2), bool>> friend EA_CONSTEXPR add_pointer_t<      variant_alternative_t<I, variant<Types2...>>> get_if(      variant<Types2...>* pv) EA_NOEXCEPT;\n\t\ttemplate <size_t I, class... Types2, enable_if_t<I < sizeof...(Types2), bool>> friend EA_CONSTEXPR add_pointer_t<const variant_alternative_t<I, variant<Types2...>>> get_if(const variant<Types2...>* pv) EA_NOEXCEPT;\n\n\t\t// NOTE(rparolin): get accessors require internal access to the variant storage class\n\t\ttemplate <size_t I, class... Types2, enable_if_t<I < sizeof...(Types2), bool>> friend EA_CONSTEXPR       variant_alternative_t<I, variant<Types2...>>&  get(variant<Types2...>& v);\n\t\ttemplate <size_t I, class... Types2, enable_if_t<I < sizeof...(Types2), bool>> friend EA_CONSTEXPR       variant_alternative_t<I, variant<Types2...>>&& get(variant<Types2...>&& v);\n\t\ttemplate <size_t I, class... Types2, enable_if_t<I < sizeof...(Types2), bool>> friend EA_CONSTEXPR const variant_alternative_t<I, variant<Types2...>>&  get(const variant<Types2...>& v);\n\t\ttemplate <size_t I, class... Types2, enable_if_t<I < sizeof...(Types2), bool>> friend EA_CONSTEXPR const variant_alternative_t<I, variant<Types2...>>&& get(const variant<Types2...>&& v);\n\t};\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.9, swap\n\t//\n\ttemplate <class... Types>\n\tvoid swap(variant<Types...>& lhs, variant<Types...>& rhs)\n\t\tEA_NOEXCEPT(EA_NOEXCEPT(lhs.swap(rhs)))\n\t{\n\t\tlhs.swap(rhs);\n\t}\n\n\n\t// visit is a bit convoluted, in order to fulfill a few requirements:\n\t//   - It must support visiting multiple variants using a single visitor and a single function call. The\n\t//     visitor in this case should have one function for each possible combination of types:\n\t//\n\t//     struct MyVisitor {\n\t//         void operator()(int, int);\n\t//         void operator()(string, string);\n\t//         void operator()(int, string);\n\t//         void operator()(string, int);\n\t//     };\n\t//\n\t//     variant<int, string> a = 42;\n\t//     variant<int, string> b = \"hello\";\n\t//     visit(MyVisitor{}, a, b); // calls MyVisitor::operator()(int, string)\n\t//\n\t//   - It must be declared constexpr\n\t//   - It must be constant-time for the case of visiting a single variant\n\t//\n\t//   - 20.7.7 states that variant visitation requires all combinations of visitors to return the same type.\n\t//\n\t// NOTE(mwinkler):\n\t// Visit creates an N-Dimensional matrix whereby each dimension is M wide.\n\t// Where N == sizeof...(Variants) and M == variant_size_v<Variant>\n\t//\n\t// variant<int, bool, float> v;\n\t// visit(Visitor{}, v, v);\n\t//\n\t// This creates a 3x3 matrix of potential visitors.\n\t// The argument indices into the variants are as follows.\n\t// [0, 0], [0, 1], [0, 2]\n\t// [1, 0], [1, 1], [1, 2]\n\t// [2, 0], [2, 1], [2, 2]\n\t//\n\t// These indices are compile-time constants but the variants have a runtime index.\n\t// Therefore we must instantiate an NxNxN... matrix of function pointers who are\n\t// templated on the indices based on their position in the matrix and then\n\t// at runtime index into the array to call the correct function pointer that can\n\t// get the correct alternatives in the variants.\n\t//\n\t// There are a couple of ways to do this. We can construct the matrix bottom up or top down.\n\t//\n\t// Constructing a matrix bottom up would look something as follows.\n\t//\n\t// make_visitor_matrix_recurse(eastl::index_sequence<>{}, eastl::make_index_sequence<eastl::variant_size_v<eastl::decay_t<Variants>>>{}...);\n\t//\n\t// make_visitor_matrix_recurse(eastl::index_sequence<Is...>) { return templated function pointer on Is... }\n\t//\n\t// make_visitor_matrix_recurse(eastl::index_sequence<Is...>, eastl::index_sequence<Js...>, RestIndex... rest)\n\t//    return make_array(make_visitor_matrix_recurse(eastl::index_sequence<Is..., Js>{}, rest...)...);\n\t//\n\t// Essentially we construct the matrix bottom up, row by row of indices and return an array of function pointers.\n\t// The end result is a NxNxN... array on the stack which can be indexed by each variant in order as follows,\n\t// array[v0.index()][v1.index()][vn.index()]();\n\t//\n\t// The downside with this approach is the massive NxNxN... array that is created on the stack.\n\t//\n\t// The other approach is to build the matrix top down and use tail recursion to ensure there is only one\n\t// N sized array on the stack. The downside here is the extra function calls, but we feel this approach provides\n\t// a good balance between performance and memory usage.\n\t//\n\t// We construct the matrix top down by first creating an N sized array that is indexed by the first variant.\n\t// This calls a function that recursively creates another N sized array that is indexed by the second variant.\n\t// The recursion continues until we reach the base case which is the last variant. At this point we know\n\t// the compile-time value of the N indices needed to get each alternative from each variant to invoke the visitor upon.\n\t// Essentially we create a tree of function pointers like so.\n\t//\n\t//\n\t//\t\t\t\t\t\t  +------------------------------------------------------------------+\n\t//\t\t\t\t\t\t  |\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |\n\t//\t\t\t\t\t\t  |\t   0\t\t\t\t\t\t   1\t\t\t\t\t\t\t N\t |\n\t//\t\t\t\t\t\t  |\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |\n\t//\t\t\t\t\t\t  |\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |\n\t//\t\t\t\t\t\t  +----+---------------------------+---------------------------------+\n\t//\t\t\t\t\t\t\t   |\t\t\t\t\t\t   |\n\t//\t\t\t\t\t\t\t   |\t\t\t\t\t\t   |\n\t//\t\t\t\t\t\t\t   |\t\t\t\t\t\t   |\n\t//\t\t\t\t\t\t\t   |\t\t\t\t\t\t   |\n\t//\t\t\t\t\t\t\t   |\t\t\t\t\t\t   |\n\t//\t+--------------------------+-----------------+\t  +----+------------------------------------+\n\t//\t|\t\t\t\t\t\t\t\t\t\t\t |\t  |\t\t\t\t\t\t\t\t\t\t\t|\n\t//\t|0,0\t\t\t\t  0,1\t\t\t\t  0,N|\t  |1,0\t\t\t\t   1,1\t\t\t\t 1,N|\n\t//\t|\t\t\t\t\t\t\t\t\t\t\t |\t  |\t\t\t\t\t\t\t\t\t\t\t|\n\t//\t|\t\t\t\t\t\t\t\t\t\t\t |\t  |\t\t\t\t\t\t\t\t\t\t\t|\n\t//\t+--------------------------------------------+\t  +-----------------------------------------+\n\t//\n\t// Essentially each call creates a N sized array of function pointers that is the concatention of the indices known so far\n\t// and the index of itself in the array whereby the leaf function pointer does the final invoke of the visitor.\n\t//\n\n\t// Since decltype() is not one of the contexts where an overloaded function can be used without arguments;\n\t// We use this function to deduce the function pointer types.\n\t// We also return an eastl::array<> since we cannot return C-style arrays as value types.\n\ttemplate <typename T>\n\tstatic EA_CONSTEXPR array<decay_t<T>, 1> make_visitor_array(T&& t)\n\t{\n\t\treturn { { eastl::forward<T>(t) } };\n\t}\n\n\ttemplate <typename T, typename... Ts>\n\tstatic EA_CONSTEXPR array<decay_t<T>, sizeof...(Ts) + 1> make_visitor_array(T&& t, Ts&&... ts)\n\t{\n\t\tstatic_assert(conjunction_v<is_same<decay_t<T>, decay_t<Ts>>...>, \"`visit` variant visitation requires that all visitors have the same return type!\");\n\n\t\treturn { { eastl::forward<T>(t), eastl::forward<Ts>(ts)... } };\n\t}\n\n\n\ttemplate <size_t N, typename Variant, typename... Variants, eastl::enable_if_t<N == 0, int> = 0>\n\tstatic EA_CONSTEXPR decltype(auto) get_variant_n(Variant&& variant, Variants&&...)\n\t{\n\t\treturn eastl::forward<Variant>(variant);\n\t}\n\n\ttemplate <size_t N, typename Variant, typename... Variants, eastl::enable_if_t<N != 0, int> = 0>\n\tstatic EA_CONSTEXPR decltype(auto) get_variant_n(Variant&&, Variants&&... variants)\n\t{\n\t\treturn get_variant_n<N - 1>(eastl::forward<Variants>(variants)...);\n\t}\n\n\n\ttemplate <typename Visitor, typename Index, typename Array, typename... Variants>\n\tstatic EA_CONSTEXPR decltype(auto) call_visitor_at_index(Array&& array, Index index, Visitor&& visitor, Variants&&... variants)\n\t{\n\t\treturn array[static_cast<typename Array::size_type>(index)](eastl::forward<Visitor>(visitor), eastl::forward<Variants>(variants)...);\n\t}\n\n\ttemplate <size_t VariantsIndex, typename Visitor, typename Array, typename... Variants>\n\tstatic EA_CONSTEXPR decltype(auto) call_visitor_at(Array&& array, Visitor&& visitor, Variants&&... variants)\n\t{\n\t\treturn call_visitor_at_index(eastl::forward<Array>(array),\n\t\t\t\t\t\t\t\t\t get_variant_n<VariantsIndex>(eastl::forward<Variants>(variants)...).index(),\n\t\t\t\t\t\t\t\t\t eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t eastl::forward<Variants>(variants)...);\n\t}\n\n\n\t// abstracts calling visit on 2 or more variants\n\ttemplate <typename VariantIndexSequence, typename Visitor, typename... Variants>\n\tstruct visitor_caller_n;\n\n\ttemplate <typename Visitor, typename... Variants, size_t... VariantIndices>\n\tstruct visitor_caller_n<index_sequence<VariantIndices...>, Visitor, Variants...>\n\t{\n\t\tusing return_type = invoke_result_t<Visitor, variant_alternative_t<0, remove_reference_t<Variants>>...>;\n\n\t\ttemplate <size_t... VariantArgIndices>\n\t\tstatic EA_CONSTEXPR return_type invoke_visitor_leaf(Visitor&& visitor, Variants&&... variants)\n\t\t{\n\t\t\treturn eastl::invoke(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t eastl::get<VariantArgIndices>(eastl::forward<Variants>(variants))...);\n\t\t}\n\n\t\ttemplate <size_t... VariantArgIndices>\n\t\tstatic EA_CONSTEXPR auto make_invoke_visitor_leaf(index_sequence<VariantArgIndices...>)\n\t\t{\n\t\t\treturn &invoke_visitor_leaf<VariantArgIndices...>;\n\t\t}\n\n\n\t\ttemplate <size_t... VariantArgIndices>\n\t\tstatic EA_CONSTEXPR return_type invoke_visitor_recurse(Visitor&& visitor, Variants&&... variants)\n\t\t{\n\t\t\treturn call(index_sequence<VariantArgIndices...>{},\n\t\t\t\t\t\teastl::forward<Visitor>(visitor),\n\t\t\t\t\t\teastl::forward<Variants>(variants)...);\n\t\t}\n\n\t\ttemplate <size_t... VariantArgIndices>\n\t\tstatic EA_CONSTEXPR auto make_invoke_visitor_recurse(index_sequence<VariantArgIndices...>)\n\t\t{\n\t\t\treturn &invoke_visitor_recurse<VariantArgIndices...>;\n\t\t}\n\n\n\t\ttemplate <typename VariantArgIndexSequence, enable_if_t<internal::index_sequence_size_v<VariantArgIndexSequence> + 1 == sizeof...(Variants), int> = 0>\n\t\tstatic EA_CPP14_CONSTEXPR decltype(auto) call(VariantArgIndexSequence, Visitor&& visitor, Variants&&... variants)\n\t\t{\n\t\t\tEA_CPP14_CONSTEXPR auto callers = make_visitor_array(make_invoke_visitor_leaf(meta::double_pack_expansion_t<VariantArgIndexSequence, VariantIndices>{})...);\n\n\t\t\treturn call_visitor_at<internal::index_sequence_size_v<VariantArgIndexSequence>>(eastl::move(callers),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Variants>(variants)...);\n\t\t}\n\n\t\ttemplate <typename VariantArgIndexSequence, enable_if_t<internal::index_sequence_size_v<VariantArgIndexSequence> + 1 != sizeof...(Variants), int> = 0>\n\t\tstatic EA_CPP14_CONSTEXPR decltype(auto) call(VariantArgIndexSequence, Visitor&& visitor, Variants&&... variants)\n\t\t{\n\t\t\tEA_CPP14_CONSTEXPR auto callers = make_visitor_array(make_invoke_visitor_recurse(meta::double_pack_expansion_t<VariantArgIndexSequence, VariantIndices>{})...);\n\n\t\t\treturn call_visitor_at<internal::index_sequence_size_v<VariantArgIndexSequence>>(eastl::move(callers),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Variants>(variants)...);\n\t\t}\n\n\t};\n\n\ttemplate <typename VariantIndexSequence, typename Visitor, typename... Variants>\n\tstatic EA_CONSTEXPR decltype(auto) call_initial_n(VariantIndexSequence, Visitor&& visitor, Variants&&... variants)\n\t{\n\t\treturn visitor_caller_n<VariantIndexSequence, Visitor, Variants...>::call(index_sequence<>{}, eastl::forward<Visitor>(visitor), eastl::forward<Variants>(variants)...);\n\t}\n\n\n\t// abstracts calling visit on 2 or more variants with return types convertible to R\n\ttemplate <typename R, typename VariantIndexSequence, typename Visitor, typename... Variants>\n\tstruct visitor_caller_n_r;\n\n\ttemplate <typename R, size_t... VariantIndices, typename Visitor, typename... Variants>\n\tstruct visitor_caller_n_r<R, index_sequence<VariantIndices...>, Visitor, Variants...>\n\t{\n\t\ttemplate <typename R_, size_t... VariantArgIndices>\n\t\tstruct visitor_leaf_r\n\t\t{\n\t\t\tstatic EA_CONSTEXPR R_ invoke_visitor_leaf_r(Visitor&& visitor, Variants&&... variants)\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t eastl::get<VariantArgIndices>(eastl::forward<Variants>(variants))...);\n\t\t\t}\n\t\t};\n\n\t\t// void return type must discard the return values of the visitor even if the visitor returns a value.\n\t\ttemplate <size_t... VariantArgIndices>\n\t\tstruct visitor_leaf_r<void, VariantArgIndices...>\n\t\t{\n\t\t\tstatic EA_CONSTEXPR void invoke_visitor_leaf_r(Visitor&& visitor, Variants&&... variants)\n\t\t\t{\n\t\t\t\teastl::invoke(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t  eastl::get<VariantArgIndices>(eastl::forward<Variants>(variants))...);\n\t\t\t}\n\t\t};\n\t\ttemplate <size_t... VariantArgIndices> struct visitor_leaf_r<const void, VariantArgIndices...> : public visitor_leaf_r<void, VariantArgIndices...> {};\n\t\ttemplate <size_t... VariantArgIndices> struct visitor_leaf_r<volatile void, VariantArgIndices...> : public visitor_leaf_r<void, VariantArgIndices...> {};\n\t\ttemplate <size_t... VariantArgIndices> struct visitor_leaf_r<const volatile void, VariantArgIndices...> : public visitor_leaf_r<void, VariantArgIndices...> {};\n\n\t\ttemplate <typename R_, size_t... VariantArgIndices>\n\t\tstatic EA_CONSTEXPR auto make_invoke_visitor_leaf_r(index_sequence<VariantArgIndices...>)\n\t\t{\n\t\t\treturn &visitor_leaf_r<R_, VariantArgIndices...>::invoke_visitor_leaf_r;\n\t\t}\n\n\n\t\ttemplate <typename R_, size_t... VariantArgIndices>\n\t\tstruct visitor_recurse_r\n\t\t{\n\t\t\tstatic EA_CONSTEXPR R_ invoke_visitor_recurse_r(Visitor&& visitor, Variants&&... variants)\n\t\t\t{\n\t\t\t\treturn call_r(index_sequence<VariantArgIndices...>{},\n\t\t\t\t\t\t\t  eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t  eastl::forward<Variants>(variants)...);\n\t\t\t}\n\t\t};\n\n\t\ttemplate <typename R_, size_t... VariantArgIndices>\n\t\tstatic EA_CONSTEXPR auto make_invoke_visitor_recurse_r(index_sequence<VariantArgIndices...>)\n\t\t{\n\t\t\treturn &visitor_recurse_r<R_, VariantArgIndices...>::invoke_visitor_recurse_r;\n\t\t}\n\n\n\t\ttemplate <typename VariantArgIndexSequence, enable_if_t<internal::index_sequence_size_v<VariantArgIndexSequence> + 1 == sizeof...(Variants), int> = 0>\n\t\tstatic EA_CPP14_CONSTEXPR decltype(auto) call_r(VariantArgIndexSequence, Visitor&& visitor, Variants&&... variants)\n\t\t{\n\t\t\tEA_CPP14_CONSTEXPR auto callers = make_visitor_array(make_invoke_visitor_leaf_r<R>(meta::double_pack_expansion_t<VariantArgIndexSequence, VariantIndices>{})...);\n\n\t\t\treturn call_visitor_at<internal::index_sequence_size_v<VariantArgIndexSequence>>(eastl::move(callers),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Variants>(variants)...);\n\t\t}\n\n\t\ttemplate <typename VariantArgIndexSequence, enable_if_t<internal::index_sequence_size_v<VariantArgIndexSequence> + 1 != sizeof...(Variants), int> = 0>\n\t\tstatic EA_CPP14_CONSTEXPR decltype(auto) call_r(VariantArgIndexSequence, Visitor&& visitor, Variants&&... variants)\n\t\t{\n\t\t\tEA_CPP14_CONSTEXPR auto callers = make_visitor_array(make_invoke_visitor_recurse_r<R>(meta::double_pack_expansion_t<VariantArgIndexSequence, VariantIndices>{})...);\n\n\t\t\treturn call_visitor_at<internal::index_sequence_size_v<VariantArgIndexSequence>>(eastl::move(callers),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Variants>(variants)...);\n\t\t}\n\n\t};\n\n\ttemplate <typename R, typename VariantIndexSequence, typename Visitor, typename... Variants>\n\tstatic EA_CONSTEXPR decltype(auto) call_initial_n_r(VariantIndexSequence, Visitor&& visitor, Variants&&... variants)\n\t{\n\t\treturn visitor_caller_n_r<R, VariantIndexSequence, Visitor, Variants...>::call_r(index_sequence<>{}, eastl::forward<Visitor>(visitor), eastl::forward<Variants>(variants)...);\n\t}\n\n\n\t// abstracts calling visit on a single variant\n\tstruct visitor_caller_one\n\t{\n\n\t\ttemplate <typename Visitor, typename Variant, size_t I>\n\t\tstatic EA_CONSTEXPR decltype(auto) invoke_visitor(Visitor&& visitor, Variant&& variant)\n\t\t{\n\t\t\treturn eastl::invoke(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t eastl::get<I>(eastl::forward<Variant>(variant)));\n\t\t}\n\n\t\ttemplate <typename Visitor, typename Variant, size_t... VariantArgIndices>\n\t\tstatic EA_CPP14_CONSTEXPR decltype(auto) call_index(Visitor&& visitor, Variant&& variant, index_sequence<VariantArgIndices...>)\n\t\t{\n\t\t\tEA_CPP14_CONSTEXPR auto callers = make_visitor_array((&invoke_visitor<Visitor, Variant, VariantArgIndices>)...);\n\n\t\t\treturn call_visitor_at_index(eastl::move(callers), eastl::forward<Variant>(variant).index(),\n\t\t\t\t\t\t\t\t\t\t eastl::forward<Visitor>(visitor), eastl::forward<Variant>(variant));\n\t\t}\n\n\t\ttemplate <typename Visitor, typename Variant>\n\t\tstatic EA_CONSTEXPR decltype(auto) call(Visitor&& visitor, Variant&& variant)\n\t\t{\n\t\t\treturn call_index(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t  eastl::forward<Variant>(variant),\n\t\t\t\t\t\t\t  make_index_sequence<variant_size_v<decay_t<Variant>>>{});\n\t\t}\n\n\t};\n\n\n\ttemplate <typename R>\n\tstruct visitor_r\n\t{\n\t\ttemplate <typename Visitor, typename Variant, size_t I>\n\t\tstatic EA_CONSTEXPR R invoke_visitor_r(Visitor&& visitor, Variant&& variant)\n\t\t{\n\t\t\treturn eastl::invoke(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t eastl::get<I>(eastl::forward<Variant>(variant)));\n\t\t}\n\t};\n\n\t// void return type must discard the return values of the visitor even if the visitor returns a value.\n\ttemplate <>\n\tstruct visitor_r<void>\n\t{\n\t\ttemplate <typename Visitor, typename Variant, size_t I>\n\t\tstatic EA_CONSTEXPR void invoke_visitor_r(Visitor&& visitor, Variant&& variant)\n\t\t{\n\t\t\teastl::invoke(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t  eastl::get<I>(eastl::forward<Variant>(variant)));\n\t\t}\n\t};\n\ttemplate<> struct visitor_r<const void> : public visitor_r<void> {};\n\ttemplate<> struct visitor_r<volatile void> : public visitor_r<void> {};\n\ttemplate<> struct visitor_r<const volatile void> : public visitor_r<void> {};\n\n\t// abstracts calling visit on a single variant with return types convertible to R\n\tstruct visitor_caller_one_r\n\t{\n\t\ttemplate <typename R, typename Visitor, typename Variant, size_t... VariantArgIndices>\n\t\tstatic EA_CPP14_CONSTEXPR decltype(auto) call_index_r(Visitor&& visitor, Variant&& variant, eastl::index_sequence<VariantArgIndices...>)\n\t\t{\n\t\t\tEA_CPP14_CONSTEXPR auto callers = make_visitor_array(&visitor_r<R>::template invoke_visitor_r<Visitor, Variant, VariantArgIndices>...);\n\n\t\t\treturn callers[static_cast<typename decltype(callers)::size_type>(eastl::forward<Variant>(variant).index())](eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t eastl::forward<Variant>(variant));\n\t\t}\n\n\t\ttemplate <typename R, typename Visitor, typename Variant>\n\t\tstatic EA_CONSTEXPR decltype(auto) call_r(Visitor&& visitor, Variant&& variant)\n\t\t{\n\t\t\treturn call_index_r<R>(eastl::forward<Visitor>(visitor), eastl::forward<Variant>(variant), eastl::make_index_sequence<eastl::variant_size_v<eastl::decay_t<Variant>>>());\n\t\t}\n\n\t};\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.6, visitation\n\t//\n\t// Example:\n\t//     struct MyVisitor\n\t//     {\n\t//         auto operator()(int) {};\n\t//         auto operator()(long) {};\n\t//         auto operator()(string) {};\n\t//     };\n\t//\n\t//     variant<int, long, string> v = \"Hello, Variant\";\n\t//     visit(MyVisitor{}, v);  // calls MyVisitor::operator()(string) {}\n\t//\n\tEA_DISABLE_VC_WARNING(4100) // warning C4100: 't': unreferenced formal parameter\n\ttemplate <typename... Variants>\n\tstatic EA_CPP14_CONSTEXPR void visit_throw_bad_variant_access(Variants&&... variants)\n\t{\n\t#if EASTL_EXCEPTIONS_ENABLED\n\t\tusing bool_array_type = bool[];\n\t\tbool badAccess = false;\n\n\t\t(void)bool_array_type{ (badAccess |= eastl::forward<Variants>(variants).valueless_by_exception(), false)... };\n\n\t\tif (badAccess)\n\t\t{\n\t\t\tthrow bad_variant_access();\n\t\t}\n\t#endif\n\t}\n\tEA_RESTORE_VC_WARNING()\n\n\ttemplate <typename... Variants>\n\tstatic EA_CONSTEXPR void visit_static_assert_check(Variants&&...)\n\t{\n\t\tstatic_assert(sizeof...(Variants) > 0, \"`visit` at least one variant instance must be passed as an argument to the visit function\");\n\n\t\tusing variant_type = decay_t<meta::get_type_at_t<0, Variants...>>;\n\t\tstatic_assert(conjunction_v<is_same<variant_type, decay_t<Variants>>...>,\n\t\t\t\t\t  \"`visit` all variants passed to eastl::visit() must have the same type\");\n\t}\n\n\tnamespace internal\n\t{\n\t\t// visit() overloads participate in overload resolution only if the visitor is callable with every combination of the variants' alternative types.\n\t\t// informally, for a call to visit(visitor, variant1, variant2, ...):\n\t\t//   visitor(Variant1Alt, Variant2Alt...) must be valid for every possible combination of variant alternatives, where Variant1Alt is an alternative type for Variant1, etc.\n\t\t// see https://en.cppreference.com/w/cpp/utility/variant/visit for details.\n\t\ttemplate<typename ... Ts> variant<Ts...>& as_variant_impl(variant<Ts...>&);\n\t\ttemplate<typename ... Ts> const variant<Ts...>& as_variant_impl(const variant<Ts...>&);\n\t\ttemplate<typename ... Ts> variant<Ts...>&& as_variant_impl(variant<Ts...>&&);\n\t\ttemplate<typename ... Ts> const variant<Ts...>&& as_variant_impl(const variant<Ts...>&&);\n\t\ttemplate<typename T> using as_variant = decltype(as_variant_impl(declval<T>()));\n\n\t\tstruct visitor_caller_one_with_index\n\t\t{\n\t\t\ttemplate <typename Visitor, typename Variant, size_t I>\n\t\t\tstatic EA_CONSTEXPR decltype(auto) invoke_visitor(Visitor&& visitor, Variant&& variant)\n\t\t\t{\n\t\t\t\treturn eastl::invoke(eastl::forward<Visitor>(visitor),\n\t\t\t\t\teastl::integral_constant<size_t, I>{},\n\t\t\t\t\teastl::get<I>(eastl::forward<Variant>(variant)));\n\t\t\t}\n\n\t\t\ttemplate <typename Visitor, typename Variant, size_t... VariantArgIndices>\n\t\t\tstatic EA_CPP14_CONSTEXPR decltype(auto) call_index(Visitor&& visitor, Variant&& variant, index_sequence<VariantArgIndices...>)\n\t\t\t{\n\t\t\t\tEA_CPP14_CONSTEXPR auto callers = make_visitor_array((&invoke_visitor<Visitor, Variant, VariantArgIndices>)...);\n\n\t\t\t\treturn call_visitor_at_index(eastl::move(callers), eastl::forward<Variant>(variant).index(),\n\t\t\t\t\teastl::forward<Visitor>(visitor), eastl::forward<Variant>(variant));\n\t\t\t}\n\n\t\t\ttemplate <typename Visitor, typename Variant>\n\t\t\tstatic EA_CONSTEXPR decltype(auto) call(Visitor&& visitor, Variant&& variant)\n\t\t\t{\n\t\t\t\treturn call_index(eastl::forward<Visitor>(visitor),\n\t\t\t\t\teastl::forward<Variant>(variant),\n\t\t\t\t\tmake_index_sequence<variant_size_v<decay_t<Variant>>>{});\n\t\t\t}\n\n\t\t};\n\n\t\t// internal only, so asserts & validation are omitted.\n\t\ttemplate <typename Visitor, typename Variant>\n\t\tEA_CPP14_CONSTEXPR decltype(auto) visit_with_index(Visitor&& visitor, Variant&& variant)\n\t\t{\n\t\t\treturn visitor_caller_one_with_index::call(eastl::forward<Visitor>(visitor), eastl::forward<Variant>(variant));\n\t\t}\n\t} // namespace internal\n\n\t// visit\n\t//\n\ttemplate <typename Visitor, typename Variant, typename = eastl::void_t<internal::as_variant<Variant>>>\n\tEA_CPP14_CONSTEXPR decltype(auto) visit(Visitor&& visitor, Variant&& variant)\n\t{\n\t\tvisit_static_assert_check(eastl::forward<Variant>(variant));\n\n\t\tvisit_throw_bad_variant_access(eastl::forward<Variant>(variant));\n\n\t\treturn visitor_caller_one::call(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t\teastl::forward<Variant>(variant));\n\t}\n\n\ttemplate <typename Visitor, typename... Variants, typename = eastl::void_t<internal::as_variant<Variants>...>>\n\tEA_CPP14_CONSTEXPR decltype(auto) visit(Visitor&& visitor, Variants&&... variants)\n\t{\n\t\tvisit_static_assert_check(eastl::forward<Variants>(variants)...);\n\n\t\tvisit_throw_bad_variant_access(eastl::forward<Variants>(variants)...);\n\n\t\treturn call_initial_n(make_index_sequence<variant_size_v<decay_t<meta::get_type_at_t<0, Variants...>>>>{},\n\t\t\t\t\t\t\t  eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t  eastl::forward<Variants>(variants)...);\n\n\t}\n\n\t// C++20: overload with a user specifiable return type\n\ttemplate <typename R, typename Visitor, typename Variant, typename = eastl::void_t<internal::as_variant<Variant>>>\n\tEA_CPP14_CONSTEXPR R visit(Visitor&& visitor, Variant&& variant)\n\t{\n\t\tvisit_static_assert_check(eastl::forward<Variant>(variant));\n\n\t\tvisit_throw_bad_variant_access(eastl::forward<Variant>(variant));\n\n\t\treturn visitor_caller_one_r::call_r<R>(eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t\t\t\t   eastl::forward<Variant>(variant));\n\t}\n\n\t// C++20: overload with a user specifiable return type\n\ttemplate <typename R, typename Visitor, typename... Variants, typename = eastl::void_t<internal::as_variant<Variants>...>>\n\tEA_CPP14_CONSTEXPR R visit(Visitor&& visitor, Variants&&... variants)\n\t{\n\t\tvisit_static_assert_check(eastl::forward<Variants>(variants)...);\n\n\t\tvisit_throw_bad_variant_access(eastl::forward<Variants>(variants)...);\n\n\t\treturn call_initial_n_r<R>(make_index_sequence<variant_size_v<decay_t<meta::get_type_at_t<0, Variants...>>>>{},\n\t\t\t\t\t\t\t\t   eastl::forward<Visitor>(visitor),\n\t\t\t\t\t\t\t\t   eastl::forward<Variants>(variants)...);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.5, relational operators\n\t//\n\tnamespace internal\n\t{\n\n\t\t// For relational operators we do not need to create the NxN matrix of comparisons since we know already\n\t\t// that both the lhs and rhs variants have the same index. We just need to compare the value of the types at that\n\t\t// index for equality. Therefore the visitation is simpler than visit() for relational operators.\n\t\t//\n\t\tstruct variant_relational_comparison\n\t\t{\n\t\t\ttemplate <typename Compare, size_t I, typename Variant>\n\t\t\tstatic EA_CONSTEXPR bool invoke_relational_visitor(const Variant& lhs, const Variant& rhs)\n\t\t\t{\n\t\t\t\treturn eastl::invoke(Compare{}, eastl::get<I>(lhs), eastl::get<I>(rhs));\n\t\t\t}\n\n\t\t\ttemplate <typename Compare, typename Variant, size_t... VariantArgIndices>\n\t\t\tstatic EA_CPP14_CONSTEXPR bool call_index(const Variant& lhs, const Variant& rhs, eastl::index_sequence<VariantArgIndices...>)\n\t\t\t{\n\t\t\t\tusing invoke_relational_visitor_func_ptr = bool (*)(const Variant&, const Variant&);\n\n\t\t\t\tEA_CPP14_CONSTEXPR invoke_relational_visitor_func_ptr visitors[] = { static_cast<invoke_relational_visitor_func_ptr>(&invoke_relational_visitor<Compare, VariantArgIndices, Variant>)... };\n\n\t\t\t\treturn visitors[lhs.index()](lhs, rhs);\n\t\t\t}\n\n\t\t\ttemplate <typename Compare, typename Variant>\n\t\t\tstatic EA_CONSTEXPR bool call(const Variant& lhs, const Variant& rhs)\n\t\t\t{\n\t\t\t\treturn call_index<Compare>(lhs, rhs, eastl::make_index_sequence<eastl::variant_size_v<eastl::decay_t<Variant>>>());\n\t\t\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\t\ttemplate <typename Compare, size_t I, typename Variant>\n\t\t\tstatic EA_CONSTEXPR std::compare_three_way_result_t<Variant> invoke_relational_visitor_three_way(const Variant& lhs, const Variant& rhs)\n\t\t\t{\n\t\t\t\treturn eastl::invoke(Compare{}, eastl::get<I>(lhs), eastl::get<I>(rhs));\n\t\t\t}\n\n\t\t\ttemplate <typename Compare, typename Variant, size_t... VariantArgIndices>\n\t\t\tstatic EA_CONSTEXPR std::compare_three_way_result_t<Variant> call_index_three_way(const Variant& lhs, const Variant& rhs, eastl::index_sequence<VariantArgIndices...>)\n\t\t\t{\n\t\t\t\tusing invoke_relational_visitor_func_ptr = std::compare_three_way_result_t<Variant> (*)(const Variant&, const Variant&);\n\n\t\t\t\tEA_CONSTEXPR invoke_relational_visitor_func_ptr visitors[] = {static_cast<invoke_relational_visitor_func_ptr>(&invoke_relational_visitor_three_way<Compare, VariantArgIndices, Variant>)...};\n\n\t\t\t\treturn visitors[lhs.index()](lhs, rhs);\n\t\t\t}\n\n\t\t\ttemplate <typename Compare, typename Variant>\n\t\t\tstatic EA_CONSTEXPR std::compare_three_way_result_t<Variant> call_three_way(const Variant& lhs, const Variant& rhs)\n\t\t\t{\n\t\t\t\treturn call_index_three_way<Compare>(lhs, rhs, eastl::make_index_sequence<eastl::variant_size_v<eastl::decay_t<Variant>>>());\n\t\t\t}\n#endif\n\t\t};\n\n\t\ttemplate <typename Compare, typename Variant>\n\t\tstatic EA_CONSTEXPR bool CompareVariantRelational(const Variant& lhs, const Variant& rhs)\n\t\t{\n\t\t\treturn variant_relational_comparison::call<Compare>(lhs, rhs);\n\t\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\ttemplate <typename Compare, typename Variant>\n\t\tstatic EA_CONSTEXPR std::compare_three_way_result_t<Variant> CompareVariantRelationalThreeWay(const Variant& lhs, const Variant& rhs)\n\t\t{\n\t\t\treturn variant_relational_comparison::call_three_way<Compare>(lhs, rhs);\n\t\t}\n#endif\n\n\t} // namespace internal\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// 20.7.5, relational operators\n\t//\n\ttemplate <class... Types>\n\tEA_CPP14_CONSTEXPR bool operator==(const variant<Types...>& lhs, const variant<Types...>& rhs)\n\t{\n\t\tif (lhs.index() != rhs.index()) return false;\n\t\tif (lhs.valueless_by_exception()) return true;\n\n\t\treturn internal::CompareVariantRelational<eastl::equal_to<>>(lhs, rhs);\n\t}\n\n\ttemplate <class... Types>\n\tEA_CPP14_CONSTEXPR bool operator!=(const variant<Types...>& lhs, const variant<Types...>& rhs)\n\t{\n\t\tif (lhs.index() != rhs.index()) return true;\n\t\tif (lhs.valueless_by_exception()) return false;\n\n\t\treturn internal::CompareVariantRelational<eastl::not_equal_to<>>(lhs, rhs);\n\t}\n\n\ttemplate <class... Types>\n\tEA_CPP14_CONSTEXPR bool operator<(const variant<Types...>& lhs, const variant<Types...>& rhs)\n\t{\n\t\tif (rhs.valueless_by_exception()) return false;\n\t\tif (lhs.valueless_by_exception()) return true;\n\t\tif (lhs.index() < rhs.index()) return true;\n\t\tif (lhs.index() > rhs.index()) return false;\n\n\t\treturn internal::CompareVariantRelational<eastl::less<>>(lhs, rhs);\n\t}\n\n\ttemplate <class... Types>\n\tEA_CPP14_CONSTEXPR bool operator>(const variant<Types...>& lhs, const variant<Types...>& rhs)\n\t{\n\t\tif (lhs.valueless_by_exception()) return false;\n\t\tif (rhs.valueless_by_exception()) return true;\n\t\tif (lhs.index() > rhs.index()) return true;\n\t\tif (lhs.index() < rhs.index()) return false;\n\n\t\treturn internal::CompareVariantRelational<eastl::greater<>>(lhs, rhs);\n\t}\n\n\ttemplate <class... Types>\n\tEA_CPP14_CONSTEXPR bool operator<=(const variant<Types...>& lhs, const variant<Types...>& rhs)\n\t{\n\t\tif (lhs.valueless_by_exception()) return true;\n\t\tif (rhs.valueless_by_exception()) return false;\n\t\tif (lhs.index() < rhs.index()) return true;\n\t\tif (lhs.index() > rhs.index()) return false;\n\n\t\treturn internal::CompareVariantRelational<eastl::less_equal<>>(lhs, rhs);\n\t}\n\n\ttemplate <class... Types>\n\tEA_CPP14_CONSTEXPR bool operator>=(const variant<Types...>& lhs, const variant<Types...>& rhs)\n\t{\n\t\tif (rhs.valueless_by_exception()) return true;\n\t\tif (lhs.valueless_by_exception()) return false;\n\t\tif (lhs.index() > rhs.index()) return true;\n\t\tif (lhs.index() < rhs.index()) return false;\n\n\t\treturn internal::CompareVariantRelational<eastl::greater_equal<>>(lhs, rhs);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <class... Types> requires (std::three_way_comparable<Types> && ...)\n\tEA_CONSTEXPR std::common_comparison_category_t<std::compare_three_way_result_t<Types>...> operator<=>(const variant<Types...>& lhs, const variant<Types...>& rhs)\n\t{\n\t\tif (lhs.valueless_by_exception() && rhs.valueless_by_exception()) return std::strong_ordering::equal;\n\t\tif (lhs.valueless_by_exception()) return std::strong_ordering::less;\n\t\tif (rhs.valueless_by_exception()) return std::strong_ordering::greater;\n\t\tif (auto result = (lhs.index() <=> rhs.index()); result != 0) return result;\n\n\t\treturn internal::CompareVariantRelationalThreeWay<std::compare_three_way>(lhs, rhs);\n\n\t}\n#endif\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING()\n\n#endif // EASTL_VARIANT_H\n"
  },
  {
    "path": "include/EASTL/vector.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// This file implements a vector (array-like container), much like the C++ \n// std::vector class.\n// The primary distinctions between this vector and std::vector are:\n//    - vector has a couple extension functions that increase performance.\n//    - vector can contain objects with alignment requirements. std::vector \n//      cannot do so without a bit of tedious non-portable effort.\n//    - vector supports debug memory naming natively.\n//    - vector is easier to read, debug, and visualize.\n//    - vector is savvy to an environment that doesn't have exception handling,\n//      as is sometimes the case with console or embedded environments.\n//    - vector has less deeply nested function calls and allows the user to \n//      enable forced inlining in debug builds in order to reduce bloat.\n//    - vector<bool> is a vector of boolean values and not a bit vector.\n//    - vector guarantees that memory is contiguous and that vector::iterator\n//      is nothing more than a pointer to T.\n//    - vector has an explicit data() method for obtaining a pointer to storage \n//      which is safe to call even if the block is empty. This avoids the \n//      common &v[0], &v.front(), and &*v.begin() constructs that trigger false \n//      asserts in STL debugging modes.\n//    - vector data is guaranteed to be contiguous.\n//    - vector has a set_capacity() function which frees excess capacity. \n//      The only way to do this with std::vector is via the cryptic non-obvious \n//      trick of using: vector<SomeClass>(x).swap(x);\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_VECTOR_H\n#define EASTL_VECTOR_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <EASTL/memory.h>\n#include <EASTL/numeric_limits.h>\n#include <EASTL/bonus/compressed_pair.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <new>\n#include <stddef.h>\n#if EASTL_EXCEPTIONS_ENABLED\n\t#include <stdexcept> // std::out_of_range, std::length_error, std::logic_error.\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\n// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc\n// 4480 - nonstandard extension used: specifying underlying type for enum\n// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.\nEA_DISABLE_VC_WARNING(4530 4480 4571);\n\n// 4345 - Behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized\n// 4244 - Argument: conversion from 'int' to 'const eastl::vector<T>::value_type', possible loss of data\n// 4127 - Conditional expression is constant\nEA_DISABLE_VC_WARNING(4345 4244 4127);\n\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n#if EASTL_NOMINMAX\n\t#ifdef min\n\t\t#undef min\n\t#endif\n\t#ifdef max\n\t\t#undef max\n\t#endif\n#endif\n\nnamespace eastl\n{\n\n\t/// EASTL_VECTOR_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_VECTOR_DEFAULT_NAME\n\t\t#define EASTL_VECTOR_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" vector\" // Unless the user overrides something, this is \"EASTL vector\".\n\t#endif\n\n\n\t/// EASTL_VECTOR_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_VECTOR_DEFAULT_ALLOCATOR\n\t\t#define EASTL_VECTOR_DEFAULT_ALLOCATOR allocator_type(EASTL_VECTOR_DEFAULT_NAME)\n\t#endif\n\n\tnamespace internal\n\t{\n\t\ttemplate <class SizeType, class IntSourceType>\n\t\tinline void AssertValueFitsInType(IntSourceType n, const char* assertMessage)\n\t\t{\n\t\t\tEA_UNUSED(n);\n\t\t\tEA_UNUSED(assertMessage);\n\n\t\t\tEA_CONSTEXPR_IF (eastl::is_signed_v<IntSourceType>)\n\t\t\t\tEASTL_ASSERT_MSG(n >= 0, \"Attempting to initialize/insert a vector with a negative number of elements!\");\n\n\t\t\t[[maybe_unused]] constexpr bool kSizeTypeMaxIsEnough =\n\t\t\t    static_cast<uintmax_t>(eastl::numeric_limits<IntSourceType>::max()) <=\n\t\t\t    static_cast<uintmax_t>(eastl::numeric_limits<SizeType>::max());\n\t\t\tEASTL_ASSERT_MSG(\n\t\t\t    kSizeTypeMaxIsEnough || static_cast<IntSourceType>(eastl::numeric_limits<SizeType>::max()) >= n,\n\t\t\t    assertMessage);\n\t\t}\n\t} // namespace internal\n\n\n\t/// VectorBase\n\t///\n\t/// The reason we have a VectorBase class is that it makes exception handling\n\t/// simpler to implement because memory allocation is implemented entirely \n\t/// in this class. If a user creates a vector which needs to allocate\n\t/// memory in the constructor, VectorBase handles it. If an exception is thrown\n\t/// by the allocator then the exception throw jumps back to the user code and \n\t/// no try/catch code need be written in the vector or VectorBase constructor. \n\t/// If an exception is thrown in the vector (not VectorBase) constructor, the \n\t/// destructor for VectorBase will be called automatically (and free the allocated\n\t/// memory) before the execution jumps back to the user code.\n\t/// However, if the vector class were to handle both allocation and initialization\n\t/// then it would have no choice but to implement an explicit try/catch statement\n\t/// for all pathways that allocate memory. This increases code size and decreases\n\t/// performance and makes the code a little harder read and maintain.\n\t///\n\t/// The C++ standard (15.2 paragraph 2) states: \n\t///    \"An object that is partially constructed or partially destroyed will\n\t///     have destructors executed for all its fully constructed subobjects,\n\t///     that is, for subobjects for which the constructor has been completed\n\t///     execution and the destructor has not yet begun execution.\"\n\t///\n\t/// The C++ standard (15.3 paragraph 11) states: \n\t///    \"The fully constructed base classes and members of an object shall \n\t///     be destroyed before entering the handler of a function-try-block\n\t///     of a constructor or destructor for that block.\"\n\t///\n\ttemplate <typename T, typename Allocator>\n\tstruct VectorBase\n\t{\n\t\ttypedef Allocator    allocator_type;\n\t\ttypedef eastl_size_t size_type;\n\t\ttypedef ptrdiff_t    difference_type;\n\n\t\t#if defined(_MSC_VER) && (_MSC_VER >= 1400) && (_MSC_VER <= 1600) && !EASTL_STD_CPP_ONLY  // _MSC_VER of 1400 means VS2005, 1600 means VS2010. VS2012 generates errors with usage of enum:size_type.\n\t\t\tenum : size_type {                      // Use Microsoft enum language extension, allowing for smaller debug symbols than using a static const. Users have been affected by this.\n\t\t\t\tnpos     = (size_type)-1,\n\t\t\t\tkMaxSize = (size_type)-2\n\t\t\t};\n\t\t#else\n\t\t\tstatic const size_type npos     = (size_type)-1;      /// 'npos' means non-valid position or simply non-position.\n\t\t\tstatic const size_type kMaxSize = (size_type)-2;      /// -1 is reserved for 'npos'. It also happens to be slightly beneficial that kMaxSize is a value less than -1, as it helps us deal with potential integer wraparound issues.\n\t\t#endif\n\n\t\tsize_type GetNewCapacity(size_type currentSize);\n\n\tprotected:\n\t\tT*                                          mpBegin;\n\t\tT*                                          mpEnd;\n\t\teastl::compressed_pair<T*, allocator_type>  mCapacityAllocator;\n\n\t\tT*& internalCapacityPtr() EA_NOEXCEPT { return mCapacityAllocator.first(); }\n\t\tT* const& internalCapacityPtr() const EA_NOEXCEPT { return mCapacityAllocator.first(); }\n\t\tallocator_type&  internalAllocator() EA_NOEXCEPT { return mCapacityAllocator.second(); }\n\t\tconst allocator_type&  internalAllocator() const EA_NOEXCEPT { return mCapacityAllocator.second(); }\n\n\tpublic:\n\t\tVectorBase();\n\t\tVectorBase(const allocator_type& allocator);\n\t\tVectorBase(size_type n, const allocator_type& allocator);\n\n\t   ~VectorBase();\n\n\t\tconst allocator_type& get_allocator() const EA_NOEXCEPT;\n\t\tallocator_type&       get_allocator() EA_NOEXCEPT;\n\t\tvoid                  set_allocator(const allocator_type& allocator);\n\n\tprotected:\n\t\tT*        DoAllocate(size_type n);\n\t\tvoid      DoFree(T* p, size_type n);\n\n\t}; // VectorBase\n\n\n\n\n\t/// vector\n\t///\n\t/// Implements a dynamic array.\n\t///\n\ttemplate <typename T, typename Allocator = EASTLAllocatorType>\n\tclass vector : public VectorBase<T, Allocator>\n\t{\n\t\ttypedef VectorBase<T, Allocator>                      base_type;\n\t\ttypedef vector<T, Allocator>                          this_type;\n\n\t\ttemplate <class T2, class Allocator2, class U>\n\t\tfriend typename vector<T2, Allocator2>::size_type erase_unsorted(vector<T2, Allocator2>& c, const U& value);\n\n\t\ttemplate <class T2, class Allocator2, class P>\n\t\tfriend typename vector<T2, Allocator2>::size_type erase_unsorted_if(vector<T2, Allocator2>& c, P predicate);\n\n\tprotected:\n\t\tusing base_type::mpBegin;\n\t\tusing base_type::mpEnd;\n\t\tusing base_type::mCapacityAllocator;\n\t\tusing base_type::DoAllocate;\n\t\tusing base_type::DoFree;\n\t\tusing base_type::internalCapacityPtr;\n\t\tusing base_type::internalAllocator;\n\n\tpublic:\n\t\ttypedef T                                             value_type;\n\t\ttypedef T*                                            pointer;\n\t\ttypedef const T*                                      const_pointer;\n\t\ttypedef T&                                            reference;\n\t\ttypedef const T&                                      const_reference;  // Maintainer note: We want to leave iterator defined as T* -- at least in release builds -- as this gives some algorithms an advantage that optimizers cannot get around.\n\t\ttypedef T*                                            iterator;         // Note: iterator is simply T* right now, but this will likely change in the future, at least for debug builds. \n\t\ttypedef const T*                                      const_iterator;   //       Do not write code that relies on iterator being T*. The reason it will \n\t\ttypedef eastl::reverse_iterator<iterator>             reverse_iterator; //       change in the future is that a debugging iterator system will be created.\n\t\ttypedef eastl::reverse_iterator<const_iterator>       const_reverse_iterator;    \n\t\ttypedef typename base_type::size_type                 size_type;\n\t\ttypedef typename base_type::difference_type           difference_type;\n\t\ttypedef typename base_type::allocator_type            allocator_type;\n\n\t\tusing base_type::npos;\n\t\tusing base_type::GetNewCapacity;\n\n\t\tstatic_assert(!is_const<value_type>::value, \"vector<T> value_type must be non-const.\");\n\t\tstatic_assert(!is_volatile<value_type>::value, \"vector<T> value_type must be non-volatile.\");\n\n\tpublic:\n\t\tvector() EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(EASTL_VECTOR_DEFAULT_ALLOCATOR));\n\t\texplicit vector(const allocator_type& allocator) EA_NOEXCEPT;\n\t\texplicit vector(size_type n, const allocator_type& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR);\n\t\tvector(size_type n, const value_type& value, const allocator_type& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR);\n\t\tvector(const this_type& x);\n\t\tvector(const this_type& x, const allocator_type& allocator);\n\t\tvector(this_type&& x) EA_NOEXCEPT;\n\t\tvector(this_type&& x, const allocator_type& allocator);\n\t\tvector(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR);\n\n\t\t// note: this has pre-C++11 semantics:\n\t\t// this constructor is equivalent to the constructor vector(static_cast<size_type>(first), static_cast<value_type>(last), allocator) if InputIterator is an integral type.\n\t\ttemplate <typename InputIterator>\n\t\tvector(InputIterator first, InputIterator last, const allocator_type& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR);\n\n\t   ~vector();\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x); // TODO(c++17): noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value)\n\n\t\tvoid swap(this_type& x); // TODO(c++17): noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value)\n\n\t\tvoid assign(size_type n, const value_type& value);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid assign(InputIterator first, InputIterator last);\n\n\t\tvoid assign(std::initializer_list<value_type> ilist);\n\n\t\titerator       begin() EA_NOEXCEPT;\n\t\tconst_iterator begin() const EA_NOEXCEPT;\n\t\tconst_iterator cbegin() const EA_NOEXCEPT;\n\n\t\titerator       end() EA_NOEXCEPT;\n\t\tconst_iterator end() const EA_NOEXCEPT;\n\t\tconst_iterator cend() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rbegin() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crbegin() const EA_NOEXCEPT;\n\n\t\treverse_iterator       rend() EA_NOEXCEPT;\n\t\tconst_reverse_iterator rend() const EA_NOEXCEPT;\n\t\tconst_reverse_iterator crend() const EA_NOEXCEPT;\n\n\t\tbool      empty() const EA_NOEXCEPT;\n\t\tsize_type size() const EA_NOEXCEPT;\n\t\tsize_type capacity() const EA_NOEXCEPT;\n\n\t\tvoid resize(size_type n, const value_type& value);\n\t\tvoid resize(size_type n);\n\t\tvoid reserve(size_type n);\n\t\tvoid set_capacity(size_type n = base_type::npos);   // Revises the capacity to the user-specified value. Resizes the container to match the capacity if the requested capacity n is less than the current size. If n == npos then the capacity is reallocated (if necessary) such that capacity == size.\n\t\tvoid shrink_to_fit();                               // C++11 function which is the same as set_capacity().\n\n\t\tpointer       data() EA_NOEXCEPT;\n\t\tconst_pointer data() const EA_NOEXCEPT;\n\n\t\treference       operator[](size_type n);\n\t\tconst_reference operator[](size_type n) const;\n\n\t\treference       at(size_type n);\n\t\tconst_reference at(size_type n) const;\n\n\t\treference       front();\n\t\tconst_reference front() const;\n\n\t\treference       back();\n\t\tconst_reference back() const;\n\n\t\tvoid      push_back(const value_type& value);\n\t\treference push_back();\n\t\tvoid*     push_back_uninitialized();\n\t\tvoid      push_back(value_type&& value);\n\t\tvoid      pop_back();\n\n\t\ttemplate<class... Args>\n\t\titerator emplace(const_iterator position, Args&&... args);\n\n\t\ttemplate<class... Args>\n\t\treference emplace_back(Args&&... args);\n\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\titerator insert(const_iterator position, size_type n, const value_type& value);\n\t\titerator insert(const_iterator position, value_type&& value);\n\t\titerator insert(const_iterator position, std::initializer_list<value_type> ilist);\n\n\t\t// note: this has pre-C++11 semantics:\n\t\t// this function is equivalent to insert(const_iterator position, static_cast<size_type>(first), static_cast<value_type>(last)) if InputIterator is an integral type.\n\t\t// ie. same as insert(const_iterator position, size_type n, const value_type& value)\n\t\ttemplate <typename InputIterator>\n\t\titerator insert(const_iterator position, InputIterator first, InputIterator last);\n\n\t\titerator erase_first(const T& value);\n\t\titerator erase_first_unsorted(const T& value); // Same as erase, except it doesn't preserve order, but is faster because it simply copies the last item in the vector over the erased position.\n\t\treverse_iterator erase_last(const T& value);\n\t\treverse_iterator erase_last_unsorted(const T& value); // Same as erase, except it doesn't preserve order, but is faster because it simply copies the last item in the vector over the erased position.\n\n\t\titerator erase(const_iterator position);\n\t\titerator erase(const_iterator first, const_iterator last);\n\t\titerator erase_unsorted(const_iterator position);         // Same as erase, except it doesn't preserve order, but is faster because it simply copies the last item in the vector over the erased position.\n\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\t\treverse_iterator erase_unsorted(const_reverse_iterator position);\n\n\t\tvoid clear() EA_NOEXCEPT;\n\t\tvoid reset_lose_memory() EA_NOEXCEPT;                       // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tbool validate() const EA_NOEXCEPT;\n\t\tint  validate_iterator(const_iterator i) const EA_NOEXCEPT;\n\n\tprotected:\n\t\t// These functions do the real work of maintaining the vector. You will notice\n\t\t// that many of them have the same name but are specialized on iterator_tag\n\t\t// (iterator categories). This is because in these cases there is an optimized\n\t\t// implementation that can be had for some cases relative to others. Functions\n\t\t// which aren't referenced are neither compiled nor linked into the application.\n\t\ttemplate <bool bMove> struct should_move_or_copy_tag{};\n\t\tusing should_copy_tag = should_move_or_copy_tag<false>;\n\t\tusing should_move_tag = should_move_or_copy_tag<true>;\n\n\t\ttemplate <typename ForwardIterator> // Allocates a pointer of array count n and copy-constructs it with [first,last).\n\t\tpointer DoRealloc(size_type newCapacity, ForwardIterator first, ForwardIterator last, should_copy_tag);\n\n\t\ttemplate <typename ForwardIterator> // Allocates a pointer of array count n and copy-constructs it with [first,last).\n\t\tpointer DoRealloc(size_type newCapacity, ForwardIterator first, ForwardIterator last, should_move_tag);\n\n\t\ttemplate <typename Integer>\n\t\tvoid DoInit(Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoInit(InputIterator first, InputIterator last, false_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoInitFromIterator(InputIterator first, InputIterator last, eastl::input_iterator_tag);\n\n\t\ttemplate <typename ForwardIterator>\n\t\tvoid DoInitFromIterator(ForwardIterator first, ForwardIterator last, eastl::forward_iterator_tag);\n\n\t\ttemplate <typename Integer, bool bMove>\n\t\tvoid DoAssign(Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator, bool bMove>\n\t\tvoid DoAssign(InputIterator first, InputIterator last, false_type);\n\n\t\tvoid DoAssignValues(size_type n, const value_type& value);\n\n\t\ttemplate <typename InputIterator, bool bMove>\n\t\tvoid DoAssignFromIterator(InputIterator first, InputIterator last, eastl::input_iterator_tag);\n\n\t\ttemplate <typename RandomAccessIterator, bool bMove>\n\t\tvoid DoAssignFromIterator(RandomAccessIterator first, RandomAccessIterator last, eastl::random_access_iterator_tag);\n\n\t\ttemplate <typename Integer>\n\t\tvoid DoInsert(const_iterator position, Integer n, Integer value, true_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoInsert(const_iterator position, InputIterator first, InputIterator last, false_type);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid DoInsertFromIterator(const_iterator position, InputIterator first, InputIterator last, eastl::input_iterator_tag);\n\n\t\ttemplate <typename BidirectionalIterator>\n\t\tvoid DoInsertFromIterator(const_iterator position, BidirectionalIterator first, BidirectionalIterator last, eastl::bidirectional_iterator_tag);\n\n\t\tvoid DoInsertValues(const_iterator position, size_type n, const value_type& value);\n\n\t\tvoid DoInsertValuesEnd(size_type n); // Default constructs n values\n\t\tvoid DoInsertValuesEnd(size_type n, const value_type& value);\n\n\t\ttemplate<typename... Args>\n\t\tvoid DoInsertValue(const_iterator position, Args&&... args);\n\n\t\ttemplate<typename... Args>\n\t\tvoid DoInsertValueEnd(Args&&... args);\n\n\t\tvoid DoClearCapacity();\n\n\t\tvoid DoGrow(size_type newCapacity);\n\n\t\tvoid DoSwap(this_type& x);\n\n\t}; // class vector\n\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// VectorBase\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline VectorBase<T, Allocator>::VectorBase()\n\t\t: mpBegin(NULL), \n\t\t  mpEnd(NULL),\n\t\t  mCapacityAllocator(NULL, allocator_type(EASTL_VECTOR_DEFAULT_NAME))\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline VectorBase<T, Allocator>::VectorBase(const allocator_type& allocator)\n\t\t: mpBegin(NULL), \n\t\t  mpEnd(NULL),\n\t\t  mCapacityAllocator(NULL, allocator)\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline VectorBase<T, Allocator>::VectorBase(size_type n, const allocator_type& allocator)\n\t\t: mCapacityAllocator(allocator)\n\t{\n\t\tmpBegin    = DoAllocate(n);\n\t\tmpEnd      = mpBegin;\n\t\tinternalCapacityPtr() = mpBegin + n;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline VectorBase<T, Allocator>::~VectorBase()\n\t{\n\t\tif(mpBegin)\n\t\t\tEASTLFree(internalAllocator(), mpBegin, (internalCapacityPtr() - mpBegin) * sizeof(T));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline const typename VectorBase<T, Allocator>::allocator_type&\n\tVectorBase<T, Allocator>::get_allocator() const EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename VectorBase<T, Allocator>::allocator_type&\n\tVectorBase<T, Allocator>::get_allocator() EA_NOEXCEPT\n\t{\n\t\treturn internalAllocator();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void VectorBase<T, Allocator>::set_allocator(const allocator_type& allocator)\n\t{\n\t\tif(mpBegin != internalCapacityPtr() && internalAllocator() != allocator)\n\t\t\tEASTL_THROW_MSG_OR_ASSERT(std::logic_error, \"vector::set_allocator -- cannot change allocator after allocations have been made.\");\n\t\tinternalAllocator() = allocator;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline T* VectorBase<T, Allocator>::DoAllocate(size_type n)\n\t{\n\t\t// If n is zero, then we allocate no memory and just return nullptr. \n\t\t// This is fine, as our default ctor initializes with NULL pointers. \n\t\tif(EASTL_LIKELY(n))\n\t\t{\n\t\t\tauto* p = (T*)allocate_memory(internalAllocator(), n * sizeof(T), EASTL_ALIGN_OF(T), 0);\n\t\t\tEASTL_ASSERT_MSG(p != nullptr, \"the behaviour of eastl::allocators that return nullptr is not defined.\");\n\t\t\treturn p;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void VectorBase<T, Allocator>::DoFree(T* p, size_type n)\n\t{\n\t\tif(p)\n\t\t\tEASTLFree(internalAllocator(), p, n * sizeof(T)); \n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename VectorBase<T, Allocator>::size_type\n\tVectorBase<T, Allocator>::GetNewCapacity(size_type currentSize)\n\t{\n\t\t// This function must return a value larger than currentSize.\n\t\tif (currentSize > 0)\n\t\t{\n\t\t\tif (currentSize < (numeric_limits<size_type>::max() / 2))\n\t\t\t{\n\t\t\t\treturn 2 * currentSize;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tEASTL_ASSERT_MSG(currentSize < numeric_limits<size_type>::max(), \"Vector growth will overflow the value of the capacity! This is extremely bad!\");\n\t\t\t\treturn numeric_limits<size_type>::max();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// vector\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector() EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(EASTL_VECTOR_DEFAULT_ALLOCATOR))\n\t\t: base_type()\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(const allocator_type& allocator) EA_NOEXCEPT\n\t\t: base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(size_type n, const allocator_type& allocator)\n\t\t: base_type(n, allocator)\n\t{\n\t\teastl::uninitialized_value_construct_n(mpBegin, n);\n\t\tmpEnd = mpBegin + n;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(size_type n, const value_type& value, const allocator_type& allocator)\n\t\t: base_type(n, allocator)\n\t{\n\t\teastl::uninitialized_fill_n(mpBegin, n, value);\n\t\tmpEnd = mpBegin + n;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(const this_type& x)\n\t\t: base_type(x.size(), x.internalAllocator())\n\t{\n\t\tmpEnd = eastl::uninitialized_copy(x.mpBegin, x.mpEnd, mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(const this_type& x, const allocator_type& allocator)\n\t\t: base_type(x.size(), allocator)\n\t{\n\t\tmpEnd = eastl::uninitialized_copy(x.mpBegin, x.mpEnd, mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(this_type&& x) EA_NOEXCEPT\n\t\t: base_type(eastl::move(x.internalAllocator()))  // vector requires move-construction of allocator in this case.\n\t{\n\t\tDoSwap(x);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(this_type&& x, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tif (internalAllocator() == x.internalAllocator()) // If allocators are equivalent...\n\t\t\tDoSwap(x);\n\t\telse \n\t\t{\n\t\t\tthis_type temp(eastl::move(*this)); // move construct so we don't require the use of copy-ctors that prevent the use of move-only types.\n\t\t\ttemp.swap(x);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::vector(std::initializer_list<value_type> ilist, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInit(ilist.begin(), ilist.end(), false_type());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline vector<T, Allocator>::vector(InputIterator first, InputIterator last, const allocator_type& allocator)\n\t\t: base_type(allocator)\n\t{\n\t\tDoInit(first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline vector<T, Allocator>::~vector()\n\t{\n\t\t// Call destructor for the values. Parent class will free the memory.\n\t\teastl::destruct(mpBegin, mpEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename vector<T, Allocator>::this_type&\n\tvector<T, Allocator>::operator=(const this_type& x)\n\t{\n\t\tif(this != &x) // If not assigning to self...\n\t\t{\n\t\t\t// If (EASTL_ALLOCATOR_COPY_ENABLED == 1) and the current contents are allocated by an \n\t\t\t// allocator that's unequal to x's allocator, we need to reallocate our elements with \n\t\t\t// our current allocator and reallocate it with x's allocator. If the allocators are \n\t\t\t// equal then we can use a more optimal algorithm that doesn't reallocate our elements\n\t\t\t// but instead can copy them in place.\n\n\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\tbool bSlowerPathwayRequired = (internalAllocator() != x.internalAllocator());\n\t\t\t#else\n\t\t\t\tbool bSlowerPathwayRequired = false;\n\t\t\t#endif\n\n\t\t\tif(bSlowerPathwayRequired)\n\t\t\t{\n\t\t\t\tDoClearCapacity(); // Must clear the capacity instead of clear because set_capacity frees our memory, unlike clear.\n\n\t\t\t\t#if EASTL_ALLOCATOR_COPY_ENABLED\n\t\t\t\t\tinternalAllocator() = x.internalAllocator();\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tDoAssign<const_iterator, false>(x.begin(), x.end(), eastl::false_type());\n\t\t}\n\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename vector<T, Allocator>::this_type&\n\tvector<T, Allocator>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\ttypedef typename std::initializer_list<value_type>::iterator InputIterator;\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\tDoAssignFromIterator<InputIterator, false>(ilist.begin(), ilist.end(), IC()); // initializer_list has const elements and so we can't move from them.\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttypename vector<T, Allocator>::this_type&\n\tvector<T, Allocator>::operator=(this_type&& x)\n\t{\n\t\tif(this != &x)\n\t\t{\n\t\t\tDoClearCapacity(); // To consider: Are we really required to clear here? x is going away soon and will clear itself in its dtor.\n\t\t\tswap(x);           // member swap handles the case that x has a different allocator than our allocator by doing a copy.\n\t\t}\n\t\treturn *this; \n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::assign(size_type n, const value_type& value)\n\t{\n\t\tDoAssignValues(n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>                              \n\tinline void vector<T, Allocator>::assign(InputIterator first, InputIterator last)\n\t{\n\t\t// It turns out that the C++ std::vector<int, int> specifies a two argument\n\t\t// version of assign that takes (int size, int value). These are not iterators, \n\t\t// so we need to do a template compiler trick to do the right thing.\n\t\tDoAssign<InputIterator, false>(first, last, is_integral<InputIterator>());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::assign(std::initializer_list<value_type> ilist)\n\t{\n\t\ttypedef typename std::initializer_list<value_type>::iterator InputIterator;\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\tDoAssignFromIterator<InputIterator, false>(ilist.begin(), ilist.end(), IC()); // initializer_list has const elements and so we can't move from them.\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::begin() EA_NOEXCEPT\n\t{\n\t\treturn mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_iterator\n\tvector<T, Allocator>::begin() const EA_NOEXCEPT\n\t{\n\t\treturn mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_iterator\n\tvector<T, Allocator>::cbegin() const EA_NOEXCEPT\n\t{\n\t\treturn mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::end() EA_NOEXCEPT\n\t{\n\t\treturn mpEnd;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_iterator\n\tvector<T, Allocator>::end() const EA_NOEXCEPT\n\t{\n\t\treturn mpEnd;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_iterator\n\tvector<T, Allocator>::cend() const EA_NOEXCEPT\n\t{\n\t\treturn mpEnd;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reverse_iterator\n\tvector<T, Allocator>::rbegin() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(mpEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reverse_iterator\n\tvector<T, Allocator>::rbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mpEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reverse_iterator\n\tvector<T, Allocator>::crbegin() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mpEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reverse_iterator\n\tvector<T, Allocator>::rend() EA_NOEXCEPT\n\t{\n\t\treturn reverse_iterator(mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reverse_iterator\n\tvector<T, Allocator>::rend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reverse_iterator\n\tvector<T, Allocator>::crend() const EA_NOEXCEPT\n\t{\n\t\treturn const_reverse_iterator(mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tbool vector<T, Allocator>::empty() const EA_NOEXCEPT\n\t{\n\t\treturn (mpBegin == mpEnd);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::size_type\n\tvector<T, Allocator>::size() const EA_NOEXCEPT\n\t{\n\t\treturn (size_type)(mpEnd - mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::size_type\n\tvector<T, Allocator>::capacity() const EA_NOEXCEPT\n\t{\n\t\treturn (size_type)(internalCapacityPtr() - mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::resize(size_type n, const value_type& value)\n\t{\n\t\tif(n > (size_type)(mpEnd - mpBegin))  // We expect that more often than not, resizes will be upsizes.\n\t\t\tDoInsertValuesEnd(n - ((size_type)(mpEnd - mpBegin)), value);\n\t\telse\n\t\t{\n\t\t\teastl::destruct(mpBegin + n, mpEnd);\n\t\t\tmpEnd = mpBegin + n;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::resize(size_type n)\n\t{\n\t\t// Alternative implementation:\n\t\t// resize(n, value_type());\n\n\t\tif(n > (size_type)(mpEnd - mpBegin))  // We expect that more often than not, resizes will be upsizes.\n\t\t\tDoInsertValuesEnd(n - ((size_type)(mpEnd - mpBegin)));\n\t\telse\n\t\t{\n\t\t\teastl::destruct(mpBegin + n, mpEnd);\n\t\t\tmpEnd = mpBegin + n;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::reserve(size_type n)\n\t{\n\t\t// If the user wants to reduce the reserved memory, there is the set_capacity function.\n\t\tif(n > size_type(internalCapacityPtr() - mpBegin)) // If n > capacity ...\n\t\t\tDoGrow(n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::set_capacity(size_type n)\n\t{\n\t\tif((n == npos) || (n <= (size_type)(mpEnd - mpBegin))) // If new capacity <= size...\n\t\t{\n\t\t\tif(n == 0)  // Very often n will be 0, and clear will be faster than resize and use less stack space.\n\t\t\t\tclear();\n\t\t\telse if(n < (size_type)(mpEnd - mpBegin))\n\t\t\t\tresize(n);\n\n\t\t\tshrink_to_fit();\n\t\t}\n\t\telse // Else new capacity > size.\n\t\t{\n\t\t\tpointer const pNewData = DoRealloc(n, mpBegin, mpEnd, should_move_tag());\n\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\tconst ptrdiff_t nPrevSize = mpEnd - mpBegin;\n\t\t\tmpBegin    = pNewData;\n\t\t\tmpEnd      = pNewData + nPrevSize;\n\t\t\tinternalCapacityPtr() = mpBegin + n;\n\t\t}\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::shrink_to_fit()\n\t{\n\t\t// This is the simplest way to accomplish this, and it is as efficient as any other.\n\t\tthis_type temp = this_type(move_iterator<iterator>(begin()), move_iterator<iterator>(end()), internalAllocator());\n\n\t\t// Call DoSwap() rather than swap() as we know our allocators match and we don't want to invoke the code path\n\t\t// handling non matching allocators as it imposes additional restrictions on the type of T to be copyable\n\t\tDoSwap(temp);\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::pointer\n\tvector<T, Allocator>::data() EA_NOEXCEPT\n\t{\n\t\treturn mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_pointer\n\tvector<T, Allocator>::data() const EA_NOEXCEPT\n\t{\n\t\treturn mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reference\n\tvector<T, Allocator>::operator[](size_type n)\n\t{\n\t    #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(n >= (static_cast<size_type>(mpEnd - mpBegin))))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::operator[] -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t// We allow the user to use a reference to v[0] of an empty container. But this was merely grandfathered in and ideally we shouldn't allow such access to [0].\n\t\t\tif (EASTL_UNLIKELY((n != 0) && (n >= (static_cast<size_type>(mpEnd - mpBegin)))))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn *(mpBegin + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reference\n\tvector<T, Allocator>::operator[](size_type n) const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY(n >= (static_cast<size_type>(mpEnd - mpBegin))))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::operator[] -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\t// We allow the user to use a reference to v[0] of an empty container. But this was merely grandfathered in and ideally we shouldn't allow such access to [0].\n\t\t\tif (EASTL_UNLIKELY((n != 0) && (n >= (static_cast<size_type>(mpEnd - mpBegin)))))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::operator[] -- out of range\");\n\t\t#endif\n\n\t\treturn *(mpBegin + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reference\n\tvector<T, Allocator>::at(size_type n)\n\t{\n\t\t// The difference between at() and operator[] is it signals\n\t\t// the requested position is out of range by throwing an\n\t\t// out_of_range exception.\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= (static_cast<size_type>(mpEnd - mpBegin))))\n\t\t\t\tthrow std::out_of_range(\"vector::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= (static_cast<size_type>(mpEnd - mpBegin))))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::at -- out of range\");\n\t\t#endif\n\n\t\treturn *(mpBegin + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reference\n\tvector<T, Allocator>::at(size_type n) const\n\t{\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= (static_cast<size_type>(mpEnd - mpBegin))))\n\t\t\t\tthrow std::out_of_range(\"vector::at -- out of range\");\n\t\t#elif EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(n >= (static_cast<size_type>(mpEnd - mpBegin))))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::at -- out of range\");\n\t\t#endif\n\n\t\treturn *(mpBegin + n);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reference\n\tvector<T, Allocator>::front()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin))) // We don't allow the user to reference an empty container.\n\t\t\t\tEASTL_FAIL_MSG(\"vector::front -- empty vector\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn *mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reference\n\tvector<T, Allocator>::front() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED\n\t\t\tif (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin))) // We don't allow the user to reference an empty container.\n\t\t\t\tEASTL_FAIL_MSG(\"vector::front -- empty vector\");\n\t\t#else\n\t\t\t// We allow the user to reference an empty container.\n\t\t#endif\n\n\t\treturn *mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reference\n\tvector<T, Allocator>::back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t// if mpEnd is nullptr the expression (mpEnd - 1) is undefined behaviour.\n\t\t\t// any use of back() with an empty vector is thus conceptually wrong.\n\t\t\tif (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::back -- empty vector\");\n\t\t#endif\n\n\t\treturn *(mpEnd - 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::const_reference\n\tvector<T, Allocator>::back() const\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t// if mpEnd is nullptr the expression (mpEnd - 1) is undefined behaviour.\n\t\t\t// any use of back() with an empty vector is thus conceptually wrong.\n\t\t\tif (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::back -- empty vector\");\n\t\t#endif\n\n\t\treturn *(mpEnd - 1);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::push_back(const value_type& value)\n\t{\n\t\tif (mpEnd < internalCapacityPtr())\n\t\t\tdetail::allocator_construct(internalAllocator(), mpEnd++, value);\n\t\telse\n\t\t\tDoInsertValueEnd(value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::push_back(value_type&& value)\n\t{\n\t\tif (mpEnd < internalCapacityPtr())\n\t\t\tdetail::allocator_construct(internalAllocator(), mpEnd++, eastl::move(value));\n\t\telse\n\t\t\tDoInsertValueEnd(eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reference\n\tvector<T, Allocator>::push_back()\n\t{\n\t\tif(mpEnd < internalCapacityPtr())\n\t\t\tdetail::allocator_construct(internalAllocator(), mpEnd++);\n\t\telse\n\t\t\tDoInsertValueEnd();\n\n\t\treturn *(mpEnd - 1); // Same as return back();\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void* vector<T, Allocator>::push_back_uninitialized()\n\t{\n\t\tif(mpEnd == internalCapacityPtr())\n\t\t{\n\t\t\tconst size_type nPrevSize = size_type(mpEnd - mpBegin);\n\t\t\tconst size_type nNewCapacity  = GetNewCapacity(nPrevSize);\n\t\t\tDoGrow(nNewCapacity);\n\t\t}\n \n\t\treturn mpEnd++;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::pop_back()\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY(mpEnd <= mpBegin))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::pop_back -- empty vector\");\n\t\t#endif\n\n\t\t--mpEnd;\n\t\tmpEnd->~value_type();\n\t}\n\n\tEA_DISABLE_VC_WARNING(4702) // unreachable code: suppress warning because allocator_construct may always throw.\n\ttemplate <typename T, typename Allocator>\n\ttemplate<class... Args>\n\tinline typename vector<T, Allocator>::iterator \n\tvector<T, Allocator>::emplace(const_iterator position, Args&&... args)\n\t{\n\t\tconst ptrdiff_t n = position - mpBegin; // Save this because we might reallocate.\n\n\t\tif((mpEnd == internalCapacityPtr()) || (position != mpEnd))\n\t\t\tDoInsertValue(position, eastl::forward<Args>(args)...);\n\t\telse\n\t\t{\n\t\t\tdetail::allocator_construct(internalAllocator(), mpEnd, eastl::forward<Args>(args)...);\n\t\t\t++mpEnd; // Increment this after the construction above in case the construction throws an exception.\n\t\t}\n\n\t\treturn mpBegin + n;\n\t}\n\tEA_RESTORE_VC_WARNING()\n\n\tEA_DISABLE_VC_WARNING(4702) // unreachable code: suppress warning because allocator_construct may always throw.\n\ttemplate <typename T, typename Allocator>\n\ttemplate<class... Args>\n\tinline typename vector<T, Allocator>::reference\n\tvector<T, Allocator>::emplace_back(Args&&... args)\n\t{\n\t\tif(mpEnd < internalCapacityPtr())\n\t\t{\n\t\t\tdetail::allocator_construct(internalAllocator(), mpEnd, eastl::forward<Args>(args)...);\n\t\t\t++mpEnd; // Increment this after the construction above in case the construction throws an exception.\n\t\t}\n\t\telse\n\t\t\tDoInsertValueEnd(eastl::forward<Args>(args)...);\n\n\t\treturn back();\n\t}\n\tEA_RESTORE_VC_WARNING()\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::insert(const_iterator position, const value_type& value)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((position < mpBegin) || (position > mpEnd)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::insert -- invalid position\");\n\t\t#endif\n\n\t\t// We implment a quick pathway for the case that the insertion position is at the end and we have free capacity for it.\n\t\tconst ptrdiff_t n = position - mpBegin; // Save this because we might reallocate.\n\n\t\tif((mpEnd == internalCapacityPtr()) || (position != mpEnd))\n\t\t\tDoInsertValue(position, value);\n\t\telse\n\t\t{\n\t\t\tdetail::allocator_construct(internalAllocator(), mpEnd, value);\n\t\t\t++mpEnd; // Increment this after the construction above in case the construction throws an exception.\n\t\t}\n\n\t\treturn mpBegin + n;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>       \n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::insert(const_iterator position, value_type&& value)\n\t{\n\t\treturn emplace(position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::insert(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\tconst ptrdiff_t p = position - mpBegin; // Save this because we might reallocate.\n\t\tDoInsertValues(position, n, value);\n\t\treturn mpBegin + p;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::insert(const_iterator position, InputIterator first, InputIterator last)\n\t{\n\t\tconst ptrdiff_t n = position - mpBegin; // Save this because we might reallocate.\n\t\tDoInsert(position, first, last, is_integral<InputIterator>());\n\t\treturn mpBegin + n;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>       \n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::insert(const_iterator position, std::initializer_list<value_type> ilist)\n\t{\n\t\tconst ptrdiff_t n = position - mpBegin; // Save this because we might reallocate.\n\t\tDoInsert(position, ilist.begin(), ilist.end(), false_type());\n\t\treturn mpBegin + n;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::erase(const_iterator position)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((position < mpBegin) || (position >= mpEnd)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::erase -- invalid position\");\n\t\t#endif\n\n\t\t// C++11 stipulates that position is const_iterator, but the return value is iterator.\n\t\titerator destPosition = const_cast<value_type*>(position);        \n\n\t\tif((position + 1) < mpEnd)\n\t\t\teastl::move(destPosition + 1, mpEnd, destPosition);\n\t\t--mpEnd;\n\t\tmpEnd->~value_type();\n\t\treturn destPosition;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::erase(const_iterator first, const_iterator last)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((first < mpBegin) || (first > mpEnd) || (last < mpBegin) || (last > mpEnd) || (last < first)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::erase -- invalid position\");\n\t\t#endif\n \n\t\tif (first != last)\n\t\t{\n\t\t\titerator const position = const_cast<value_type*>(eastl::move(const_cast<value_type*>(last), const_cast<value_type*>(mpEnd), const_cast<value_type*>(first)));\n\t\t\teastl::destruct(position, mpEnd);\n\t\t\tmpEnd -= (last - first);\n\t\t}\n \n\t\treturn const_cast<value_type*>(first);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator\n\tvector<T, Allocator>::erase_unsorted(const_iterator position)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((position < mpBegin) || (position >= mpEnd)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::erase -- invalid position\");\n\t\t#endif\n\n\t\t// C++11 stipulates that position is const_iterator, but the return value is iterator.\n\t\titerator destPosition = const_cast<value_type*>(position);\n\t\t*destPosition = eastl::move(*(mpEnd - 1));\n\n\t\t// pop_back();\n\t\t--mpEnd;\n\t\tmpEnd->~value_type();\n\n\t\treturn destPosition;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator vector<T, Allocator>::erase_first(const T& value)\n\t{\n\t\tstatic_assert(eastl::has_equality_v<T>, \"T must be comparable\");\n\n\t\titerator it = eastl::find(begin(), end(), value);\n\n\t\tif (it != end())\n\t\t\treturn erase(it);\n\t\telse\n\t\t\treturn it;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::iterator \n\tvector<T, Allocator>::erase_first_unsorted(const T& value)\n\t{\n\t\tstatic_assert(eastl::has_equality_v<T>, \"T must be comparable\");\n\n\t\titerator it = eastl::find(begin(), end(), value);\n\n\t\tif (it != end())\n\t\t\treturn erase_unsorted(it);\n\t\telse\n\t\t\treturn it;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reverse_iterator \n\tvector<T, Allocator>::erase_last(const T& value)\n\t{\n\t\tstatic_assert(eastl::has_equality_v<T>, \"T must be comparable\");\n\n\t\treverse_iterator it = eastl::find(rbegin(), rend(), value);\n\n\t\tif (it != rend())\n\t\t\treturn erase(it);\n\t\telse\n\t\t\treturn it;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reverse_iterator \n\tvector<T, Allocator>::erase_last_unsorted(const T& value)\n\t{\n\t\tstatic_assert(eastl::has_equality_v<T>, \"T must be comparable\");\n\n\t\treverse_iterator it = eastl::find(rbegin(), rend(), value);\n\n\t\tif (it != rend())\n\t\t\treturn erase_unsorted(it);\n\t\telse\n\t\t\treturn it;\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reverse_iterator\n\tvector<T, Allocator>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase((++position).base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reverse_iterator\n\tvector<T, Allocator>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\t// Version which erases in order from first to last.\n\t\t// difference_type i(first.base() - last.base());\n\t\t// while(i--)\n\t\t//     first = erase(first);\n\t\t// return first;\n\n\t\t// Version which erases in order from last to first, but is slightly more efficient:\n\t\treturn reverse_iterator(erase(last.base(), first.base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline typename vector<T, Allocator>::reverse_iterator\n\tvector<T, Allocator>::erase_unsorted(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(erase_unsorted((++position).base()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::clear() EA_NOEXCEPT\n\t{\n\t\teastl::destruct(mpBegin, mpEnd);\n\t\tmpEnd = mpBegin;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::reset_lose_memory() EA_NOEXCEPT\n\t{\n\t\t// The reset function is a special extension function which unilaterally \n\t\t// resets the container to an empty state without freeing the memory of \n\t\t// the contained objects. This is useful for very quickly tearing down a \n\t\t// container built into scratch memory.\n\t\tmpBegin = mpEnd = internalCapacityPtr() = NULL;\n\t}\n\n\n\t// swap exchanges the contents of two containers. With respect to the containers allocators,\n\t// the C11++ Standard (23.2.1/7) states that the behavior of a call to a container's swap function \n\t// is undefined unless the objects being swapped have allocators that compare equal or \n\t// allocator_traits<allocator_type>::propagate_on_container_swap::value is true (propagate_on_container_swap\n\t// is false by default). EASTL doesn't have allocator_traits and so this doesn't directly apply,\n\t// but EASTL has the effective behavior of propagate_on_container_swap = true for all allocators. \n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::swap(this_type& x)\n\t{\n\t#if defined(EASTL_VECTOR_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR) && EASTL_VECTOR_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t\tif(internalAllocator() == x.internalAllocator()) // If allocators are equivalent...\n\t\t\tDoSwap(x);\n\t\telse // else swap the contents.\n\t\t{\n\t\t\tconst this_type temp(*this); // Can't call eastl::swap because that would\n\t\t\t*this = x;                   // itself call this member swap function.\n\t\t\tx     = temp;\n\t\t}\n\t#else\n\t\t// NOTE(rparolin): The previous implementation required T to be copy-constructible in the fall-back case where\n\t\t// allocators with unique instances copied elements.  This was an unnecessary restriction and prevented the common\n\t\t// usage of vector with non-copyable types (eg. eastl::vector<non_copyable> or eastl::vector<unique_ptr>). \n\t\t// \n\t\t// The previous implementation violated the following requirements of vector::swap so the fall-back code has\n\t\t// been removed.  EASTL implicitly defines 'propagate_on_container_swap = true' therefore the fall-back case is\n\t\t// not required.  We simply swap the contents and the allocator as that is the common expectation of\n\t\t// users and does not put the container into an invalid state since it can not free its memory via its current\n\t\t// allocator instance.\n\t\t//\n\t\t// http://en.cppreference.com/w/cpp/container/vector/swap\n\t\t// \"Exchanges the contents of the container with those of other. Does not invoke any move, copy, or swap\n\t\t// operations on individual elements.\"\n\t\t//\n\t    // http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer\n\t    // \"Swapping two containers with unequal allocators if propagate_on_container_swap is false is undefined\n\t    // behavior.\"\n\n\t\tDoSwap(x);\n\t#endif\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename ForwardIterator>\n\tinline typename vector<T, Allocator>::pointer\n\tvector<T, Allocator>::DoRealloc(size_type newCapacity, ForwardIterator first, ForwardIterator last, should_copy_tag)\n\t{\n\t\tT* const p = DoAllocate(newCapacity);      // p is of type T* but is not constructed. \n\t\teastl::uninitialized_copy(first, last, p); // copy-constructs p from [first,last).\n\t\treturn p;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename ForwardIterator>\n\tinline typename vector<T, Allocator>::pointer\n\tvector<T, Allocator>::DoRealloc(size_type newCapacity, ForwardIterator first, ForwardIterator last, should_move_tag)\n\t{\n\t\tT* const p = DoAllocate(newCapacity);                  // p is of type T* but is not constructed. \n\t\teastl::uninitialized_move_if_noexcept(first, last, p); // move-constructs p from [first,last).\n\t\treturn p;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Integer>\n\tinline void vector<T, Allocator>::DoInit(Integer n, Integer value, true_type)\n\t{\n\t\tinternal::AssertValueFitsInType<size_type>(\n\t\t    n, \"Attempting to initialize a vector larger than can fit in a size_type!\");\n\n\t\tmpBegin    = DoAllocate(static_cast<size_type>(n));\n\t\tinternalCapacityPtr() = mpBegin + n;\n\t\tmpEnd      = internalCapacityPtr();\n\n\t\teastl::uninitialized_fill_n(mpBegin, n, value);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline void vector<T, Allocator>::DoInit(InputIterator first, InputIterator last, false_type)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>:: iterator_category IC;\n\t\tDoInitFromIterator(first, last, IC());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline void vector<T, Allocator>::DoInitFromIterator(InputIterator first, InputIterator last, eastl::input_iterator_tag)\n\t{\n\t\t// To do: Use emplace_back instead of push_back(). Our emplace_back will work below without any ifdefs.\n\t\tfor(; first != last; ++first)  // InputIterators by definition actually only allow you to iterate through them once.\n\t\t\tpush_back(*first);        // Thus the standard *requires* that we do this (inefficient) implementation.\n\t}                                 // Luckily, InputIterators are in practice almost never used, so this code will likely never get executed.\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename ForwardIterator>\n\tinline void vector<T, Allocator>::DoInitFromIterator(ForwardIterator first, ForwardIterator last, eastl::forward_iterator_tag)\n\t{\n\t\tconst auto d = eastl::distance(first, last);\n\n\t\tinternal::AssertValueFitsInType<size_type>(\n\t\t    d, \"Attempting to initialize a vector larger than can fit in a size_type!\");\n\n\t\tconst size_type n = static_cast<size_type>(d);\n\t\tmpBegin = DoAllocate(n);\n\t\tinternalCapacityPtr() = mpBegin + n;\n\t\tmpEnd      = internalCapacityPtr();\n\n\t\teastl::uninitialized_copy(first, last, mpBegin);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Integer, bool bMove>\n\tinline void vector<T, Allocator>::DoAssign(Integer n, Integer value, true_type)\n\t{\n\t\tinternal::AssertValueFitsInType<size_type>(n, \"Attempting to assign more values than can fit in a size_type!\");\n\t\tDoAssignValues(static_cast<size_type>(n), static_cast<value_type>(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator, bool bMove>\n\tinline void vector<T, Allocator>::DoAssign(InputIterator first, InputIterator last, false_type)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\tDoAssignFromIterator<InputIterator, bMove>(first, last, IC());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::DoAssignValues(size_type n, const value_type& value)\n\t{\n\t\tif(n > size_type(internalCapacityPtr() - mpBegin)) // If n > capacity ...\n\t\t{\n\t\t\tthis_type temp(n, value, internalAllocator()); // We have little choice but to reallocate with new memory.\n\t\t\tswap(temp);\n\t\t}\n\t\telse if(n > size_type(mpEnd - mpBegin)) // If n > size ...\n\t\t{\n\t\t\teastl::fill(mpBegin, mpEnd, value);\n\t\t\teastl::uninitialized_fill_n(mpEnd, n - size_type(mpEnd - mpBegin), value);\n\t\t\tmpEnd += n - size_type(mpEnd - mpBegin);\n\t\t}\n\t\telse // else 0 <= n <= size\n\t\t{\n\t\t\teastl::fill_n(mpBegin, n, value);\n\t\t\terase(mpBegin + n, mpEnd);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator, bool bMove>\n\tvoid vector<T, Allocator>::DoAssignFromIterator(InputIterator first, InputIterator last, eastl::input_iterator_tag)\n\t{\n\t\titerator position(mpBegin);\n\n\t\twhile((position != mpEnd) && (first != last))\n\t\t{\n\t\t\t*position = *first;\n\t\t\t++first;\n\t\t\t++position;\n\t\t}\n\t\tif(first == last)\n\t\t\terase(position, mpEnd);\n\t\telse\n\t\t\tinsert(mpEnd, first, last);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename RandomAccessIterator, bool bMove>\n\tvoid vector<T, Allocator>::DoAssignFromIterator(RandomAccessIterator first, RandomAccessIterator last, eastl::random_access_iterator_tag)\n\t{\n\t\tconst auto d = eastl::distance(first, last);\n\t\tinternal::AssertValueFitsInType<size_type>(d, \"Attempting to assign more values than can fit in a size_type!\");\n\n\t\tconst size_type n = static_cast<size_type>(d);\n\n\t\tif(n > size_type(internalCapacityPtr() - mpBegin)) // If n > capacity ...\n\t\t{\n\t\t\tpointer const pNewData = DoRealloc(n, first, last, should_move_or_copy_tag<bMove>());\n\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\tmpBegin    = pNewData;\n\t\t\tmpEnd      = mpBegin + n;\n\t\t\tinternalCapacityPtr() = mpEnd;\n\t\t}\n\t\telse if(n <= size_type(mpEnd - mpBegin)) // If n <= size ...\n\t\t{\n\t\t\tpointer const pNewEnd = eastl::copy(first, last, mpBegin); // Since we are copying to mpBegin, we don't have to worry about needing copy_backward or a memmove-like copy (as opposed to memcpy-like copy).\n\t\t\teastl::destruct(pNewEnd, mpEnd);\n\t\t\tmpEnd = pNewEnd;\n\t\t}\n\t\telse // else size < n <= capacity\n\t\t{\n\t\t\tRandomAccessIterator position = first + (mpEnd - mpBegin);\n\t\t\teastl::copy(first, position, mpBegin); // Since we are copying to mpBegin, we don't have to worry about needing copy_backward or a memmove-like copy (as opposed to memcpy-like copy).\n\t\t\tmpEnd = eastl::uninitialized_copy(position, last, mpEnd);\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename Integer>\n\tinline void vector<T, Allocator>::DoInsert(const_iterator position, Integer n, Integer value, true_type)\n\t{\n\t\tinternal::AssertValueFitsInType<size_type>(\n\t\t    n, \"Attempting to insert more elements than can can fit in size_type!\");\n\n\t\tDoInsertValues(position, static_cast<size_type>(n), static_cast<value_type>(value));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline void vector<T, Allocator>::DoInsert(const_iterator position, InputIterator first, InputIterator last, false_type)\n\t{\n\t\ttypedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;\n\t\tDoInsertFromIterator(position, first, last, IC());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename InputIterator>\n\tinline void vector<T, Allocator>::DoInsertFromIterator(const_iterator position, InputIterator first, InputIterator last, eastl::input_iterator_tag)\n\t{\n\t\tfor(; first != last; ++first, ++position)\n\t\t\tposition = insert(position, *first);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate <typename BidirectionalIterator>\n\tvoid vector<T, Allocator>::DoInsertFromIterator(const_iterator position, BidirectionalIterator first, BidirectionalIterator last, eastl::bidirectional_iterator_tag)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((position < mpBegin) || (position > mpEnd)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::insert -- invalid position\");\n\t\t#endif\n\n\t\t// C++11 stipulates that position is const_iterator, but the return value is iterator.\n\t\titerator destPosition = const_cast<value_type*>(position);\n\n\t\tif(first != last)\n\t\t{\n\t\t\tconst auto d = eastl::distance(first, last);\n\t\t\tinternal::AssertValueFitsInType<size_type>(d, \"Attempting to insert more elements than can fit in a vector.\");\n\n\t\t\tconst size_type n = static_cast<size_type>(d);  // n is the number of elements we are inserting.\n\n\t\t\tif(n <= size_type(internalCapacityPtr() - mpEnd)) // If n fits within the existing capacity...\n\t\t\t{\n\t\t\t\tconst size_type nExtra = static_cast<size_type>(mpEnd - destPosition);\n\n\t\t\t\tif(n < nExtra) // If the inserted values are entirely within initialized memory (i.e. are before mpEnd)...\n\t\t\t\t{\n\t\t\t\t\teastl::uninitialized_move(mpEnd - n, mpEnd, mpEnd);\n\t\t\t\t\teastl::move_backward(destPosition, mpEnd - n, mpEnd); // We need move_backward because of potential overlap issues.\n\t\t\t\t\teastl::copy(first, last, destPosition);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tBidirectionalIterator iTemp = first;\n\t\t\t\t\teastl::advance(iTemp, nExtra);\n\t\t\t\t\teastl::uninitialized_copy(iTemp, last, mpEnd);\n\t\t\t\t\teastl::uninitialized_move(destPosition, mpEnd, mpEnd + n - nExtra);\n\t\t\t\t\teastl::copy_backward(first, iTemp, destPosition + nExtra);\n\t\t\t\t}\n\n\t\t\t\tmpEnd += n;\n\t\t\t}\n\t\t\telse // else we need to expand our capacity.\n\t\t\t{\n\t\t\t\tconst size_type nPrevSize = size_type(mpEnd - mpBegin);\n\t\t\t\tconst size_type nGrowCapacity = GetNewCapacity(nPrevSize);\n\t\t\t\tEASTL_ASSERT_MSG(nPrevSize <= eastl::numeric_limits<size_type>::max() - n, \"Size overflow: Attempting to insert more elements than can fit in a vector.\");\n\t\t\t\tconst size_type nNewCapacity = eastl::max(nGrowCapacity, nPrevSize + n);\n\t\t\t\tpointer const   pNewData  = DoAllocate(nNewCapacity);\n\n\t\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\t\tpointer pNewEnd = pNewData;\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(mpBegin, destPosition, pNewData);\n\t\t\t\t\t\tpNewEnd = eastl::uninitialized_copy(first, last, pNewEnd);\n\t\t\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(destPosition, mpEnd, pNewEnd);\n\t\t\t\t\t}\n\t\t\t\t\tcatch(...)\n\t\t\t\t\t{\n\t\t\t\t\t\teastl::destruct(pNewData, pNewEnd);\n\t\t\t\t\t\tDoFree(pNewData, nNewCapacity);\n\t\t\t\t\t\tthrow;\n\t\t\t\t\t}\n\t\t\t\t#else\n\t\t\t\t\tpointer pNewEnd = eastl::uninitialized_move(mpBegin, destPosition, pNewData);\n\t\t\t\t\tpNewEnd         = eastl::uninitialized_copy(first, last, pNewEnd);\n\t\t\t\t\tpNewEnd         = eastl::uninitialized_move(destPosition, mpEnd, pNewEnd);\n\t\t\t\t#endif\n\n\t\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\t\tmpBegin    = pNewData;\n\t\t\t\tmpEnd      = pNewEnd;\n\t\t\t\tinternalCapacityPtr() = pNewData + nNewCapacity;\n\t\t\t}\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::DoInsertValues(const_iterator position, size_type n, const value_type& value)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((position < mpBegin) || (position > mpEnd)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::insert -- invalid position\");\n\t\t#endif\n\n\t\t// C++11 stipulates that position is const_iterator, but the return value is iterator.\n\t\titerator destPosition = const_cast<value_type*>(position);\n\n\t\tif(n <= size_type(internalCapacityPtr() - mpEnd)) // If n is <= capacity...\n\t\t{\n\t\t\tif(n > 0) // To do: See if there is a way we can eliminate this 'if' statement.\n\t\t\t{\n\t\t\t\t// To consider: Make this algorithm work more like DoInsertValue whereby a pointer to value is used.\n\t\t\t\tconst value_type temp  = value;\n\t\t\t\tconst size_type nExtra = static_cast<size_type>(mpEnd - destPosition);\n\n\t\t\t\tif(n < nExtra)\n\t\t\t\t{\n\t\t\t\t\teastl::uninitialized_move(mpEnd - n, mpEnd, mpEnd);\n\t\t\t\t\teastl::move_backward(destPosition, mpEnd - n, mpEnd); // We need move_backward because of potential overlap issues.\n\t\t\t\t\teastl::fill(destPosition, destPosition + n, temp);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\teastl::uninitialized_fill_n(mpEnd, n - nExtra, temp);\n\t\t\t\t\teastl::uninitialized_move(destPosition, mpEnd, mpEnd + n - nExtra);\n\t\t\t\t\teastl::fill(destPosition, mpEnd, temp);\n\t\t\t\t}\n\n\t\t\t\tmpEnd += n;\n\t\t\t}\n\t\t}\n\t\telse // else n > capacity\n\t\t{\n\t\t\tconst size_type nPrevSize = size_type(mpEnd - mpBegin);\n\t\t\tconst size_type nGrowCapacity = GetNewCapacity(nPrevSize);\n\t\t\tEASTL_ASSERT_MSG(nPrevSize <= eastl::numeric_limits<size_type>::max() - n, \"Size overflow: Attempting to insert more elements than can fit in a vector.\");\n\t\t\tconst size_type nNewCapacity  = eastl::max(nGrowCapacity, nPrevSize + n);\n\t\t\tpointer const pNewData    = DoAllocate(nNewCapacity);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tpointer pNewEnd = pNewData;\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(mpBegin, destPosition, pNewData);\n\t\t\t\t\teastl::uninitialized_fill_n(pNewEnd, n, value);\n\t\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(destPosition, mpEnd, pNewEnd + n);\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\teastl::destruct(pNewData, pNewEnd);\n\t\t\t\t\tDoFree(pNewData, nNewCapacity);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tpointer pNewEnd = eastl::uninitialized_move(mpBegin, destPosition, pNewData);\n\t\t\t\teastl::uninitialized_fill_n(pNewEnd, n, value);\n\t\t\t\tpNewEnd = eastl::uninitialized_move(destPosition, mpEnd, pNewEnd + n);\n\t\t\t#endif\n\n\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\tmpBegin    = pNewData;\n\t\t\tmpEnd      = pNewEnd;\n\t\t\tinternalCapacityPtr() = pNewData + nNewCapacity;\n\t\t}\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::DoClearCapacity() // This function exists because set_capacity() currently indirectly requires value_type to be default-constructible, \n\t{                                            // and some functions that need to clear our capacity (e.g. operator=) aren't supposed to require default-constructibility. \n\t\tclear();\n\t\tthis_type temp(eastl::move(*this));  // This is the simplest way to accomplish this, \n\t\tswap(temp);                          // and it is as efficient as any other.\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::DoGrow(size_type newCapacity)\n\t{\n\t\tpointer const pNewData = DoAllocate(newCapacity);\n\n\t\tpointer pNewEnd = eastl::uninitialized_move_if_noexcept(mpBegin, mpEnd, pNewData);\n\n\t\teastl::destruct(mpBegin, mpEnd);\n\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\tmpBegin    = pNewData;\n\t\tmpEnd      = pNewEnd;\n\t\tinternalCapacityPtr() = pNewData + newCapacity;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline void vector<T, Allocator>::DoSwap(this_type& x)\n\t{\n\t\teastl::swap(mpBegin,    x.mpBegin);\n\t\teastl::swap(mpEnd,      x.mpEnd);\n\t\teastl::swap(mCapacityAllocator, x.mCapacityAllocator); // We do this even if EASTL_ALLOCATOR_COPY_ENABLED is 0.\n\t}\n\n\t// The code duplication between this and the version that takes no value argument and default constructs the values\n\t// is unfortunate but not easily resolved without relying on C++11 perfect forwarding.\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::DoInsertValuesEnd(size_type n, const value_type& value)\n\t{\n\t\tif(n > size_type(internalCapacityPtr() - mpEnd))\n\t\t{\n\t\t\tconst size_type nPrevSize = size_type(mpEnd - mpBegin);\n\t\t\tconst size_type nGrowCapacity = GetNewCapacity(nPrevSize);\n\t\t\tEASTL_ASSERT_MSG(nPrevSize <= eastl::numeric_limits<size_type>::max() - n, \"Size overflow: Attempting to insert more elements than can fit in a vector.\");\n\t\t\tconst size_type nNewCapacity = eastl::max(nGrowCapacity, nPrevSize + n);\n\t\t\tpointer const pNewData = DoAllocate(nNewCapacity);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tpointer pNewEnd = pNewData; // Assign pNewEnd a value here in case the copy throws.\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(mpBegin, mpEnd, pNewData);\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\teastl::destruct(pNewData, pNewEnd);\n\t\t\t\t\tDoFree(pNewData, nNewCapacity);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tpointer pNewEnd = eastl::uninitialized_move(mpBegin, mpEnd, pNewData);\n\t\t\t#endif\n\n\t\t\teastl::uninitialized_fill_n(pNewEnd, n, value);\n\t\t\tpNewEnd += n;\n\n\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\tmpBegin    = pNewData;\n\t\t\tmpEnd      = pNewEnd;\n\t\t\tinternalCapacityPtr() = pNewData + nNewCapacity;\n\t\t}\n\t\telse\n\t\t{\n\t\t\teastl::uninitialized_fill_n(mpEnd, n, value);\n\t\t\tmpEnd += n;\n\t\t}\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\tvoid vector<T, Allocator>::DoInsertValuesEnd(size_type n)\n\t{\n\t\tif (n > size_type(internalCapacityPtr() - mpEnd))\n\t\t{\n\t\t\tconst size_type nPrevSize = size_type(mpEnd - mpBegin);\n\t\t\tconst size_type nGrowCapacity = GetNewCapacity(nPrevSize);\n\t\t\tEASTL_ASSERT_MSG(nPrevSize <= eastl::numeric_limits<size_type>::max() - n, \"Size overflow: Attempting to insert more elements than can fit in a vector.\");\n\t\t\tconst size_type nNewCapacity = eastl::max(nGrowCapacity, nPrevSize + n);\n\t\t\tpointer const pNewData = DoAllocate(nNewCapacity);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tpointer pNewEnd = pNewData;  // Assign pNewEnd a value here in case the copy throws.\n\t\t\t\ttry { pNewEnd = eastl::uninitialized_move_if_noexcept(mpBegin, mpEnd, pNewData); }\n\t\t\t\tcatch (...)\n\t\t\t\t{\n\t\t\t\t\teastl::destruct(pNewData, pNewEnd);\n\t\t\t\t\tDoFree(pNewData, nNewCapacity);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tpointer pNewEnd = eastl::uninitialized_move(mpBegin, mpEnd, pNewData);\n\t\t\t#endif\n\n\t\t\teastl::uninitialized_value_construct_n(pNewEnd, n);\n\t\t\tpNewEnd += n;\n\n\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\tmpBegin = pNewData;\n\t\t\tmpEnd = pNewEnd;\n\t\t\tinternalCapacityPtr() = pNewData + nNewCapacity;\n\t\t}\n\t\telse\n\t\t{\n\t\t\teastl::uninitialized_value_construct_n(mpEnd, n);\n\t\t\tmpEnd += n;\n\t\t}\n\t}\n\n\ttemplate <typename T, typename Allocator>\n\ttemplate<typename... Args>\n\tvoid vector<T, Allocator>::DoInsertValue(const_iterator position, Args&&... args)\n\t{\n\t\t// To consider: It's feasible that the args is from a value_type comes from within the current sequence itself and \n\t\t// so we need to be sure to handle that case. This is different from insert(position, const value_type&) because in \n\t\t// this case value is potentially being modified.\n\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\tif(EASTL_UNLIKELY((position < mpBegin) || (position > mpEnd)))\n\t\t\t\tEASTL_FAIL_MSG(\"vector::insert/emplace -- invalid position\");\n\t\t#endif\n\n\t\t// C++11 stipulates that position is const_iterator, but the return value is iterator.\n\t\titerator destPosition = const_cast<value_type*>(position);\n\n\t\tif(mpEnd != internalCapacityPtr()) // If size < capacity ...\n\t\t{\n\t\t\t// We need to take into account the possibility that args is a value_type that comes from within the vector itself.\n\t\t\t// creating a temporary value on the stack here is not an optimal way to solve this because sizeof(value_type) may be\n\t\t\t// too much for the given platform. An alternative solution may be to specialize this function for the case of the\n\t\t\t// argument being const value_type& or value_type&&.\n\t\t\tEASTL_ASSERT(position < mpEnd);                                 // While insert at end() is valid, our design is such that calling code should handle that case before getting here, as our streamlined logic directly doesn't handle this particular case due to resulting negative ranges.\n\t\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\t\tauto value = value_type(eastl::forward<Args>(args)...);     // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t\t#else\n\t\t\t\tvalue_type  value(eastl::forward<Args>(args)...);           // Need to do this before the move_backward below because maybe args refers to something within the moving range.\n\t\t\t#endif\n\t\t\tdetail::allocator_construct(internalAllocator(), mpEnd, eastl::move(*(mpEnd - 1))); // mpEnd is uninitialized memory, so we must construct into it instead of move into it like we do with the other elements below.\n\t\t\teastl::move_backward(destPosition, mpEnd - 1, mpEnd);           // We need to go backward because of potential overlap issues.\n\t\t\teastl::destruct(destPosition);\n\t\t\tdetail::allocator_construct(internalAllocator(), destPosition, eastl::move(value)); // Move the value argument to the given position.\n\t\t\t++mpEnd;\n\t\t}\n\t\telse // else (size == capacity)\n\t\t{\n\t\t\tconst size_type nPosSize  = size_type(destPosition - mpBegin); // Index of the insertion position.\n\t\t\tconst size_type nPrevSize = size_type(mpEnd - mpBegin);\n\t\t\tconst size_type nNewCapacity = GetNewCapacity(nPrevSize);\n\t\t\tpointer const pNewData = DoAllocate(nNewCapacity);\n\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tpointer pNewEnd = pNewData;\n\t\t\t\ttry\n\t\t\t\t{   // To do: We are not handling exceptions properly below.  In particular we don't want to \n\t\t\t\t\t// call eastl::destruct on the entire range if only the first part of the range was constructed.\n\t\t\t\t\tdetail::allocator_construct(internalAllocator(), pNewData + nPosSize, eastl::forward<Args>(args)...); // Because the old data is potentially being moved rather than copied, we need to move.\n\t\t\t\t\tpNewEnd = NULL;                                                                             // Set to NULL so that in catch we can tell the exception occurred during the next call.\n\t\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(mpBegin, destPosition, pNewData);           // the value first, because it might possibly be a reference to the old data being moved.\n\t\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(destPosition, mpEnd, ++pNewEnd);\n\t\t\t\t}\n\t\t\t\tcatch(...)\n\t\t\t\t{\n\t\t\t\t\tif(pNewEnd)\n\t\t\t\t\t\teastl::destruct(pNewData, pNewEnd);                                         // Destroy what has been constructed so far.\n\t\t\t\t\telse\n\t\t\t\t\t\teastl::destruct(pNewData + nPosSize);                                       // The exception occurred during the first uninitialized move, so destroy only the value at nPosSize.\n\t\t\t\t    DoFree(pNewData, nNewCapacity);\n\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t#else\n\t\t\t\tdetail::allocator_construct(internalAllocator(), pNewData + nPosSize, eastl::forward<Args>(args)...); // Because the old data is potentially being moved rather than copied, we need to move\n\t\t\t\tpointer pNewEnd = eastl::uninitialized_move(mpBegin, destPosition, pNewData);\t\t\t\t\t// the value first, because it might possibly be a reference to the old data being moved.\n\t\t\t\tpNewEnd = eastl::uninitialized_move(destPosition, mpEnd, ++pNewEnd);\n\t\t\t#endif\n\n\t\t\teastl::destruct(mpBegin, mpEnd);\n\t\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\t\tmpBegin    = pNewData;\n\t\t\tmpEnd      = pNewEnd;\n\t\t\tinternalCapacityPtr() = pNewData + nNewCapacity;\n\t\t}\n\t}\n\n\t// assumes mpEnd == internalCapacityPtr(), ie. create a new array and move existing elements into it while inserting the new element at the end.\n\ttemplate <typename T, typename Allocator>\n\ttemplate<typename... Args>\n\tvoid vector<T, Allocator>::DoInsertValueEnd(Args&&... args)\n\t{\n\t\tconst size_type nPrevSize = size_type(mpEnd - mpBegin);\n\t\tconst size_type nNewCapacity = GetNewCapacity(nPrevSize);\n\t\tpointer const   pNewData  = DoAllocate(nNewCapacity);\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tpointer pNewEnd;\n\t\t\ttry\n\t\t    {\n\t\t\t    detail::allocator_construct(internalAllocator(), pNewData + nPrevSize, eastl::forward<Args>(args)...);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t    {\n\t\t\t    DoFree(pNewData, nNewCapacity);\n\t\t\t    throw;\n\t\t\t}\n\n\t\t\ttry\n\t\t\t{\n\t\t\t\tpNewEnd = eastl::uninitialized_move_if_noexcept(mpBegin, mpEnd, pNewData);\n\t\t\t\tpNewEnd++;\n\t\t\t}\n\t\t\tcatch(...)\n\t\t    {\n\t\t\t    eastl::destroy_at(pNewData + nPrevSize);\n\t\t\t\t// if uninitialized_move_if_noexcept throws, then it must also have destroyed any elements it constructed.\n\t\t\t\t// ie. pNewData does not contain any objects here, nothing to destroy.\n\t\t\t\tDoFree(pNewData, nNewCapacity);\n\t\t\t\tthrow;\n\t\t\t}\n\t\t#else\n\t\t\t// Because args... may potentially reference an element (or its sub-object) of this vector, we need to construct\n\t\t\t// the new element first, prior to moving it (leaving it in an unspecified state) with the call to uninitialized_move.\n\t\t\tdetail::allocator_construct(internalAllocator(), pNewData + nPrevSize, eastl::forward<Args>(args)...);\n\t\t\tpointer pNewEnd = eastl::uninitialized_move(mpBegin, mpEnd, pNewData);\n\t\t\tpNewEnd++;\n\t\t#endif\n\n\t\teastl::destruct(mpBegin, mpEnd);\n\t\tDoFree(mpBegin, (size_type)(internalCapacityPtr() - mpBegin));\n\n\t\tmpBegin    = pNewData;\n\t\tmpEnd      = pNewEnd;\n\t\tinternalCapacityPtr() = pNewData + nNewCapacity;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool vector<T, Allocator>::validate() const EA_NOEXCEPT\n\t{\n\t\tif(mpEnd < mpBegin)\n\t\t\treturn false;\n\t\tif(internalCapacityPtr() < mpEnd)\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline int vector<T, Allocator>::validate_iterator(const_iterator i) const EA_NOEXCEPT\n\t{\n\t\tif(i >= mpBegin)\n\t\t{\n\t\t\tif(i < mpEnd)\n\t\t\t\treturn (isf_valid | isf_current | isf_can_dereference);\n\n\t\t\tif(i <= mpEnd)\n\t\t\t\treturn (isf_valid | isf_current);\n\t\t}\n\n\t\treturn isf_none;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator==(const vector<T, Allocator>& a, const vector<T, Allocator>& b)\n\t{\n\t\treturn ((a.size() == b.size()) && eastl::equal(a.begin(), a.end(), b.begin()));\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\ttemplate <typename T, typename Allocator>\n\tinline synth_three_way_result<T> operator<=>(const vector<T, Allocator>& a, const vector<T, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(), synth_three_way{});\n\t}\n#else\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator!=(const vector<T, Allocator>& a, const vector<T, Allocator>& b)\n\t{\n\t\treturn ((a.size() != b.size()) || !eastl::equal(a.begin(), a.end(), b.begin()));\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<(const vector<T, Allocator>& a, const vector<T, Allocator>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>(const vector<T, Allocator>& a, const vector<T, Allocator>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator<=(const vector<T, Allocator>& a, const vector<T, Allocator>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename T, typename Allocator>\n\tinline bool operator>=(const vector<T, Allocator>& a, const vector<T, Allocator>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n#endif\n\n\ttemplate <typename T, typename Allocator>\n\tinline void swap(vector<T, Allocator>& a, vector<T, Allocator>& b) EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(a.swap(b)))\n\t{\n\t\ta.swap(b);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase / erase_if\n\t// \n\t// https://en.cppreference.com/w/cpp/container/vector/erase2\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class T, class Allocator, class U>\n\ttypename vector<T, Allocator>::size_type erase(vector<T, Allocator>& c, const U& value)\n\t{\n\t\t// Erases all elements that compare equal to value from the container. \n\t\tauto origEnd = c.end();\n\t\tauto newEnd = eastl::remove(c.begin(), origEnd, value);\n\t\tauto numRemoved = eastl::distance(newEnd, origEnd);\n\t\tc.erase(newEnd, origEnd);\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the vector\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename vector<T, Allocator>::size_type>(numRemoved);\n\t}\n\n\ttemplate <class T, class Allocator, class Predicate>\n\ttypename vector<T, Allocator>::size_type erase_if(vector<T, Allocator>& c, Predicate predicate)\n\t{\n\t\t// Erases all elements that satisfy the predicate pred from the container. \n\t\tauto origEnd = c.end();\n\t\tauto newEnd = eastl::remove_if(c.begin(), origEnd, predicate);\n\t\tauto numRemoved = eastl::distance(newEnd, origEnd);\n\t\tc.erase(newEnd, origEnd);\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the vector\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename vector<T, Allocator>::size_type>(numRemoved);\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_unsorted\n\t// \n\t// This serves a similar purpose as erase above but with the difference\n\t// that it doesn't preserve the relative order of what is left in the\n\t// vector.\n\t//\n\t// Effects: Removes all elements equal to value from the vector while\n\t// optimizing for speed with the potential reordering of elements as a\n\t// side effect.\n\t//\n\t// Complexity: Linear\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class T, class Allocator, class U>\n\ttypename vector<T, Allocator>::size_type erase_unsorted(vector<T, Allocator>& c, const U& value)\n\t{\n\t\tauto itRemove = c.begin();\n\t\tauto ritMove = c.rbegin();\n\n\t\twhile(true)\n\t\t{\n\t\t\titRemove = eastl::find(itRemove, ritMove.base(), value);\n\t\t\tif (itRemove == ritMove.base()) // any elements to remove?\n\t\t\t\tbreak;\n\n\t\t\tritMove = eastl::find_if(ritMove, eastl::make_reverse_iterator(itRemove), [&value](const T& elem) { return elem != value; });\n\t\t\tif (itRemove == ritMove.base()) // any elements that can be moved into place?\n\t\t\t\tbreak;\n\n\t\t\t*itRemove = eastl::move(*ritMove);\n\t\t\t++itRemove;\n\t\t\t++ritMove;\n\t\t}\n\n\t\t// now all elements in the range [itRemove, c.end()) are either to be removed or have already been moved from.\n\n\t\tauto numRemoved = eastl::distance(itRemove, c.end());\n\n\t\teastl::destruct(itRemove, c.end());\n\t\tc.mpEnd = itRemove;\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the vector\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename vector<T, Allocator>::size_type>(numRemoved);\n\t}\n\n\t///////////////////////////////////////////////////////////////////////\n\t// erase_unsorted_if\n\t// \n\t// This serves a similar purpose as erase_if above but with the\n\t// difference that it doesn't preserve the relative order of what is\n\t// left in the vector.\n\t//\n\t// Effects: Removes all elements that return true for the predicate\n\t// while optimizing for speed with the potential reordering of elements\n\t// as a side effect.\n\t//\n\t// Complexity: Linear\n\t//\n\t///////////////////////////////////////////////////////////////////////\n\ttemplate <class T, class Allocator, class Predicate>\n\ttypename vector<T, Allocator>::size_type erase_unsorted_if(vector<T, Allocator>& c, Predicate predicate)\n\t{\n\t\t// Erases all elements that satisfy predicate from the container. \n\t\tauto itRemove = c.begin();\n\t\tauto ritMove = c.rbegin();\n\n\t\twhile(true)\n\t\t{\n\t\t\titRemove = eastl::find_if(itRemove, ritMove.base(), predicate);\n\t\t\tif (itRemove == ritMove.base()) // any elements to remove?\n\t\t\t\tbreak;\n\n\t\t\tritMove = eastl::find_if(ritMove, eastl::make_reverse_iterator(itRemove), not_fn(predicate));\n\t\t\tif (itRemove == ritMove.base()) // any elements that can be moved into place?\n\t\t\t\tbreak;\n\n\t\t\t*itRemove = eastl::move(*ritMove);\n\t\t\t++itRemove;\n\t\t\t++ritMove;\n\t\t}\n\n\t\t// now all elements in the range [itRemove, c.end()) are either to be removed or have already been moved from.\n\n\t\tauto numRemoved = eastl::distance(itRemove, c.end());\n\n\t\teastl::destruct(itRemove, c.end());\n\t\tc.mpEnd = itRemove;\n\n\t\t// Note: This is technically a lossy conversion when size_type\n\t\t// is 32bits and ptrdiff_t is 64bits (could happen on 64bit\n\t\t// systems when EASTL_SIZE_T_32BIT is set). In practice this\n\t\t// is fine because if EASTL_SIZE_T_32BIT is set then the vector\n\t\t// should not have more elements than fit in a uint32_t and so\n\t\t// the distance here should fit in a size_type.\n\t\treturn static_cast<typename vector<T, Allocator>::size_type>(numRemoved);\n\t}\n\n} // namespace eastl\n\n\nEA_RESTORE_VC_WARNING();\nEA_RESTORE_VC_WARNING();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "include/EASTL/vector_map.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//////////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////////\n// This file implements vector_map. It acts much like std::map, except its \n// underlying representation is a random access container such as vector. \n// These containers are sometimes also known as \"sorted vectors.\"  \n// vector_maps have an advantage over conventional maps in that their memory\n// is contiguous and node-less. The result is that lookups are faster, more \n// cache friendly (which potentially more so benefits speed), and the container\n// uses less memory. The downside is that inserting new items into the container\n// is slower if they are inserted in random order instead of in sorted order.\n// This tradeoff is well-worth it for many cases. Note that vector_map allows\n// you to use a deque or other random access container which may perform\n// better for you than vector.\n//\n// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n// that the modification of the container potentially invalidates all \n// existing iterators into the container, unlike what happens with conventional\n// sets and maps.\n// \n// This type could conceptually use a eastl::array as its underlying container,\n// however the current design requires an allocator aware container.\n// Consider using a fixed_vector instead.\n//////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef EASTL_VECTOR_MAP_H\n#define EASTL_VECTOR_MAP_H\n\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/functional.h>\n#include <EASTL/vector.h>\n#include <EASTL/utility.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n#if EASTL_EXCEPTIONS_ENABLED\n#include <stdexcept>\n#endif\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_VECTOR_MAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_VECTOR_MAP_DEFAULT_NAME\n\t\t#define EASTL_VECTOR_MAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" vector_map\" // Unless the user overrides something, this is \"EASTL vector_map\".\n\t#endif\n\n\n\t/// EASTL_VECTOR_MAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_VECTOR_MAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_VECTOR_MAP_DEFAULT_ALLOCATOR allocator_type(EASTL_VECTOR_MAP_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// map_value_compare\n\t///\n\t/// Our adapter for the comparison function in the template parameters.\n\t///\n\t/// todo: deprecate this. shouldn't have all these member functions available (including constructor) and shouldn't be a public type.\n\ttemplate <typename Key, typename Value, typename Compare>\n\tclass map_value_compare : public Compare\n\t{\n\tpublic:\n\t\texplicit map_value_compare(const Compare& x)\n\t\t\t: Compare(x) {}\n\n\t\tbool operator()(const Value& a, const Value& b) const\n\t\t\t{ return Compare::operator()(a.first, b.first); }\n\n\t\tbool operator()(const Value& a, const Key& b) const\n\t\t\t{ return Compare::operator()(a.first, b); }\n\n\t\tbool operator()(const Key& a, const Value& b) const\n\t\t\t{ return Compare::operator()(a, b.first); }\n\n\t\tbool operator()(const Key& a, const Key& b) const\n\t\t\t{ return Compare::operator()(a, b); }\n\n\t}; // map_value_compare\n\n\n\n\t/// vector_map\n\t///\n\t/// Implements a map via a random access container such as a vector.\n\t///\n\t/// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n\t/// that the modification of the container potentially invalidates all \n\t/// existing iterators into the container, unlike what happens with conventional\n\t/// sets and maps.\n\t///\n\t/// This type could conceptually use a eastl::array as its underlying container,\n\t/// however the current design requires an allocator aware container.\n\t/// Consider using a fixed_vector instead.\n\t///\n\t/// Note that we set the value_type to be pair<Key, T> and not pair<const Key, T>.\n\t/// This means that the underlying container (e.g vector) is a container of pair<Key, T>.\n\t/// Our vector and deque implementations are optimized to assign values in-place and \n\t/// using a vector of pair<const Key, T> (note the const) would make it hard to use\n\t/// our existing vector implementation without a lot of headaches. As a result, \n\t/// at least for the time being we do away with the const. This means that the \n\t/// insertion type varies between map and vector_map in that the latter doesn't take\n\t/// const. This also means that a certain amount of automatic safety provided by \n\t/// the implementation is lost, as the compiler will let the wayward user modify \n\t/// a key and thus make the container no longer ordered behind its back.\n\t///\n\ttemplate <typename Key, typename T, typename Compare = eastl::less<Key>, \n\t\t\t  typename Allocator = EASTLAllocatorType, \n\t\t\t  typename RandomAccessContainer = eastl::vector<eastl::pair<Key, T>, Allocator> >\n\tclass vector_map : protected map_value_compare<Key, eastl::pair<Key, T>, Compare>, public RandomAccessContainer\n\t{\n\tpublic:\n\t\ttypedef RandomAccessContainer                                         base_type;\n\t\ttypedef vector_map<Key, T, Compare, Allocator, RandomAccessContainer> this_type;\n\t\ttypedef Allocator                                                     allocator_type;\n\t\ttypedef Key                                                           key_type;\n\t\ttypedef T                                                             mapped_type;\n\t\ttypedef eastl::pair<Key, T>                                           value_type;\n\t\ttypedef Compare                                                       key_compare;\n\t\ttypedef map_value_compare<Key, value_type, Compare>                   value_compare;\n\t\ttypedef value_type*                                                   pointer;\n\t\ttypedef const value_type*                                             const_pointer;\n\t\ttypedef value_type&                                                   reference;\n\t\ttypedef const value_type&                                             const_reference;\n\t\ttypedef typename base_type::size_type                                 size_type;\n\t\ttypedef typename base_type::difference_type                           difference_type;\n\t\ttypedef typename base_type::iterator                                  iterator;\n\t\ttypedef typename base_type::const_iterator                            const_iterator;\n\t\ttypedef typename base_type::reverse_iterator                          reverse_iterator;\n\t\ttypedef typename base_type::const_reverse_iterator                    const_reverse_iterator;\n\t\ttypedef eastl::pair<iterator, bool>                                   insert_return_type;\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::get_allocator;\n\n\tpublic:\n\t\t// We have an empty ctor and a ctor that takes an allocator instead of one for both\n\t\t// because this way our RandomAccessContainer wouldn't be required to have an constructor\n\t\t// that takes allocator_type. \n\t\tvector_map();\n\t\texplicit vector_map(const allocator_type& allocator);\n\t\texplicit vector_map(const key_compare& comp, const allocator_type& allocator = EASTL_VECTOR_MAP_DEFAULT_ALLOCATOR);\n\t\tvector_map(const this_type& x);\n\t\tvector_map(this_type&& x);\n\t\tvector_map(this_type&& x, const allocator_type& allocator);\n\t\tvector_map(std::initializer_list<value_type> ilist, const key_compare& compare = key_compare(), const allocator_type& allocator = EASTL_VECTOR_MAP_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_map(InputIterator first, InputIterator last); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_map(InputIterator first, InputIterator last, const key_compare& compare); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tconst key_compare& key_comp() const;\n\t\tkey_compare&       key_comp();\n\n\t\tconst value_compare& value_comp() const;\n\t\tvalue_compare&       value_comp();\n\n\t\t// Inherited from base class:\n\t\t//\n\t\t//     allocator_type& get_allocator();\n\t\t//     void            set_allocator(const allocator_type& allocator);\n\t\t//\n\t\t//     iterator       begin();\n\t\t//     const_iterator begin() const;\n\t\t//     const_iterator cbegin() const;\n\t\t//\n\t\t//     iterator       end();\n\t\t//     const_iterator end() const;\n\t\t//     const_iterator cend() const;\n\t\t//\n\t\t//     reverse_iterator       rbegin();\n\t\t//     const_reverse_iterator rbegin() const;\n\t\t//     const_reverse_iterator crbegin() const;\n\t\t//\n\t\t//     reverse_iterator       rend();\n\t\t//     const_reverse_iterator rend() const;\n\t\t//     const_reverse_iterator crend() const;\n\t\t//\n\t\t//     size_type size() const;\n\t\t//     bool      empty() const;\n\t\t//     void      clear();\n\n\t\ttemplate <class... Args>\n\t\teastl::pair<iterator, bool> emplace(Args&&... args);\n\n\t\ttemplate <class... Args> \n\t\titerator emplace_hint(const_iterator position, Args&&... args);\n\n\t\ttemplate <typename P, typename = eastl::enable_if_t<eastl::is_constructible_v<value_type, P&&>>>\n\t\tpair<iterator, bool> insert(P&& otherValue);\n\n\t\teastl::pair<iterator, bool> insert(const value_type& value);\n\t\tpair<iterator, bool>        insert(const key_type& otherValue);\n\t\tpair<iterator, bool>        insert(key_type&& otherValue);\n\t\titerator                    insert(const_iterator position, const value_type& value);\n\t\titerator                    insert(const_iterator position, value_type&& value);\n\t\tvoid                        insert(std::initializer_list<value_type> ilist);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(InputIterator first, InputIterator last);\n\n\t\ttemplate <typename Iter = iterator, typename eastl::enable_if<!eastl::is_same_v<Iter, const_iterator>, int>::type = 0>\n\t\titerator         erase(iterator position) { return erase(const_iterator(position)); }\n\t\titerator         erase(const_iterator position);\n\t\titerator         erase(const_iterator first, const_iterator last);\n\t\tsize_type        erase(const key_type& k) { return DoErase(k); }\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!(eastl::is_convertible_v<KX&&, iterator> || eastl::is_convertible_v<KX&&, const_iterator>)\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type        erase(KX&& k) { return DoErase(eastl::forward<KX>(k)); }\n\n\t\titerator       find(const key_type& k) { return DoFind(k); }\n\t\tconst_iterator find(const key_type& k) const { return DoFind(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       find(const KX& k) { return DoFind(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator find(const KX& k) const { return DoFind(k); }\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\titerator       find_as(const U& u, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\tconst_iterator find_as(const U& u, BinaryPredicate predicate) const;\n\n\t\tbool contains(const key_type& key) const { return DoFind(key) != end(); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tbool contains(const KX& key) const { return DoFind(key) != end(); }\n\n\t\tsize_type count(const key_type& k) const { return DoCount(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& k) const { return DoCount(k); }\n\n\t\titerator       lower_bound(const key_type& k) { return DoLowerBound(k); }\n\t\tconst_iterator lower_bound(const key_type& k) const { return DoLowerBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       lower_bound(const KX& k) { return DoLowerBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator lower_bound(const KX& k) const { return DoLowerBound(k); }\n\n\t\titerator       upper_bound(const key_type& k) { return DoUpperBound(k); }\n\t\tconst_iterator upper_bound(const key_type& k) const { return DoUpperBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       upper_bound(const KX& k) { return DoUpperBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator upper_bound(const KX& k) const { return DoUpperBound(k); }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const key_type& k) { return DoEqualRange(k); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const { return DoEqualRange(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& k) { return DoEqualRange(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& k) const { return DoEqualRange(k); }\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\teastl::pair<iterator, iterator>             equal_range(const U& u, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const U& u, BinaryPredicate) const;\n\n\t\t// Note: vector_map operator[] returns a reference to the mapped_type, same as map does.\n\t\t// But there's an important difference: This reference can be invalidated by -any- changes  \n\t\t// to the vector_map that cause it to change capacity. This is unlike map, with which \n\t\t// mapped_type references are invalidated only if that mapped_type element itself is removed\n\t\t// from the map. This is because vector is array-based and map is node-based. As a result\n\t\t// the following code that is safe for map is unsafe for vector_map for the case that \n\t\t// the vMap[100] doesn't already exist in the vector_map:\n\t\t//     vMap[100] = vMap[0]\n\t\tmapped_type& operator[](const key_type& k) { return DoGetElement(k); }\n\t\tmapped_type& operator[](key_type&& k) { return DoGetElement(eastl::move(k)); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tmapped_type& operator[](KX&& k) { return DoGetElement(eastl::forward<KX>(k)); }\n\n\t\t// non-standard! this was originally inherited from vector with incorrect semantics.\n\t\t// this is only defined so that we can deprecate it.\n\t\t// use `*(map.begin() + index)` if you want to get an element by index.\n\t\tEASTL_REMOVE_AT_2024_SEPT reference at(size_type index);\n\t\tEASTL_REMOVE_AT_2024_SEPT const_reference at(size_type index) const;\n\t\t// after the deprecation period the above should be replaced with:\n\t\t// mapped_type& at(const key_type& k) { return at_key(k); }\n\t\t// const mapped_type& at(const key_type& k) const { return at_key(k); }\n\n\t\t// aka. the standard's at() member function.\n\t\tmapped_type& at_key(const key_type& k) { return DoAtKey(k); }\n\t\tconst mapped_type& at_key(const key_type& k) const { return DoAtKey(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tmapped_type& at_key(const KX& k) { return DoAtKey(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst mapped_type& at_key(const KX& k) const { return DoAtKey(k); }\n\n\t\t// Functions which are disallowed due to being unsafe. \n\t\tvoid      push_back(const value_type& value) = delete;\n\t\treference push_back()                        = delete;\n\t\tvoid*     push_back_uninitialized()          = delete;\n\t\ttemplate <class... Args>\n\t\treference emplace_back(Args&&...)            = delete;\n\n\t\t// NOTE(rparolin): It is undefined behaviour if user code fails to ensure the container\n\t\t// invariants are respected by performing an explicit call to 'sort' before any other\n\t\t// operations on the container are performed that do not clear the elements.\n\t\t//\n\t\t// 'push_back_unsorted' and 'emplace_back_unsorted' do not satisfy container invariants\n\t\t// for being sorted. We provide these overloads explicitly labelled as '_unsorted' as an\n\t\t// optimization opportunity when batch inserting elements so users can defer the cost of\n\t\t// sorting the container once when all elements are contained. This was done to clarify\n\t\t// the intent of code by leaving a trace that a manual call to sort is required.\n\t\t// \n\t\ttemplate <typename... Args> decltype(auto) push_back_unsorted(Args&&... args)    \n\t\t\t{ return base_type::push_back(eastl::forward<Args>(args)...); }\n\t\ttemplate <typename... Args> decltype(auto) emplace_back_unsorted(Args&&... args) \n\t\t\t{ return base_type::emplace_back(eastl::forward<Args>(args)...); }\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tsize_type        DoErase(KX&& k);\n\n\t\ttemplate<typename KX>\n\t\titerator DoFind(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoFind(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\tsize_type DoCount(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& k);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoLowerBound(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoLowerBound(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoUpperBound(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoUpperBound(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\tmapped_type& DoGetElement(KX&& k);\n\n\t\ttemplate<typename KX>\n\t\tmapped_type& DoAtKey(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst mapped_type& DoAtKey(const KX& k) const;\n\n\t}; // vector_map\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// vector_map\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>::vector_map()\n\t\t: value_compare(C()), base_type()\n\t{\n\t\tget_allocator().set_name(EASTL_VECTOR_MAP_DEFAULT_NAME);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(const allocator_type& allocator)\n\t\t: value_compare(C()), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(const key_compare& comp, const allocator_type& allocator)\n\t\t: value_compare(comp), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(const this_type& x)\n\t\t: value_compare(x), base_type(x)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(this_type&& x)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)))\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one. \n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(this_type&& x, const allocator_type& allocator)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)), allocator)\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one. \n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(std::initializer_list<value_type> ilist, const key_compare& compare, const allocator_type& allocator)\n\t\t: value_compare(compare), base_type(allocator)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(InputIterator first, InputIterator last)\n\t\t: value_compare(key_compare()), base_type(EASTL_VECTOR_MAP_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_map<K, T, C, A, RAC>::vector_map(InputIterator first, InputIterator last, const key_compare& compare)\n\t\t: value_compare(compare), base_type(EASTL_VECTOR_MAP_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>&\n\tvector_map<K, T, C, A, RAC>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\tvalue_compare::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>&\n\tvector_map<K, T, C, A, RAC>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(eastl::move(static_cast<base_type&&>(x)));\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_map<K, T, C, A, RAC>&\n\tvector_map<K, T, C, A, RAC>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline void vector_map<K, T, C, A, RAC>::swap(this_type& x)\n\t{\n\t\tbase_type::swap(x);\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline const typename vector_map<K, T, C, A, RAC>::key_compare&\n\tvector_map<K, T, C, A, RAC>::key_comp() const\n\t{\n\t\treturn static_cast<const key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::key_compare&\n\tvector_map<K, T, C, A, RAC>::key_comp()\n\t{\n\t\treturn static_cast<key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline const typename vector_map<K, T, C, A, RAC>::value_compare&\n\tvector_map<K, T, C, A, RAC>::value_comp() const\n\t{\n\t\treturn static_cast<const value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::value_compare&\n\tvector_map<K, T, C, A, RAC>::value_comp()\n\t{\n\t\treturn static_cast<value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <class... Args>\n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, bool>\n\tvector_map<K, T, C, A, RAC>::emplace(Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\t\treturn insert(eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <class... Args>\n\tinline typename vector_map<K, T, C, A, RAC>::iterator \n\tvector_map<K, T, C, A, RAC>::emplace_hint(const_iterator position, Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\n\t\treturn insert(position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, bool>\n\tvector_map<K, T, C, A, RAC>::insert(const value_type& value)\n\t{\n\t\tconst iterator itLB(lower_bound(value.first));\n\n\t\tif((itLB != end()) && !value_compare::operator()(value, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, value), true);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename P, typename>\n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, bool>\n\tvector_map<K, T, C, A, RAC>::insert(P&& otherValue)\n\t{\n\t\tvalue_type value(eastl::forward<P>(otherValue));\n\t\tconst iterator itLB(lower_bound(value.first));\n\n\t\tif((itLB != end()) && !value_compare::operator()(value, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, eastl::move(value)), true);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, bool>\n\tvector_map<K, T, C, A, RAC>::insert(const key_type& otherValue)\n\t{\n\t\tvalue_type value(eastl::pair_first_construct, otherValue);\n\t\tconst iterator itLB(lower_bound(value.first));\n\n\t\tif((itLB != end()) && !value_compare::operator()(value, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, eastl::move(value)), true);\n\t}\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, bool>\n\tvector_map<K, T, C, A, RAC>::insert(key_type&& otherValue)\n\t{\n\t\tvalue_type value(eastl::pair_first_construct, eastl::move(otherValue));\n\t\tconst iterator itLB(lower_bound(value.first));\n\n\t\tif((itLB != end()) && !value_compare::operator()(value, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, eastl::move(value)), true);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttypename vector_map<K, T, C, A, RAC>::iterator\n\tvector_map<K, T, C, A, RAC>::insert(const_iterator position, const value_type& value)\n\t{\n\t\t// We assume that the user knows what he is doing and has supplied us with\n\t\t// a position that is right where value should be inserted (put in front of). \n\t\t// We do a test to see if the position is correct. If so then we insert, \n\t\t// if not then we ignore the input position.\n\n\t\tif((position == end()) || value_compare::operator()(value, *position))  // If the element at position is greater than value...\n\t\t{\n\t\t\tif((position == begin()) || value_compare::operator()(*(position - 1), value)) // If the element before position is less than value...\n\t\t\t\treturn base_type::insert(position, value);\n\t\t}\n\n\t\t// In this case we either have an incorrect position or value is already present.\n\t\t// We fall back to the regular insert function. An optimization would be to detect\n\t\t// that the element is already present, but that's only useful if the user supplied\n\t\t// a good position but a present element.\n\t\tconst eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, bool> result = insert(value);\n\n\t\treturn result.first;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttypename vector_map<K, T, C, A, RAC>::iterator\n\tvector_map<K, T, C, A, RAC>::insert(const_iterator position, value_type&& value)\n\t{\n\t\tif((position == end()) || value_compare::operator()(value, *position))  // If the element at position is greater than value...\n\t\t{\n\t\t\tif((position == begin()) || value_compare::operator()(*(position - 1), value)) // If the element before position is less than value...\n\t\t\t\treturn base_type::insert(position, eastl::move(value));\n\t\t}\n\n\t\tconst eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, bool> result = insert(eastl::move(value));\n\n\t\treturn result.first;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline void vector_map<K, T, C, A, RAC>::insert(std::initializer_list<value_type> ilist)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline void vector_map<K, T, C, A, RAC>::insert(InputIterator first, InputIterator last)\n\t{\n\t\t// To consider: Improve the speed of this by getting the length of the \n\t\t//              input range and resizing our container to that size\n\t\t//              before doing the insertions. We can't use reserve\n\t\t//              because we don't know if we are using a vector or not.\n\t\t//              Alternatively, force the user to do the reservation.\n\t\t// To consider: When inserting values that come from a container\n\t\t//              like this container, use the property that they are \n\t\t//              known to be sorted and speed up the inserts here.\n\t\tfor(; first != last; ++first)\n\t\t\tinsert(*first);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::iterator\n\tvector_map<K, T, C, A, RAC>::erase(const_iterator position)\n\t{\n\t\t// Note that we return iterator and not void. This allows for more efficient use of \n\t\t// the container and is consistent with the C++ language defect report #130 (DR 130)\n\t\treturn base_type::erase(position);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::iterator\n\tvector_map<K, T, C, A, RAC>::erase(const_iterator first, const_iterator last)\n\t{\n\t\treturn base_type::erase(first, last);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::size_type\n\tvector_map<K, T, C, A, RAC>::DoErase(KX&& k)\n\t{\n\t\tconst iterator it(find(eastl::forward<KX>(k)));\n\n\t\tif(it != end()) // If it exists...\n\t\t{\n\t\t\terase(it);\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::reverse_iterator\n\tvector_map<K, T, C, A, RAC>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(base_type::erase((++position).base()));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::reverse_iterator\n\tvector_map<K, T, C, A, RAC>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\treturn reverse_iterator(base_type::erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::iterator\n\tvector_map<K, T, C, A, RAC>::DoFind(const KX& k)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(k));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::const_iterator\n\tvector_map<K, T, C, A, RAC>::DoFind(const KX& k) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(k));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_map<K, T, C, A, RAC>::iterator\n\tvector_map<K, T, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(u, predicate));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_map<K, T, C, A, RAC>::const_iterator\n\tvector_map<K, T, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(u, predicate));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::size_type\n\tvector_map<K, T, C, A, RAC>::DoCount(const KX& k) const\n\t{\n\t\tconst const_iterator it(find(k));\n\t\treturn (it != end()) ? (size_type)1 : (size_type)0;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::iterator\n\tvector_map<K, T, C, A, RAC>::DoLowerBound(const KX& k)\n\t{\n\t\tauto comp = [this](const value_type& value, const KX& key) { return static_cast<const key_compare&>(*this)(value.first, key); };\n\t\treturn eastl::lower_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::const_iterator\n\tvector_map<K, T, C, A, RAC>::DoLowerBound(const KX& k) const\n\t{\n\t\tauto comp = [this](const value_type& value, const KX& key) { return static_cast<const key_compare&>(*this)(value.first, key); };\n\t\treturn eastl::lower_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::iterator \n\tvector_map<K, T, C, A, RAC>::DoUpperBound(const KX& k)\n\t{\n\t\tauto comp = [this](const KX& key, const value_type& value) { return static_cast<const key_compare&>(*this)(key, value.first); };\n\t\treturn eastl::upper_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::const_iterator\n\tvector_map<K, T, C, A, RAC>::DoUpperBound(const KX& k) const\n\t{\n\t\tauto comp = [this](const KX& key, const value_type& value) { return static_cast<const key_compare&>(*this)(key, value.first); };\n\t\treturn eastl::upper_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, typename vector_map<K, T, C, A, RAC>::iterator>\n\tvector_map<K, T, C, A, RAC>::DoEqualRange(const KX& k)\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst iterator itLower(lower_bound(k));\n\n\t\tif((itLower == end()) || static_cast<key_compare&>(*this)(k, itLower->first)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<iterator, iterator>(itLower, itLower);\n\n\t\titerator itUpper(itLower);\n\t\treturn eastl::pair<iterator, iterator>(itLower, ++itUpper);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::const_iterator, typename vector_map<K, T, C, A, RAC>::const_iterator>\n\tvector_map<K, T, C, A, RAC>::DoEqualRange(const KX& k) const\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst const_iterator itLower(lower_bound(k));\n\n\t\tif((itLower == end()) || static_cast<const key_compare&>(*this)(k, itLower->first)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itLower);\n\n\t\tconst_iterator itUpper(itLower);\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);\n\t}\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate> \n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::iterator, typename vector_map<K, T, C, A, RAC>::iterator>\n\tvector_map<K, T, C, A, RAC>::equal_range(const U& u, BinaryPredicate predicate)\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tmap_value_compare<U, value_type, BinaryPredicate> predicate_cmp(predicate);\n\n\t\tconst iterator itLower(eastl::lower_bound(begin(), end(), u, predicate_cmp));\n\n\t\tif((itLower == end()) || predicate_cmp(u, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<iterator, iterator>(itLower, itLower);\n\n\t\titerator itUpper(itLower);\n\t\treturn eastl::pair<iterator, iterator>(itLower, ++itUpper);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate> \n\tinline eastl::pair<typename vector_map<K, T, C, A, RAC>::const_iterator, typename vector_map<K, T, C, A, RAC>::const_iterator>\n\tvector_map<K, T, C, A, RAC>::equal_range(const U& u, BinaryPredicate predicate) const\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tmap_value_compare<U, value_type, BinaryPredicate> predicate_cmp(predicate);\n\n\t\tconst const_iterator itLower(eastl::lower_bound(begin(), end(), u, predicate_cmp));\n\n\t\tif((itLower == end()) || predicate_cmp(u, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itLower);\n\n\t\tconst_iterator itUpper(itLower);\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::mapped_type&\n\tvector_map<K, T, C, A, RAC>::DoGetElement(KX&& k)\n\t{\n\t\titerator itLB(lower_bound(k));\n\n\t\tif((itLB == end()) || key_comp()(k, (*itLB).first))\n\t\t\titLB = insert(itLB, value_type(eastl::forward<KX>(k), mapped_type()));\n\t\treturn (*itLB).second;\n\t}\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::reference\n\t\tvector_map<K, T, C, A, RAC>::at(size_type index)\n\t{\n\t\treturn *(begin() + index);\n\t}\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_map<K, T, C, A, RAC>::const_reference\n\t\tvector_map<K, T, C, A, RAC>::at(size_type index) const\n\t{\n\t\treturn *(begin() + index);\n\t}\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_map<K, T, C, A, RAC>::mapped_type&\n\t\tvector_map<K, T, C, A, RAC>::DoAtKey(const KX& k)\n\t{\n\t\t// use the use const version of ::at to remove duplication\n\t\treturn const_cast<mapped_type&>(const_cast<vector_map<K, T, C, A, RAC> const*>(this)->at_key(k));\n\t}\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline const typename vector_map<K, T, C, A, RAC>::mapped_type&\n\t\tvector_map<K, T, C, A, RAC>::DoAtKey(const KX& k) const\n\t{\n\t\tconst_iterator itLB(lower_bound(k));\n\n\t\tif ((itLB == end()) || key_comp()(k, itLB->first))\n\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tthrow std::out_of_range(\"vector_map::at key does not exist\");\n#else\n\t\t\tEASTL_FAIL_MSG(\"vector_map::at key does not exist\");\n#endif\n\t\t}\n\n\t\treturn itLB->second;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator==(const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& a, \n\t\t\t\t\t\t   const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& b) \n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(b.begin(), b.end(), a.begin()); \n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator<(const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t  const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), a.value_comp());\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator!=(const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator>(const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t  const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator<=(const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator>=(const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline void swap(vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t vector_map<Key, T, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/vector_multimap.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//////////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////////\n// This file implements vector_multimap. It acts much like std::multimap, except \n// its underlying representation is a random access container such as vector. \n// These containers are sometimes also known as \"sorted vectors.\"  \n// vector_maps have an advantage over conventional maps in that their memory\n// is contiguous and node-less. The result is that lookups are faster, more \n// cache friendly (which potentially more so benefits speed), and the container\n// uses less memory. The downside is that inserting new items into the container\n// is slower if they are inserted in random order instead of in sorted order.\n// This tradeoff is well-worth it for many cases. Note that vector_multimap allows\n// you to use a deque or other random access container which may perform\n// better for you than vector.\n//\n// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n// that the modification of the container potentially invalidates all \n// existing iterators into the container, unlike what happens with conventional\n// sets and maps.\n// \n// This type could conceptually use a eastl::array as its underlying container,\n// however the current design requires an allocator aware container.\n// Consider using a fixed_vector instead.\n//////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef EASTL_VECTOR_MULTIMAP_H\n#define EASTL_VECTOR_MULTIMAP_H\n\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/functional.h>\n#include <EASTL/vector.h>\n#include <EASTL/utility.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_VECTOR_MULTIMAP_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_VECTOR_MULTIMAP_DEFAULT_NAME\n\t\t#define EASTL_VECTOR_MULTIMAP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" vector_multimap\" // Unless the user overrides something, this is \"EASTL vector_multimap\".\n\t#endif\n\n\n\t/// EASTL_VECTOR_MULTIMAP_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_VECTOR_MULTIMAP_DEFAULT_ALLOCATOR\n\t\t#define EASTL_VECTOR_MULTIMAP_DEFAULT_ALLOCATOR allocator_type(EASTL_VECTOR_MULTIMAP_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// multimap_value_compare\n\t///\n\t/// Our adapter for the comparison function in the template parameters.\n\t///\n\t/// todo: deprecate this. shouldn't have all these member functions available (including constructor) and shouldn't be a public type.\n\ttemplate <typename Key, typename Value, typename Compare>\n\tclass multimap_value_compare : public Compare\n\t{\n\tpublic:\n\t\texplicit multimap_value_compare(const Compare& x)\n\t\t\t: Compare(x) {}\n\n\t\tbool operator()(const Value& a, const Value& b) const\n\t\t\t{ return Compare::operator()(a.first, b.first); }\n\n\t\tbool operator()(const Value& a, const Key& b) const\n\t\t\t{ return Compare::operator()(a.first, b); }\n\n\t\tbool operator()(const Key& a, const Value& b) const\n\t\t\t{ return Compare::operator()(a, b.first); }\n\n\t\tbool operator()(const Key& a, const Key& b) const\n\t\t\t{ return Compare::operator()(a, b); }\n\n\t}; // multimap_value_compare\n\n\tnamespace internal {\n\ttemplate <typename Value, typename Compare>\n\tstruct equal_range_comp\n\t{\n\t\tconst Compare& comp;\n\n\t\texplicit equal_range_comp(const Compare& x)\n\t\t\t: comp(x) {}\n\n\t\ttemplate<typename KX>\n\t\tbool operator()(const KX& lhs, const Value& rhs) const\n\t\t{\n\t\t\treturn comp(lhs, rhs.first);\n\t\t}\n\n\t\ttemplate<typename KX>\n\t\tbool operator()(const Value& lhs, const KX& rhs) const\n\t\t{\n\t\t\treturn comp(lhs.first, rhs);\n\t\t}\n\n\t}; // equal_range_comp\n\t}\n\n\t/// vector_multimap\n\t///\n\t/// Implements a multimap via a random access container such as a vector.\n\t///\n\t/// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n\t/// that the modification of the container potentially invalidates all \n\t/// existing iterators into the container, unlike what happens with conventional\n\t/// sets and maps.\n\t///\n\t/// This type could conceptually use a eastl::array as its underlying container,\n\t/// however the current design requires an allocator aware container.\n\t/// Consider using a fixed_vector instead.\n\t///\n\t/// Note that we set the value_type to be pair<Key, T> and not pair<const Key, T>.\n\t/// This means that the underlying container (e.g vector) is a container of pair<Key, T>.\n\t/// Our vector and deque implementations are optimized to assign values in-place and \n\t/// using a vector of pair<const Key, T> (note the const) would make it hard to use\n\t/// our existing vector implementation without a lot of headaches. As a result, \n\t/// at least for the time being we do away with the const. This means that the \n\t/// insertion type varies between map and vector_map in that the latter doesn't take\n\t/// const. This also means that a certain amount of automatic safety provided by \n\t/// the implementation is lost, as the compiler will let the wayward user modify \n\t/// a key and thus make the container no longer ordered behind its back.\n\t///\n\ttemplate <typename Key, typename T, typename Compare = eastl::less<Key>, \n\t\t\t  typename Allocator = EASTLAllocatorType,\n\t\t\t  typename RandomAccessContainer = eastl::vector<eastl::pair<Key, T>, Allocator> >\n\tclass vector_multimap : protected multimap_value_compare<Key, eastl::pair<Key, T>, Compare>, public RandomAccessContainer\n\t{\n\tpublic:\n\t\ttypedef RandomAccessContainer                                              base_type;\n\t\ttypedef vector_multimap<Key, T, Compare, Allocator, RandomAccessContainer> this_type;\n\t\ttypedef Allocator                                                          allocator_type;\n\t\ttypedef Key                                                                key_type;\n\t\ttypedef T                                                                  mapped_type;\n\t\ttypedef eastl::pair<Key, T>                                                value_type;\n\t\ttypedef Compare                                                            key_compare;\n\t\ttypedef multimap_value_compare<Key, value_type, Compare>                   value_compare;\n\t\ttypedef value_type*                                                        pointer;\n\t\ttypedef const value_type*                                                  const_pointer;\n\t\ttypedef value_type&                                                        reference;\n\t\ttypedef const value_type&                                                  const_reference;\n\t\ttypedef typename base_type::size_type                                      size_type;\n\t\ttypedef typename base_type::difference_type                                difference_type;\n\t\ttypedef typename base_type::iterator                                       iterator;\n\t\ttypedef typename base_type::const_iterator                                 const_iterator;\n\t\ttypedef typename base_type::reverse_iterator                               reverse_iterator;\n\t\ttypedef typename base_type::const_reverse_iterator                         const_reverse_iterator;\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::get_allocator;\n\n\tpublic:\n\t\t// We have an empty ctor and a ctor that takes an allocator instead of one for both\n\t\t// because this way our RandomAccessContainer wouldn't be required to have an constructor\n\t\t// that takes allocator_type. \n\t\tvector_multimap();\n\t\texplicit vector_multimap(const allocator_type& allocator);\n\t\texplicit vector_multimap(const key_compare& comp, const allocator_type& allocator = EASTL_VECTOR_MULTIMAP_DEFAULT_ALLOCATOR);\n\t\tvector_multimap(const this_type& x);\n\t\tvector_multimap(this_type&& x);\n\t\tvector_multimap(this_type&& x, const allocator_type& allocator);\n\t\tvector_multimap(std::initializer_list<value_type> ilist, const key_compare& compare = key_compare(), const allocator_type& allocator = EASTL_VECTOR_MULTIMAP_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_multimap(InputIterator first, InputIterator last); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_multimap(InputIterator first, InputIterator last, const key_compare& compare); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tconst key_compare& key_comp() const;\n\t\tkey_compare&       key_comp();\n\n\t\tconst value_compare& value_comp() const;\n\t\tvalue_compare&       value_comp();\n\n\t\t// Inherited from base class:\n\t\t//\n\t\t//     allocator_type& get_allocator();\n\t\t//     void            set_allocator(const allocator_type& allocator);\n\t\t//\n\t\t//     iterator       begin();\n\t\t//     const_iterator begin() const;\n\t\t//     const_iterator cbegin() const;\n\t\t//\n\t\t//     iterator       end();\n\t\t//     const_iterator end() const;\n\t\t//     const_iterator cend() const;\n\t\t//\n\t\t//     reverse_iterator       rbegin();\n\t\t//     const_reverse_iterator rbegin() const;\n\t\t//     const_reverse_iterator crbegin() const;\n\t\t//\n\t\t//     reverse_iterator       rend();\n\t\t//     const_reverse_iterator rend() const;\n\t\t//     const_reverse_iterator crend() const;\n\t\t//\n\t\t//     size_type size() const;\n\t\t//     bool      empty() const;\n\t\t//     void      clear();\n\n\t\ttemplate <class... Args>\n\t\titerator emplace(Args&&... args);\n\n\t\ttemplate <class... Args> \n\t\titerator emplace_hint(const_iterator position, Args&&... args);\n\n\t\titerator insert(const value_type& value);   // The signature of this function was change in EASTL v2.05.00 from (the mistaken) pair<iterator, bool> to (the correct) iterator.\n\n\t\ttemplate <typename P, typename = eastl::enable_if_t<eastl::is_constructible_v<value_type, P&&>>>\n\t\titerator insert(P&& otherValue);\n\n\t\titerator insert(const key_type& otherValue);\n\t\titerator insert(key_type&& otherValue);\n\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\titerator insert(const_iterator position, value_type&& value);\n\n\t\tvoid insert(std::initializer_list<value_type> ilist);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(InputIterator first, InputIterator last);\n\n\t\titerator  erase(const_iterator position);\n\t\titerator  erase(const_iterator first, const_iterator last);\n\t\tsize_type erase(const key_type& k) { return DoErase(k); }\n\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!(eastl::is_convertible_v<KX&&, iterator> || eastl::is_convertible_v<KX&&, const_iterator>)\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type erase(KX&& k) { return DoErase(eastl::forward<KX>(k)); }\n\n\t\titerator       find(const key_type& k) { return DoFind(k); }\n\t\tconst_iterator find(const key_type& k) const { return DoFind(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       find(const KX& k) { return DoFind(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator find(const KX& k) const { return DoFind(k); }\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\titerator       find_as(const U& u, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\tconst_iterator find_as(const U& u, BinaryPredicate predicate) const;\n\n\t\tbool contains(const key_type& key) const { return DoFind(key) != end(); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tbool contains(const KX& key) const { return DoFind(key) != end(); }\n\n\t\tsize_type count(const key_type& k) const { return DoCount(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& k) const { return DoCount(k); }\n\n\t\titerator       lower_bound(const key_type& k) { return DoLowerBound(k); }\n\t\tconst_iterator lower_bound(const key_type& k) const { return DoLowerBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       lower_bound(const KX& k) { return DoLowerBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator lower_bound(const KX& k) const { return DoLowerBound(k); }\n\n\t\titerator       upper_bound(const key_type& k) { return DoUpperBound(k); }\n\t\tconst_iterator upper_bound(const key_type& k) const { return DoUpperBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       upper_bound(const KX& k) { return DoUpperBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator upper_bound(const KX& k) const { return DoUpperBound(k); }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const key_type& k) { return DoEqualRange(k); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const { return DoEqualRange(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& key) { return DoEqualRange(key); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& key) const { return DoEqualRange(key); }\n\n\t\t/// equal_range_small\n\t\t/// This is a special version of equal_range which is optimized for the \n\t\t/// case of there being few or no duplicated keys in the tree.\n\t\teastl::pair<iterator, iterator>             equal_range_small(const key_type& k) { return DoEqualRangeSmall(k); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const key_type& k) const { return DoEqualRangeSmall(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range_small(const KX& k) { return DoEqualRangeSmall(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const KX& k) const { return DoEqualRangeSmall(k); }\n\n\t\t// Functions which are disallowed due to being unsafe. \n\t\tvoid      push_back(const value_type& value) = delete;\n\t\treference push_back()                        = delete;\n\t\tvoid*     push_back_uninitialized()          = delete;\n\t\ttemplate <class... Args>\n\t\treference emplace_back(Args&&...)            = delete;\n\n\t\t// NOTE(rparolin): It is undefined behaviour if user code fails to ensure the container\n\t\t// invariants are respected by performing an explicit call to 'sort' before any other\n\t\t// operations on the container are performed that do not clear the elements.\n\t\t//\n\t\t// 'push_back_unsorted' and 'emplace_back_unsorted' do not satisfy container invariants\n\t\t// for being sorted. We provide these overloads explicitly labelled as '_unsorted' as an\n\t\t// optimization opportunity when batch inserting elements so users can defer the cost of\n\t\t// sorting the container once when all elements are contained. This was done to clarify\n\t\t// the intent of code by leaving a trace that a manual call to sort is required.\n\t\t// \n\t\ttemplate <typename... Args> decltype(auto) push_back_unsorted(Args&&... args)    \n\t\t\t{ return base_type::push_back(eastl::forward<Args>(args)...); }\n\t\ttemplate <typename... Args> decltype(auto) emplace_back_unsorted(Args&&... args) \n\t\t\t{ return base_type::emplace_back(eastl::forward<Args>(args)...); }\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tsize_type        DoErase(KX&& k);\n\n\t\ttemplate<typename KX>\n\t\titerator DoFind(const KX& key);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoFind(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\tsize_type DoCount(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& key) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoLowerBound(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoLowerBound(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoUpperBound(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoUpperBound(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRangeSmall(const KX& key);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRangeSmall(const KX& key) const;\n\t}; // vector_multimap\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// vector_multimap\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap()\n\t\t: value_compare(C()), base_type()\n\t{\n\t#if EASTL_NAME_ENABLED\n\t\tget_allocator().set_name(EASTL_VECTOR_MULTIMAP_DEFAULT_NAME);\n\t#endif\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(const allocator_type& allocator)\n\t\t: value_compare(C()), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(const key_compare& comp, const allocator_type& allocator)\n\t\t: value_compare(comp), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(const this_type& x)\n\t\t: value_compare(x), base_type(x)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(this_type&& x)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)))\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one.\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(this_type&& x, const allocator_type& allocator)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)), allocator)\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one.\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(std::initializer_list<value_type> ilist, const key_compare& compare, const allocator_type& allocator)\n\t\t: value_compare(compare), base_type(allocator)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(InputIterator first, InputIterator last)\n\t\t: value_compare(key_compare()), base_type(EASTL_VECTOR_MULTIMAP_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_multimap<K, T, C, A, RAC>::vector_multimap(InputIterator first, InputIterator last, const key_compare& compare)\n\t\t: value_compare(compare), base_type(EASTL_VECTOR_MULTIMAP_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::this_type&\n\tvector_multimap<K, T, C, A, RAC>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\tvalue_compare::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::this_type&\n\tvector_multimap<K, T, C, A, RAC>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(eastl::move(x));\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::this_type&\n\tvector_multimap<K, T, C, A, RAC>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline void vector_multimap<K, T, C, A, RAC>::swap(this_type& x)\n\t{\n\t\tbase_type::swap(x);\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline const typename vector_multimap<K, T, C, A, RAC>::key_compare&\n\tvector_multimap<K, T, C, A, RAC>::key_comp() const\n\t{\n\t\treturn static_cast<const key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::key_compare&\n\tvector_multimap<K, T, C, A, RAC>::key_comp()\n\t{\n\t\treturn static_cast<key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline const typename vector_multimap<K, T, C, A, RAC>::value_compare&\n\tvector_multimap<K, T, C, A, RAC>::value_comp() const\n\t{\n\t\treturn static_cast<const value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::value_compare&\n\tvector_multimap<K, T, C, A, RAC>::value_comp()\n\t{\n\t\treturn static_cast<value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <class... Args>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::emplace(Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\t\treturn insert(eastl::move(value));\n\t}\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <class... Args> \n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::emplace_hint(const_iterator position, Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\t\treturn insert(position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::insert(const value_type& value)\n\t{\n\t\tconst iterator itUB(upper_bound(value.first));\n\t\treturn base_type::insert(itUB, value);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename P, typename>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::insert(P&& otherValue)\n\t{\n\t\tvalue_type value(eastl::forward<P>(otherValue));\n\t\tconst iterator itUB(upper_bound(value.first));\n\t\treturn base_type::insert(itUB, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::insert(const key_type& otherValue)\n\t{\n\t\tvalue_type value(eastl::pair_first_construct, otherValue);\n\t\tconst iterator itUB(upper_bound(value.first));\n\t\treturn base_type::insert(itUB, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::insert(key_type&& otherValue)\n\t{\n\t\tvalue_type value(eastl::pair_first_construct, eastl::move(otherValue));\n\t\tconst iterator itUB(upper_bound(value.first));\n\t\treturn base_type::insert(itUB, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::insert(const_iterator position, const value_type& value)\n\t{\n\t\t// We assume that the user knows what he is doing and has supplied us with\n\t\t// a position that is right where value should be inserted (put in front of). \n\t\t// We do a test to see if the position is correct. If so then we insert, \n\t\t// if not then we ignore the input position. However, \n\n\t\tif((position == end()) || !value_compare::operator()(*position, value))  // If value is <= the element at position...\n\t\t{\n\t\t\tif((position == begin()) || !value_compare::operator()(value, *(position - 1))) // If value is >= the element before position...\n\t\t\t\treturn base_type::insert(position, value);\n\t\t}\n\n\t\t// In this case we have an incorrect position. We fall back to the regular insert function.\n\t\treturn insert(value);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::insert(const_iterator position, value_type&& value)\n\t{\n\t\tif((position == end()) || !value_compare::operator()(*position, value))  // If value is <= the element at position...\n\t\t{\n\t\t\tif((position == begin()) || !value_compare::operator()(value, *(position - 1))) // If value is >= the element before position...\n\t\t\t\treturn base_type::insert(position, eastl::move(value));\n\t\t}\n\n\t\t// In this case we have an incorrect position. We fall back to the regular insert function.\n\t\treturn insert(eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline void vector_multimap<K, T, C, A, RAC>::insert(std::initializer_list<value_type> ilist)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline void vector_multimap<K, T, C, A, RAC>::insert(InputIterator first, InputIterator last)\n\t{\n\t\t// To consider: Improve the speed of this by getting the length of the \n\t\t//              input range and resizing our container to that size\n\t\t//              before doing the insertions. We can't use reserve\n\t\t//              because we don't know if we are using a vector or not.\n\t\t//              Alternatively, force the user to do the reservation.\n\t\t// To consider: When inserting values that come from a container\n\t\t//              like this container, use the property that they are \n\t\t//              known to be sorted and speed up the inserts here.\n\t\tfor(; first != last; ++first)\n\t\t\tbase_type::insert(upper_bound((*first).first), *first);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::erase(const_iterator position)           \n\t{\n\t\t// Note that we return iterator and not void. This allows for more efficient use of \n\t\t// the container and is consistent with the C++ language defect report #130 (DR 130)\n\t\treturn base_type::erase(position);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::erase(const_iterator first, const_iterator last)\n\t{\n\t\treturn base_type::erase(first, last);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::size_type\n\tvector_multimap<K, T, C, A, RAC>::DoErase(KX&& k)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(k));\n\n\t\tif(pairIts.first != pairIts.second)\n\t\t\tbase_type::erase(pairIts.first, pairIts.second);\n\n\t\treturn (size_type)eastl::distance(pairIts.first, pairIts.second); // This can result in any value >= 0.\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::reverse_iterator\n\tvector_multimap<K, T, C, A, RAC>::erase(const_reverse_iterator position)           \n\t{\n\t\treturn reverse_iterator(base_type::erase((++position).base()));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline typename vector_multimap<K, T, C, A, RAC>::reverse_iterator\n\tvector_multimap<K, T, C, A, RAC>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\treturn reverse_iterator(base_type::erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::DoFind(const KX& k)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(k));\n\n\t\tif(pairIts.first != pairIts.second)\n\t\t\treturn pairIts.first;\n\t\treturn end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::const_iterator\n\tvector_multimap<K, T, C, A, RAC>::DoFind(const KX& k) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(k));\n\n\t\tif(pairIts.first != pairIts.second)\n\t\t\treturn pairIts.first;\n\t\treturn end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_multimap<K, T, C, A, RAC>::const_iterator\n\tvector_multimap<K, T, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(eastl::equal_range(begin(), end(), u, internal::equal_range_comp<value_type, BinaryPredicate>(predicate)));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(eastl::equal_range(begin(), end(), u, internal::equal_range_comp<value_type, BinaryPredicate>(predicate)));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::size_type\n\tvector_multimap<K, T, C, A, RAC>::DoCount(const KX& k) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(k));\n\t\treturn (size_type)eastl::distance(pairIts.first, pairIts.second); \n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::DoLowerBound(const KX& k)\n\t{\n\t\tauto comp = [this](const value_type& value, const KX& key) { return static_cast<const key_compare&>(*this)(value.first, key); };\n\t\treturn eastl::lower_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::const_iterator\n\tvector_multimap<K, T, C, A, RAC>::DoLowerBound(const KX& k) const\n\t{\n\t\tauto comp = [this](const value_type& value, const KX& key) { return static_cast<const key_compare&>(*this)(value.first, key); };\n\t\treturn eastl::lower_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::iterator\n\tvector_multimap<K, T, C, A, RAC>::DoUpperBound(const KX& k)\n\t{\n\t\tauto comp = [this](const KX& key, const value_type& value) { return static_cast<const key_compare&>(*this)(key, value.first); };\n\t\treturn eastl::upper_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multimap<K, T, C, A, RAC>::const_iterator \n\tvector_multimap<K, T, C, A, RAC>::DoUpperBound(const KX& k) const\n\t{\n\t\tauto comp = [this](const KX& key, const value_type& value) { return static_cast<const key_compare&>(*this)(key, value.first); };\n\t\treturn eastl::upper_bound(begin(), end(), k, comp);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multimap<K, T, C, A, RAC>::iterator, typename vector_multimap<K, T, C, A, RAC>::iterator>\n\tvector_multimap<K, T, C, A, RAC>::DoEqualRange(const KX& k)\n\t{\n\t\treturn eastl::equal_range(begin(), end(), k, internal::equal_range_comp<value_type, key_compare>(*this));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multimap<K, T, C, A, RAC>::const_iterator, typename vector_multimap<K, T, C, A, RAC>::const_iterator>\n\tvector_multimap<K, T, C, A, RAC>::DoEqualRange(const KX& k) const\n\t{\n\t\treturn eastl::equal_range(begin(), end(), k, internal::equal_range_comp<value_type, key_compare>(*this));\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multimap<K, T, C, A, RAC>::iterator, typename vector_multimap<K, T, C, A, RAC>::iterator>\n\tvector_multimap<K, T, C, A, RAC>::DoEqualRangeSmall(const KX& k)\n\t{\n\t\tconst iterator itLower(lower_bound(k));\n\t\titerator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !static_cast<key_compare&>(*this)(k, itUpper->first))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<iterator, iterator>(itLower, itUpper);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multimap<K, T, C, A, RAC>::const_iterator, typename vector_multimap<K, T, C, A, RAC>::const_iterator>\n\tvector_multimap<K, T, C, A, RAC>::DoEqualRangeSmall(const KX& k) const\n\t{\n\t\tconst const_iterator itLower(lower_bound(k));\n\t\tconst_iterator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !static_cast<const key_compare&>(*this)(k, itUpper->first))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itUpper);\n\t}\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline bool operator==(const vector_multimap<K, T, C, A, RAC>& a, \n\t\t\t\t\t\t   const vector_multimap<K, T, C, A, RAC>& b) \n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(b.begin(), b.end(), a.begin());\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline bool operator<(const vector_multimap<K, T, C, A, RAC>& a,\n\t\t\t\t\t\t  const vector_multimap<K, T, C, A, RAC>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), a.value_comp());\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline bool operator!=(const vector_multimap<K, T, C, A, RAC>& a,\n\t\t\t\t\t\t   const vector_multimap<K, T, C, A, RAC>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline bool operator>(const vector_multimap<K, T, C, A, RAC>& a,\n\t\t\t\t\t\t  const vector_multimap<K, T, C, A, RAC>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline bool operator<=(const vector_multimap<K, T, C, A, RAC>& a,\n\t\t\t\t\t\t   const vector_multimap<K, T, C, A, RAC>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline bool operator>=(const vector_multimap<K, T, C, A, RAC>& a,\n\t\t\t\t\t\t   const vector_multimap<K, T, C, A, RAC>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename K, typename T, typename C, typename A, typename RAC>\n\tinline void swap(vector_multimap<K, T, C, A, RAC>& a,\n\t\t\t\t\t vector_multimap<K, T, C, A, RAC>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/vector_multiset.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//////////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////////\n// This file implements vector_multiset. It acts much like std::multiset, except \n// its underlying representation is a random access container such as vector. \n// These containers are sometimes also known as \"sorted vectors.\"  \n// vector_sets have an advantage over conventional sets in that their memory\n// is contiguous and node-less. The result is that lookups are faster, more \n// cache friendly (which potentially more so benefits speed), and the container\n// uses less memory. The downside is that inserting new items into the container\n// is slower if they are inserted in random order instead of in sorted order.\n// This tradeoff is well-worth it for many cases. Note that vector_multiset allows\n// you to use a deque or other random access container which may perform\n// better for you than vector.\n//\n// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n// that the modification of the container potentially invalidates all \n// existing iterators into the container, unlike what happens with conventional\n// sets and maps.\n// \n// This type could conceptually use a eastl::array as its underlying container,\n// however the current design requires an allocator aware container.\n// Consider using a fixed_vector instead.\n//////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_VECTOR_MULTISET_H\n#define EASTL_VECTOR_MULTISET_H\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/functional.h>\n#include <EASTL/vector.h>\n#include <EASTL/utility.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_VECTOR_MULTISET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_VECTOR_MULTISET_DEFAULT_NAME\n\t\t#define EASTL_VECTOR_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" vector_multiset\" // Unless the user overrides something, this is \"EASTL vector_multiset\".\n\t#endif\n\n\n\t/// EASTL_VECTOR_MULTISET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_VECTOR_MULTISET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_VECTOR_MULTISET_DEFAULT_ALLOCATOR allocator_type(EASTL_VECTOR_MULTISET_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// vector_multiset\n\t///\n\t/// Implements a multiset via a random access container such as a vector.\n\t/// This container is also known as a sorted_vector. We choose to call it \n\t/// vector_multiset, as that is a more consistent universally applicable name\n\t/// for it in this library.\n\t///\n\t/// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n\t/// that the modification of the container potentially invalidates all \n\t/// existing iterators into the container, unlike what happens with conventional\n\t/// sets and maps.\n\t/// \n\t/// This type could conceptually use a eastl::array as its underlying container,\n\t/// however the current design requires an allocator aware container.\n\t/// Consider using a fixed_vector instead.\n\t///\n\t/// To consider: std::multiset has the limitation that values in the set cannot\n\t/// be modified, with the idea that modifying them would change their sort\n\t/// order. We have the opportunity to make it so that values can be modified\n\t/// via changing iterators to be non-const, with the downside being that \n\t/// the container can get screwed up if the user screws up. Alternatively,\n\t/// we can do what std STL does and require the user to make their stored\n\t/// classes use 'mutable' as needed. See the C++ standard defect report\n\t/// #103 (DR 103) for a discussion of this.\n\t///\n\ttemplate <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType, \n\t\t\t  typename RandomAccessContainer = eastl::vector<Key, Allocator> >\n\tclass vector_multiset : protected Compare, public RandomAccessContainer\n\t{\n\tpublic:\n\t\ttypedef RandomAccessContainer                                           base_type;\n\t\ttypedef vector_multiset<Key, Compare, Allocator, RandomAccessContainer> this_type;\n\t\ttypedef Allocator                                                       allocator_type;\n\t\ttypedef Key                                                             key_type;\n\t\ttypedef Key                                                             value_type;\n\t\ttypedef Compare                                                         key_compare;\n\t\ttypedef Compare                                                         value_compare;\n\t\ttypedef value_type*                                                     pointer;\n\t\ttypedef const value_type*                                               const_pointer;\n\t\ttypedef value_type&                                                     reference;\n\t\ttypedef const value_type&                                               const_reference;\n\t\ttypedef typename base_type::size_type                                   size_type;\n\t\ttypedef typename base_type::difference_type                             difference_type;\n\t\ttypedef typename base_type::iterator                                    iterator;         // **Currently typedefing from iterator instead of const_iterator due to const issues **: Note that we typedef from const_iterator. This is by design, as sets are sorted and values cannot be modified. To consider: allow values to be modified and thus risk changing their sort values.\n\t\ttypedef typename base_type::const_iterator                              const_iterator;\n\t\ttypedef typename base_type::reverse_iterator                            reverse_iterator; // See notes directly above regarding const_iterator.\n\t\ttypedef typename base_type::const_reverse_iterator                      const_reverse_iterator;\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::get_allocator;\n\n\tpublic:\n\t\t// We have an empty ctor and a ctor that takes an allocator instead of one for both\n\t\t// because this way our RandomAccessContainer wouldn't be required to have an constructor\n\t\t// that takes allocator_type. \n\t\tvector_multiset();\n\t\texplicit vector_multiset(const allocator_type& allocator);\n\t\texplicit vector_multiset(const key_compare& comp, const allocator_type& allocator = EASTL_VECTOR_MULTISET_DEFAULT_ALLOCATOR);\n\t\tvector_multiset(const this_type& x);\n\t\tvector_multiset(this_type&& x);\n\t\tvector_multiset(this_type&& x, const allocator_type& allocator);\n\t\tvector_multiset(std::initializer_list<value_type> ilist, const key_compare& compare = key_compare(), const allocator_type& allocator = EASTL_VECTOR_MULTISET_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_multiset(InputIterator first, InputIterator last); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_multiset(InputIterator first, InputIterator last, const key_compare& compare); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tconst key_compare& key_comp() const;\n\t\tkey_compare&       key_comp();\n\n\t\tconst value_compare& value_comp() const;\n\t\tvalue_compare&       value_comp();\n\n\t\t// Inherited from base class:\n\t\t//\n\t\t//     allocator_type& get_allocator();\n\t\t//     void            set_allocator(const allocator_type& allocator);\n\t\t//\n\t\t//     iterator       begin();\n\t\t//     const_iterator begin() const;\n\t\t//     const_iterator cbegin() const;\n\t\t//\n\t\t//     iterator       end();\n\t\t//     const_iterator end() const;\n\t\t//     const_iterator cend() const;\n\t\t//\n\t\t//     reverse_iterator       rbegin();\n\t\t//     const_reverse_iterator rbegin() const;\n\t\t//     const_reverse_iterator crbegin() const;\n\t\t//\n\t\t//     reverse_iterator       rend();\n\t\t//     const_reverse_iterator rend() const;\n\t\t//     const_reverse_iterator crend() const;\n\t\t//\n\t\t//     size_type size() const;\n\t\t//     bool      empty() const;\n\t\t//     void      clear();\n\n\t\ttemplate <class... Args>\n\t\titerator emplace(Args&&... args);\n\n\t\ttemplate <class... Args> \n\t\titerator emplace_hint(const_iterator position, Args&&... args);\n\n\t\titerator insert(const value_type& value);   // The signature of this function was change in EASTL v2.05.00 from (the mistaken) pair<iterator, bool> to (the correct) iterator.\n\t\titerator insert(value_type&& value);\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\titerator insert(const_iterator position, value_type&& value);\n\t\tvoid     insert(std::initializer_list<value_type> ilist);\n\n\t\t// this function implicitly converts to value_type, which it shouldn't.\n\t\ttemplate <typename P, eastl::enable_if_t<!eastl::is_convertible_v<P&&, value_type> && eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Replace call with insert(value_type(...)) or emplace(...).\")\n\t\titerator insert(P&& otherValue);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(InputIterator first, InputIterator last);\n\n\t\ttemplate <typename Iter = iterator, typename eastl::enable_if<!eastl::is_same_v<Iter, const_iterator>, int>::type = 0>\n\t\titerator\t\t erase(iterator position) { return erase(const_iterator(position)); }\n\t\titerator         erase(const_iterator position);\n\t\titerator         erase(const_iterator first, const_iterator last);\n\t\tsize_type        erase(const key_type& k) { return DoErase(k); }\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, iterator> && !eastl::is_convertible_v<KX&&, const_iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type\t\t erase(KX&& k) { return DoErase(eastl::forward<KX>(k)); }\n\n\t\titerator       find(const key_type& k) { return DoFind(k); }\n\t\tconst_iterator find(const key_type& k) const { return DoFind(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       find(const KX& k) { return DoFind(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator find(const KX& k) const { return DoFind(k); }\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\titerator       find_as(const U& u, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\tconst_iterator find_as(const U& u, BinaryPredicate predicate) const;\n\n\t\tbool contains(const key_type& key) const { return DoFind(key) != end(); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tbool contains(const KX& key) const { return DoFind(key) != end(); }\n\n\t\tsize_type count(const key_type& k) const { return DoCount(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& k) const { return DoCount(k); }\n\n\t\titerator       lower_bound(const key_type& k) { return DoLowerBound(k); }\n\t\tconst_iterator lower_bound(const key_type& k) const { return DoLowerBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       lower_bound(const KX& k) { return DoLowerBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator lower_bound(const KX& k) const { return DoLowerBound(k); }\n\n\t\titerator       upper_bound(const key_type& k) { return DoUpperBound(k); }\n\t\tconst_iterator upper_bound(const key_type& k) const { return DoUpperBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       upper_bound(const KX& k) { return DoUpperBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator upper_bound(const KX& k) const { return DoUpperBound(k); }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const key_type& k) { return DoEqualRange(k); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const { return DoEqualRange(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& k) { return DoEqualRange(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& k) const { return DoEqualRange(k); }\n\n\t\t/// equal_range_small\n\t\t/// This is a special version of equal_range which is optimized for the \n\t\t/// case of there being few or no duplicated keys in the tree.\n\t\teastl::pair<iterator, iterator>             equal_range_small(const key_type& k) { return DoEqualRangeSmall(k); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const key_type& k) const { return DoEqualRangeSmall(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range_small(const KX& k) { return DoEqualRangeSmall(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range_small(const KX& k) const { return DoEqualRangeSmall(k); }\n\t\t\n\t\t// Functions which are disallowed due to being unsafe. \n\t\tvoid      push_back(const value_type& value) = delete;\n\t\treference push_back()                        = delete;\n\t\tvoid*     push_back_uninitialized()          = delete;\n\t\ttemplate <class... Args>\n\t\treference emplace_back(Args&&...)            = delete;\n\n\t\t// NOTE(rparolin): It is undefined behaviour if user code fails to ensure the container\n\t\t// invariants are respected by performing an explicit call to 'sort' before any other\n\t\t// operations on the container are performed that do not clear the elements.\n\t\t//\n\t\t// 'push_back_unsorted' and 'emplace_back_unsorted' do not satisfy container invariants\n\t\t// for being sorted. We provide these overloads explicitly labelled as '_unsorted' as an\n\t\t// optimization opportunity when batch inserting elements so users can defer the cost of\n\t\t// sorting the container once when all elements are contained. This was done to clarify\n\t\t// the intent of code by leaving a trace that a manual call to sort is required.\n\t\t// \n\t\ttemplate <typename... Args> decltype(auto) push_back_unsorted(Args&&... args)    \n\t\t\t{ return base_type::push_back(eastl::forward<Args>(args)...); }\n\t\ttemplate <typename... Args> decltype(auto) emplace_back_unsorted(Args&&... args) \n\t\t\t{ return base_type::emplace_back(eastl::forward<Args>(args)...); }\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tsize_type        DoErase(KX && k);\n\n\t\ttemplate<typename KX>\n\t\titerator DoFind(const KX & k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoFind(const KX & k) const;\n\n\t\ttemplate<typename KX>\n\t\tsize_type DoCount(const KX & k) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX & k);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX & k) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoLowerBound(const KX & k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoLowerBound(const KX & k) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoUpperBound(const KX & k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoUpperBound(const KX & k) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>\t\t\t\tDoEqualRangeSmall(const KX& k);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRangeSmall(const KX& k) const;\n\t}; // vector_multiset\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// vector_multiset\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset()\n\t\t: value_compare(), base_type()\n\t{\n\t\tget_allocator().set_name(EASTL_VECTOR_MULTISET_DEFAULT_NAME);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(const allocator_type& allocator)\n\t\t: value_compare(), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(const key_compare& comp, const allocator_type& allocator)\n\t\t: value_compare(comp), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(InputIterator first, InputIterator last)\n\t\t: value_compare(), base_type(EASTL_VECTOR_MULTISET_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(InputIterator first, InputIterator last, const key_compare& compare)\n\t\t: value_compare(compare), base_type(EASTL_VECTOR_MULTISET_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(const this_type& x)\n\t\t: value_compare(x), base_type(x)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(this_type&& x)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)))\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one. \n\t}\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(this_type&& x, const allocator_type& allocator)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)), allocator)\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one. \n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>::vector_multiset(std::initializer_list<value_type> ilist, const key_compare& compare, const allocator_type& allocator)\n\t\t: value_compare(compare), base_type(allocator)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>&\n\tvector_multiset<K, C, A, RAC>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\tvalue_compare::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>&\n\tvector_multiset<K, C, A, RAC>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(eastl::move(x));\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_multiset<K, C, A, RAC>&\n\tvector_multiset<K, C, A, RAC>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline void vector_multiset<K, C, A, RAC>::swap(this_type& x)\n\t{\n\t\tbase_type::swap(x);\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline const typename vector_multiset<K, C, A, RAC>::key_compare&\n\tvector_multiset<K, C, A, RAC>::key_comp() const\n\t{\n\t\treturn static_cast<const key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::key_compare&\n\tvector_multiset<K, C, A, RAC>::key_comp()\n\t{\n\t\treturn static_cast<key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline const typename vector_multiset<K, C, A, RAC>::value_compare&\n\tvector_multiset<K, C, A, RAC>::value_comp() const\n\t{\n\t\treturn static_cast<const value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::value_compare&\n\tvector_multiset<K, C, A, RAC>::value_comp()\n\t{\n\t\treturn static_cast<value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <class... Args>\n\ttypename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::emplace(Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\t\treturn insert(eastl::move(value));\n\t}\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <class... Args> \n\ttypename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::emplace_hint(const_iterator position, Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\t\treturn insert(position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::insert(const value_type& value)\n\t{\n\t\tconst iterator itUB(upper_bound(value));\n\t\treturn base_type::insert(itUB, value);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::insert(value_type&& value)\n\t{\n\t\tconst iterator itUB(upper_bound(value));\n\t\treturn base_type::insert(itUB, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename P, eastl::enable_if_t<!eastl::is_convertible_v<P&&, K> && eastl::is_constructible_v<K, P&&>, bool>>\n\ttypename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::insert(P&& otherValue)\n\t{\n\t\tvalue_type value(eastl::forward<P>(otherValue));\n\t\tconst iterator itUB(upper_bound(value));\n\t\treturn base_type::insert(itUB, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline void vector_multiset<K, C, A, RAC>::insert(std::initializer_list<value_type> ilist)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::insert(const_iterator position, const value_type& value)\n\t{\n\t\t// We assume that the user knows what he is doing and has supplied us with\n\t\t// a position that is right where value should be inserted (put in front of). \n\t\t// We do a test to see if the position is correct. If so then we insert, \n\t\t// if not then we ignore the input position. However, \n\n\t\tif((position == end()) || !value_compare::operator()(*position, value))  // If value is <= the element at position...\n\t\t{\n\t\t\tif((position == begin()) || !value_compare::operator()(value, *(position - 1))) // If value is >= the element before position...\n\t\t\t\treturn base_type::insert(position, value);\n\t\t}\n\n\t\t// In this case we have an incorrect position. We fall back to the regular insert function.\n\t\treturn insert(value);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttypename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::insert(const_iterator position, value_type&& value)\n\t{\n\t\tif((position == end()) || !value_compare::operator()(*position, value))  // If value is <= the element at position...\n\t\t{\n\t\t\tif((position == begin()) || !value_compare::operator()(value, *(position - 1))) // If value is >= the element before position...\n\t\t\t\treturn base_type::insert(position, eastl::move(value));\n\t\t}\n\n\t\t// In this case we have an incorrect position. We fall back to the regular insert function.\n\t\treturn insert(eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline void vector_multiset<K, C, A, RAC>::insert(InputIterator first, InputIterator last)\n\t{\n\t\t// To consider: Improve the speed of this by getting the length of the \n\t\t//              input range and resizing our container to that size\n\t\t//              before doing the insertions. We can't use reserve\n\t\t//              because we don't know if we are using a vector or not.\n\t\t//              Alternatively, force the user to do the reservation.\n\t\t// To consider: When inserting values that come from a container\n\t\t//              like this container, use the property that they are \n\t\t//              known to be sorted and speed up the inserts here.\n\t\tfor(; first != last; ++first)                               \n\t\t\tbase_type::insert(upper_bound(*first), *first);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator \n\tvector_multiset<K, C, A, RAC>::erase(const_iterator position)\n\t{\n\t\t// Note that we return iterator and not void. This allows for more efficient use of \n\t\t// the container and is consistent with the C++ language defect report #130 (DR 130)\n\t\treturn base_type::erase(position);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::erase(const_iterator first, const_iterator last)\n\t{\n\t\treturn base_type::erase(first, last);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::reverse_iterator \n\tvector_multiset<K, C, A, RAC>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(base_type::erase((++position).base()));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_multiset<K, C, A, RAC>::reverse_iterator\n\tvector_multiset<K, C, A, RAC>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\treturn reverse_iterator(base_type::erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::size_type\n\tvector_multiset<K, C, A, RAC>::DoErase(KX&& k)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(k));\n\n\t\tif(pairIts.first != pairIts.second)\n\t\t\tbase_type::erase(pairIts.first, pairIts.second);\n\n\t\treturn (size_type)eastl::distance(pairIts.first, pairIts.second); // This can result in any value >= 0.\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::DoFind(const KX& k)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(k));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::const_iterator\n\tvector_multiset<K, C, A, RAC>::DoFind(const KX& k) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(k));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(eastl::equal_range(begin(), end(), u, predicate));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_multiset<K, C, A, RAC>::const_iterator\n\tvector_multiset<K, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(eastl::equal_range(begin(), end(), u, predicate));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::size_type\n\tvector_multiset<K, C, A, RAC>::DoCount(const KX& k) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(k));\n\t\treturn (size_type)eastl::distance(pairIts.first, pairIts.second);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::DoLowerBound(const KX& k)\n\t{\n\t\treturn eastl::lower_bound(begin(), end(), k, static_cast<value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::const_iterator\n\tvector_multiset<K, C, A, RAC>::DoLowerBound(const KX& k) const\n\t{\n\t\treturn eastl::lower_bound(begin(), end(), k, static_cast<const value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::iterator\n\tvector_multiset<K, C, A, RAC>::DoUpperBound(const KX& k)\n\t{\n\t\treturn eastl::upper_bound(begin(), end(), k, static_cast<value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_multiset<K, C, A, RAC>::const_iterator\n\tvector_multiset<K, C, A, RAC>::DoUpperBound(const KX& k) const\n\t{\n\t\treturn eastl::upper_bound(begin(), end(), k, static_cast<const value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multiset<K, C, A, RAC>::iterator, typename vector_multiset<K, C, A, RAC>::iterator>\n\tvector_multiset<K, C, A, RAC>::DoEqualRange(const KX& k)\n\t{\n\t\treturn eastl::equal_range(begin(), end(), k, static_cast<value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multiset<K, C, A, RAC>::const_iterator, typename vector_multiset<K, C, A, RAC>::const_iterator>\n\tvector_multiset<K, C, A, RAC>::DoEqualRange(const KX& k) const\n\t{\n\t\treturn eastl::equal_range(begin(), end(), k, static_cast<const value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multiset<K, C, A, RAC>::iterator, typename vector_multiset<K, C, A, RAC>::iterator>\n\tvector_multiset<K, C, A, RAC>::DoEqualRangeSmall(const KX& k)\n\t{\n\t\tconst iterator itLower(lower_bound(k));\n\t\titerator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !value_compare::operator()(k, *itUpper))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<iterator, iterator>(itLower, itUpper);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_multiset<K, C, A, RAC>::const_iterator, typename vector_multiset<K, C, A, RAC>::const_iterator>\n\tvector_multiset<K, C, A, RAC>::DoEqualRangeSmall(const KX& k) const\n\t{\n\t\tconst const_iterator itLower(lower_bound(k));\n\t\tconst_iterator       itUpper(itLower);\n\n\t\twhile((itUpper != end()) && !value_compare::operator()(k, *itUpper))\n\t\t\t++itUpper;\n\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itUpper);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator==(const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& a, \n\t\t\t\t\t\t   const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& b) \n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(b.begin(), b.end(), a.begin());\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator<(const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t  const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), a.value_comp());\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator!=(const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator>(const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t  const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator<=(const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator>=(const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline void swap(vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t vector_multiset<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/vector_set.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n//////////////////////////////////////////////////////////////////////////////\n\n//////////////////////////////////////////////////////////////////////////////\n// This file implements vector_set. It acts much like std::set, except its \n// underlying representation is a random access container such as vector. \n// These containers are sometimes also known as \"sorted vectors.\"  \n// vector_sets have an advantage over conventional sets in that their memory\n// is contiguous and node-less. The result is that lookups are faster, more \n// cache friendly (which potentially more so benefits speed), and the container\n// uses less memory. The downside is that inserting new items into the container\n// is slower if they are inserted in random order instead of in sorted order.\n// This tradeoff is well-worth it for many cases. Note that vector_set allows\n// you to use a deque or other random access container which may perform\n// better for you than vector.\n//\n// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n// that the modification of the container potentially invalidates all \n// existing iterators into the container, unlike what happens with conventional\n// sets and maps.\n// \n// This type could conceptually use a eastl::array as its underlying container,\n// however the current design requires an allocator aware container.\n// Consider using a fixed_vector instead.\n//////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_VECTOR_SET_H\n#define EASTL_VECTOR_SET_H\n\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n#include <EASTL/functional.h>\n#include <EASTL/vector.h>\n#include <EASTL/utility.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/initializer_list.h>\n#include <stddef.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\n\n\nnamespace eastl\n{\n\n\t/// EASTL_VECTOR_SET_DEFAULT_NAME\n\t///\n\t/// Defines a default container name in the absence of a user-provided name.\n\t///\n\t#ifndef EASTL_VECTOR_SET_DEFAULT_NAME\n\t\t#define EASTL_VECTOR_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX \" vector_set\" // Unless the user overrides something, this is \"EASTL vector_set\".\n\t#endif\n\n\n\t/// EASTL_VECTOR_SET_DEFAULT_ALLOCATOR\n\t///\n\t#ifndef EASTL_VECTOR_SET_DEFAULT_ALLOCATOR\n\t\t#define EASTL_VECTOR_SET_DEFAULT_ALLOCATOR allocator_type(EASTL_VECTOR_SET_DEFAULT_NAME)\n\t#endif\n\n\n\n\t/// vector_set\n\t///\n\t/// Implements a set via a random access container such as a vector.\n\t/// This container is also known as a sorted_vector. We choose to call it \n\t/// vector_set, as that is a more consistent universally applicable name\n\t/// for it in this library.\n\t///\n\t/// Note that with vector_set, vector_multiset, vector_map, vector_multimap\n\t/// that the modification of the container potentially invalidates all \n\t/// existing iterators into the container, unlike what happens with conventional\n\t/// sets and maps.\n\t/// \n\t/// This type could conceptually use a eastl::array as its underlying container,\n\t/// however the current design requires an allocator aware container.\n\t/// Consider using a fixed_vector instead.\n\t///\n\t/// To consider: std::set has the limitation that values in the set cannot\n\t/// be modified, with the idea that modifying them would change their sort\n\t/// order. We have the opportunity to make it so that values can be modified\n\t/// via changing iterators to be non-const, with the downside being that \n\t/// the container can get screwed up if the user screws up. Alternatively,\n\t/// we can do what std STL does and require the user to make their stored\n\t/// classes use 'mutable' as needed. See the C++ standard defect report\n\t/// #103 (DR 103) for a discussion of this.\n\t///\n\ttemplate <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType, \n\t\t\t  typename RandomAccessContainer = eastl::vector<Key, Allocator> >\n\tclass vector_set : protected Compare, public RandomAccessContainer\n\t{\n\tpublic:\n\t\ttypedef RandomAccessContainer                                      base_type;\n\t\ttypedef vector_set<Key, Compare, Allocator, RandomAccessContainer> this_type;\n\t\ttypedef Allocator                                                  allocator_type;\n\t\ttypedef Key                                                        key_type;\n\t\ttypedef Key                                                        value_type;\n\t\ttypedef Compare                                                    key_compare;\n\t\ttypedef Compare                                                    value_compare;\n\t\ttypedef value_type*                                                pointer;\n\t\ttypedef const value_type*                                          const_pointer;\n\t\ttypedef value_type&                                                reference;\n\t\ttypedef const value_type&                                          const_reference;\n\t\ttypedef typename base_type::size_type                              size_type;\n\t\ttypedef typename base_type::difference_type                        difference_type;\n\t\ttypedef typename base_type::iterator                               iterator;         // **Currently typedefing from iterator instead of const_iterator due to const issues **: Note that we typedef from const_iterator. This is by design, as sets are sorted and values cannot be modified. To consider: allow values to be modified and thus risk changing their sort values.\n\t\ttypedef typename base_type::const_iterator                         const_iterator;\n\t\ttypedef typename base_type::reverse_iterator                       reverse_iterator; // See notes directly above regarding const_iterator.\n\t\ttypedef typename base_type::const_reverse_iterator                 const_reverse_iterator;\n\t\ttypedef eastl::pair<iterator, bool>                                insert_return_type;\n\n\t\tusing base_type::begin;\n\t\tusing base_type::end;\n\t\tusing base_type::get_allocator;\n\n\tpublic:\n\t\t// We have an empty ctor and a ctor that takes an allocator instead of one for both\n\t\t// because this way our RandomAccessContainer wouldn't be required to have an constructor\n\t\t// that takes allocator_type. \n\t\tvector_set();\n\t\texplicit vector_set(const allocator_type& allocator);\n\t\texplicit vector_set(const key_compare& compare, const allocator_type& allocator = EASTL_VECTOR_SET_DEFAULT_ALLOCATOR);\n\t\tvector_set(const this_type& x);\n\t\tvector_set(this_type&& x);\n\t\tvector_set(this_type&& x, const allocator_type& allocator);\n\t\tvector_set(std::initializer_list<value_type> ilist, const key_compare& compare = key_compare(), const allocator_type& allocator = EASTL_VECTOR_SET_DEFAULT_ALLOCATOR);\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_set(InputIterator first, InputIterator last); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\ttemplate <typename InputIterator>\n\t\tvector_set(InputIterator first, InputIterator last, const key_compare& compare); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.\n\n\t\tthis_type& operator=(const this_type& x);\n\t\tthis_type& operator=(std::initializer_list<value_type> ilist);\n\t\tthis_type& operator=(this_type&& x);\n\n\t\tvoid swap(this_type& x);\n\n\t\tconst key_compare& key_comp() const;\n\t\tkey_compare&       key_comp();\n\n\t\tconst value_compare& value_comp() const;\n\t\tvalue_compare&       value_comp();\n\n\t\t// Inherited from base class:\n\t\t//\n\t\t//     allocator_type& get_allocator();\n\t\t//     void            set_allocator(const allocator_type& allocator);\n\t\t//\n\t\t//     iterator       begin();\n\t\t//     const_iterator begin() const;\n\t\t//     const_iterator cbegin() const;\n\t\t//\n\t\t//     iterator       end();\n\t\t//     const_iterator end() const;\n\t\t//     const_iterator cend() const;\n\t\t//\n\t\t//     reverse_iterator       rbegin();\n\t\t//     const_reverse_iterator rbegin() const;\n\t\t//     const_reverse_iterator crbegin() const;\n\t\t//\n\t\t//     reverse_iterator       rend();\n\t\t//     const_reverse_iterator rend() const;\n\t\t//     const_reverse_iterator crend() const;\n\t\t//\n\t\t//     size_type size() const;\n\t\t//     bool      empty() const;\n\t\t//     void      clear();\n\n\t\ttemplate <class... Args>\n\t\teastl::pair<iterator, bool> emplace(Args&&... args);\n\n\t\ttemplate <class... Args> \n\t\titerator emplace_hint(const_iterator position, Args&&... args);\n\n\t\teastl::pair<iterator, bool> insert(const value_type& value);\n\t\teastl::pair<iterator, bool> insert(value_type&& value);\n\n\t\t// this function implicitly converts to value_type, which it shouldn't. Additionally, it does not correctly support heterogeneous insertion (unconditionally creates a key_type).\n\t\ttemplate <typename P, typename Cmp = Compare, eastl::enable_if_t<!eastl::is_convertible_v<P&&, value_type> && !eastl::detail::is_transparent_comparison_v<Cmp> && eastl::is_constructible_v<value_type, P&&>, bool> = true>\n\t\tEA_REMOVE_AT_2025_OCT_MSG(\"Replace call with insert(value_type(...)) or emplace(...) or declare container with a transparent comparator.\")\n\t\tpair<iterator, bool> insert(P&& otherValue);\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tpair<iterator, bool> insert(KX&& key);\n\n\t\titerator insert(const_iterator position, const value_type& value);\n\t\titerator insert(const_iterator position, value_type&& value);\n\n\t\tvoid insert(std::initializer_list<value_type> ilist);\n\n\t\ttemplate <typename InputIterator>\n\t\tvoid insert(InputIterator first, InputIterator last);\n\n\t\ttemplate <typename Iter = iterator, typename eastl::enable_if<!eastl::is_same_v<Iter, const_iterator>, int>::type = 0>\n\t\titerator  erase(iterator position) { return erase(const_iterator(position)); }\n\t\titerator  erase(const_iterator position);\n\t\titerator  erase(const_iterator first, const_iterator last);\n\t\tsize_type erase(const key_type& k) { return DoErase(k); }\n\n\t\treverse_iterator erase(const_reverse_iterator position);\n\t\treverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\n\t\ttemplate<typename KX, typename Cmp = Compare,\n\t\t\teastl::enable_if_t<!eastl::is_convertible_v<KX&&, iterator> && !eastl::is_convertible_v<KX&&, const_iterator>\n\t\t\t&& eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type erase(KX&& k) { return DoErase(eastl::forward<KX>(k)); }\n\n\t\titerator       find(const key_type& k) { return DoFind(k); }\n\t\tconst_iterator find(const key_type& k) const { return DoFind(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       find(const KX& k) { return DoFind(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator find(const KX& k) const { return DoFind(k); }\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\titerator       find_as(const U& u, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename BinaryPredicate>\n\t\tconst_iterator find_as(const U& u, BinaryPredicate predicate) const;\n\n\t\tbool contains(const key_type& key) const { return DoFind(key) != end(); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tbool contains(const KX& key) const { return DoFind(key) != end(); }\n\n\t\tsize_type count(const key_type& k) const { return DoCount(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tsize_type count(const KX& k) const { return DoCount(k); }\n\n\t\titerator       lower_bound(const key_type& k) { return DoLowerBound(k); }\n\t\tconst_iterator lower_bound(const key_type& k) const { return DoLowerBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       lower_bound(const KX& k) { return DoLowerBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator lower_bound(const KX& k) const { return DoLowerBound(k); }\n\n\t\titerator       upper_bound(const key_type& k) { return DoUpperBound(k); }\n\t\tconst_iterator upper_bound(const key_type& k) const { return DoUpperBound(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\titerator       upper_bound(const KX& k) { return DoUpperBound(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\tconst_iterator upper_bound(const KX& k) const { return DoUpperBound(k); }\n\n\t\teastl::pair<iterator, iterator>             equal_range(const key_type& k) { return DoEqualRange(k); }\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const { return DoEqualRange(k); }\n\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<iterator, iterator>             equal_range(const KX& k) { return DoEqualRange(k); }\n\t\ttemplate<typename KX, typename Cmp = Compare, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool> = true>\n\t\teastl::pair<const_iterator, const_iterator> equal_range(const KX& k) const { return DoEqualRange(k); }\n\n\t\ttemplate <typename U, typename BinaryPredicate> \n\t\teastl::pair<iterator, iterator>             equal_range(const U& u, BinaryPredicate predicate);\n\n\t\ttemplate <typename U, typename BinaryPredicate> \n\t\teastl::pair<const_iterator, const_iterator> equal_range(const U& u, BinaryPredicate) const;\n\n\t\t// Functions which are disallowed due to being unsafe. \n\t\tvoid      push_back(const value_type& value) = delete;\n\t\treference push_back()                        = delete;\n\t\tvoid*     push_back_uninitialized()          = delete;\n\t\ttemplate <class... Args>\n\t\treference emplace_back(Args&&...)            = delete;\n\n\t\t// NOTE(rparolin): It is undefined behaviour if user code fails to ensure the container\n\t\t// invariants are respected by performing an explicit call to 'sort' before any other\n\t\t// operations on the container are performed that do not clear the elements.\n\t\t//\n\t\t// 'push_back_unsorted' and 'emplace_back_unsorted' do not satisfy container invariants\n\t\t// for being sorted. We provide these overloads explicitly labelled as '_unsorted' as an\n\t\t// optimization opportunity when batch inserting elements so users can defer the cost of\n\t\t// sorting the container once when all elements are contained. This was done to clarify\n\t\t// the intent of code by leaving a trace that a manual call to sort is required.\n\t\t// \n\t\ttemplate <typename... Args> decltype(auto) push_back_unsorted(Args&&... args)    \n\t\t\t{ return base_type::push_back(eastl::forward<Args>(args)...); }\n\t\ttemplate <typename... Args> decltype(auto) emplace_back_unsorted(Args&&... args) \n\t\t\t{ return base_type::emplace_back(eastl::forward<Args>(args)...); }\n\n\tprivate:\n\t\ttemplate<typename KX>\n\t\tsize_type        DoErase(KX&& k);\n\n\t\ttemplate<typename KX>\n\t\titerator DoFind(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoFind(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\tsize_type DoCount(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\teastl::pair<iterator, iterator>             DoEqualRange(const KX& k);\n\t\ttemplate<typename KX>\n\t\teastl::pair<const_iterator, const_iterator> DoEqualRange(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoLowerBound(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoLowerBound(const KX& k) const;\n\n\t\ttemplate<typename KX>\n\t\titerator       DoUpperBound(const KX& k);\n\t\ttemplate<typename KX>\n\t\tconst_iterator DoUpperBound(const KX& k) const;\n\t}; // vector_set\n\n\n\n\n\n\t///////////////////////////////////////////////////////////////////////\n\t// vector_set\n\t///////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>::vector_set()\n\t\t: value_compare(), base_type()\n\t{\n\t\tget_allocator().set_name(EASTL_VECTOR_SET_DEFAULT_NAME);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>::vector_set(const allocator_type& allocator)\n\t\t: value_compare(), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>::vector_set(const key_compare& compare, const allocator_type& allocator)\n\t\t: value_compare(compare), base_type(allocator)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>::vector_set(const this_type& x)\n\t\t: value_compare(x), base_type(x)\n\t{\n\t\t// Empty\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>::vector_set(this_type&& x)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)))\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one. \n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>::vector_set(this_type&& x, const allocator_type& allocator)\n\t\t// careful to only copy / move the distinct base sub-objects of x:\n\t\t: value_compare(static_cast<value_compare&>(x)), base_type(eastl::move(static_cast<base_type&&>(x)), allocator)\n\t{\n\t\t// Empty. Note: x is left with empty contents but its original value_compare instead of the default one. \n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>::vector_set(std::initializer_list<value_type> ilist, const key_compare& compare, const allocator_type& allocator)\n\t\t: value_compare(compare), base_type(allocator)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_set<K, C, A, RAC>::vector_set(InputIterator first, InputIterator last)\n\t\t: value_compare(), base_type(EASTL_VECTOR_SET_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline vector_set<K, C, A, RAC>::vector_set(InputIterator first, InputIterator last, const key_compare& compare)\n\t\t: value_compare(compare), base_type(EASTL_VECTOR_SET_DEFAULT_ALLOCATOR)\n\t{\n\t\tinsert(first, last);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>&\n\tvector_set<K, C, A, RAC>::operator=(const this_type& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\tvalue_compare::operator=(x);\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>&\n\tvector_set<K, C, A, RAC>::operator=(this_type&& x)\n\t{\n\t\tbase_type::operator=(eastl::move(x));\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline vector_set<K, C, A, RAC>&\n\tvector_set<K, C, A, RAC>::operator=(std::initializer_list<value_type> ilist)\n\t{\n\t\tbase_type::clear();\n\t\tinsert(ilist.begin(), ilist.end());\n\t\treturn *this;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline void vector_set<K, C, A, RAC>::swap(this_type& x)\n\t{\n\t\tbase_type::swap(x);\n\t\tusing eastl::swap;\n\t\tswap(static_cast<value_compare&>(*this), static_cast<value_compare&>(x));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline const typename vector_set<K, C, A, RAC>::key_compare&\n\tvector_set<K, C, A, RAC>::key_comp() const\n\t{\n\t\treturn static_cast<const key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::key_compare&\n\tvector_set<K, C, A, RAC>::key_comp()\n\t{\n\t\treturn static_cast<key_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline const typename vector_set<K, C, A, RAC>::value_compare&\n\tvector_set<K, C, A, RAC>::value_comp() const\n\t{\n\t\treturn static_cast<const value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::value_compare&\n\tvector_set<K, C, A, RAC>::value_comp()\n\t{\n\t\treturn static_cast<value_compare&>(*this);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <class... Args>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::iterator, bool>\n\tvector_set<K, C, A, RAC>::emplace(Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\n\t\treturn insert(eastl::move(value));\n\t}\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <class... Args>\n\tinline typename vector_set<K, C, A, RAC>::iterator \n\tvector_set<K, C, A, RAC>::emplace_hint(const_iterator position, Args&&... args)\n\t{\n\t\t#if EASTL_USE_FORWARD_WORKAROUND\n\t\t\tauto value = value_type(eastl::forward<Args>(args)...);  // Workaround for compiler bug in VS2013 which results in a compiler internal crash while compiling this code.\n\t\t#else\n\t\t\tvalue_type  value(eastl::forward<Args>(args)...);\n\t\t#endif\n\n\t\treturn insert(position, eastl::move(value));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::iterator, bool>\n\tvector_set<K, C, A, RAC>::insert(const value_type& value)\n\t{\n\t\tconst iterator itLB(lower_bound(value));\n\n\t\tif((itLB != end()) && !value_compare::operator()(value, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, value), true);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::iterator, bool>\n\tvector_set<K, C, A, RAC>::insert(value_type&& value)\n\t{\n\t\tconst iterator itLB(lower_bound(value));\n\n\t\tif((itLB != end()) && !value_compare::operator()(value, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, eastl::move(value)), true);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename P, typename Cmp, eastl::enable_if_t<!eastl::is_convertible_v<P&&, K> && !eastl::detail::is_transparent_comparison_v<Cmp>&& eastl::is_constructible_v<K, P&&>, bool>>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::iterator, bool>\n\tvector_set<K, C, A, RAC>::insert(P&& otherValue)\n\t{\n\t\tvalue_type value(eastl::forward<P>(otherValue));\n\t\tconst iterator itLB(lower_bound(value));\n\n\t\tif ((itLB != end()) && !value_compare::operator()(value, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, eastl::move(value)), true);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate<typename KX, typename Cmp, eastl::enable_if_t<eastl::detail::is_transparent_comparison_v<Cmp>, bool>>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::iterator, bool>\n\tvector_set<K, C, A, RAC>::insert(KX&& key)\n\t{\n\t\tconst iterator itLB(lower_bound(key));\n\n\t\tif ((itLB != end()) && !value_compare::operator()(key, *itLB))\n\t\t\treturn eastl::pair<iterator, bool>(itLB, false);\n\t\treturn eastl::pair<iterator, bool>(base_type::insert(itLB, value_type(eastl::forward<KX>(key))), true);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::iterator \n\tvector_set<K, C, A, RAC>::insert(const_iterator position, const value_type& value)\n\t{\n\t\t// We assume that the user knows what he is doing and has supplied us with\n\t\t// a position that is right where value should be inserted (put in front of). \n\t\t// We do a test to see if the position is correct. If so then we insert, \n\t\t// if not then we ignore the input position.\n\n\t\tif((position == end()) || value_compare::operator()(value, *position))  // If the element at position is greater than value...\n\t\t{\n\t\t\tif((position == begin()) || value_compare::operator()(*(position - 1), value)) // If the element before position is less than value...\n\t\t\t\treturn base_type::insert(position, value);\n\t\t}\n\n\t\t// In this case we either have an incorrect position or value is already present.\n\t\t// We fall back to the regular insert function. An optimization would be to detect\n\t\t// that the element is already present, but that's only useful if the user supplied\n\t\t// a good position but a present element.\n\t\tconst eastl::pair<iterator, bool> result = insert(value);\n\n\t\treturn result.first;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::iterator \n\tvector_set<K, C, A, RAC>::insert(const_iterator position, value_type&& value)\n\t{\n\t\t// See the other version of this function for documentation.\n\t\tif((position == end()) || value_compare::operator()(value, *position))  // If the element at position is greater than value...\n\t\t{\n\t\t\tif((position == begin()) || value_compare::operator()(*(position - 1), value)) // If the element before position is less than value...\n\t\t\t\treturn base_type::insert(position, eastl::move(value));\n\t\t}\n\n\t\tconst eastl::pair<iterator, bool> result = insert(eastl::move(value));\n\n\t\treturn result.first;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline void vector_set<K, C, A, RAC>::insert(std::initializer_list<value_type> ilist)\n\t{\n\t\tinsert(ilist.begin(), ilist.end());\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename InputIterator>\n\tinline void vector_set<K, C, A, RAC>::insert(InputIterator first, InputIterator last)\n\t{\n\t\t// To consider: Improve the speed of this by getting the length of the \n\t\t//              input range and resizing our container to that size\n\t\t//              before doing the insertions. We can't use reserve\n\t\t//              because we don't know if we are using a vector or not.\n\t\t//              Alternatively, force the user to do the reservation.\n\t\t// To consider: When inserting values that come from a container\n\t\t//              like this container, use the property that they are \n\t\t//              known to be sorted and speed up the inserts here.\n\t\tfor(; first != last; ++first)\n\t\t\tinsert(*first);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::iterator \n\tvector_set<K, C, A, RAC>::erase(const_iterator position)\n\t{\n\t\t// Note that we return iterator and not void. This allows for more efficient use of \n\t\t// the container and is consistent with the C++ language defect report #130 (DR 130)\n\t\treturn base_type::erase(position);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::iterator\n\tvector_set<K, C, A, RAC>::erase(const_iterator first, const_iterator last)\n\t{\n\t\treturn base_type::erase(first, last);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::size_type\n\tvector_set<K, C, A, RAC>::DoErase(KX&& k)\n\t{\n\t\tconst iterator it(find(eastl::forward<KX>(k)));\n\n\t\tif(it != end()) // If it exists...\n\t\t{\n\t\t\terase(it);\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::reverse_iterator \n\tvector_set<K, C, A, RAC>::erase(const_reverse_iterator position)\n\t{\n\t\treturn reverse_iterator(base_type::erase((++position).base()));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\tinline typename vector_set<K, C, A, RAC>::reverse_iterator\n\tvector_set<K, C, A, RAC>::erase(const_reverse_iterator first, const_reverse_iterator last)\n\t{\n\t\treturn reverse_iterator(base_type::erase((++last).base(), (++first).base()));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::iterator\n\tvector_set<K, C, A, RAC>::DoFind(const KX& k)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(k));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::const_iterator\n\tvector_set<K, C, A, RAC>::DoFind(const KX& k) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(k));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_set<K, C, A, RAC>::iterator\n\tvector_set<K, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate)\n\t{\n\t\tconst eastl::pair<iterator, iterator> pairIts(equal_range(u, predicate));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename U, typename BinaryPredicate>\n\tinline typename vector_set<K, C, A, RAC>::const_iterator\n\tvector_set<K, C, A, RAC>::find_as(const U& u, BinaryPredicate predicate) const\n\t{\n\t\tconst eastl::pair<const_iterator, const_iterator> pairIts(equal_range(u, predicate));\n\t\treturn (pairIts.first != pairIts.second) ? pairIts.first : end();\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::size_type\n\tvector_set<K, C, A, RAC>::DoCount(const KX& k) const\n\t{\n\t\tconst const_iterator it(find(k));\n\t\treturn (it != end()) ? (size_type)1 : (size_type)0;\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::iterator\n\tvector_set<K, C, A, RAC>::DoLowerBound(const KX& k)\n\t{\n\t\treturn eastl::lower_bound(begin(), end(), k, static_cast<value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::const_iterator\n\tvector_set<K, C, A, RAC>::DoLowerBound(const KX& k) const\n\t{\n\t\treturn eastl::lower_bound(begin(), end(), k, static_cast<const value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::iterator\n\tvector_set<K, C, A, RAC>::DoUpperBound(const KX& k)\n\t{\n\t\treturn eastl::upper_bound(begin(), end(), k, static_cast<value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline typename vector_set<K, C, A, RAC>::const_iterator\n\tvector_set<K, C, A, RAC>::DoUpperBound(const KX& k) const\n\t{\n\t\treturn eastl::upper_bound(begin(), end(), k, static_cast<const value_compare&>(*this));\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::iterator, typename vector_set<K, C, A, RAC>::iterator>\n\tvector_set<K, C, A, RAC>::DoEqualRange(const KX& k)\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst iterator itLower(lower_bound(k));\n\n\t\tif((itLower == end()) || value_compare::operator()(k, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<iterator, iterator>(itLower, itLower);\n\n\t\titerator itUpper(itLower);\n\t\treturn eastl::pair<iterator, iterator>(itLower, ++itUpper);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate <typename KX>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::const_iterator, typename vector_set<K, C, A, RAC>::const_iterator>\n\tvector_set<K, C, A, RAC>::DoEqualRange(const KX& k) const\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst const_iterator itLower(lower_bound(k));\n\n\t\tif((itLower == end()) || value_compare::operator()(k, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itLower);\n\n\t\tconst_iterator itUpper(itLower);\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);\n\t}\n\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate<typename U, typename BinaryPredicate>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::iterator, typename vector_set<K, C, A, RAC>::iterator>\n\tvector_set<K, C, A, RAC>::equal_range(const U& u, BinaryPredicate predicate)\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst iterator itLower(eastl::lower_bound(begin(), end(), u, predicate));\n\n\t\tif((itLower == end()) || predicate(u, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<iterator, iterator>(itLower, itLower);\n\n\t\titerator itUpper(itLower);\n\t\treturn eastl::pair<iterator, iterator>(itLower, ++itUpper);\n\t}\n\n\ttemplate <typename K, typename C, typename A, typename RAC>\n\ttemplate<typename U, typename BinaryPredicate>\n\tinline eastl::pair<typename vector_set<K, C, A, RAC>::const_iterator, typename vector_set<K, C, A, RAC>::const_iterator>\n\tvector_set<K, C, A, RAC>::equal_range(const U& u, BinaryPredicate predicate) const\n\t{\n\t\t// The resulting range will either be empty or have one element,\n\t\t// so instead of doing two tree searches (one for lower_bound and \n\t\t// one for upper_bound), we do just lower_bound and see if the \n\t\t// result is a range of size zero or one.\n\t\tconst const_iterator itLower(eastl::lower_bound(begin(), end(), u, predicate));\n\n\t\tif((itLower == end()) || predicate(u, *itLower)) // If at the end or if (k is < itLower)...\n\t\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, itLower);\n\n\t\tconst_iterator itUpper(itLower);\n\t\treturn eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// global operators\n\t///////////////////////////////////////////////////////////////////////////\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator==(const vector_set<Key, Compare, Allocator, RandomAccessContainer>& a, \n\t\t\t\t\t\t   const vector_set<Key, Compare, Allocator, RandomAccessContainer>& b) \n\t{\n\t\treturn (a.size() == b.size()) && eastl::equal(b.begin(), b.end(), a.begin());\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator<(const vector_set<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t  const vector_set<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn eastl::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), a.value_comp());\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator!=(const vector_set<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_set<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(a == b);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator>(const vector_set<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t  const vector_set<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn b < a;\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator<=(const vector_set<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_set<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(b < a);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline bool operator>=(const vector_set<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t\t   const vector_set<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\treturn !(a < b);\n\t}\n\n\n\ttemplate <typename Key, typename Compare, typename Allocator, typename RandomAccessContainer>\n\tinline void swap(vector_set<Key, Compare, Allocator, RandomAccessContainer>& a,\n\t\t\t\t\t vector_set<Key, Compare, Allocator, RandomAccessContainer>& b)\n\t{\n\t\ta.swap(b);\n\t}\n\n\n} // namespace eastl\n\n\n#endif // Header include guard\n\n\n\n\n"
  },
  {
    "path": "include/EASTL/version.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_VERSION_H\n#define EASTL_VERSION_H\n\n#include <EABase/eabase.h>\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n\t#pragma once\n#endif\n\n#include <EASTL/internal/config.h>\n\n#endif\n"
  },
  {
    "path": "include/EASTL/weak_ptr.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_WEAK_PTR_H\n#define EASTL_WEAK_PTR_H\n\n\n// This header file is deprecated. The implementation has moved:\n#include <EASTL/shared_ptr.h>\n\n\n#endif\n\n\n\n"
  },
  {
    "path": "scripts/CMake/CommonCppFlags.cmake",
    "content": "#-------------------------------------------------------------------------------------------\n# Compiler Flag Detection\n#-------------------------------------------------------------------------------------------\ninclude(CheckCXXCompilerFlag)\n\ncheck_cxx_compiler_flag(\"-fchar8_t\" EASTL_HAS_FCHAR8T_FLAG)\ncheck_cxx_compiler_flag(\"/Zc:char8_t\" EASTL_HAS_ZCCHAR8T_FLAG)\n\nif(EASTL_HAS_FCHAR8T_FLAG)\n    set(EASTL_CHAR8T_FLAG \"-fchar8_t\")\n    set(EASTL_NO_CHAR8T_FLAG \"-fno-char8_t\")\nelseif(EASTL_HAS_ZCCHAR8T_FLAG)\n    set(EASTL_CHAR8T_FLAG \"/Zc:char8_t\")\n    set(EASTL_NO_CHAR8T_FLAG \"/Zc:char8_t-\")\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Compiler Flags\n#-------------------------------------------------------------------------------------------\nif(UNIX AND \"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"Intel\" )\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++11 -fasm-blocks\" )\nendif()\n\n# NOT LESS == GREATER_OR_EQUAL; CMake doesn't support this out of the box.\nif(CMAKE_CXX_COMPILER_ID MATCHES \"AppleClang\")\n    if(NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"6.2\"))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++17\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"6.2\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"6.1\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++14\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"6.1\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"4.3\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1y\")\n    endif()\n    # It seems Apple started changing version numbers after 3.1, going straight to 4.0 after 3.1.\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"4.3\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.1\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++11\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.1\")\n        message(FATAL_ERROR \"Building with a Apple clang version less than 3.1 is not supported.\")\n    endif()\nelseif(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_CXX_SIMULATE_ID MATCHES \"MSVC\") # clang, but not clang-cl.\n    # non-Apple clangs uses different versioning.\n    if(NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"5.0.0\"))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++17\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"5.0.0\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.5.0\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++14\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.5.0\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.2\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1y\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.2\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.0\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++11\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"3.0\")\n        message(FATAL_ERROR \"Building with a clang version less than 3.0 is not supported.\")\n    endif()\nelseif(CMAKE_CXX_COMPILER_ID MATCHES \"GNU\")\n    if(NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"7.0.0\"))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++17\")\n    endif()\n    if((CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"7.0.0\") AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"5.2.0\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++14\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"5.2.0\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"4.8.1\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1y\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"4.8.1\" AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"4.7.3\")))\n        SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++11\")\n    endif()\n    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS \"4.7.3\")\n        message(FATAL_ERROR \"Building with a gcc version less than 4.7.3 is not supported.\")\n    endif()\nelseif(CMAKE_CXX_COMPILER_ID MATCHES \"MSVC\")\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /std:c++latest /W4 /permissive-\")\nendif()\n\n\nif (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_CXX_COMPILER_ID MATCHES \"GNU\")\n    set(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG\")\n    set(CMAKE_C_FLAGS_DEBUG \"${CMAKE_C_FLAGS_DEBUG} -D_DEBUG\")\nendif()\n"
  },
  {
    "path": "scripts/build.sh",
    "content": "build_folder=build\n\nrm -rf $build_folder\nmkdir $build_folder\npushd $build_folder\n\ncmake .. -DEASTL_BUILD_TESTS:BOOL=OFF -DEASTL_BUILD_BENCHMARK:BOOL=ON\ncmake --build . --config Release -- -j 32 \n\ncmake .. -DEASTL_BUILD_TESTS:BOOL=OFF -DEASTL_BUILD_BENCHMARK:BOOL=OFF\ncmake --build . --config Release -- -j 32 \n \ncmake .. -DEASTL_BUILD_TESTS:BOOL=ON -DEASTL_BUILD_BENCHMARK:BOOL=OFF\ncmake --build . --config Release -- -j 32 \n \ncmake .. -DEASTL_BUILD_TESTS:BOOL=ON -DEASTL_BUILD_BENCHMARK:BOOL=ON\ncmake --build . --config Release -- -j 32 \ncmake --build . --config Debug -- -j 32\ncmake --build . --config RelWithDebInfo -- -j 32\ncmake --build . --config MinSizeRel -- -j 32\npushd test\nctest -C Release -V\nctest -C Debug -V\nctest -C RelWithDebInfo -V\nctest -C MinSizeRel -V\npopd\npopd\n"
  },
  {
    "path": "source/allocator_eastl.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/allocator.h>\n\n\n///////////////////////////////////////////////////////////////////////////////\n// ReadMe\n//\n// This file implements the default application allocator. \n// You can replace this allocator.cpp file with a different one,\n// you can define EASTL_USER_DEFINED_ALLOCATOR below to ignore this file,\n// or you can modify the EASTL config.h file to redefine how allocators work.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTL_USER_DEFINED_ALLOCATOR // If the user hasn't declared that he has defined an allocator implementation elsewhere...\n\n\tnamespace eastl\n\t{\n\n\t\t/// gDefaultAllocator\n\t\t/// Default global allocator instance. \n\t\tEASTL_API allocator   gDefaultAllocator;\n\t\tEASTL_API allocator* gpDefaultAllocator = &gDefaultAllocator;\n\n\t\tEASTL_API allocator* GetDefaultAllocator()\n\t\t{\n\t\t\treturn gpDefaultAllocator;\n\t\t}\n\n\t\tEASTL_API allocator* SetDefaultAllocator(allocator* pAllocator)\n\t\t{\n\t\t\tallocator* const pPrevAllocator = gpDefaultAllocator;\n\t\t\tgpDefaultAllocator = pAllocator;\n\t\t\treturn pPrevAllocator;\n\t\t}\n\n\t} // namespace eastl\n\n\n#endif // EASTL_USER_DEFINED_ALLOCATOR\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/assert.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/string.h>\n#include <EABase/eabase.h>\n\n#if defined(EA_PLATFORM_WINDOWS_KERNEL)\n\t#include <Wdm.h>\n#elif defined(EA_PLATFORM_MICROSOFT)\n\tEA_DISABLE_ALL_VC_WARNINGS();\n\t#if defined(EA_COMPILER_MSVC)\n\t\t#include <crtdbg.h>\n\t#endif\n\t#ifndef WIN32_LEAN_AND_MEAN\n\t\t#define WIN32_LEAN_AND_MEAN\n\t#endif\n\t#include <Windows.h>\n\tEA_RESTORE_ALL_VC_WARNINGS();\n#elif defined(EA_PLATFORM_ANDROID)\n\t#include <android/log.h>\n#else\n\t#include <stdio.h>\n#endif\n\n\n\n\nnamespace eastl\n{\n\tvoid AssertionFailureFunctionDefault(void* instructionPointer, const char* pExpression, void* pContext);\n\n\t/// gpAssertionFailureFunction\n\t///\n\t/// Global assertion failure function pointer. Set by SetAssertionFailureFunction.\n\t///\n\tEASTL_API EASTL_AssertionFailureFunctionEx gpAssertionFailureFunction        = AssertionFailureFunctionDefault;\n\tEASTL_API void*                          gpAssertionFailureFunctionContext = NULL;\n\n\n\n\t/// SetAssertionFailureFunction\n\t///\n\t/// Sets the function called when an assertion fails. If this function is not called\n\t/// by the user, a default function will be used. The user may supply a context parameter\n\t/// which will be passed back to the user in the function call. This is typically used\n\t/// to store a C++ 'this' pointer, though other things are possible.\n\t///\n\t/// There is no thread safety here, so the user needs to externally make sure that\n\t/// this function is not called in a thread-unsafe way. The easiest way to do this is\n\t/// to just call this function once from the main thread on application startup.\n\t///\n\tEASTL_API void SetAssertionFailureFunction(EASTL_AssertionFailureFunction pAssertionFailureFunction, void* pContext)\n\t{\n\t\tstatic EASTL_AssertionFailureFunction assertionFailureFunction_;\n\t\tassertionFailureFunction_ = pAssertionFailureFunction;\n\n\t\tgpAssertionFailureFunction = [](void* instructionPointer, const char* pExpression, void* pContext)\n\t\t{\n\t\t\tEA_UNUSED(instructionPointer);\n\n\t\t\tif (assertionFailureFunction_)\n\t\t\t\tassertionFailureFunction_(pExpression, pContext);\n\t\t};\n\t}\n\tEASTL_API void SetAssertionFailureFunction(EASTL_AssertionFailureFunctionEx pAssertionFailureFunction, void* pContext)\n\t{\n\t\tgpAssertionFailureFunction = pAssertionFailureFunction;\n\t\tgpAssertionFailureFunctionContext = pContext;\n\t}\n\n\n\t/// AssertionFailureFunctionDefault\n\t///\n\tvoid AssertionFailureFunctionDefault(void* instructionPointer, const char* pExpression, void* pContext)\n\t{\n\t\tEA_UNUSED(instructionPointer);\n\n\t\tAssertionFailureFunctionDefault(pExpression, pContext);\n\t}\n\tEASTL_API void AssertionFailureFunctionDefault(const char* pExpression, void* /*pContext*/)\n\t{\n\t\t#if EASTL_ASSERT_ENABLED\n\t\t\t#if defined(EA_PLATFORM_WINDOWS_KERNEL)\n\t\t\t\tDbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, \"%s\", pExpression);\n\t\t\t#elif defined(EA_PLATFORM_MICROSOFT)\n\t\t\t\tprintf(\"%s\\n\", pExpression); // Write the message to stdout\n\t\t\t\tif(::IsDebuggerPresent())\n\t\t\t\t{\n\t\t\t\t\tOutputDebugStringA(pExpression);\n\t\t\t\t}\n\t\t\t#elif defined(EA_PLATFORM_ANDROID)\n\t\t\t\t__android_log_print(ANDROID_LOG_INFO, \"PRINTF\", \"%s\\n\", pExpression);\n\t\t\t#else\n\t\t\t\tprintf(\"%s\\n\", pExpression); // Write the message to stdout, which happens to be the trace view for many console debug machines.\n\t\t\t#endif\n\t\t#else\n\t\t\tEA_UNUSED(pExpression);\n\t\t#endif\n\n\t\tEASTL_DEBUG_BREAK();\n\t}\n\n\t/// AssertionFailure\n\t///\n\tEASTL_API void AssertionFailure(const char* pExpression)\n\t{\n\t\tAssertionFailure(nullptr, pExpression);\n\t}\n\n\tEASTL_API void AssertionFailure(void* instructionPointer, const char* pExpression)\n\t{\n\t\tif (gpAssertionFailureFunction)\n\t\t\tgpAssertionFailureFunction(instructionPointer, pExpression, gpAssertionFailureFunctionContext);\n\t}\n\n\n} // namespace eastl\n"
  },
  {
    "path": "source/atomic.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/atomic.h>\n\n\nnamespace eastl\n{\n\nnamespace internal\n{\n\n\nstatic void EastlCompilerBarrierDataDependencyFunc(void*)\n{\n}\n\nvolatile CompilerBarrierDataDependencyFuncPtr gCompilerBarrierDataDependencyFunc = &EastlCompilerBarrierDataDependencyFunc;\n\n\n} // namespace internal\n\n} // namespace eastl\n"
  },
  {
    "path": "source/fixed_pool.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/fixed_pool.h>\n#include <EASTL/fixed_allocator.h>\n\n\n\nnamespace eastl\n{\n\n\n\tEASTL_API void fixed_pool_base::init(void* pMemory, size_t memorySize, size_t nodeSize,\n\t\t\t\t\t\t\t   size_t alignment, size_t /*alignmentOffset*/)\n\t{\n\t\t// To do: Support alignmentOffset.\n\n\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\tmnCurrentSize = 0;\n\t\t\tmnPeakSize    = 0;\n\t\t#endif\n\n\t\tif(pMemory)\n\t\t{\n\t\t\t// Assert that alignment is a power of 2 value (e.g. 1, 2, 4, 8, 16, etc.)\n\t\t\tEASTL_ASSERT((alignment & (alignment - 1)) == 0);\n\n\t\t\t// Make sure alignment is a valid value.\n\t\t\tif(alignment < 1)\n\t\t\t\talignment = 1;\n\n\t\t\tmpNext      = (Link*)(((uintptr_t)pMemory + (alignment - 1)) & ~(alignment - 1));\n\t\t\tmemorySize -= (uintptr_t)mpNext - (uintptr_t)pMemory;\n\t\t\tpMemory     = mpNext;\n\n\t\t\t// The node size must be at least as big as a Link, which itself is sizeof(void*).\n\t\t\tif(nodeSize < sizeof(Link))\n\t\t\t\tnodeSize = ((sizeof(Link) + (alignment - 1))) & ~(alignment - 1);\n\n\t\t\t// If the user passed in a memory size that wasn't a multiple of the node size,\n\t\t\t// we need to chop down the memory size so that the last node is not a whole node.\n\t\t\tmemorySize = (memorySize / nodeSize) * nodeSize;\n\n\t\t\tmpCapacity = (Link*)((uintptr_t)pMemory + memorySize);\n\t\t\tmpHead     = NULL;\n\t\t\tmnNodeSize = nodeSize;\n\t\t}\n\t}\n\n\n} // namespace eastl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/hashtable.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/hashtable.h>\n#include <EASTL/utility.h>\n#include <math.h>  // Not all compilers support <cmath> and std::ceilf(), which we need below.\n#include <stddef.h>\n\n\nEA_DISABLE_VC_WARNING(4267); // 'argument' : conversion from 'size_t' to 'const uint32_t', possible loss of data. This is a bogus warning resulting from a bug in VC++.\n\n\nnamespace eastl\n{\n\n\t/// gpEmptyBucketArray\n\t///\n\t/// A shared representation of an empty hash table. This is present so that\n\t/// a new empty hashtable allocates no memory. It has two entries, one for \n\t/// the first lone empty (NULL) bucket, and one for the non-NULL trailing sentinel.\n\t/// \n\tEASTL_API void* gpEmptyBucketArray[2] = { NULL, (void*)uintptr_t(~0) };\n\n\n\n\t/// gPrimeNumberArray\n\t///\n\t/// This is an array of prime numbers. This is the same set of prime\n\t/// numbers suggested by the C++ standard proposal. These are numbers\n\t/// which are separated by 8% per entry.\n\t/// \n\t/// To consider: Allow the user to specify their own prime number array.\n\t///\n\tconst uint32_t gPrimeNumberArray[] =\n\t{\n\t\t2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u,\n\t\t37u, 41u, 43u, 47u, 53u, 59u, 61u, 67u, 71u, 73u, 79u,\n\t\t83u, 89u, 97u, 103u, 109u, 113u, 127u, 137u, 139u, 149u,\n\t\t157u, 167u, 179u, 193u, 199u, 211u, 227u, 241u, 257u,\n\t\t277u, 293u, 313u, 337u, 359u, 383u, 409u, 439u, 467u,\n\t\t503u, 541u, 577u, 619u, 661u, 709u, 761u, 823u, 887u,\n\t\t953u, 1031u, 1109u, 1193u, 1289u, 1381u, 1493u, 1613u,\n\t\t1741u, 1879u, 2029u, 2179u, 2357u, 2549u, 2753u, 2971u,\n\t\t3209u, 3469u, 3739u, 4027u, 4349u, 4703u, 5087u, 5503u,\n\t\t5953u, 6427u, 6949u, 7517u, 8123u, 8783u, 9497u, 10273u,\n\t\t11113u, 12011u, 12983u, 14033u, 15173u, 16411u, 17749u,\n\t\t19183u, 20753u, 22447u, 24281u, 26267u, 28411u, 30727u,\n\t\t33223u, 35933u, 38873u, 42043u, 45481u, 49201u, 53201u,\n\t\t57557u, 62233u, 67307u, 72817u, 78779u, 85229u, 92203u,\n\t\t99733u, 107897u, 116731u, 126271u, 136607u, 147793u,\n\t\t159871u, 172933u, 187091u, 202409u, 218971u, 236897u,\n\t\t256279u, 277261u, 299951u, 324503u, 351061u, 379787u,\n\t\t410857u, 444487u, 480881u, 520241u, 562841u, 608903u,\n\t\t658753u, 712697u, 771049u, 834181u, 902483u, 976369u,\n\t\t1056323u, 1142821u, 1236397u, 1337629u, 1447153u, 1565659u,\n\t\t1693859u, 1832561u, 1982627u, 2144977u, 2320627u, 2510653u,\n\t\t2716249u, 2938679u, 3179303u, 3439651u, 3721303u, 4026031u,\n\t\t4355707u, 4712381u, 5098259u, 5515729u, 5967347u, 6456007u,\n\t\t6984629u, 7556579u, 8175383u, 8844859u, 9569143u, 10352717u,\n\t\t11200489u, 12117689u, 13109983u, 14183539u, 15345007u,\n\t\t16601593u, 17961079u, 19431899u, 21023161u, 22744717u,\n\t\t24607243u, 26622317u, 28802401u, 31160981u, 33712729u,\n\t\t36473443u, 39460231u, 42691603u, 46187573u, 49969847u,\n\t\t54061849u, 58488943u, 63278561u, 68460391u, 74066549u,\n\t\t80131819u, 86693767u, 93793069u, 101473717u, 109783337u,\n\t\t118773397u, 128499677u, 139022417u, 150406843u, 162723577u,\n\t\t176048909u, 190465427u, 206062531u, 222936881u, 241193053u,\n\t\t260944219u, 282312799u, 305431229u, 330442829u, 357502601u,\n\t\t386778277u, 418451333u, 452718089u, 489790921u, 529899637u,\n\t\t573292817u, 620239453u, 671030513u, 725980837u, 785430967u,\n\t\t849749479u, 919334987u, 994618837u, 1076067617u, 1164186217u,\n\t\t1259520799u, 1362662261u, 1474249943u, 1594975441u,\n\t\t1725587117u, 1866894511u, 2019773507u, 2185171673u,\n\t\t2364114217u, 2557710269u, 2767159799u, 2993761039u,\n\t\t3238918481u, 3504151727u, 3791104843u, 4101556399u,\n\t\t4294967291u,\n\t\t4294967291u // Sentinel so we don't have to test result of lower_bound\n\t};\n\n\n\t/// kPrimeCount\n\t///\n\t/// The number of prime numbers in gPrimeNumberArray.\n\t///\n\tconst uint32_t kPrimeCount = (sizeof(gPrimeNumberArray) / sizeof(gPrimeNumberArray[0]) - 1);\n\n\n\t/// GetPrevBucketCountOnly\n\t/// Return a bucket count no greater than nBucketCountHint.\n\t///\n\tuint32_t prime_rehash_policy::GetPrevBucketCountOnly(uint32_t nBucketCountHint)\n\t{\n\t\tconst uint32_t nPrime = *(eastl::upper_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nBucketCountHint) - 1);\n\t\treturn nPrime;\n\t}\n\n\n\t/// GetPrevBucketCount\n\t/// Return a bucket count no greater than nBucketCountHint.\n\t/// This function has a side effect of updating mnNextResize.\n\t///\n\tuint32_t prime_rehash_policy::GetPrevBucketCount(uint32_t nBucketCountHint) const\n\t{\n\t\tconst uint32_t nPrime = *(eastl::upper_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nBucketCountHint) - 1);\n\n\t\tmnNextResize = (uint32_t)ceilf(nPrime * mfMaxLoadFactor);\n\t\treturn nPrime;\n\t}\n\n\n\t/// GetNextBucketCount\n\t/// Return a prime no smaller than nBucketCountHint.\n\t/// This function has a side effect of updating mnNextResize.\n\t///\n\tuint32_t prime_rehash_policy::GetNextBucketCount(uint32_t nBucketCountHint) const\n\t{\n\t\tconst uint32_t nPrime = *eastl::lower_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nBucketCountHint);\n\n\t\tmnNextResize = (uint32_t)ceilf(nPrime * mfMaxLoadFactor);\n\t\treturn nPrime;\n\t}\n\n\n\t/// GetBucketCount\n\t/// Return the smallest prime p such that alpha p >= nElementCount, where alpha \n\t/// is the load factor. This function has a side effect of updating mnNextResize.\n\t///\n\tuint32_t prime_rehash_policy::GetBucketCount(uint32_t nElementCount) const\n\t{\n\t\tconst uint32_t nMinBucketCount = (uint32_t)(nElementCount / mfMaxLoadFactor);\n\t\tconst uint32_t nPrime          = *eastl::lower_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, nMinBucketCount);\n\n\t\tmnNextResize = (uint32_t)ceilf(nPrime * mfMaxLoadFactor);\n\t\treturn nPrime;\n\t}\n\n\n\t/// GetRehashRequired\n\t/// Finds the smallest prime p such that alpha p > nElementCount + nElementAdd.\n\t/// If p > nBucketCount, return pair<bool, uint32_t>(true, p); otherwise return\n\t/// pair<bool, uint32_t>(false, 0). In principle this isn't very different from GetBucketCount.\n\t/// This function has a side effect of updating mnNextResize.\n\t///\n\teastl::pair<bool, uint32_t>\n\tprime_rehash_policy::GetRehashRequired(uint32_t nBucketCount, uint32_t nElementCount, uint32_t nElementAdd) const\n\t{\n\t\tif((nElementCount + nElementAdd) > mnNextResize) // It is significant that we specify > next resize and not >= next resize.\n\t\t{\n\t\t\tif(nBucketCount == 1) // We force rehashing to occur if the bucket count is < 2.\n\t\t\t\tnBucketCount = 0;\n\n\t\t\tfloat fMinBucketCount = (nElementCount + nElementAdd) / mfMaxLoadFactor;\n\n\t\t\tif(fMinBucketCount > (float)nBucketCount)\n\t\t\t{\n\t\t\t\tfMinBucketCount       = eastl::max_alt(fMinBucketCount, mfGrowthFactor * nBucketCount);\n\t\t\t\tconst uint32_t nPrime = *eastl::lower_bound(gPrimeNumberArray, gPrimeNumberArray + kPrimeCount, (uint32_t)fMinBucketCount);\n\t\t\t\tmnNextResize          = (uint32_t)ceilf(nPrime * mfMaxLoadFactor);\n\n\t\t\t\treturn eastl::pair<bool, uint32_t>(true, nPrime);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tmnNextResize = (uint32_t)ceilf(nBucketCount * mfMaxLoadFactor);\n\t\t\t\treturn eastl::pair<bool, uint32_t>(false, (uint32_t)0);\n\t\t\t}\n\t\t}\n\n\t\treturn eastl::pair<bool, uint32_t>(false, (uint32_t)0);\n\t}\n\n\n} // namespace eastl\n\nEA_RESTORE_VC_WARNING();\n"
  },
  {
    "path": "source/intrusive_list.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n#include <EASTL/intrusive_list.h>\n\n\nnamespace eastl\n{\n\n\n\tEASTL_API void intrusive_list_base::reverse() EA_NOEXCEPT\n\t{\n\t\tintrusive_list_node* pNode = &mAnchor;\n\t\tdo {\n\t\t\tintrusive_list_node* const pTemp = pNode->mpNext;\n\t\t\tpNode->mpNext = pNode->mpPrev;\n\t\t\tpNode->mpPrev = pTemp;\n\t\t\tpNode         = pNode->mpPrev;\n\t\t} \n\t\twhile(pNode != &mAnchor);\n\t}\n\n\n\n\tEASTL_API bool intrusive_list_base::validate() const\n\t{\n\t\tconst intrusive_list_node *p = &mAnchor;\n\t\tconst intrusive_list_node *q = p;\n\n\t\t// We do two tests below:\n\t\t//\n\t\t// 1) Prev and next pointers are symmetric. We check (p->next->prev == p)\n\t\t//    for each node, which is enough to verify all links.\n\t\t//\n\t\t// 2) Loop check. We bump the q pointer at one-half rate compared to the\n\t\t//    p pointer; (p == q) if and only if we are at the start (which we\n\t\t//    don't check) or if there is a loop somewhere in the list.\n\n\t\tdo {\n\t\t\t// validate node (even phase)\n\t\t\tif (p->mpNext->mpPrev != p)\n\t\t\t\treturn false;               // broken linkage detected\n\n\t\t\t// bump only fast pointer\n\t\t\tp = p->mpNext;\n\t\t\tif (p == &mAnchor)\n\t\t\t\tbreak;\n\n\t\t\tif (p == q)\n\t\t\t\treturn false;               // loop detected\n\n\t\t\t// validate node (odd phase)\n\t\t\tif (p->mpNext->mpPrev != p)\n\t\t\t\treturn false;               // broken linkage detected\n\n\t\t\t// bump both pointers\n\t\t\tp = p->mpNext;\n\t\t\tq = q->mpNext;\n\n\t\t\tif (p == q)\n\t\t\t\treturn false;               // loop detected\n\n\t\t} while(p != &mAnchor);\n\n\t\treturn true;\n\t}\n\n\n} // namespace eastl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/numeric_limits.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/numeric_limits.h>\n\n\nnamespace eastl\n{\n\t// bool\n\tconstexpr bool                  numeric_limits<bool>::is_specialized;\n\tconstexpr int                   numeric_limits<bool>::digits;\n\tconstexpr int                   numeric_limits<bool>::digits10;\n\tconstexpr bool                  numeric_limits<bool>::is_signed;\n\tconstexpr bool                  numeric_limits<bool>::is_integer;\n\tconstexpr bool                  numeric_limits<bool>::is_exact;\n\tconstexpr int                   numeric_limits<bool>::radix;\n\tconstexpr int                   numeric_limits<bool>::min_exponent;\n\tconstexpr int                   numeric_limits<bool>::min_exponent10;\n\tconstexpr int                   numeric_limits<bool>::max_exponent;\n\tconstexpr int                   numeric_limits<bool>::max_exponent10;\n\tconstexpr bool                  numeric_limits<bool>::is_bounded;\n\tconstexpr bool                  numeric_limits<bool>::is_modulo;\n\tconstexpr bool                  numeric_limits<bool>::traps;\n\tconstexpr bool                  numeric_limits<bool>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<bool>::round_style;\n\tconstexpr bool                  numeric_limits<bool>::has_infinity;\n\tconstexpr bool                  numeric_limits<bool>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<bool>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<bool>::has_denorm;\n\tconstexpr bool                  numeric_limits<bool>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<bool>::is_iec559;\n\n\t// char\n\tconstexpr bool                  numeric_limits<char>::is_specialized;\n\tconstexpr int                   numeric_limits<char>::digits;\n\tconstexpr int                   numeric_limits<char>::digits10;\n\tconstexpr bool                  numeric_limits<char>::is_signed;\n\tconstexpr bool                  numeric_limits<char>::is_integer;\n\tconstexpr bool                  numeric_limits<char>::is_exact;\n\tconstexpr int                   numeric_limits<char>::radix;\n\tconstexpr int                   numeric_limits<char>::min_exponent;\n\tconstexpr int                   numeric_limits<char>::min_exponent10;\n\tconstexpr int                   numeric_limits<char>::max_exponent;\n\tconstexpr int                   numeric_limits<char>::max_exponent10;\n\tconstexpr bool                  numeric_limits<char>::is_bounded;\n\tconstexpr bool                  numeric_limits<char>::is_modulo;\n\tconstexpr bool                  numeric_limits<char>::traps;\n\tconstexpr bool                  numeric_limits<char>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<char>::round_style;\n\tconstexpr bool                  numeric_limits<char>::has_infinity;\n\tconstexpr bool                  numeric_limits<char>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<char>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<char>::has_denorm;\n\tconstexpr bool                  numeric_limits<char>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<char>::is_iec559;\n\n\t// unsigned char\n\tconstexpr bool                  numeric_limits<unsigned char>::is_specialized;\n\tconstexpr int                   numeric_limits<unsigned char>::digits;\n\tconstexpr int                   numeric_limits<unsigned char>::digits10;\n\tconstexpr bool                  numeric_limits<unsigned char>::is_signed;\n\tconstexpr bool                  numeric_limits<unsigned char>::is_integer;\n\tconstexpr bool                  numeric_limits<unsigned char>::is_exact;\n\tconstexpr int                   numeric_limits<unsigned char>::radix;\n\tconstexpr int                   numeric_limits<unsigned char>::min_exponent;\n\tconstexpr int                   numeric_limits<unsigned char>::min_exponent10;\n\tconstexpr int                   numeric_limits<unsigned char>::max_exponent;\n\tconstexpr int                   numeric_limits<unsigned char>::max_exponent10;\n\tconstexpr bool                  numeric_limits<unsigned char>::is_bounded;\n\tconstexpr bool                  numeric_limits<unsigned char>::is_modulo;\n\tconstexpr bool                  numeric_limits<unsigned char>::traps;\n\tconstexpr bool                  numeric_limits<unsigned char>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<unsigned char>::round_style;\n\tconstexpr bool                  numeric_limits<unsigned char>::has_infinity;\n\tconstexpr bool                  numeric_limits<unsigned char>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<unsigned char>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<unsigned char>::has_denorm;\n\tconstexpr bool                  numeric_limits<unsigned char>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<unsigned char>::is_iec559;\n\n\t// signed char\n\tconstexpr bool                  numeric_limits<signed char>::is_specialized;\n\tconstexpr int                   numeric_limits<signed char>::digits;\n\tconstexpr int                   numeric_limits<signed char>::digits10;\n\tconstexpr bool                  numeric_limits<signed char>::is_signed;\n\tconstexpr bool                  numeric_limits<signed char>::is_integer;\n\tconstexpr bool                  numeric_limits<signed char>::is_exact;\n\tconstexpr int                   numeric_limits<signed char>::radix;\n\tconstexpr int                   numeric_limits<signed char>::min_exponent;\n\tconstexpr int                   numeric_limits<signed char>::min_exponent10;\n\tconstexpr int                   numeric_limits<signed char>::max_exponent;\n\tconstexpr int                   numeric_limits<signed char>::max_exponent10;\n\tconstexpr bool                  numeric_limits<signed char>::is_bounded;\n\tconstexpr bool                  numeric_limits<signed char>::is_modulo;\n\tconstexpr bool                  numeric_limits<signed char>::traps;\n\tconstexpr bool                  numeric_limits<signed char>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<signed char>::round_style;\n\n\tconstexpr bool                  numeric_limits<signed char>::has_infinity;\n\tconstexpr bool                  numeric_limits<signed char>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<signed char>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<signed char>::has_denorm;\n\tconstexpr bool                  numeric_limits<signed char>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<signed char>::is_iec559;\n\n\t// wchar_t\n\tconstexpr bool                  numeric_limits<wchar_t>::is_specialized;\n\tconstexpr int                   numeric_limits<wchar_t>::digits;\n\tconstexpr int                   numeric_limits<wchar_t>::digits10;\n\tconstexpr bool                  numeric_limits<wchar_t>::is_signed;\n\tconstexpr bool                  numeric_limits<wchar_t>::is_integer;\n\tconstexpr bool                  numeric_limits<wchar_t>::is_exact;\n\tconstexpr int                   numeric_limits<wchar_t>::radix;\n\tconstexpr int                   numeric_limits<wchar_t>::min_exponent;\n\tconstexpr int                   numeric_limits<wchar_t>::min_exponent10;\n\tconstexpr int                   numeric_limits<wchar_t>::max_exponent;\n\tconstexpr int                   numeric_limits<wchar_t>::max_exponent10;\n\tconstexpr bool                  numeric_limits<wchar_t>::is_bounded;\n\tconstexpr bool                  numeric_limits<wchar_t>::is_modulo;\n\tconstexpr bool                  numeric_limits<wchar_t>::traps;\n\tconstexpr bool                  numeric_limits<wchar_t>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<wchar_t>::round_style;\n\tconstexpr bool                  numeric_limits<wchar_t>::has_infinity;\n\tconstexpr bool                  numeric_limits<wchar_t>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<wchar_t>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<wchar_t>::has_denorm;\n\tconstexpr bool                  numeric_limits<wchar_t>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<wchar_t>::is_iec559;\n\n\t// char8_t\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE // If char8_t is a true unique type (as called for by the C++20 Standard)\n\t\tconstexpr bool                  numeric_limits<char8_t>::is_specialized;\n\t\tconstexpr int                   numeric_limits<char8_t>::digits;\n\t\tconstexpr int                   numeric_limits<char8_t>::digits10;\n\t\tconstexpr bool                  numeric_limits<char8_t>::is_signed;\n\t\tconstexpr bool                  numeric_limits<char8_t>::is_integer;\n\t\tconstexpr bool                  numeric_limits<char8_t>::is_exact;\n\t\tconstexpr int                   numeric_limits<char8_t>::radix;\n\t\tconstexpr int                   numeric_limits<char8_t>::min_exponent;\n\t\tconstexpr int                   numeric_limits<char8_t>::min_exponent10;\n\t\tconstexpr int                   numeric_limits<char8_t>::max_exponent;\n\t\tconstexpr int                   numeric_limits<char8_t>::max_exponent10;\n\t\tconstexpr bool                  numeric_limits<char8_t>::is_bounded;\n\t\tconstexpr bool                  numeric_limits<char8_t>::is_modulo;\n\t\tconstexpr bool                  numeric_limits<char8_t>::traps;\n\t\tconstexpr bool                  numeric_limits<char8_t>::tinyness_before;\n\t\tconstexpr float_round_style     numeric_limits<char8_t>::round_style;\n\t\tconstexpr bool                  numeric_limits<char8_t>::has_infinity;\n\t\tconstexpr bool                  numeric_limits<char8_t>::has_quiet_NaN;\n\t\tconstexpr bool                  numeric_limits<char8_t>::has_signaling_NaN;\n\t\tconstexpr float_denorm_style    numeric_limits<char8_t>::has_denorm;\n\t\tconstexpr bool                  numeric_limits<char8_t>::has_denorm_loss;\n\t\tconstexpr bool                  numeric_limits<char8_t>::is_iec559;\n\t#endif\n\n\t// char16_t\n\t#if EA_CHAR16_NATIVE // If char16_t is a true unique type (as called for by the C++11 Standard)...\n\t\tconstexpr bool                  numeric_limits<char16_t>::is_specialized;\n\t\tconstexpr int                   numeric_limits<char16_t>::digits;\n\t\tconstexpr int                   numeric_limits<char16_t>::digits10;\n\t\tconstexpr bool                  numeric_limits<char16_t>::is_signed;\n\t\tconstexpr bool                  numeric_limits<char16_t>::is_integer;\n\t\tconstexpr bool                  numeric_limits<char16_t>::is_exact;\n\t\tconstexpr int                   numeric_limits<char16_t>::radix;\n\t\tconstexpr int                   numeric_limits<char16_t>::min_exponent;\n\t\tconstexpr int                   numeric_limits<char16_t>::min_exponent10;\n\t\tconstexpr int                   numeric_limits<char16_t>::max_exponent;\n\t\tconstexpr int                   numeric_limits<char16_t>::max_exponent10;\n\t\tconstexpr bool                  numeric_limits<char16_t>::is_bounded;\n\t\tconstexpr bool                  numeric_limits<char16_t>::is_modulo;\n\t\tconstexpr bool                  numeric_limits<char16_t>::traps;\n\t\tconstexpr bool                  numeric_limits<char16_t>::tinyness_before;\n\t\tconstexpr float_round_style     numeric_limits<char16_t>::round_style;\n\t\tconstexpr bool                  numeric_limits<char16_t>::has_infinity;\n\t\tconstexpr bool                  numeric_limits<char16_t>::has_quiet_NaN;\n\t\tconstexpr bool                  numeric_limits<char16_t>::has_signaling_NaN;\n\t\tconstexpr float_denorm_style    numeric_limits<char16_t>::has_denorm;\n\t\tconstexpr bool                  numeric_limits<char16_t>::has_denorm_loss;\n\t\tconstexpr bool                  numeric_limits<char16_t>::is_iec559;\n\t#endif\n\n\t// char32_t\n\t#if EA_CHAR32_NATIVE // If char32_t is a true unique type (as called for by the C++11 Standard)...\n\t\tconstexpr bool                  numeric_limits<char32_t>::is_specialized;\n\t\tconstexpr int                   numeric_limits<char32_t>::digits;\n\t\tconstexpr int                   numeric_limits<char32_t>::digits10;\n\t\tconstexpr bool                  numeric_limits<char32_t>::is_signed;\n\t\tconstexpr bool                  numeric_limits<char32_t>::is_integer;\n\t\tconstexpr bool                  numeric_limits<char32_t>::is_exact;\n\t\tconstexpr int                   numeric_limits<char32_t>::radix;\n\t\tconstexpr int                   numeric_limits<char32_t>::min_exponent;\n\t\tconstexpr int                   numeric_limits<char32_t>::min_exponent10;\n\t\tconstexpr int                   numeric_limits<char32_t>::max_exponent;\n\t\tconstexpr int                   numeric_limits<char32_t>::max_exponent10;\n\t\tconstexpr bool                  numeric_limits<char32_t>::is_bounded;\n\t\tconstexpr bool                  numeric_limits<char32_t>::is_modulo;\n\t\tconstexpr bool                  numeric_limits<char32_t>::traps;\n\t\tconstexpr bool                  numeric_limits<char32_t>::tinyness_before;\n\t\tconstexpr float_round_style     numeric_limits<char32_t>::round_style;\n\t\tconstexpr bool                  numeric_limits<char32_t>::has_infinity;\n\t\tconstexpr bool                  numeric_limits<char32_t>::has_quiet_NaN;\n\t\tconstexpr bool                  numeric_limits<char32_t>::has_signaling_NaN;\n\t\tconstexpr float_denorm_style    numeric_limits<char32_t>::has_denorm;\n\t\tconstexpr bool                  numeric_limits<char32_t>::has_denorm_loss;\n\t\tconstexpr bool                  numeric_limits<char32_t>::is_iec559;\n\t#endif\n\t\n\t// unsigned short\n\tconstexpr bool                  numeric_limits<unsigned short>::is_specialized;\n\tconstexpr int                   numeric_limits<unsigned short>::digits;\n\tconstexpr int                   numeric_limits<unsigned short>::digits10;\n\tconstexpr bool                  numeric_limits<unsigned short>::is_signed;\n\tconstexpr bool                  numeric_limits<unsigned short>::is_integer;\n\tconstexpr bool                  numeric_limits<unsigned short>::is_exact;\n\tconstexpr int                   numeric_limits<unsigned short>::radix;\n\tconstexpr int                   numeric_limits<unsigned short>::min_exponent;\n\tconstexpr int                   numeric_limits<unsigned short>::min_exponent10;\n\tconstexpr int                   numeric_limits<unsigned short>::max_exponent;\n\tconstexpr int                   numeric_limits<unsigned short>::max_exponent10;\n\tconstexpr bool                  numeric_limits<unsigned short>::is_bounded;\n\tconstexpr bool                  numeric_limits<unsigned short>::is_modulo;\n\tconstexpr bool                  numeric_limits<unsigned short>::traps;\n\tconstexpr bool                  numeric_limits<unsigned short>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<unsigned short>::round_style;\n\tconstexpr bool                  numeric_limits<unsigned short>::has_infinity;\n\tconstexpr bool                  numeric_limits<unsigned short>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<unsigned short>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<unsigned short>::has_denorm;\n\tconstexpr bool                  numeric_limits<unsigned short>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<unsigned short>::is_iec559;\n\n\t// short\n\tconstexpr bool                  numeric_limits<short>::is_specialized;\n\tconstexpr int                   numeric_limits<short>::digits;\n\tconstexpr int                   numeric_limits<short>::digits10;\n\tconstexpr bool                  numeric_limits<short>::is_signed;\n\tconstexpr bool                  numeric_limits<short>::is_integer;\n\tconstexpr bool                  numeric_limits<short>::is_exact;\n\tconstexpr int                   numeric_limits<short>::radix;\n\tconstexpr int                   numeric_limits<short>::min_exponent;\n\tconstexpr int                   numeric_limits<short>::min_exponent10;\n\tconstexpr int                   numeric_limits<short>::max_exponent;\n\tconstexpr int                   numeric_limits<short>::max_exponent10;\n\tconstexpr bool                  numeric_limits<short>::is_bounded;\n\tconstexpr bool                  numeric_limits<short>::is_modulo;\n\tconstexpr bool                  numeric_limits<short>::traps;\n\tconstexpr bool                  numeric_limits<short>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<short>::round_style;\n\tconstexpr bool                  numeric_limits<short>::has_infinity;\n\tconstexpr bool                  numeric_limits<short>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<short>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<short>::has_denorm;\n\tconstexpr bool                  numeric_limits<short>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<short>::is_iec559;\n\n\t// unsigned int\n\tconstexpr bool                  numeric_limits<unsigned int>::is_specialized;\n\tconstexpr int                   numeric_limits<unsigned int>::digits;\n\tconstexpr int                   numeric_limits<unsigned int>::digits10;\n\tconstexpr bool                  numeric_limits<unsigned int>::is_signed;\n\tconstexpr bool                  numeric_limits<unsigned int>::is_integer;\n\tconstexpr bool                  numeric_limits<unsigned int>::is_exact;\n\tconstexpr int                   numeric_limits<unsigned int>::radix;\n\tconstexpr int                   numeric_limits<unsigned int>::min_exponent;\n\tconstexpr int                   numeric_limits<unsigned int>::min_exponent10;\n\tconstexpr int                   numeric_limits<unsigned int>::max_exponent;\n\tconstexpr int                   numeric_limits<unsigned int>::max_exponent10;\n\tconstexpr bool                  numeric_limits<unsigned int>::is_bounded;\n\tconstexpr bool                  numeric_limits<unsigned int>::is_modulo;\n\tconstexpr bool                  numeric_limits<unsigned int>::traps;\n\tconstexpr bool                  numeric_limits<unsigned int>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<unsigned int>::round_style;\n\tconstexpr bool                  numeric_limits<unsigned int>::has_infinity;\n\tconstexpr bool                  numeric_limits<unsigned int>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<unsigned int>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<unsigned int>::has_denorm;\n\tconstexpr bool                  numeric_limits<unsigned int>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<unsigned int>::is_iec559;\n\n\t// int\n\tconstexpr bool                  numeric_limits<int>::is_specialized;\n\tconstexpr int                   numeric_limits<int>::digits;\n\tconstexpr int                   numeric_limits<int>::digits10;\n\tconstexpr bool                  numeric_limits<int>::is_signed;\n\tconstexpr bool                  numeric_limits<int>::is_integer;\n\tconstexpr bool                  numeric_limits<int>::is_exact;\n\tconstexpr int                   numeric_limits<int>::radix;\n\tconstexpr int                   numeric_limits<int>::min_exponent;\n\tconstexpr int                   numeric_limits<int>::min_exponent10;\n\tconstexpr int                   numeric_limits<int>::max_exponent;\n\tconstexpr int                   numeric_limits<int>::max_exponent10;\n\tconstexpr bool                  numeric_limits<int>::is_bounded;\n\tconstexpr bool                  numeric_limits<int>::is_modulo;\n\tconstexpr bool                  numeric_limits<int>::traps;\n\tconstexpr bool                  numeric_limits<int>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<int>::round_style;\n\tconstexpr bool                  numeric_limits<int>::has_infinity;\n\tconstexpr bool                  numeric_limits<int>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<int>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<int>::has_denorm;\n\tconstexpr bool                  numeric_limits<int>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<int>::is_iec559;\n\n\t// unsigned long\n\tconstexpr bool                  numeric_limits<unsigned long>::is_specialized;\n\tconstexpr int                   numeric_limits<unsigned long>::digits;\n\tconstexpr int                   numeric_limits<unsigned long>::digits10;\n\tconstexpr bool                  numeric_limits<unsigned long>::is_signed;\n\tconstexpr bool                  numeric_limits<unsigned long>::is_integer;\n\tconstexpr bool                  numeric_limits<unsigned long>::is_exact;\n\tconstexpr int                   numeric_limits<unsigned long>::radix;\n\tconstexpr int                   numeric_limits<unsigned long>::min_exponent;\n\tconstexpr int                   numeric_limits<unsigned long>::min_exponent10;\n\tconstexpr int                   numeric_limits<unsigned long>::max_exponent;\n\tconstexpr int                   numeric_limits<unsigned long>::max_exponent10;\n\tconstexpr bool                  numeric_limits<unsigned long>::is_bounded;\n\tconstexpr bool                  numeric_limits<unsigned long>::is_modulo;\n\tconstexpr bool                  numeric_limits<unsigned long>::traps;\n\tconstexpr bool                  numeric_limits<unsigned long>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<unsigned long>::round_style;\n\tconstexpr bool                  numeric_limits<unsigned long>::has_infinity;\n\tconstexpr bool                  numeric_limits<unsigned long>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<unsigned long>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<unsigned long>::has_denorm;\n\tconstexpr bool                  numeric_limits<unsigned long>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<unsigned long>::is_iec559;\n\n\t// long\n\tconstexpr bool                  numeric_limits<long>::is_specialized;\n\tconstexpr int                   numeric_limits<long>::digits;\n\tconstexpr int                   numeric_limits<long>::digits10;\n\tconstexpr bool                  numeric_limits<long>::is_signed;\n\tconstexpr bool                  numeric_limits<long>::is_integer;\n\tconstexpr bool                  numeric_limits<long>::is_exact;\n\tconstexpr int                   numeric_limits<long>::radix;\n\tconstexpr int                   numeric_limits<long>::min_exponent;\n\tconstexpr int                   numeric_limits<long>::min_exponent10;\n\tconstexpr int                   numeric_limits<long>::max_exponent;\n\tconstexpr int                   numeric_limits<long>::max_exponent10;\n\tconstexpr bool                  numeric_limits<long>::is_bounded;\n\tconstexpr bool                  numeric_limits<long>::is_modulo;\n\tconstexpr bool                  numeric_limits<long>::traps;\n\tconstexpr bool                  numeric_limits<long>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<long>::round_style;\n\tconstexpr bool                  numeric_limits<long>::has_infinity;\n\tconstexpr bool                  numeric_limits<long>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<long>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<long>::has_denorm;\n\tconstexpr bool                  numeric_limits<long>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<long>::is_iec559;\n\n\t// unsigned long long\n\tconstexpr bool                  numeric_limits<unsigned long long>::is_specialized;\n\tconstexpr int                   numeric_limits<unsigned long long>::digits;\n\tconstexpr int                   numeric_limits<unsigned long long>::digits10;\n\tconstexpr bool                  numeric_limits<unsigned long long>::is_signed;\n\tconstexpr bool                  numeric_limits<unsigned long long>::is_integer;\n\tconstexpr bool                  numeric_limits<unsigned long long>::is_exact;\n\tconstexpr int                   numeric_limits<unsigned long long>::radix;\n\tconstexpr int                   numeric_limits<unsigned long long>::min_exponent;\n\tconstexpr int                   numeric_limits<unsigned long long>::min_exponent10;\n\tconstexpr int                   numeric_limits<unsigned long long>::max_exponent;\n\tconstexpr int                   numeric_limits<unsigned long long>::max_exponent10;\n\tconstexpr bool                  numeric_limits<unsigned long long>::is_bounded;\n\tconstexpr bool                  numeric_limits<unsigned long long>::is_modulo;\n\tconstexpr bool                  numeric_limits<unsigned long long>::traps;\n\tconstexpr bool                  numeric_limits<unsigned long long>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<unsigned long long>::round_style;\n\tconstexpr bool                  numeric_limits<unsigned long long>::has_infinity;\n\tconstexpr bool                  numeric_limits<unsigned long long>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<unsigned long long>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<unsigned long long>::has_denorm;\n\tconstexpr bool                  numeric_limits<unsigned long long>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<unsigned long long>::is_iec559;\n\n\t// long long\n\tconstexpr bool                  numeric_limits<long long>::is_specialized;\n\tconstexpr int                   numeric_limits<long long>::digits;\n\tconstexpr int                   numeric_limits<long long>::digits10;\n\tconstexpr bool                  numeric_limits<long long>::is_signed;\n\tconstexpr bool                  numeric_limits<long long>::is_integer;\n\tconstexpr bool                  numeric_limits<long long>::is_exact;\n\tconstexpr int                   numeric_limits<long long>::radix;\n\tconstexpr int                   numeric_limits<long long>::min_exponent;\n\tconstexpr int                   numeric_limits<long long>::min_exponent10;\n\tconstexpr int                   numeric_limits<long long>::max_exponent;\n\tconstexpr int                   numeric_limits<long long>::max_exponent10;\n\tconstexpr bool                  numeric_limits<long long>::is_bounded;\n\tconstexpr bool                  numeric_limits<long long>::is_modulo;\n\tconstexpr bool                  numeric_limits<long long>::traps;\n\tconstexpr bool                  numeric_limits<long long>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<long long>::round_style;\n\tconstexpr bool                  numeric_limits<long long>::has_infinity;\n\tconstexpr bool                  numeric_limits<long long>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<long long>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<long long>::has_denorm;\n\tconstexpr bool                  numeric_limits<long long>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<long long>::is_iec559;\n\n\t// __uint128_t\n\t#if (EA_COMPILER_INTMAX_SIZE >= 16) && (defined(EA_COMPILER_GNUC) || defined(__clang__)) // If __int128_t/__uint128_t is supported...\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::is_specialized;\n\t\tconstexpr int                   numeric_limits<__uint128_t>::digits;\n\t\tconstexpr int                   numeric_limits<__uint128_t>::digits10;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::is_signed;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::is_integer;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::is_exact;\n\t\tconstexpr int                   numeric_limits<__uint128_t>::radix;\n\t\tconstexpr int                   numeric_limits<__uint128_t>::min_exponent;\n\t\tconstexpr int                   numeric_limits<__uint128_t>::min_exponent10;\n\t\tconstexpr int                   numeric_limits<__uint128_t>::max_exponent;\n\t\tconstexpr int                   numeric_limits<__uint128_t>::max_exponent10;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::is_bounded;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::is_modulo;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::traps;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::tinyness_before;\n\t\tconstexpr float_round_style     numeric_limits<__uint128_t>::round_style;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::has_infinity;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::has_quiet_NaN;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::has_signaling_NaN;\n\t\tconstexpr float_denorm_style    numeric_limits<__uint128_t>::has_denorm;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::has_denorm_loss;\n\t\tconstexpr bool                  numeric_limits<__uint128_t>::is_iec559;\n\t#endif\n\n\t// __int128_t\n\t#if (EA_COMPILER_INTMAX_SIZE >= 16) && (defined(EA_COMPILER_GNUC) || defined(__clang__)) // If __int128_t/__uint128_t is supported...\n\t\tconstexpr bool                  numeric_limits<__int128_t>::is_specialized;\n\t\tconstexpr int                   numeric_limits<__int128_t>::digits;\n\t\tconstexpr int                   numeric_limits<__int128_t>::digits10;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::is_signed;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::is_integer;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::is_exact;\n\t\tconstexpr int                   numeric_limits<__int128_t>::radix;\n\t\tconstexpr int                   numeric_limits<__int128_t>::min_exponent;\n\t\tconstexpr int                   numeric_limits<__int128_t>::min_exponent10;\n\t\tconstexpr int                   numeric_limits<__int128_t>::max_exponent;\n\t\tconstexpr int                   numeric_limits<__int128_t>::max_exponent10;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::is_bounded;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::is_modulo;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::traps;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::tinyness_before;\n\t\tconstexpr float_round_style     numeric_limits<__int128_t>::round_style;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::has_infinity;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::has_quiet_NaN;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::has_signaling_NaN;\n\t\tconstexpr float_denorm_style    numeric_limits<__int128_t>::has_denorm;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::has_denorm_loss;\n\t\tconstexpr bool                  numeric_limits<__int128_t>::is_iec559;\n\t#endif\n\n\t// float\n\tconstexpr bool                  numeric_limits<float>::is_specialized;\n\tconstexpr int                   numeric_limits<float>::digits;\n\tconstexpr int                   numeric_limits<float>::digits10;\n\tconstexpr bool                  numeric_limits<float>::is_signed;\n\tconstexpr bool                  numeric_limits<float>::is_integer;\n\tconstexpr bool                  numeric_limits<float>::is_exact;\n\tconstexpr int                   numeric_limits<float>::radix;\n\tconstexpr int                   numeric_limits<float>::min_exponent;\n\tconstexpr int                   numeric_limits<float>::min_exponent10;\n\tconstexpr int                   numeric_limits<float>::max_exponent;\n\tconstexpr int                   numeric_limits<float>::max_exponent10;\n\tconstexpr bool                  numeric_limits<float>::is_bounded;\n\tconstexpr bool                  numeric_limits<float>::is_modulo;\n\tconstexpr bool                  numeric_limits<float>::traps;\n\tconstexpr bool                  numeric_limits<float>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<float>::round_style;\n\tconstexpr bool                  numeric_limits<float>::has_infinity;\n\tconstexpr bool                  numeric_limits<float>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<float>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<float>::has_denorm;\n\tconstexpr bool                  numeric_limits<float>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<float>::is_iec559;\n\n\t// double\n\tconstexpr bool                  numeric_limits<double>::is_specialized;\n\tconstexpr int                   numeric_limits<double>::digits;\n\tconstexpr int                   numeric_limits<double>::digits10;\n\tconstexpr bool                  numeric_limits<double>::is_signed;\n\tconstexpr bool                  numeric_limits<double>::is_integer;\n\tconstexpr bool                  numeric_limits<double>::is_exact;\n\tconstexpr int                   numeric_limits<double>::radix;\n\tconstexpr int                   numeric_limits<double>::min_exponent;\n\tconstexpr int                   numeric_limits<double>::min_exponent10;\n\tconstexpr int                   numeric_limits<double>::max_exponent;\n\tconstexpr int                   numeric_limits<double>::max_exponent10;\n\tconstexpr bool                  numeric_limits<double>::is_bounded;\n\tconstexpr bool                  numeric_limits<double>::is_modulo;\n\tconstexpr bool                  numeric_limits<double>::traps;\n\tconstexpr bool                  numeric_limits<double>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<double>::round_style;\n\tconstexpr bool                  numeric_limits<double>::has_infinity;\n\tconstexpr bool                  numeric_limits<double>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<double>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<double>::has_denorm;\n\tconstexpr bool                  numeric_limits<double>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<double>::is_iec559;\n\n\t// long double\n\tconstexpr bool                  numeric_limits<long double>::is_specialized;\n\tconstexpr int                   numeric_limits<long double>::digits;\n\tconstexpr int                   numeric_limits<long double>::digits10;\n\tconstexpr bool                  numeric_limits<long double>::is_signed;\n\tconstexpr bool                  numeric_limits<long double>::is_integer;\n\tconstexpr bool                  numeric_limits<long double>::is_exact;\n\tconstexpr int                   numeric_limits<long double>::radix;\n\tconstexpr int                   numeric_limits<long double>::min_exponent;\n\tconstexpr int                   numeric_limits<long double>::min_exponent10;\n\tconstexpr int                   numeric_limits<long double>::max_exponent;\n\tconstexpr int                   numeric_limits<long double>::max_exponent10;\n\tconstexpr bool                  numeric_limits<long double>::is_bounded;\n\tconstexpr bool                  numeric_limits<long double>::is_modulo;\n\tconstexpr bool                  numeric_limits<long double>::traps;\n\tconstexpr bool                  numeric_limits<long double>::tinyness_before;\n\tconstexpr float_round_style     numeric_limits<long double>::round_style;\n\tconstexpr bool                  numeric_limits<long double>::has_infinity;\n\tconstexpr bool                  numeric_limits<long double>::has_quiet_NaN;\n\tconstexpr bool                  numeric_limits<long double>::has_signaling_NaN;\n\tconstexpr float_denorm_style    numeric_limits<long double>::has_denorm;\n\tconstexpr bool                  numeric_limits<long double>::has_denorm_loss;\n\tconstexpr bool                  numeric_limits<long double>::is_iec559;\n\n} // namespace eastl\n"
  },
  {
    "path": "source/red_black_tree.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// The tree insert and erase functions below are based on the original \n// HP STL tree functions. Use of these functions was been approved by\n// EA legal on November 4, 2005 and the approval documentation is available\n// from the EASTL maintainer or from the EA legal deparatment on request.\n// \n// Copyright (c) 1994\n// Hewlett-Packard Company\n// \n// Permission to use, copy, modify, distribute and sell this software\n// and its documentation for any purpose is hereby granted without fee,\n// provided that the above copyright notice appear in all copies and\n// that both that copyright notice and this permission notice appear\n// in supporting documentation. Hewlett-Packard Company makes no\n// representations about the suitability of this software for any\n// purpose. It is provided \"as is\" without express or implied warranty.\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/red_black_tree.h>\n#include <stddef.h>\n\n\n\nnamespace eastl\n{\n\t// Forward declarations\n\trbtree_node_base* RBTreeRotateLeft(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot);\n\trbtree_node_base* RBTreeRotateRight(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot);\n\n\n\n\t/// RBTreeIncrement\n\t/// Returns the next item in a sorted red-black tree.\n\t///\n\tEASTL_API rbtree_node_base* RBTreeIncrement(const rbtree_node_base* pNode)\n\t{\n\t\tif(pNode->mpNodeRight) \n\t\t{\n\t\t\tpNode = pNode->mpNodeRight;\n\n\t\t\twhile(pNode->mpNodeLeft)\n\t\t\t\tpNode = pNode->mpNodeLeft;\n\t\t}\n\t\telse \n\t\t{\n\t\t\trbtree_node_base* pNodeTemp = pNode->mpNodeParent;\n\n\t\t\twhile(pNode == pNodeTemp->mpNodeRight) \n\t\t\t{\n\t\t\t\tpNode = pNodeTemp;\n\t\t\t\tpNodeTemp = pNodeTemp->mpNodeParent;\n\t\t\t}\n\n\t\t\tif(pNode->mpNodeRight != pNodeTemp)\n\t\t\t\tpNode = pNodeTemp;\n\t\t}\n\n\t\treturn const_cast<rbtree_node_base*>(pNode);\n\t}\n\n\n\n\t/// RBTreeIncrement\n\t/// Returns the previous item in a sorted red-black tree.\n\t///\n\tEASTL_API rbtree_node_base* RBTreeDecrement(const rbtree_node_base* pNode)\n\t{\n\t\tif((pNode->mpNodeParent->mpNodeParent == pNode) && (pNode->mColor == kRBTreeColorRed))\n\t\t\treturn pNode->mpNodeRight;\n\t\telse if(pNode->mpNodeLeft)\n\t\t{\n\t\t\trbtree_node_base* pNodeTemp = pNode->mpNodeLeft;\n\n\t\t\twhile(pNodeTemp->mpNodeRight)\n\t\t\t\tpNodeTemp = pNodeTemp->mpNodeRight;\n\n\t\t\treturn pNodeTemp;\n\t\t}\n\n\t\trbtree_node_base* pNodeTemp = pNode->mpNodeParent;\n\n\t\twhile(pNode == pNodeTemp->mpNodeLeft) \n\t\t{\n\t\t\tpNode     = pNodeTemp;\n\t\t\tpNodeTemp = pNodeTemp->mpNodeParent;\n\t\t}\n\n\t\treturn const_cast<rbtree_node_base*>(pNodeTemp);\n\t}\n\n\n\n\t/// RBTreeGetBlackCount\n\t/// Counts the number of black nodes in an red-black tree, from pNode down to the given bottom node.  \n\t/// We don't count red nodes because red-black trees don't really care about\n\t/// red node counts; it is black node counts that are significant in the \n\t/// maintenance of a balanced tree.\n\t///\n\tEASTL_API size_t RBTreeGetBlackCount(const rbtree_node_base* pNodeTop, const rbtree_node_base* pNodeBottom)\n\t{\n\t\tsize_t nCount = 0;\n\n\t\tfor(; pNodeBottom; pNodeBottom = pNodeBottom->mpNodeParent)\n\t\t{\n\t\t\tif(pNodeBottom->mColor == kRBTreeColorBlack) \n\t\t\t\t++nCount;\n\n\t\t\tif(pNodeBottom == pNodeTop) \n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn nCount;\n\t}\n\n\n\t/// RBTreeRotateLeft\n\t/// Does a left rotation about the given node. \n\t/// If you want to understand tree rotation, any book on algorithms will\n\t/// discuss the topic in detail.\n\t///\n\trbtree_node_base* RBTreeRotateLeft(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot)\n\t{\n\t\trbtree_node_base* const pNodeTemp = pNode->mpNodeRight;\n\n\t\tpNode->mpNodeRight = pNodeTemp->mpNodeLeft;\n\n\t\tif(pNodeTemp->mpNodeLeft)\n\t\t\tpNodeTemp->mpNodeLeft->mpNodeParent = pNode;\n\t\tpNodeTemp->mpNodeParent = pNode->mpNodeParent;\n\t\t\n\t\tif(pNode == pNodeRoot)\n\t\t\tpNodeRoot = pNodeTemp;\n\t\telse if(pNode == pNode->mpNodeParent->mpNodeLeft)\n\t\t\tpNode->mpNodeParent->mpNodeLeft = pNodeTemp;\n\t\telse\n\t\t\tpNode->mpNodeParent->mpNodeRight = pNodeTemp;\n\n\t\tpNodeTemp->mpNodeLeft = pNode;\n\t\tpNode->mpNodeParent = pNodeTemp;\n\n\t\treturn pNodeRoot;\n\t}\n\n\n\n\t/// RBTreeRotateRight\n\t/// Does a right rotation about the given node. \n\t/// If you want to understand tree rotation, any book on algorithms will\n\t/// discuss the topic in detail.\n\t///\n\trbtree_node_base* RBTreeRotateRight(rbtree_node_base* pNode, rbtree_node_base* pNodeRoot)\n\t{\n\t\trbtree_node_base* const pNodeTemp = pNode->mpNodeLeft;\n\n\t\tpNode->mpNodeLeft = pNodeTemp->mpNodeRight;\n\n\t\tif(pNodeTemp->mpNodeRight)\n\t\t\tpNodeTemp->mpNodeRight->mpNodeParent = pNode;\n\t\tpNodeTemp->mpNodeParent = pNode->mpNodeParent;\n\n\t\tif(pNode == pNodeRoot)\n\t\t\tpNodeRoot = pNodeTemp;\n\t\telse if(pNode == pNode->mpNodeParent->mpNodeRight)\n\t\t\tpNode->mpNodeParent->mpNodeRight = pNodeTemp;\n\t\telse\n\t\t\tpNode->mpNodeParent->mpNodeLeft = pNodeTemp;\n\n\t\tpNodeTemp->mpNodeRight = pNode;\n\t\tpNode->mpNodeParent = pNodeTemp;\n\n\t\treturn pNodeRoot;\n\t}\n\n\n\n\n\t/// RBTreeInsert\n\t/// Insert a node into the tree and rebalance the tree as a result of the \n\t/// disturbance the node introduced.\n\t///\n\tEASTL_API void RBTreeInsert(rbtree_node_base* pNode,\n\t\t\t\t\t\t\t\trbtree_node_base* pNodeParent, \n\t\t\t\t\t\t\t\trbtree_node_base* pNodeAnchor,\n\t\t\t\t\t\t\t\tRBTreeSide insertionSide)\n\t{\n\t\trbtree_node_base*& pNodeRootRef = pNodeAnchor->mpNodeParent;\n\n\t\t// Initialize fields in new node to insert.\n\t\tpNode->mpNodeParent = pNodeParent;\n\t\tpNode->mpNodeRight  = NULL;\n\t\tpNode->mpNodeLeft   = NULL;\n\t\tpNode->mColor       = kRBTreeColorRed;\n\n\t\t// Insert the node.\n\t\tif(insertionSide == kRBTreeSideLeft)\n\t\t{\n\t\t\tpNodeParent->mpNodeLeft = pNode; // Also makes (leftmost = pNode) when (pNodeParent == pNodeAnchor)\n\n\t\t\tif(pNodeParent == pNodeAnchor)\n\t\t\t{\n\t\t\t\tpNodeAnchor->mpNodeParent = pNode;\n\t\t\t\tpNodeAnchor->mpNodeRight = pNode;\n\t\t\t}\n\t\t\telse if(pNodeParent == pNodeAnchor->mpNodeLeft)\n\t\t\t\tpNodeAnchor->mpNodeLeft = pNode; // Maintain leftmost pointing to min node\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpNodeParent->mpNodeRight = pNode;\n\n\t\t\tif(pNodeParent == pNodeAnchor->mpNodeRight)\n\t\t\t\tpNodeAnchor->mpNodeRight = pNode; // Maintain rightmost pointing to max node\n\t\t}\n\n\t\t// Rebalance the tree.\n\t\twhile((pNode != pNodeRootRef) && (pNode->mpNodeParent->mColor == kRBTreeColorRed)) \n\t\t{\n\t\t\tEA_ANALYSIS_ASSUME(pNode->mpNodeParent != NULL);\n\t\t\trbtree_node_base* const pNodeParentParent = pNode->mpNodeParent->mpNodeParent;\n\n\t\t\tif(pNode->mpNodeParent == pNodeParentParent->mpNodeLeft) \n\t\t\t{\n\t\t\t\trbtree_node_base* const pNodeTemp = pNodeParentParent->mpNodeRight;\n\n\t\t\t\tif(pNodeTemp && (pNodeTemp->mColor == kRBTreeColorRed)) \n\t\t\t\t{\n\t\t\t\t\tpNode->mpNodeParent->mColor = kRBTreeColorBlack;\n\t\t\t\t\tpNodeTemp->mColor = kRBTreeColorBlack;\n\t\t\t\t\tpNodeParentParent->mColor = kRBTreeColorRed;\n\t\t\t\t\tpNode = pNodeParentParent;\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\tif(pNode->mpNodeParent && pNode == pNode->mpNodeParent->mpNodeRight) \n\t\t\t\t\t{\n\t\t\t\t\t\tpNode = pNode->mpNodeParent;\n\t\t\t\t\t\tpNodeRootRef = RBTreeRotateLeft(pNode, pNodeRootRef);\n\t\t\t\t\t}\n\n\t\t\t\t\tEA_ANALYSIS_ASSUME(pNode->mpNodeParent != NULL);\n\t\t\t\t\tpNode->mpNodeParent->mColor = kRBTreeColorBlack;\n\t\t\t\t\tpNodeParentParent->mColor = kRBTreeColorRed;\n\t\t\t\t\tpNodeRootRef = RBTreeRotateRight(pNodeParentParent, pNodeRootRef);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse \n\t\t\t{\n\t\t\t\trbtree_node_base* const pNodeTemp = pNodeParentParent->mpNodeLeft;\n\n\t\t\t\tif(pNodeTemp && (pNodeTemp->mColor == kRBTreeColorRed)) \n\t\t\t\t{\n\t\t\t\t\tpNode->mpNodeParent->mColor = kRBTreeColorBlack;\n\t\t\t\t\tpNodeTemp->mColor = kRBTreeColorBlack;\n\t\t\t\t\tpNodeParentParent->mColor = kRBTreeColorRed;\n\t\t\t\t\tpNode = pNodeParentParent;\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\tEA_ANALYSIS_ASSUME(pNode != NULL && pNode->mpNodeParent != NULL);\n\n\t\t\t\t\tif(pNode == pNode->mpNodeParent->mpNodeLeft) \n\t\t\t\t\t{\n\t\t\t\t\t\tpNode = pNode->mpNodeParent;\n\t\t\t\t\t\tpNodeRootRef = RBTreeRotateRight(pNode, pNodeRootRef);\n\t\t\t\t\t}\n\n\t\t\t\t\tpNode->mpNodeParent->mColor = kRBTreeColorBlack;\n\t\t\t\t\tpNodeParentParent->mColor = kRBTreeColorRed;\n\t\t\t\t\tpNodeRootRef = RBTreeRotateLeft(pNodeParentParent, pNodeRootRef);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tEA_ANALYSIS_ASSUME(pNodeRootRef != NULL);\n\t\tpNodeRootRef->mColor = kRBTreeColorBlack;\n\n\t} // RBTreeInsert\n\n\n\n\n\t/// RBTreeErase\n\t/// Erase a node from the tree.\n\t///\n\tEASTL_API void RBTreeErase(rbtree_node_base* pNode, rbtree_node_base* pNodeAnchor)\n\t{\n\t\trbtree_node_base*& pNodeRootRef      = pNodeAnchor->mpNodeParent;\n\t\trbtree_node_base*& pNodeLeftmostRef  = pNodeAnchor->mpNodeLeft;\n\t\trbtree_node_base*& pNodeRightmostRef = pNodeAnchor->mpNodeRight;\n\t\trbtree_node_base*  pNodeSuccessor    = pNode;\n\t\trbtree_node_base*  pNodeChild        = NULL;\n\t\trbtree_node_base*  pNodeChildParent  = NULL;\n\n\t\tif(pNodeSuccessor->mpNodeLeft == NULL)         // pNode has at most one non-NULL child.\n\t\t\tpNodeChild = pNodeSuccessor->mpNodeRight;  // pNodeChild might be null.\n\t\telse if(pNodeSuccessor->mpNodeRight == NULL)   // pNode has exactly one non-NULL child.\n\t\t\tpNodeChild = pNodeSuccessor->mpNodeLeft;   // pNodeChild is not null.\n\t\telse \n\t\t{\n\t\t\t// pNode has two non-null children. Set pNodeSuccessor to pNode's successor. pNodeChild might be NULL.\n\t\t\tpNodeSuccessor = pNodeSuccessor->mpNodeRight;\n\n\t\t\twhile(pNodeSuccessor->mpNodeLeft)\n\t\t\t\tpNodeSuccessor = pNodeSuccessor->mpNodeLeft;\n\n\t\t\tpNodeChild = pNodeSuccessor->mpNodeRight;\n\t\t}\n\n\t\t// Here we remove pNode from the tree and fix up the node pointers appropriately around it.\n\t\tif(pNodeSuccessor == pNode) // If pNode was a leaf node (had both NULL children)...\n\t\t{\n\t\t\tpNodeChildParent = pNodeSuccessor->mpNodeParent;  // Assign pNodeReplacement's parent.\n\n\t\t\tif(pNodeChild) \n\t\t\t\tpNodeChild->mpNodeParent = pNodeSuccessor->mpNodeParent;\n\n\t\t\tif(pNode == pNodeRootRef) // If the node being deleted is the root node...\n\t\t\t\tpNodeRootRef = pNodeChild; // Set the new root node to be the pNodeReplacement.\n\t\t\telse \n\t\t\t{\n\t\t\t\tif(pNode == pNode->mpNodeParent->mpNodeLeft) // If pNode is a left node...\n\t\t\t\t\tpNode->mpNodeParent->mpNodeLeft  = pNodeChild;  // Make pNode's replacement node be on the same side.\n\t\t\t\telse\n\t\t\t\t\tpNode->mpNodeParent->mpNodeRight = pNodeChild;\n\t\t\t\t// Now pNode is disconnected from the bottom of the tree (recall that in this pathway pNode was determined to be a leaf).\n\t\t\t}\n\n\t\t\tif(pNode == pNodeLeftmostRef) // If pNode is the tree begin() node...\n\t\t\t{\n\t\t\t\t// Because pNode is the tree begin(), pNode->mpNodeLeft must be NULL.\n\t\t\t\t// Here we assign the new begin() (first node).\n\t\t\t\tif(pNode->mpNodeRight && pNodeChild)\n\t\t\t\t{\n\t\t\t\t\tEASTL_ASSERT(pNodeChild != NULL); // Logically pNodeChild should always be valid.\n\t\t\t\t\tpNodeLeftmostRef = RBTreeGetMinChild(pNodeChild); \n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tpNodeLeftmostRef = pNode->mpNodeParent; // This  makes (pNodeLeftmostRef == end()) if (pNode == root node)\n\t\t\t}\n\n\t\t\tif(pNode == pNodeRightmostRef) // If pNode is the tree last (rbegin()) node...\n\t\t\t{\n\t\t\t\t// Because pNode is the tree rbegin(), pNode->mpNodeRight must be NULL.\n\t\t\t\t// Here we assign the new rbegin() (last node)\n\t\t\t\tif(pNode->mpNodeLeft && pNodeChild)\n\t\t\t\t{\n\t\t\t\t\tEASTL_ASSERT(pNodeChild != NULL); // Logically pNodeChild should always be valid.\n\t\t\t\t\tpNodeRightmostRef = RBTreeGetMaxChild(pNodeChild);\n\t\t\t\t}\n\t\t\t\telse // pNodeChild == pNode->mpNodeLeft\n\t\t\t\t\tpNodeRightmostRef = pNode->mpNodeParent; // makes pNodeRightmostRef == &mAnchor if pNode == pNodeRootRef\n\t\t\t}\n\t\t}\n\t\telse // else (pNodeSuccessor != pNode)\n\t\t{\n\t\t\t// Relink pNodeSuccessor in place of pNode. pNodeSuccessor is pNode's successor.\n\t\t\t// We specifically set pNodeSuccessor to be on the right child side of pNode, so fix up the left child side.\n\t\t\tpNode->mpNodeLeft->mpNodeParent = pNodeSuccessor; \n\t\t\tpNodeSuccessor->mpNodeLeft = pNode->mpNodeLeft;\n\n\t\t\tif(pNodeSuccessor == pNode->mpNodeRight) // If pNode's successor was at the bottom of the tree... (yes that's effectively what this statement means)\n\t\t\t\tpNodeChildParent = pNodeSuccessor; // Assign pNodeReplacement's parent.\n\t\t\telse\n\t\t\t{\n\t\t\t\tpNodeChildParent = pNodeSuccessor->mpNodeParent;\n\n\t\t\t\tif(pNodeChild)\n\t\t\t\t\tpNodeChild->mpNodeParent = pNodeChildParent;\n\n\t\t\t\tpNodeChildParent->mpNodeLeft = pNodeChild;\n\n\t\t\t\tpNodeSuccessor->mpNodeRight = pNode->mpNodeRight;\n\t\t\t\tpNode->mpNodeRight->mpNodeParent = pNodeSuccessor;\n\t\t\t}\n\n\t\t\tif(pNode == pNodeRootRef)\n\t\t\t\tpNodeRootRef = pNodeSuccessor;\n\t\t\telse if(pNode == pNode->mpNodeParent->mpNodeLeft)\n\t\t\t\tpNode->mpNodeParent->mpNodeLeft = pNodeSuccessor;\n\t\t\telse \n\t\t\t\tpNode->mpNodeParent->mpNodeRight = pNodeSuccessor;\n\n\t\t\t// Now pNode is disconnected from the tree.\n\n\t\t\tpNodeSuccessor->mpNodeParent = pNode->mpNodeParent;\n\t\t\teastl::swap(pNodeSuccessor->mColor, pNode->mColor);\n\t\t}\n\n\t\t// Here we do tree balancing as per the conventional red-black tree algorithm.\n\t\tif(pNode->mColor == kRBTreeColorBlack) \n\t\t{ \n\t\t\twhile((pNodeChild != pNodeRootRef) && ((pNodeChild == NULL) || (pNodeChild->mColor == kRBTreeColorBlack)))\n\t\t\t{\n\t\t\t\tif(pNodeChild == pNodeChildParent->mpNodeLeft) \n\t\t\t\t{\n\t\t\t\t\trbtree_node_base* pNodeTemp = pNodeChildParent->mpNodeRight;\n\n\t\t\t\t\tif(pNodeTemp->mColor == kRBTreeColorRed) \n\t\t\t\t\t{\n\t\t\t\t\t\tpNodeTemp->mColor = kRBTreeColorBlack;\n\t\t\t\t\t\tpNodeChildParent->mColor = kRBTreeColorRed;\n\t\t\t\t\t\tpNodeRootRef = RBTreeRotateLeft(pNodeChildParent, pNodeRootRef);\n\t\t\t\t\t\tpNodeTemp = pNodeChildParent->mpNodeRight;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(((pNodeTemp->mpNodeLeft  == NULL) || (pNodeTemp->mpNodeLeft->mColor  == kRBTreeColorBlack)) &&\n\t\t\t\t\t\t((pNodeTemp->mpNodeRight == NULL) || (pNodeTemp->mpNodeRight->mColor == kRBTreeColorBlack))) \n\t\t\t\t\t{\n\t\t\t\t\t\tpNodeTemp->mColor = kRBTreeColorRed;\n\t\t\t\t\t\tpNodeChild = pNodeChildParent;\n\t\t\t\t\t\tpNodeChildParent = pNodeChildParent->mpNodeParent;\n\t\t\t\t\t} \n\t\t\t\t\telse \n\t\t\t\t\t{\n\t\t\t\t\t\tif((pNodeTemp->mpNodeRight == NULL) || (pNodeTemp->mpNodeRight->mColor == kRBTreeColorBlack)) \n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpNodeTemp->mpNodeLeft->mColor = kRBTreeColorBlack;\n\t\t\t\t\t\t\tpNodeTemp->mColor = kRBTreeColorRed;\n\t\t\t\t\t\t\tpNodeRootRef = RBTreeRotateRight(pNodeTemp, pNodeRootRef);\n\t\t\t\t\t\t\tpNodeTemp = pNodeChildParent->mpNodeRight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpNodeTemp->mColor = pNodeChildParent->mColor;\n\t\t\t\t\t\tpNodeChildParent->mColor = kRBTreeColorBlack;\n\n\t\t\t\t\t\tif(pNodeTemp->mpNodeRight) \n\t\t\t\t\t\t\tpNodeTemp->mpNodeRight->mColor = kRBTreeColorBlack;\n\n\t\t\t\t\t\tpNodeRootRef = RBTreeRotateLeft(pNodeChildParent, pNodeRootRef);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t\telse \n\t\t\t\t{   \n\t\t\t\t\t// The following is the same as above, with mpNodeRight <-> mpNodeLeft.\n\t\t\t\t\trbtree_node_base* pNodeTemp = pNodeChildParent->mpNodeLeft;\n\n\t\t\t\t\tif(pNodeTemp->mColor == kRBTreeColorRed) \n\t\t\t\t\t{\n\t\t\t\t\t\tpNodeTemp->mColor        = kRBTreeColorBlack;\n\t\t\t\t\t\tpNodeChildParent->mColor = kRBTreeColorRed;\n\n\t\t\t\t\t\tpNodeRootRef = RBTreeRotateRight(pNodeChildParent, pNodeRootRef);\n\t\t\t\t\t\tpNodeTemp = pNodeChildParent->mpNodeLeft;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(((pNodeTemp->mpNodeRight == NULL) || (pNodeTemp->mpNodeRight->mColor == kRBTreeColorBlack)) &&\n\t\t\t\t\t\t((pNodeTemp->mpNodeLeft  == NULL) || (pNodeTemp->mpNodeLeft->mColor  == kRBTreeColorBlack))) \n\t\t\t\t\t{\n\t\t\t\t\t\tpNodeTemp->mColor = kRBTreeColorRed;\n\t\t\t\t\t\tpNodeChild       = pNodeChildParent;\n\t\t\t\t\t\tpNodeChildParent = pNodeChildParent->mpNodeParent;\n\t\t\t\t\t} \n\t\t\t\t\telse \n\t\t\t\t\t{\n\t\t\t\t\t\tif((pNodeTemp->mpNodeLeft == NULL) || (pNodeTemp->mpNodeLeft->mColor == kRBTreeColorBlack)) \n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpNodeTemp->mpNodeRight->mColor = kRBTreeColorBlack;\n\t\t\t\t\t\t\tpNodeTemp->mColor              = kRBTreeColorRed;\n\n\t\t\t\t\t\t\tpNodeRootRef = RBTreeRotateLeft(pNodeTemp, pNodeRootRef);\n\t\t\t\t\t\t\tpNodeTemp = pNodeChildParent->mpNodeLeft;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpNodeTemp->mColor = pNodeChildParent->mColor;\n\t\t\t\t\t\tpNodeChildParent->mColor = kRBTreeColorBlack;\n\n\t\t\t\t\t\tif(pNodeTemp->mpNodeLeft) \n\t\t\t\t\t\t\tpNodeTemp->mpNodeLeft->mColor = kRBTreeColorBlack;\n\n\t\t\t\t\t\tpNodeRootRef = RBTreeRotateRight(pNodeChildParent, pNodeRootRef);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(pNodeChild)\n\t\t\t\tpNodeChild->mColor = kRBTreeColorBlack;\n\t\t}\n\n\t} // RBTreeErase\n\n\n\n} // namespace eastl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/string.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/string.h>\n#include <EABase/eabase.h>\n#include <string.h>\n\n\nnamespace eastl\n{\n\t///////////////////////////////////////////////////////////////////////////////\n\t// Converters for DecodePart\n\t//\n\t// For some decent documentation about conversions, see:\n\t//     http://tidy.sourceforge.net/cgi-bin/lxr/source/src/utf8.c\n\t//     \n\t///////////////////////////////////////////////////////////////////////////////\n\n\t// Requires that pDest have a capacity of at least 6 chars.\n\t// Sets pResult to '\\1' in the case that c is an invalid UCS4 char.\n\tinline bool UCS4ToUTF8(uint32_t c, char*& pResult)\n\t{\n\t\tif(c < 0x00000080)\n\t\t\t*pResult++ = (char)(uint8_t)c;\n\t\telse if(c < 0x0800)\n\t\t{\n\t\t\t*pResult++ = (char)(uint8_t)(0xC0 | (c >> 6));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | (c & 0x3F));\n\t\t}\n\t\telse if(c <= 0x0000FFFF)\n\t\t{\n\t\t\t*pResult++ = (char)(uint8_t)(0xE0 | (c >> 12));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 6) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | (c & 0x3F));\n\t\t}\n\t\telse if(c <= 0x001FFFFF)\n\t\t{\n\t\t\t*pResult++ = (char)(uint8_t)(0xF0 | (c >> 18));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 12) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 6) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | (c & 0x3F));\n\t\t}\n\t\telse if(c <= 0x003FFFFFF)\n\t\t{\n\t\t\t*pResult++ = (char)(uint8_t)(0xF8 | (c >> 24));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | (c >> 18));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 12) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 6) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | (c & 0x3F));\n\t\t}\n\t\telse if(c <= 0x7FFFFFFF)\n\t\t{\n\t\t\t*pResult++ = (char)(uint8_t)(0xFC | (c >> 30));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 24) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 18) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 12) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | ((c >> 6) & 0x3F));\n\t\t\t*pResult++ = (char)(uint8_t)(0x80 | (c & 0x3F));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// values >= 0x80000000 can't be converted to UTF8.\n\t\t\t*pResult++ = '\\1';\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\n\t// Requires that pResult have a capacity of at least 3 chars.\n\t// Sets pResult to '\\1' in the case that c is an invalid UCS4 char.\n\tinline bool UCS2ToUTF8(uint16_t c, char*& pResult)\n\t{\n\t\treturn UCS4ToUTF8(c, pResult);\n\t}\n\n\n\t// Sets result to 0xffff in the case that the input UTF8 sequence is bad.\n\t// 32 bit 0xffffffff is an invalid UCS4 code point, so we can't use that as an error return value.\n\tinline bool UTF8ToUCS4(const char*& p, const char* pEnd, uint32_t& result)\n\t{\n\t\t// This could likely be implemented in a faster-executing way that uses tables.\n\n\t\tbool           success = true;\n\t\tuint32_t       c = 0xffff;\n\t\tconst char* pNext = NULL;\n\n\t\tif(p < pEnd)\n\t\t{\n\t\t\tuint8_t cChar0((uint8_t)*p), cChar1, cChar2, cChar3;\n\n\t\t\t// Asserts are disabled because we don't necessarily want to interrupt runtime execution due to this.\n\t\t\t// EASTL_ASSERT((cChar0 != 0xFE) && (cChar0 != 0xFF));     //  No byte can be 0xFE or 0xFF\n\t\t\t// Code below will effectively catch this error as it goes.\n\n\t\t\tif(cChar0 < 0x80)\n\t\t\t{\n\t\t\t\tpNext = p + 1;\n\t\t\t\tc     = cChar0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//EASTL_ASSERT((cChar0 & 0xC0) == 0xC0);              //  The top two bits need to be equal to 1\n\t\t\t\tif((cChar0 & 0xC0) != 0xC0)\n\t\t\t\t{\n\t\t\t\t\tsuccess = false;\n\t\t\t\t\tgoto Failure;\n\t\t\t\t}\n\n\t\t\t\tif((cChar0 & 0xE0) == 0xC0)\n\t\t\t\t{\n\t\t\t\t\tpNext = p + 2;\n\n\t\t\t\t\tif(pNext <= pEnd)\n\t\t\t\t\t{\n\t\t\t\t\t\tc      = (uint32_t)((cChar0 & 0x1F) << 6);\n\t\t\t\t\t\tcChar1 = static_cast<uint8_t>(p[1]);\n\t\t\t\t\t\tc     |= cChar1 & 0x3F;\n\n\t\t\t\t\t\t//EASTL_ASSERT((cChar1 & 0xC0) == 0x80);          //  All subsequent code should be b10xxxxxx\n\t\t\t\t\t\t//EASTL_ASSERT(c >= 0x0080 && c < 0x0800);        //  Check that we have the smallest coding\n\t\t\t\t\t\tif(!((cChar1 & 0xC0) == 0x80) ||\n\t\t\t\t\t\t   !(c >= 0x0080 && c < 0x0800))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if((cChar0 & 0xF0) == 0xE0)\n\t\t\t\t{\n\t\t\t\t\tpNext = p + 3;\n\n\t\t\t\t\tif(pNext <= pEnd)\n\t\t\t\t\t{\n\t\t\t\t\t\tc      = (uint32_t)((cChar0 & 0xF) << 12);\n\t\t\t\t\t\tcChar1 = static_cast<uint8_t>(p[1]);\n\t\t\t\t\t\tc     |= (cChar1 & 0x3F) << 6;\n\t\t\t\t\t\tcChar2 = static_cast<uint8_t>(p[2]);\n\t\t\t\t\t\tc     |= cChar2 & 0x3F;\n\n\t\t\t\t\t\t//EASTL_ASSERT((cChar1 & 0xC0) == 0x80);            //  All subsequent code should be b10xxxxxx\n\t\t\t\t\t\t//EASTL_ASSERT((cChar2 & 0xC0) == 0x80);            //  All subsequent code should be b10xxxxxx\n\t\t\t\t\t\t//EASTL_ASSERT(c >= 0x00000800 && c <  0x00010000); //  Check that we have the smallest coding\n\t\t\t\t\t\tif(!((cChar1 & 0xC0) == 0x80) ||\n\t\t\t\t\t\t   !((cChar2 & 0xC0) == 0x80) ||\n\t\t\t\t\t\t   !(c >= 0x00000800 && c <  0x00010000))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if((cChar0 & 0xF8) == 0xF0)\n\t\t\t\t{\n\t\t\t\t\tpNext = p + 4;\n\n\t\t\t\t\tif(pNext <= pEnd)\n\t\t\t\t\t{\n\t\t\t\t\t\tc      = (uint32_t)((cChar0 & 0x7) << 18);\n\t\t\t\t\t\tcChar1 = static_cast<uint8_t>(p[1]);\n\t\t\t\t\t\tc     |= (uint32_t)((cChar1 & 0x3F) << 12);\n\t\t\t\t\t\tcChar2 = static_cast<uint8_t>(p[2]);\n\t\t\t\t\t\tc     |= (cChar2 & 0x3F) << 6;\n\t\t\t\t\t\tcChar3 = static_cast<uint8_t>(p[3]);\n\t\t\t\t\t\tc     |= cChar3 & 0x3F;\n\n\t\t\t\t\t\t//EASTL_ASSERT((cChar0 & 0xf8) == 0xf0);            //  We handle the unicode but not UCS-4\n\t\t\t\t\t\t//EASTL_ASSERT((cChar1 & 0xC0) == 0x80);            //  All subsequent code should be b10xxxxxx\n\t\t\t\t\t\t//EASTL_ASSERT((cChar2 & 0xC0) == 0x80);            //  All subsequent code should be b10xxxxxx\n\t\t\t\t\t\t//EASTL_ASSERT((cChar3 & 0xC0) == 0x80);            //  All subsequent code should be b10xxxxxx\n\t\t\t\t\t\t//EASTL_ASSERT(c >= 0x00010000 && c <= 0x0010FFFF); //  Check that we have the smallest coding, Unicode and not ucs-4\n\t\t\t\t\t\tif(!((cChar0 & 0xf8) == 0xf0) ||\n\t\t\t\t\t\t   !((cChar1 & 0xC0) == 0x80) ||\n\t\t\t\t\t\t   !((cChar2 & 0xC0) == 0x80) ||\n\t\t\t\t\t\t   !(c >= 0x00010000 && c <= 0x0010FFFF))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if((cChar0 & 0xFC) == 0xF8)\n\t\t\t\t{\n\t\t\t\t\tpNext = p + 4;\n\n\t\t\t\t\tif(pNext <= pEnd)\n\t\t\t\t\t{\n\t\t\t\t\t\t// To do. We don't currently support extended UCS4 characters.\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if((cChar0 & 0xFE) == 0xFC)\n\t\t\t\t{\n\t\t\t\t\tpNext = p + 5;\n\n\t\t\t\t\tif(pNext <= pEnd)\n\t\t\t\t\t{\n\t\t\t\t\t\t// To do. We don't currently support extended UCS4 characters.\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsuccess = false;\n\t\t\t\t\t\tgoto Failure;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsuccess = false;\n\t\t\t\t\tgoto Failure;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tsuccess = false;\n\n\t\tFailure:\n\t\tif(success)\n\t\t{\n\t\t\tp = pNext;\n\t\t\tresult = c;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tp = p + 1;\n\t\t\tresult = 0xffff;\n\t\t}\n\n\t\treturn success;\n\t}\n\n\t// Sets result to 0xffff in the case that the input UTF8 sequence is bad.\n\t// The effect of converting UTF8 codepoints > 0xffff to UCS2 (char16_t) is to set all\n\t// such codepoints to 0xffff. EASTL doesn't have a concept of setting or maintaining \n\t// error state for string conversions, though it does have a policy of converting \n\t// impossible values to something without generating invalid strings or throwing exceptions.\n\tinline bool UTF8ToUCS2(const char*& p, const char* pEnd, uint16_t& result)\n\t{\n\t\tuint32_t u32;\n\n\t\tif(UTF8ToUCS4(p, pEnd, u32))\n\t\t{\n\t\t\tif(u32 <= 0xffff)\n\t\t\t{\n\t\t\t\tresult = (uint16_t)u32;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tresult = 0xffff;\n\t\treturn false;\n\t}\n\n\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// DecodePart\n\t///////////////////////////////////////////////////////////////////////////\n\n\tEASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char*& pDest, char* pDestEnd)\n\t{\n\t\tsize_t sourceSize = (size_t)(pSrcEnd - pSrc);\n\t\tsize_t destSize   = (size_t)(pDestEnd - pDest);\n\n\t\tif(sourceSize > destSize)\n\t\t   sourceSize = destSize;\n\n\t\tmemmove(pDest, pSrc, sourceSize * sizeof(*pSrcEnd));\n\n\t\tpSrc  += sourceSize;\n\t\tpDest += sourceSize; // Intentionally add sourceSize here.\n\n\t\treturn true;\n\t}\n\n\tEASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)\n\t{\n\t\tbool success = true;\n\n\t\twhile(success && (pSrc < pSrcEnd) && (pDest < pDestEnd))\n\t\t\tsuccess = UTF8ToUCS2(pSrc, pSrcEnd, (uint16_t&)*pDest++);\n\n\t\treturn success;\n\t}\n\n\tEASTL_API bool DecodePart(const char*& pSrc, const char* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)\n\t{\n\t\tbool success = true;\n\n\t\twhile(success && (pSrc < pSrcEnd) && (pDest < pDestEnd))\n\t\t\tsuccess = UTF8ToUCS4(pSrc, pSrcEnd, (uint32_t&)*pDest++);\n\n\t\treturn success;\n\t}\n\n\n\tEASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char*& pDest, char* pDestEnd)\n\t{\n\t\tbool success = true;\n\n\t\tEASTL_ASSERT((pDest + 6) < pDestEnd); // The user must provide ample buffer space, preferably 256 chars or more.\n\t\tpDestEnd -= 6; // Do this so that we can avoid dest buffer size checking in the loop below and the function it calls.\n\n\t\twhile(success && (pSrc < pSrcEnd) && (pDest < pDestEnd))\n\t\t\tsuccess = UCS2ToUTF8(*pSrc++, pDest);\n\n\t\treturn success;\n\t}\n\n\tEASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)\n\t{\n\t\tsize_t sourceSize = (size_t)(pSrcEnd - pSrc);\n\t\tsize_t destSize   = (size_t)(pDestEnd - pDest);\n\n\t\tif(sourceSize > destSize)\n\t\t   sourceSize = destSize;\n\n\t\tmemmove(pDest, pSrc, sourceSize * sizeof(*pSrcEnd));\n\n\t\tpSrc  += sourceSize;\n\t\tpDest += sourceSize; // Intentionally add sourceSize here.\n\n\t\treturn true;\n\t}\n\n\tEASTL_API bool DecodePart(const char16_t*& pSrc, const char16_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)\n\t{\n\t\tsize_t sourceSize = (size_t)(pSrcEnd - pSrc);\n\t\tsize_t destSize   = (size_t)(pDestEnd - pDest);\n\n\t\tif(sourceSize > destSize)\n\t\t   pSrcEnd = pSrc + destSize;\n\n\t\twhile(pSrc != pSrcEnd) // To consider: Improve this by unrolling this loop. Other tricks can improve its speed as well.\n\t\t\t*pDest++ = (char32_t)*pSrc++;\n\n\t\treturn true;\n\t}\n\n\n\tEASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char*& pDest, char* pDestEnd)\n\t{\n\t\tbool success = true;\n\n\t\tEASTL_ASSERT((pDest + 6) < pDestEnd); // The user must provide ample buffer space, preferably 256 chars or more.\n\t\tpDestEnd -= 6; // Do this so that we can avoid dest buffer size checking in the loop below and the function it calls.\n\n\t\twhile(success && (pSrc < pSrcEnd) && (pDest < pDestEnd))\n\t\t\tsuccess = UCS4ToUTF8(*pSrc++, pDest);\n\n\t\treturn success;\n\t}\n\n\tEASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)\n\t{\n\t\tsize_t sourceSize = (size_t)(pSrcEnd - pSrc);\n\t\tsize_t destSize   = (size_t)(pDestEnd - pDest);\n\n\t\tif(sourceSize > destSize)\n\t\t   pSrcEnd = pSrc + destSize;\n\n\t\twhile(pSrc != pSrcEnd) // To consider: Improve this by unrolling this loop. Other tricks can improve its speed as well.\n\t\t\t*pDest++ = (char16_t)*pSrc++;   // This is potentially losing data. We are not converting to UTF16; we are converting to UCS2.\n\n\t\treturn true;\n\t}\n\n\tEASTL_API bool DecodePart(const char32_t*& pSrc, const char32_t* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)\n\t{\n\t\tsize_t sourceSize = (size_t)(pSrcEnd - pSrc);\n\t\tsize_t destSize   = (size_t)(pDestEnd - pDest);\n\n\t\tif(sourceSize > destSize)\n\t\t   sourceSize = destSize;\n\n\t\tmemmove(pDest, pSrc, sourceSize * sizeof(*pSrcEnd));\n\n\t\tpSrc  += sourceSize;\n\t\tpDest += sourceSize; // Intentionally add sourceSize here.\n\n\t\treturn true;\n\t}\n\n\tEASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char*&  pDest, char* pDestEnd)\n\t{\n\t\tbool success = true;\n\n\t\tEASTL_ASSERT((pDest + 6) < pDestEnd); // The user must provide ample buffer space, preferably 256 chars or more.\n\t\tpDestEnd -= 6; // Do this so that we can avoid dest buffer size checking in the loop below and the function it calls.\n\n\t\twhile(success && (pSrc < pSrcEnd) && (pDest < pDestEnd))\n\t\t\tsuccess = UCS4ToUTF8((uint32_t)(unsigned)*pSrc++, pDest);\n\n\t\treturn success;\n\t}\n\n\tEASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char16_t*& pDest, char16_t* pDestEnd)\n\t{\n\t\tsize_t sourceSize = (size_t)(pSrcEnd - pSrc);\n\t\tsize_t destSize   = (size_t)(pDestEnd - pDest);\n\n\t\tif(sourceSize > destSize)\n\t\t   pSrcEnd = pSrc + destSize;\n\n\t\twhile(pSrc != pSrcEnd) // To consider: Improve this by unrolling this loop. Other tricks can improve its speed as well.\n\t\t\t*pDest++ = (char16_t)*pSrc++;   // This is potentially losing data. We are not converting to UTF16; we are converting to UCS2.\n\n\t\treturn true;\n\t}\n\n\tEASTL_API bool DecodePart(const int*& pSrc, const int* pSrcEnd, char32_t*& pDest, char32_t* pDestEnd)\n\t{\n\t\tsize_t sourceSize = (size_t)(pSrcEnd - pSrc);\n\t\tsize_t destSize   = (size_t)(pDestEnd - pDest);\n\n\t\tif(sourceSize > destSize)\n\t\t   pSrcEnd = pSrc + destSize;\n\n\t\twhile(pSrc != pSrcEnd) // To consider: Improve this by unrolling this loop. Other tricks can improve its speed as well.\n\t\t\t*pDest++ = (char32_t)*pSrc++;   // This is potentially losing data. We are not converting to UTF16; we are converting to UCS2.\n\n\t\treturn true;\n\t}\n\n\n\n} // namespace eastl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "source/thread_support.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/thread_support.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/memory.h>\n\n#if defined(EA_PLATFORM_MICROSOFT)\n\tEA_DISABLE_ALL_VC_WARNINGS();\n\t#ifndef WIN32_LEAN_AND_MEAN\n\t\t#define WIN32_LEAN_AND_MEAN\n\t#endif\n\t#include <Windows.h>\n\tEA_RESTORE_ALL_VC_WARNINGS();\n#endif\n\n\nnamespace eastl\n{\n\tnamespace Internal\n\t{\n\t\t#if EASTL_CPP11_MUTEX_ENABLED\n\t\t\t// We use the C++11 Standard Library mutex as-is.\n\t\t#else\n\t\t\t/////////////////////////////////////////////////////////////////\n\t\t\t// mutex\n\t\t\t/////////////////////////////////////////////////////////////////\n\n\t\t\tmutex::mutex()\n\t\t\t{\n\t\t\t\t#if defined(EA_PLATFORM_MICROSOFT)\n\t\t\t\t\tstatic_assert(sizeof(mMutexBuffer) == sizeof(CRITICAL_SECTION), \"mMutexBuffer size failure\");\n\t\t\t\t\t//static_assert(EA_ALIGN_OF(mMutexBuffer) >= EA_ALIGN_OF(CRITICAL_SECTION), \"mMutexBuffer alignment failure\"); // Enabling this causes the VS2012 compiler to crash.\n\n\t\t\t\t\t#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0403)\n\t\t\t\t\t\tInitializeCriticalSection((CRITICAL_SECTION*)mMutexBuffer);\n\t\t\t\t\t#elif !EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP)\n\t\t\t\t\t\tBOOL result = InitializeCriticalSectionEx((CRITICAL_SECTION*)mMutexBuffer, 10, 0);\n\t\t\t\t\t\tEASTL_ASSERT(result != 0); EA_UNUSED(result);\n\t\t\t\t\t#else\n\t\t\t\t\t\tBOOL result = InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION*)mMutexBuffer, 10);\n\t\t\t\t\t\tEASTL_ASSERT(result != 0); EA_UNUSED(result);\n\t\t\t\t\t#endif\n\n\t\t\t\t#elif defined(EA_PLATFORM_POSIX)\n\t\t\t\t\tpthread_mutexattr_t attr;\n\n\t\t\t\t\tpthread_mutexattr_init(&attr);\n\n\t\t\t\t\t#if defined(EA_HAVE_pthread_mutexattr_setpshared_DECL)\n\t\t\t\t\t\tpthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);\n\t\t\t\t\t#endif\n\n\t\t\t\t\tpthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);\n\t\t\t\t\tpthread_mutex_init(&mMutex, &attr);\n\t\t\t\t\tpthread_mutexattr_destroy(&attr);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tmutex::~mutex()\n\t\t\t{\n\t\t\t\t#if defined(EA_PLATFORM_MICROSOFT)\n\t\t\t\t\tDeleteCriticalSection((CRITICAL_SECTION*)mMutexBuffer);\n\t\t\t\t#elif defined(EA_PLATFORM_POSIX)\n\t\t\t\t\tpthread_mutex_destroy(&mMutex);\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tvoid mutex::lock()\n\t\t\t{\n\t\t\t\t#if defined(EA_PLATFORM_MICROSOFT)\n\t\t\t\t\tEnterCriticalSection((CRITICAL_SECTION*)mMutexBuffer);\n\t\t\t\t#elif defined(EA_PLATFORM_POSIX)\n\t\t\t\t\tpthread_mutex_lock(&mMutex);\n\t\t\t\t#else\n\t\t\t\t\tEASTL_FAIL_MSG(\"EASTL thread safety is not implemented yet. See EAThread for how to do this for the given platform.\");\n\t\t\t\t#endif\n\t\t\t}\n\n\t\t\tvoid mutex::unlock()\n\t\t\t{\n\t\t\t\t#if defined(EA_PLATFORM_MICROSOFT)\n\t\t\t\t\tLeaveCriticalSection((CRITICAL_SECTION*)mMutexBuffer);\n\t\t\t\t#elif defined(EA_PLATFORM_POSIX)\n\t\t\t\t\tpthread_mutex_unlock(&mMutex);\n\t\t\t\t#endif\n\t\t\t}\n\t\t#endif\n\n\n\t\t/////////////////////////////////////////////////////////////////\n\t\t// shared_ptr_auto_mutex\n\t\t/////////////////////////////////////////////////////////////////\n\n\t\t// We could solve this by having single global mutex for all shared_ptrs, a set of mutexes for shared_ptrs, \n\t\t// a single mutex for every shared_ptr, or have a template parameter that enables mutexes for just some shared_ptrs.\n\t\teastl::late_constructed<mutex, true> gSharedPtrMutex;\n\n\t\tshared_ptr_auto_mutex::shared_ptr_auto_mutex(const void* /*pSharedPtr*/)\n\t\t\t: auto_mutex(*gSharedPtrMutex.get())\n\t\t{\n\t\t}\n\n\n\t} // namespace Internal\n\n} // namespace eastl\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/CMakeLists.txt",
    "content": "#-------------------------------------------------------------------------------------------\n# Copyright (C) Electronic Arts Inc.  All rights reserved.\n#-------------------------------------------------------------------------------------------\n\n#-------------------------------------------------------------------------------------------\n# CMake info\n#-------------------------------------------------------------------------------------------\ncmake_minimum_required(VERSION 3.11)\nproject(EASTLTest CXX)\ninclude(CTest)\n\n#-------------------------------------------------------------------------------------------\n# Defines\n#-------------------------------------------------------------------------------------------\nadd_definitions(-D_CRT_SECURE_NO_WARNINGS)\nadd_definitions(-D_SCL_SECURE_NO_WARNINGS)\nadd_definitions(-DEASTL_OPENSOURCE=1)\nadd_definitions(-D_CHAR16T)\nadd_definitions(-DEASTL_THREAD_SUPPORT_AVAILABLE=0)\nif (EASTL_STD_ITERATOR_CATEGORY_ENABLED)\n  add_definitions(-DEASTL_STD_ITERATOR_CATEGORY_ENABLED=1)\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Compiler Flags\n#-------------------------------------------------------------------------------------------\nset (CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/../scripts/CMake\")\ninclude(CommonCppFlags)\n\nif (MSVC)\n\tSET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /MP\")\nendif()\n\nif (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\")\n    SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-pointer-bool-conversion -Wno-unknown-warning-option\")\nendif()\n\n# Parts of the test suite fail to compile if char8_t is enabled, so we\n# disable it and only enable for specific source files later on.\nif (EASTL_NO_CHAR8T_FLAG)\n    add_compile_options(${EASTL_NO_CHAR8T_FLAG})\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Source files\n#-------------------------------------------------------------------------------------------\nfile(GLOB EASTLTEST_SOURCES \"source/*.cpp\")\nfile(GLOB EASTLTEST_HEADERS \"source/*.inl\" \"source/*.h\")\nset(SOURCES ${EASTLTEST_SOURCES} ${EASTLTEST_HEADERS})\n\n# Compile a subset of tests with explicit char8_t support if available.\nif (EASTL_CHAR8T_FLAG)\n    message(STATUS \"Building with char8_t support in tests.\")\n    set(EASTLTEST_CHAR8T_SOURCES \"source/TestString.cpp\" \"source/TestStringView.cpp\")\n\n    set_source_files_properties(${EASTLTEST_CHAR8T_SOURCES} PROPERTIES\n        COMPILE_FLAGS ${EASTL_CHAR8T_FLAG}\n        COMPILE_DEFINITIONS \"EASTL_EXPECT_CHAR8T_SUPPORT\")\nendif()\n\n# include both source and headers in the files view in Visual Studio\nsource_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX \"Header Files\" FILES ${EASTLTEST_HEADERS})\n\n#-------------------------------------------------------------------------------------------\n# Executable definition\n#-------------------------------------------------------------------------------------------\nadd_executable(EASTLTest ${SOURCES})\n\n#-------------------------------------------------------------------------------------------\n# Include directories\n#-------------------------------------------------------------------------------------------\ntarget_include_directories(EASTLTest PUBLIC include)\n\n#-------------------------------------------------------------------------------------------\n# Dependencies \n#-------------------------------------------------------------------------------------------\nFetchContent_Declare(\n  EABase\n  GIT_REPOSITORY https://github.com/electronicarts/EABase.git\n  GIT_TAG        0699a15efdfd20b6cecf02153bfa5663decb653c\n  GIT_SUBMODULES \"\" # This should be temporary until we update the cyclic submodule dependencies in EABase.\n)\nFetchContent_MakeAvailable(EABase)\ntarget_link_libraries(EASTLTest EABase)\n\nFetchContent_Declare(\n  EAAssert\n  GIT_REPOSITORY https://github.com/electronicarts/EAAssert.git\n  GIT_TAG        e5e181255de2e883dd1f987c78ccc42ac81d3bca\n  GIT_SUBMODULES \"\" # This should be temporary until we update the cyclic submodule dependencies in EAAssert.\n)\nFetchContent_MakeAvailable(EAAssert)\ntarget_link_libraries(EASTLTest EAAssert)\n\nFetchContent_Declare(\n  EAStdC\n  GIT_REPOSITORY https://github.com/electronicarts/EAStdC.git\n  GIT_TAG        fbcc34e89c63636054334888f3a5bd7ac2fd4b76\n  GIT_SUBMODULES \"\" # This should be temporary until we update the cyclic submodule dependencies in EAStdC.\n)\nFetchContent_MakeAvailable(EAStdC)\ntarget_link_libraries(EASTLTest EAStdC)\n\nFetchContent_Declare(\n  EAMain\n  GIT_REPOSITORY https://github.com/electronicarts/EAMain.git\n  GIT_TAG        24ca8bf09e6b47b860286fc2f4c832f4009273d1\n  GIT_SUBMODULES \"\" # This should be temporary until we update the cyclic submodule dependencies in EAMain.\n)\nFetchContent_MakeAvailable(EAMain)\ntarget_link_libraries(EASTLTest EAMain)\n\nFetchContent_Declare(\n  EATest\n  GIT_REPOSITORY https://github.com/electronicarts/EATest.git\n  GIT_TAG        a59b372fc9cba517283ad6d060d2ab96e0ba34ac\n  GIT_SUBMODULES \"\" # This should be temporary until we update the cyclic submodule dependencies in EATest.\n)\nFetchContent_MakeAvailable(EATest)\ntarget_link_libraries(EASTLTest EATest)\n\nFetchContent_Declare(\n  EAThread\n  GIT_REPOSITORY https://github.com/electronicarts/EAThread.git\n  GIT_TAG        f3c6c54d19699639a5edcf5237ea8b71aca6842c\n  GIT_SUBMODULES \"\" # This should be temporary until we update the cyclic submodule dependencies in EAThread.\n)\nFetchContent_MakeAvailable(EAThread)\ntarget_link_libraries(EASTLTest EAThread)\n\ntarget_link_libraries(EASTLTest EASTL)\n\nset(THREADS_PREFER_PTHREAD_FLAG ON)\nfind_package(Threads REQUIRED)\n\nif((NOT APPLE) AND (NOT WIN32))\n    target_link_libraries(EASTLTest ${EASTLTest_Libraries} Threads::Threads rt)\nelse()\n    target_link_libraries(EASTLTest ${EASTLTest_Libraries} Threads::Threads)\nendif()\n\n#-------------------------------------------------------------------------------------------\n# Run Unit tests and verify the results.\n#-------------------------------------------------------------------------------------------\nadd_test(EASTLTestRuns EASTLTest)\nset_tests_properties (EASTLTestRuns PROPERTIES PASS_REGULAR_EXPRESSION \"RETURNCODE=0\")\n\n"
  },
  {
    "path": "test/source/ConceptImpls.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#ifndef CONCEPTSIMPLS_H\n#define CONCEPTSIMPLS_H\n\n#include <EASTL/type_traits.h>\n\n#if !defined(EA_COMPILER_NO_DEFAULTED_FUNCTIONS) && !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\n#define EASTL_TEST_CONCEPT_IMPLS\n\n// This header provides a variety of helper classes that have interfaces corresponding to the concepts used to specify\n// requirements of many STL containers and algorithms. These helper classes are used in tests to verify that containers\n// and algorithms do not impose stricter requirements than specified by the standard on their arguments.\n\n// Destructible - only valid operation on this class is to destroy it.\n\nclass Destructible\n{\npublic:\n\t~Destructible() = default;\n\n\tDestructible() = delete;\n\tDestructible(const Destructible&) = delete;\n\tDestructible(Destructible&&) = delete;\n\tDestructible& operator=(const Destructible&) = delete;\n\tDestructible& operator=(Destructible&&) = delete;\n};\n\n// Unfortunately not all compilers handle type_traits reliably correctly currently so we can't straightforwardly\n// static_assert everything that should be true of this class\nstatic_assert(eastl::is_destructible<Destructible>::value, \"eastl::is_destructible<Destructible>::value\");\n// static_assert(!eastl::is_default_constructible<Destructible>::value,\n// \"!eastl::is_default_constructible<Destructible>::value\");\n// static_assert(!is_copy_constructible<Destructible>::value, \"!eastl::is_copy_constructible<Destructible>::value\");\nstatic_assert(!eastl::is_copy_assignable<Destructible>::value, \"!eastl::is_copy_assignable<Destructible>::value\");\n// static_assert(!eastl::is_move_constructible<Destructible>::value,\n// \"!eastl::is_move_constructible<Destructible>::value\");\nstatic_assert(!eastl::is_move_assignable<Destructible>::value, \"!eastl::is_move_assignable<Destructible>::value\");\n\nclass DefaultConstructible\n{\npublic:\n\tstatic const int defaultValue = 42;\n\n\tDefaultConstructible() : value(defaultValue) {}\n\t~DefaultConstructible() = default;\n\n\tDefaultConstructible(const DefaultConstructible&) = delete;\n\tDefaultConstructible(DefaultConstructible&&) = delete;\n\tDefaultConstructible& operator=(const DefaultConstructible&) = delete;\n\tDefaultConstructible& operator=(DefaultConstructible&&) = delete;\n\n\tconst int value;\n};\n\n\nstruct NotDefaultConstructible\n{\n\tNotDefaultConstructible() = delete;\n};\nstatic_assert(!eastl::is_default_constructible<NotDefaultConstructible>::value, \"'NotDefaultConstructible' is default constructible.\");\n\n\nclass CopyConstructible\n{\npublic:\n\tstatic const int defaultValue = 42;\n\tstatic CopyConstructible Create()\n\t{\n\t\tCopyConstructible x;\n\t\treturn x;\n\t}\n\n\tCopyConstructible(const CopyConstructible&) = default;\n\t~CopyConstructible() = default;\n\n\tCopyConstructible& operator=(const CopyConstructible&) = delete;\n\tCopyConstructible& operator=(CopyConstructible&&) = delete;\n\n\tconst int value;\n\nprivate:\n\tCopyConstructible() : value(defaultValue) {}\n};\n\n// Unfortunately not all compilers handle type_traits reliably correctly currently so we can't straightforwardly\n// static_assert everything that should be true of this class\nstatic_assert(eastl::is_destructible<CopyConstructible>::value, \"eastl::is_destructible<CopyConstructible>::value\");\n// static_assert(!eastl::is_default_constructible<CopyConstructible>::value,\n// \"!eastl::is_default_constructible<CopyConstructible>::value\");\n// static_assert(is_copy_constructible<CopyConstructible>::value, \"is_copy_constructible<CopyConstructible>::value\");\nstatic_assert(eastl::is_copy_constructible<CopyConstructible>::value,\n\t\t\t  \"eastl::is_copy_constructible<CopyConstructible>::value\");\nstatic_assert(!eastl::is_copy_assignable<CopyConstructible>::value,\n\t\t\t  \"!eastl::is_copy_assignable<CopyConstructible>::value\");\n// static_assert(!eastl::is_move_constructible<CopyConstructible>::value,\n// \"!eastl::is_move_constructible<CopyConstructible>::value\");\nstatic_assert(!eastl::is_move_assignable<CopyConstructible>::value,\n\t\t\t  \"!eastl::is_move_assignable<CopyConstructible>::value\");\n\nclass MoveConstructible\n{\npublic:\n\tstatic const int defaultValue = 42;\n\tstatic MoveConstructible Create()\n\t{\n\t\treturn MoveConstructible{};\n\t}\n\n\tMoveConstructible(MoveConstructible&& x) : value(x.value) {}\n\t~MoveConstructible() = default;\n\n\tMoveConstructible(const MoveConstructible&) = delete;\n\tMoveConstructible& operator=(const MoveConstructible&) = delete;\n\tMoveConstructible& operator=(MoveConstructible&&) = delete;\n\n\tconst int value;\n\nprivate:\n\tMoveConstructible() : value(defaultValue) {}\n};\n\nclass MoveAssignable\n{\npublic:\n\tstatic const int defaultValue = 42;\n\tstatic MoveAssignable Create()\n\t{\n\t\treturn MoveAssignable{};\n\t}\n\n\tMoveAssignable(MoveAssignable&& x) : value(x.value) {}\n\tMoveAssignable& operator=(MoveAssignable&& x)\n\t{\n\t\tvalue = x.value;\n\t\treturn *this;\n\t}\n\t~MoveAssignable() = default;\n\n\tMoveAssignable(const MoveAssignable&) = delete;\n\tMoveAssignable& operator=(const MoveAssignable&) = delete;\n\n\tint value;\n\nprivate:\n\tMoveAssignable() : value(defaultValue) {}\n};\n\nstruct MoveAndDefaultConstructible\n{\n\tstatic const int defaultValue = 42;\n\n\tMoveAndDefaultConstructible() : value(defaultValue) {}\n\tMoveAndDefaultConstructible(MoveAndDefaultConstructible&& x) : value(x.value) {}\n\t~MoveAndDefaultConstructible() = default;\n\n\tMoveAndDefaultConstructible(const MoveAndDefaultConstructible&) = delete;\n\tMoveAndDefaultConstructible& operator=(const MoveAndDefaultConstructible&) = delete;\n\tMoveAndDefaultConstructible& operator=(MoveAndDefaultConstructible&&) = delete;\n\n\tconst int value;\n};\n\nstruct MissingMoveConstructor\n{\n\tMissingMoveConstructor() {}\n\tMissingMoveConstructor(const MissingMoveConstructor&) {}\n\tMissingMoveConstructor& operator=(MissingMoveConstructor&&) { return *this; }\n\tMissingMoveConstructor& operator=(const MissingMoveConstructor&) { return *this; }\n\tbool operator<(const MissingMoveConstructor&) const { return true; }\n};\n\nstruct MissingMoveAssignable\n{\n\tMissingMoveAssignable() {}\n\tMissingMoveAssignable(const MissingMoveAssignable&) {}\n\tMissingMoveAssignable(MissingMoveAssignable&&) {}\n\tMissingMoveAssignable& operator=(const MissingMoveAssignable&) { return *this; }\n\tbool operator<(const MissingMoveAssignable&) const { return true; }\n};\n\nstruct MissingEquality\n{\n\tMissingEquality& operator==(const MissingEquality&) = delete;\n};\n\n#endif  // !defined(EA_COMPILER_NO_DEFAULTED_FUNCTIONS) && !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\n#endif  // CONCEPTSIMPLS_H\n"
  },
  {
    "path": "test/source/EASTLTest.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EABase/eabase.h>\n#include <EASTL/version.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n#include <new>\n#if !defined(EA_COMPILER_NO_STANDARD_CPP_LIBRARY)\n\t#include <vector> // Used to detect the C++ Standard Library version.\n#endif\n\n#ifndef EA_PLATFORM_PLAYSTSATION2\n\t#include <wchar.h>\n#endif\n#if defined(EA_PLATFORM_WINDOWS)\n\t#include <Windows.h>\n#elif defined(EA_PLATFORM_ANDROID)\n\t#include <android/log.h>\n#endif\n#if defined(_MSC_VER) && defined(EA_PLATFORM_MICROSOFT)\n\t#include <crtdbg.h>\n#endif\n\n\n#ifdef _MSC_VER\n\t#pragma warning(pop)\n#endif\n\n\n#include \"EASTLTestAllocator.h\"\n#include \"EASTLTest.h\"  // Include this last, as it enables compiler warnings.\n\n///////////////////////////////////////////////////////////////////////////////\n// init_seg\n//\n#ifdef _MSC_VER\n\t// Set initialization order between init_seg(compiler) (.CRT$XCC) and\n\t// init_seg(lib) (.CRT$XCL). The linker sorts the .CRT sections\n\t// alphabetically so we simply need to pick a name that is between\n\t// XCC and XCL.\n\t#pragma warning(disable: 4075) // warning C4075: initializers put in unrecognized initialization area\n\t#pragma init_seg(\".CRT$XCF\")\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EA_INIT_PRIORITY\n//\n// This is simply a wrapper for the GCC init_priority attribute that allows \n// multiplatform code to be easier to read. \n//\n// Example usage:\n//     SomeClass gSomeClass EA_INIT_PRIORITY(2000);\n//\n#if !defined(EA_INIT_PRIORITY)\n\t#if defined(__GNUC__)\n\t\t#define EA_INIT_PRIORITY(x)  __attribute__ ((init_priority (x)))\n\t#else\n\t\t#define EA_INIT_PRIORITY(x)\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestObject\n//\nint64_t TestObject::sTOCount            = 0;\nint64_t TestObject::sTOCtorCount        = 0;\nint64_t TestObject::sTODtorCount        = 0;\nint64_t TestObject::sTODefaultCtorCount = 0;\nint64_t TestObject::sTOArgCtorCount     = 0;\nint64_t TestObject::sTOCopyCtorCount    = 0;\nint64_t TestObject::sTOMoveCtorCount    = 0;\nint64_t TestObject::sTOAssignCount      = 0;\nint64_t TestObject::sTOCopyAssignCount  = 0;\nint64_t TestObject::sTOMoveAssignCount  = 0;\nint64_t TestObject::sTOSwapCount\t\t= 0;\nint     TestObject::sMagicErrorCount    = 0;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// ImplicitlyConvertible\n//\nsize_t ImplicitlyConvertible::sDefaultCtorCount = 0;\nsize_t ImplicitlyConvertible::sConvertCtorCount = 0;\nsize_t ImplicitlyConvertible::sCopyCtorCount = 0;\nsize_t ImplicitlyConvertible::sMoveCtorCount = 0;\nsize_t ImplicitlyConvertible::sCopyAssignCount = 0;\nsize_t ImplicitlyConvertible::sMoveAssignCount = 0;\nconst ImplicitlyConvertible::ImplicitType ImplicitlyConvertible::implicit{};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// MallocAllocator\n//\nint    MallocAllocator::mAllocCountAll   = 0;\nint    MallocAllocator::mFreeCountAll    = 0;\nsize_t MallocAllocator::mAllocVolumeAll  = 0;\nvoid*  MallocAllocator::mpLastAllocation = NULL;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// InstanceAllocator\n//\nint InstanceAllocator::mMismatchCount = 0;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// CountingAllocator\n//\nuint64_t CountingAllocator::activeAllocCount      = 0;\nuint64_t CountingAllocator::totalAllocCount       = 0;\nuint64_t CountingAllocator::totalDeallocCount     = 0;\nuint64_t CountingAllocator::totalCtorCount        = 0;\nuint64_t CountingAllocator::defaultCtorCount      = 0;\nuint64_t CountingAllocator::copyCtorCount         = 0;\nuint64_t CountingAllocator::assignOpCount         = 0;\nuint64_t CountingAllocator::totalAllocatedMemory  = 0;\nuint64_t CountingAllocator::activeAllocatedMemory = 0;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// gEASTL_TestLevel\n//\nint gEASTL_TestLevel = 0;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTLTest_CheckMemory_Imp\n//\nint EASTLTest_CheckMemory_Imp(const char* pFile, int nLine)\n{\n\tint  nErrorCount(0);\n\tbool bMemoryOK(true);\n\n\t#if defined(_DEBUG) && (defined(EA_COMPILER_MSVC) && defined(EA_PLATFORM_MICROSOFT))\n\t\tif(!_CrtCheckMemory())\n\t\t\tbMemoryOK = false;\n\t#endif\n\n\t#ifdef EA_DEBUG\n\t\tif(!EASTLTest_ValidateHeap())\n\t\t\tbMemoryOK = false;\n\t#endif\n\n\tif(!bMemoryOK)\n\t{\n\t\tnErrorCount++;\n\t\tEASTLTest_Printf(\"Memory check failure:\\n%s: line %d\\n\\n\", pFile, nLine);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// GetStdSTLType\n//\nStdSTLType GetStdSTLType()\n{\n\t#if defined(_STLPORT_VERSION)\n\t\treturn kSTLPort;                    // Descendent of the old HP / SGI STL.\n\t#elif defined(_RWSTD_VER_STR)\n\t\treturn kSTLApache;                  // a.k.a. Rogue Wave, which is a descendent of the old HP / SGI STL.\n\t#elif defined(_CPPLIB_VER)\n\t\treturn kSTLDinkumware;              // Indicated by the presence of the central yvals.h header.\n\t#elif defined(_LIBCPP_VECTOR)\n\t\treturn kSTLClang;\n\t#elif defined(_GLIBCXX_VECTOR)\n\t\treturn kSTLGCC;                     // a.k.a. libstdc++\n\t#elif defined(_MSC_VER)\n\t\treturn kSTLMS;                      // This is a tweaked version of Dinkumware.\n\t#else\n\t\treturn kSTLUnknown;\n\t#endif\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// GetStdSTLName\n//\nconst char* GetStdSTLName()\n{\n\t// We may need to tweak this function over time. \n\t// Theoretically it is possible to have multiple standard\n\t// STL versions active, as some of them have options to \n\t// put themselves in different namespaces.\n\n\t// Tests for specific STL versions directly.\n\t#if defined(_STLPORT_VERSION)\n\t\treturn \"STLPort\";\n\t#elif defined(__SGI_STL_VECTOR)\n\t\treturn \"SGI\";\n\t#elif defined(_RWSTD_VER_STR)\n\t\treturn \"Apache\";\n\n\t// Tests for specific platforms that have specific STL versions.\n\t#elif defined(EA_PLATFORM_SONY)\n\t\treturn \"Sony Dinkumware\";\n\n\t// Special case for Dinkumware.\n\t#elif defined(_CPPLIB_VER)\n\t\t#if defined(_MSC_VER)\n\t\t\treturn \"VC++ Dinkumware\";\n\t\t#else\n\t\t\treturn \"Dinkumware\";\n\t\t#endif\n\n\t// Tests for specific compilers as a fallback.\n\t#elif defined(_MSC_VER)\n\t\treturn \"VC++ ???\";\n\t#elif defined(_LIBCPP_VECTOR)\n\t\treturn \"clang libc++\";\n\t#elif defined(__GNUC__) || defined(_GLIBCXX_VECTOR)\n\t\treturn \"GCC (or emulated GCC) libstdc++\";\n\t#else\n\t\t#error Need to be able to identify the standard STL version.\n\t#endif\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// MallocAllocator\n///////////////////////////////////////////////////////////////////////////////\n\n// The following function is defined here instead of in the header because GCC  \n// generates a bogus warning about freeing a non-heap pointer when this function\n// is declared inline.\n\nvoid MallocAllocator::deallocate(void *p, size_t n)\n{ \n\t++mFreeCount;\n\tmAllocVolume -= n;\n\t++mFreeCountAll;\n\tmAllocVolumeAll -= n;\n\n\treturn free(p);\n}\n\nvoid* MallocAllocator::allocate(size_t n, int)\n{\n\t++mAllocCount; mAllocVolume += n; ++mAllocCountAll; mAllocVolumeAll += n; mpLastAllocation = malloc(n); return mpLastAllocation;\n}\n\nvoid* MallocAllocator::allocate(size_t n, size_t, size_t, int)\n{\n\t++mAllocCount; mAllocVolume += n; ++mAllocCountAll; mAllocVolumeAll += n; mpLastAllocation = malloc(n); return mpLastAllocation;\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// CustomAllocator\n///////////////////////////////////////////////////////////////////////////////\n\nvoid* CustomAllocator::allocate(size_t n, int flags)\n{\n\treturn ::operator new[](n, get_name(), flags, 0, __FILE__, __LINE__);\n}\n\nvoid* CustomAllocator::allocate(size_t n, size_t alignment, size_t offset, int flags)\n{\n\treturn ::operator new[](n, alignment, offset, get_name(), flags, 0, __FILE__, __LINE__);\n}\n\nvoid  CustomAllocator::deallocate(void* p, size_t /*n*/)\n{\n\t::operator delete((char*)p);\n}\n\n\n\nunsigned int ExplicitString::sCtorFromStrCount = 0;\n\n\n"
  },
  {
    "path": "test/source/EASTLTest.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTLTEST_H\n#define EASTLTEST_H\n\n\n#include <EABase/eabase.h>\n#include <EAStdC/EASprintf.h>\n#include <EATest/EATest.h>\n#include <EASTL/atomic.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n#include <vector>   // For the STD_STL_TYPE defines below.\n#if EASTL_EXCEPTIONS_ENABLED\n\t#include <stdexcept>\n\t#include <new>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS();\n\n\nint TestAlgorithm();\nint TestAllocator();\nint TestAllocatorPropagate();\nint TestAny();\nint TestArray();\nint TestBit();\nint TestBadExpectedAccess();\nint TestBitVector();\nint TestBitset();\nint TestCharTraits();\nint TestChrono();\nint TestConcepts();\nint TestContainerBehaviour();\nint TestCppCXTypeTraits();\nint TestDeque();\nint TestExpected();\nint TestExtra();\nint TestFinally();\nint TestFixedFunction();\nint TestFixedHash();\nint TestFixedList();\nint TestFixedMap();\nint TestFixedSList();\nint TestFixedSet();\nint TestFixedString();\nint TestFixedTupleVector();\nint TestFixedVector();\nint TestFunctional();\nint TestHash();\nint TestHeap();\nint TestIntrusiveHash();\nint TestIntrusiveList();\nint TestIntrusiveSDList();\nint TestIntrusiveSList();\nint TestIterator();\nint TestList();\nint TestListMap();\nint TestLruCache();\nint TestMap();\nint TestMemory();\nint TestMeta();\nint TestNumericLimits();\nint TestOptional();\nint TestRandom();\nint TestRatio();\nint TestRingBuffer();\nint TestSList();\nint TestSegmentedVector();\nint TestSet();\nint TestSmartPtr();\nint TestSort();\nint TestSpan();\nint TestString();\nint TestStringHashMap();\nint TestStringMap();\nint TestStringView();\nint TestTuple();\nint TestTupleVector();\nint TestTypeTraits();\nint TestUnexpected();\nint TestUtility();\nint TestVariant();\nint TestVector();\nint TestVectorMap();\nint TestVectorSet();\nint TestAtomicBasic();\nint TestAtomicRaw();\nint TestAtomicMultiThreaded();\nint TestAtomicAsm();\nint TestBitcast();\nint TestGslAlgorithum();\nint TestGslAssertion();\nint TestGslAt();\nint TestGslByte();\nint TestGslNotNull();\nint TestGslOwner();\nint TestGslSpanCompatibility();\nint TestGslSpanExt();\nint TestGslSpan();\nint TestGslStrictNotNull();\nint TestGslUtils();\nint TestFlags();\n\n// Now enable warnings as desired.\n#ifdef _MSC_VER\n\t#pragma warning(disable: 4324)      // 'struct_name' : structure was padded due to __declspec(align())\n  //#pragma warning(disable: 4512)      // 'class' : assignment operator could not be generated\n  //#pragma warning(disable: 4100)      // 'identifier' : unreferenced formal parameter\n  //#pragma warning(disable: 4706)      // assignment within conditional expression\n\n\t#pragma warning(default: 4056)      // Floating-point constant arithmetic generates a result that exceeds the maximum allowable value\n\t#pragma warning(default: 4061)      // The enumerate has no associated handler in a switch statement\n\t#pragma warning(default: 4062)      // The enumerate has no associated handler in a switch statement, and there is no default label\n\t#pragma warning(default: 4191)      // Calling this function through the result pointer may cause your program to crash\n\t#pragma warning(default: 4217)      // Member template functions cannot be used for copy-assignment or copy-construction\n  //#pragma warning(default: 4242)      // 'variable' : conversion from 'type' to 'type', possible loss of data\n\t#pragma warning(default: 4254)      // 'operator' : conversion from 'type1' to 'type2', possible loss of data\n\t#pragma warning(default: 4255)      // 'function' : no function prototype given: converting '()' to '(void)'\n\t#pragma warning(default: 4263)      // 'function' : member function does not override any base class virtual member function\n\t#pragma warning(default: 4264)      // 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden\n\t#pragma warning(default: 4287)      // 'operator' : unsigned/negative constant mismatch\n\t#pragma warning(default: 4289)      // Nonstandard extension used : 'var' : loop control variable declared in the for-loop is used outside the for-loop scope\n\t#pragma warning(default: 4296)      // 'operator' : expression is always false\n\t#pragma warning(default: 4302)      // 'conversion' : truncation from 'type 1' to 'type 2'\n\t#pragma warning(default: 4339)      // 'type' : use of undefined type detected in CLR meta-data - use of this type may lead to a runtime exception\n\t#pragma warning(default: 4347)      // Behavior change: 'function template' is called instead of 'function'\n  //#pragma warning(default: 4514)      // unreferenced inline/local function has been removed\n\t#pragma warning(default: 4529)      // 'member_name' : forming a pointer-to-member requires explicit use of the address-of operator ('&') and a qualified name\n\t#pragma warning(default: 4545)      // Expression before comma evaluates to a function which is missing an argument list\n\t#pragma warning(default: 4546)      // Function call before comma missing argument list\n\t#pragma warning(default: 4547)      // 'operator' : operator before comma has no effect; expected operator with side-effect\n  //#pragma warning(default: 4548)      // expression before comma has no effect; expected expression with side-effect\n\t#pragma warning(default: 4549)      // 'operator' : operator before comma has no effect; did you intend 'operator'?\n\t#pragma warning(default: 4536)      // 'type name' : type-name exceeds meta-data limit of 'limit' characters\n\t#pragma warning(default: 4555)      // Expression has no effect; expected expression with side-effect\n\t#pragma warning(default: 4557)      // '__assume' contains effect 'effect'\n  //#pragma warning(default: 4619)      // #pragma warning : there is no warning number 'number'\n\t#pragma warning(default: 4623)      // 'derived class' : default constructor could not be generated because a base class default constructor is inaccessible\n  //#pragma warning(default: 4625)      // 'derived class' : copy constructor could not be generated because a base class copy constructor is inaccessible\n  //#pragma warning(default: 4626)      // 'derived class' : assignment operator could not be generated because a base class assignment operator is inaccessible\n\t#pragma warning(default: 4628)      // Digraphs not supported with -Ze. Character sequence 'digraph' not interpreted as alternate token for 'char'\n\t#pragma warning(default: 4640)      // 'instance' : construction of local static object is not thread-safe\n\t#pragma warning(default: 4668)      // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'\n\t#pragma warning(default: 4682)      // 'parameter' : no directional parameter attribute specified, defaulting to [in]\n\t#pragma warning(default: 4686)      // 'user-defined type' : possible change in behavior, change in UDT return calling convention\n  //#pragma warning(default: 4710)      // 'function' : function not inlined\n  //#pragma warning(default: 4786)      // 'identifier' : identifier was truncated to 'number' characters in the debug information\n\t#pragma warning(default: 4793)      // Native code generated for function 'function': 'reason'\n  //#pragma warning(default: 4820)      // 'bytes' bytes padding added after member 'member'\n\t#pragma warning(default: 4905)      // Wide string literal cast to 'LPSTR'\n\t#pragma warning(default: 4906)      // String literal cast to 'LPWSTR'\n\t#pragma warning(default: 4917)      // 'declarator' : a GUID cannot only be associated with a class, interface or namespace\n\t#pragma warning(default: 4928)      // Illegal copy-initialization; more than one user-defined conversion has been implicitly applied\n\t#pragma warning(default: 4931)      // We are assuming the type library was built for number-bit pointers\n\t#pragma warning(default: 4946)      // reinterpret_cast used between related classes: 'class1' and 'class2'\n\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL includes\n//\n// Intentionally keep these includes below the warning settings specified above.\n//\n#include <EASTL/iterator.h>\n#include <EASTL/algorithm.h>\n\n\n\n\n/// EASTL_TestLevel\n///\n/// Defines how extensive our testing is. A low level is for a desktop or\n/// nightly build in which the test can run quickly but still hit the\n/// majority of functionality. High level is for heavy testing and internal\n/// validation which may take numerous hours to run.\n///\nenum EASTL_TestLevel\n{\n\tkEASTL_TestLevelLow  = 1,   /// ~10 seconds for test completion.\n\tkEASTL_TestLevelHigh = 10   /// Numerous hours for test completion.\n};\n\nextern int gEASTL_TestLevel;\n\n\n\n/// EASTLTest_CheckMemory\n///\n/// Does a global memory heap validation check. Returns 0 if OK and\n/// an error count if there is a problem.\n///\n/// Example usage:\n///    EASTLTest_CheckMemory();\n///\nint EASTLTest_CheckMemory_Imp(const char* pFile, int nLine);\n#define EASTLTest_CheckMemory() EASTLTest_CheckMemory_Imp(__FILE__, __LINE__)\n\n\n\n// EASTLTEST_STD_STL_VER\n//\n#if defined(_STLPORT_VERSION)\n\t#define EASTLTEST_STD_STL_VER_STLPORT\n#elif defined(_RWSTD_VER_STR) || defined(_RWSTD_NAMESPACE_END)\n\t#define EASTLTEST_STD_STL_VER_APACHE\n#elif defined(_CPPLIB_VER)\n\t#define EASTLTEST_STD_STL_VER_DINKUMWARE\n#elif defined(__GNUC__) && defined(_CXXCONFIG)\n\t#define EASTLTEST_STD_STL_VER_GCC\n#else\n\t#define EASTLTEST_STD_STL_VER_UNKNOWN\n#endif\n\n\n\n/// StdSTLType\n///\nenum StdSTLType\n{\n\tkSTLUnknown,    // Unknown type\n\tkSTLPort,       // STLPort. Descendent of the old HP / SGI STL.\n\tkSTLApache,     // Apache stdcxx (previously RogueWave), which is a descendent of the old HP / SGI STL.\n\tkSTLClang,      // Clang native. a.k.a. libc++\n\tkSTLGCC,        // GCC native. a.k.a. libstdc++\n\tkSTLMS,         // Microsoft. Tweaked version of Dinkumware.\n\tkSTLDinkumware  // Generic Dinkumware\n};\n\nStdSTLType GetStdSTLType();\n\n\n\n\n/// GetStdSTLName\n///\n/// Returns the name of the std C++ STL available to the current build.\n/// The returned value will be one of:\n///     \"STLPort\"\n///     \"GCC\"\n///     \"VC++\"\n//      \"Apache\" // Previously RogueWave\n///\nconst char* GetStdSTLName();\n\n\n/// gEASTLTest_AllocationCount\n///\nextern eastl::atomic<int> gEASTLTest_AllocationCount;\nextern eastl::atomic<int> gEASTLTest_TotalAllocationCount;\n\n\n\n// For backwards compatibility:\n#define EASTLTest_Printf EA::UnitTest::Report\n#define VERIFY           EATEST_VERIFY\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// EASTLTest_Rand\n///\n/// Implements a basic random number generator for EASTL unit tests. It's not\n/// intended to be a robust random number generator (though it is decent),\n/// but rather is present so the unit tests can have a portable random number\n/// generator they can rely on being present.\n///\n/// Example usage:\n///    EASTLTest_Rand rng;\n///    eastl_size_t   x = rng();                      // Generate value in range of [0, 0xffffffff] (i.e. generate any uint32_t)\n///    eastl_ssize_t  y = rng.Rand(1000);             // Generate value in range of [0, 1000)\n///    eastl_ssize_t  z = rng.RandRange(-50, +30);    // Generate value in range of [-50, +30)\n///\n/// Example usage in the random_shuffle algorithm:\n///    EASTLTest_Rand rng;\n///    random_shuffle(first, last, rnd);\n///\nclass EASTLTest_Rand\n{\npublic:\n\tEASTLTest_Rand(eastl_size_t nSeed) // The user must supply a seed; we don't provide default values.\n\t\t: mnSeed(nSeed) { }\n\n\teastl_size_t Rand()\n\t{\n\t\t// This is not designed to be a high quality random number generator.\n\t\tif(mnSeed == 0)\n\t\t\tmnSeed = UINT64_C(0xfefefefefefefefe); // Can't have a seed of zero.\n\n\t\tconst uint64_t nResult64A = ((mnSeed     * UINT64_C(6364136223846793005)) + UINT64_C(1442695040888963407));\n\t\tconst uint64_t nResult64B = ((nResult64A * UINT64_C(6364136223846793005)) + UINT64_C(1442695040888963407));\n\n\t\tmnSeed = (nResult64A >> 32) ^ nResult64B;\n\n\t\treturn (eastl_size_t)mnSeed; // For eastl_size_t == uint32_t, this is a chop.\n\t}\n\n\teastl_size_t operator()() // Returns a pseudorandom value in range of [0, 0xffffffffffffffff)] (i.e. generate any eastl_size_t)\n\t\t{ return Rand(); }\n\n\teastl_size_t operator()(eastl_size_t n)  // Returns a pseudorandom value in range of [0, n)\n\t\t{ return RandLimit(n); }\n\n\teastl_size_t RandLimit(eastl_size_t nLimit) // Returns a pseudorandom value in range of [0, nLimit)\n\t{\n\t\t// Can't do the following correct solution because we don't have a portable int128_t to work with.\n\t\t// We could implement a 128 bit multiply manually. See EAStdC/int128_t.cpp.\n\t\t// return (eastl_size_t)((Rand() * (uint128_t)nLimit) >> 64);\n\n\t\treturn (Rand() % nLimit); // This results in an imperfect distribution, especially for the case of nLimit being high relative to eastl_size_t.\n\t}\n\n\teastl_ssize_t RandRange(eastl_ssize_t nBegin, eastl_ssize_t nEnd)   // Returns a pseudorandom value in range of [nBegin, nEnd)\n\t\t{ return nBegin + (eastl_ssize_t)RandLimit((eastl_size_t)(nEnd - nBegin)); }\n\nprotected:\n\tuint64_t mnSeed;\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// RandGenT\n///\n/// A wrapper for EASTLTest_Rand which generates values of the given integral\n/// data type. This is mostly useful for clearnly avoiding compiler warnings,\n/// as we intentionally enable the highest warning levels in these tests.\n///\ntemplate <typename Integer>\nstruct RandGenT\n{\n\tRandGenT(eastl_size_t nSeed)\n\t\t: mRand(nSeed) { }\n\n\tInteger operator()()\n\t\t{ return (Integer)mRand.Rand(); }\n\n\tInteger operator()(eastl_size_t n)\n\t\t{ return (Integer)mRand.RandLimit(n); }\n\n\tEASTLTest_Rand mRand;\n};\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// kMagicValue\n///\n/// Used as a unique integer. We assign this to TestObject in its constructor\n/// and verify in the TestObject destructor that the value is unchanged.\n/// This can be used to tell, for example, if an invalid object is being\n/// destroyed.\n///\nconst uint32_t kMagicValue = 0x01f1cbe8;\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// TestObject\n///\n/// Implements a generic object that is suitable for use in container tests.\n/// Note that we choose a very restricted set of functions that are available\n/// for this class. Do not add any additional functions, as that would\n/// compromise the intentions of the unit tests.\n///\nstruct TestObject\n{\n\tint             mX;                  // Value for the TestObject.\n\tbool            mbThrowOnCopy;       // Throw an exception of this object is copied, moved, or assigned to another.\n\tint64_t         mId;                 // Unique id for each object, equal to its creation number. This value is not coped from other TestObjects during any operations, including moves.\n\tuint32_t        mMagicValue;         // Used to verify that an instance is valid and that it is not corrupted. It should always be kMagicValue.\n\tstatic int64_t  sTOCount;            // Count of all current existing TestObjects.\n\tstatic int64_t  sTOCtorCount;        // Count of times any ctor was called.\n\tstatic int64_t  sTODtorCount;        // Count of times dtor was called.\n\tstatic int64_t  sTODefaultCtorCount; // Count of times the default ctor was called.\n\tstatic int64_t  sTOArgCtorCount;     // Count of times the x0,x1,x2 ctor was called.\n\tstatic int64_t  sTOCopyCtorCount;    // Count of times copy ctor was called.\n\tstatic int64_t  sTOMoveCtorCount;    // Count of times move ctor was called.\n\tstatic int64_t  sTOAssignCount;      // Count of times any assignment was called.\n\tstatic int64_t  sTOCopyAssignCount;  // Count of times copy assignment was called.\n\tstatic int64_t  sTOMoveAssignCount;  // Count of times move assignment was called.\n\tstatic int64_t  sTOSwapCount;\n\tstatic int      sMagicErrorCount;    // Number of magic number mismatch errors.\n\n\texplicit TestObject(int x = 0, bool bThrowOnCopy = false)\n\t\t: mX(x), mbThrowOnCopy(bThrowOnCopy), mMagicValue(kMagicValue)\n\t{\n\t\t++sTOCount;\n\t\t++sTOCtorCount;\n\t\t++sTODefaultCtorCount;\n\t\tmId = sTOCtorCount;\n\t}\n\n\t// This constructor exists for the purpose of testing variadiac template arguments, such as with the emplace container functions.\n\tTestObject(int x0, int x1, int x2, bool bThrowOnCopy = false)\n\t\t: mX(x0 + x1 + x2), mbThrowOnCopy(bThrowOnCopy), mMagicValue(kMagicValue)\n\t{\n\t\t++sTOCount;\n\t\t++sTOCtorCount;\n\t\t++sTOArgCtorCount;\n\t\tmId = sTOCtorCount;\n\t}\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tstruct ThrowOnConstruct {};\n\tstatic inline constexpr ThrowOnConstruct throw_on_construct{};\n\n\texplicit TestObject(ThrowOnConstruct)\n\t{\n\t\t// don't initialize any members.\n\t\tthrow \"TestObject constructor: ThrowOnConstruct\";\n\t}\n#endif\n\n\tTestObject(const TestObject& testObject)\n\t\t: mX(testObject.mX), mbThrowOnCopy(testObject.mbThrowOnCopy), mMagicValue(testObject.mMagicValue)\n\t{\n\t\tif(mbThrowOnCopy)\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow \"Disallowed TestObject copy\";\n\t\t\t#endif\n\t\t}\n\t\t++sTOCount;\n\t\t++sTOCtorCount;\n\t\t++sTOCopyCtorCount;\n\t\tmId = sTOCtorCount;\n\t}\n\n\t// Due to the nature of TestObject, there isn't much special for us to\n\t// do in our move constructor. A move constructor swaps its contents with\n\t// the other object, which is often a default-constructed object.\n\tTestObject(TestObject&& testObject)\n\t\t: mX(testObject.mX), mbThrowOnCopy(testObject.mbThrowOnCopy), mMagicValue(testObject.mMagicValue)\n\t{\n\t\tif(mbThrowOnCopy)\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow \"Disallowed TestObject copy\";\n\t\t\t#endif\n\t\t}\n\t\t++sTOCount;\n\t\t++sTOCtorCount;\n\t\t++sTOMoveCtorCount;\n\t\tmId = sTOCtorCount;  // testObject keeps its mId, and we assign ours anew.\n\t\ttestObject.mX = 0;   // We are swapping our contents with the TestObject, so give it our \"previous\" value.\n\t}\n\n\tTestObject& operator=(const TestObject& testObject)\n\t{\n\t\tif(mbThrowOnCopy)\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow \"Disallowed TestObject copy\";\n\t\t\t#endif\n\t\t}\n\n\t\t++sTOAssignCount;\n\t\t++sTOCopyAssignCount;\n\n\t\tif(&testObject != this)\n\t\t{\n\t\t\tmX = testObject.mX;\n\t\t\t// Leave mId alone.\n\t\t\tmMagicValue = testObject.mMagicValue;\n\t\t\tmbThrowOnCopy = testObject.mbThrowOnCopy;\n\t\t}\n\t\treturn *this;\n\t}\n\n\tTestObject& operator=(TestObject&& testObject)\n\t{\n\t\tif(mbThrowOnCopy)\n\t\t{\n\t\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\t\tthrow \"Disallowed TestObject copy\";\n\t\t\t#endif\n\t\t}\n\n\t\t++sTOAssignCount;\n\t\t++sTOMoveAssignCount;\n\n\t\tif(&testObject != this)\n\t\t{\n\t\t\teastl::swap(mX, testObject.mX);\n\t\t\t// Leave mId alone.\n\t\t\teastl::swap(mMagicValue, testObject.mMagicValue);\n\t\t\teastl::swap(mbThrowOnCopy, testObject.mbThrowOnCopy);\n\t\t}\n\t\treturn *this;\n\t}\n\n\t~TestObject()\n\t{\n\t\tmX = 0;\n\t\tif(mMagicValue != kMagicValue)\n\t\t\t++sMagicErrorCount;\n\t\tmMagicValue = 0;\n\t\t--sTOCount;\n\t\t++sTODtorCount;\n\t}\n\n\t// todo: Should be EA_NODISCARD. Usage should be:\n\t// EATEST_VERIFY(TestObject::Reset());\n\tstatic bool Reset()\n\t{\n\t\tconst bool result = IsClear();\n\t\tsTOCount            = 0;\n\t\tsTOCtorCount        = 0;\n\t\tsTODtorCount        = 0;\n\t\tsTODefaultCtorCount = 0;\n\t\tsTOArgCtorCount     = 0;\n\t\tsTOCopyCtorCount    = 0;\n\t\tsTOMoveCtorCount    = 0;\n\t\tsTOAssignCount\t\t= 0;\n\t\tsTOCopyAssignCount  = 0;\n\t\tsTOMoveAssignCount  = 0;\n\t\tsTOSwapCount\t\t= 0;\n\t\tsMagicErrorCount    = 0;\n\t\treturn result;\n\t}\n\n\tEA_NODISCARD static bool IsClear() // Returns true if there are no existing TestObjects and the sanity checks related to that test OK.\n\t{\n\t\treturn (sTOCount == 0) && (sTODtorCount == sTOCtorCount) && (sMagicErrorCount == 0);\n\t}\n\n\tTestObject& operator++()\n\t{\n\t\t++mX;\n\t\treturn *this;\n\t}\n\n\tTestObject operator++(int) const\n\t{\n\t\tTestObject temp(*this);\n\t\t++temp;\n\t\treturn temp;\n\t}\n};\n\n// Operators\n// We specifically define only == and <, in order to verify that\n// our containers and algorithms are not mistakenly expecting other\n// operators for the contained and manipulated classes.\ninline bool operator==(const TestObject& t1, const TestObject& t2)\n\t{ return t1.mX == t2.mX; }\n\ninline bool operator<(const TestObject& t1, const TestObject& t2)\n\t{ return t1.mX < t2.mX; }\n\ninline void swap(TestObject& t1, TestObject& t2)\n{\n\t++TestObject::sTOSwapCount;\n\teastl::swap(t1, t2);\n}\n\n// TestObject hash\n// add program defined type specialization: https://eel.is/c++draft/namespace.std#2\nnamespace eastl\n{\n\ttemplate <>\n\tstruct hash<TestObject>\n\t{\n\t\tsize_t operator()(const TestObject& a) const\n\t\t\t{ return static_cast<size_t>(a.mX); }\n\t};\n}\n\n\n// use_mX\n// Used for printing TestObject contents via the PrintSequence function,\n// which is defined below. See the PrintSequence function for documentation.\n// This function is an analog of the eastl::use_self and use_first functions.\n// We declare this all in one line because the user should never need to\n// debug usage of this function.\ntemplate <typename T> struct use_mX { int operator()(const T& t) const { return t.mX; } };\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// TestObjectHash\n///\n/// Implements a manually specified hash function for TestObjects.\n///\nstruct TestObjectHash\n{\n\tsize_t operator()(const TestObject& t) const\n\t{\n\t\treturn (size_t)t.mX;\n\t}\n};\n\n\n\nstruct ImplicitlyConvertible\n{\n\tstatic size_t sDefaultCtorCount;\n\tstatic size_t sConvertCtorCount;\n\tstatic size_t sCopyCtorCount;\n\tstatic size_t sMoveCtorCount;\n\tstatic size_t sCopyAssignCount;\n\tstatic size_t sMoveAssignCount;\n\n\tstruct ImplicitType {};\n\tstatic const ImplicitType implicit;\n\n\tImplicitlyConvertible() { ++sDefaultCtorCount; }\n\t/* implicit */ ImplicitlyConvertible(ImplicitType) { ++sConvertCtorCount; }\n\n\tImplicitlyConvertible(const ImplicitlyConvertible&) { ++sCopyCtorCount; }\n\tImplicitlyConvertible(ImplicitlyConvertible&&) { ++sMoveCtorCount; }\n\tImplicitlyConvertible& operator=(const ImplicitlyConvertible&) { ++sCopyAssignCount; return *this; }\n\tImplicitlyConvertible& operator=(ImplicitlyConvertible&&) { ++sMoveAssignCount; return *this; }\n\n\tstatic void Reset()\n\t{\n\t\tsDefaultCtorCount = 0;\n\t\tsConvertCtorCount = 0;\n\t\tsCopyCtorCount = 0;\n\t\tsMoveCtorCount = 0;\n\t\tsCopyAssignCount = 0;\n\t\tsMoveAssignCount = 0;\n\t};\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// Align16\n///\n\nstruct alignas(16) Align16\n{\n\texplicit Align16(int x = 0) : mX(x) {}\n\tint mX;\n};\n\ninline bool operator==(const Align16& a, const Align16& b)\n\t{ return (a.mX == b.mX); }\n\ninline bool operator<(const Align16& a, const Align16& b)\n\t{ return (a.mX < b.mX); }\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// Align32\n///\nstruct alignas(32) Align32\n{\n\texplicit Align32(int x = 0) : mX(x) {}\n\tint mX;\n};\n\ninline bool operator==(const Align32& a, const Align32& b)\n\t{ return (a.mX == b.mX); }\n\ninline bool operator<(const Align32& a, const Align32& b)\n\t{ return (a.mX < b.mX); }\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// Align64\n///\nstruct alignas(64) Align64\n{\n\texplicit Align64(int x = 0) : mX(x) {}\n\tint mX;\n};\n\ninline bool operator==(const Align64& a, const Align64& b)\n\t{ return (a.mX == b.mX); }\n\ninline bool operator<(const Align64& a, const Align64& b)\n\t{ return (a.mX < b.mX); }\n\nnamespace eastl\n{\n\ttemplate <>\n\tstruct hash < Align64 >\n\t{\n\t\tsize_t operator()(const Align64& a) const\n\t\t{\n\t\t\treturn static_cast<size_t>(a.mX);\n\t\t}\n\t};\n}\n\n\n\n\n\n/// test_use_self\n///\n/// Intentionally avoiding a dependency on eastl::use_self.\n///\ntemplate <typename T>\nstruct test_use_self\n{\n\tconst T& operator()(const T& x) const\n\t\t{ return x; }\n};\n\n\n\n/// GenerateIncrementalIntegers\n///\n/// Used to seed containers with incremental values based on integers.\n///\n/// Example usage:\n///     vector<int> v(10, 0);\n///     generate(v.begin(), v.end(), GenerateIncrementalIntegers<int>());\n///     // v will now have 0, 1, 2, ... 8, 9.\n///\n///     generate_n(intArray.begin(), 10, GenerateIncrementalIntegers<int>());\n///     // v will now have 0, 1, 2, ... 8, 9.\n///\n///     vector<TestObject> vTO(10, 0);\n///     generate(vTO.begin(), vTO.end(), GenerateIncrementalIntegers<TestObject>());\n///     // vTO will now have 0, 1, 2, ... 8, 9.\n///\ntemplate <typename T>\nstruct GenerateIncrementalIntegers\n{\n\tint mX;\n\n\tGenerateIncrementalIntegers(int x = 0)\n\t\t: mX(x) { }\n\n\tvoid reset(int x = 0)\n\t\t{ mX = x; }\n\n\tT operator()()\n\t\t{ return T(mX++); }\n};\n\n\n\n/// SetIncrementalIntegers\n///\n/// Used to seed containers with incremental values based on integers.\n///\n/// Example usage:\n///     vector<int> v(10, 0);\n///     for_each(v.begin(), v.end(), SetIncrementalIntegers<int>());\n///     // v will now have 0, 1, 2, ... 8, 9.\n///\ntemplate <typename T>\nstruct SetIncrementalIntegers\n{\n\tint mX;\n\n\tSetIncrementalIntegers(int x = 0)\n\t\t: mX(x) { }\n\n\tvoid reset(int x = 0)\n\t\t{ mX = x; }\n\n\tvoid operator()(T& t)\n\t\t{ t = T(mX++); }\n};\n\n\n\n/// CompareContainers\n///\n/// Does a comparison between the contents of two containers.\n///\n/// Specifically tests for the following properties:\n///     empty() is the same for both\n///     size() is the same for both\n///     iteration through both element by element yields equal values.\n///\ntemplate <typename T1, typename T2, typename ExtractValue1, typename ExtractValue2>\nint CompareContainers(const T1& t1, const T2& t2, const char* ppName,\n\t\t\t\t\t  ExtractValue1 ev1 = test_use_self<T1>(), ExtractValue2 ev2 = test_use_self<T2>())\n{\n\tint nErrorCount = 0;\n\n\t// Compare emptiness.\n\tVERIFY(t1.empty() == t2.empty());\n\n\t// Compare sizes.\n\tconst size_t nSize1 = t1.size();\n\tconst size_t nSize2 = t2.size();\n\n\tVERIFY(nSize1 == nSize2);\n\tif(nSize1 != nSize2)\n\t\tEASTLTest_Printf(\"%s: Container size difference: %u, %u\\n\", ppName, (unsigned)nSize1, (unsigned)nSize2);\n\n\t// Compare values.\n\tif(nSize1 == nSize2)\n\t{\n\t\t// Test iteration\n\t\ttypename T1::const_iterator it1 = t1.begin();\n\t\ttypename T2::const_iterator it2 = t2.begin();\n\n\t\tfor(unsigned j = 0; it1 != t1.end(); ++it1, ++it2, ++j)\n\t\t{\n\t\t\tconst typename T1::value_type& v1 = *it1;\n\t\t\tconst typename T2::value_type& v2 = *it2;\n\n\t\t\tVERIFY(ev1(v1) == ev2(v2));\n\t\t\tif(!(ev1(v1) == ev2(v2)))\n\t\t\t{\n\t\t\t\tEASTLTest_Printf(\"%s: Container iterator difference at index %d\\n\", ppName, j);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tVERIFY(it1 == t1.end());\n\t\tVERIFY(it2 == t2.end());\n\t}\n\n\treturn nErrorCount;\n}\n\n\ntemplate <typename InputIterator1, typename InputIterator2>\nbool VerifySequence(InputIterator1 firstActual, InputIterator1 lastActual, InputIterator2 firstExpected, InputIterator2 lastExpected, const char* pName)\n{\n\tsize_t     numMatching = 0;\n\n\twhile ((firstActual != lastActual) && (firstExpected != lastExpected) && (*firstActual == *firstExpected))\n\t{\n\t\t++firstActual;\n\t\t++firstExpected;\n\t\t++numMatching;\n\t}\n\n\tif (firstActual == lastActual && firstExpected == lastExpected)\n\t{\n\t\treturn true;\n\t}\n\telse if (firstActual != lastActual && firstExpected == lastExpected)\n\t{\n\t\tsize_t numActual = numMatching, numExpected = numMatching;\n\t\tfor (; firstActual != lastActual; ++firstActual)\n\t\t\t++numActual;\n\t\tif (pName)\n\t\t\tEASTLTest_Printf(\"[%s] Too many elements: expected %u, found %u\\n\", pName, numExpected, numActual);\n\t\telse\n\t\t\tEASTLTest_Printf(\"Too many elements: expected %u, found %u\\n\", numExpected, numActual);\n\t\treturn false;\n\t}\n\telse if (firstActual == lastActual && firstExpected != lastExpected)\n\t{\n\t\tsize_t numActual = numMatching, numExpected = numMatching;\n\t\tfor (; firstExpected != lastExpected; ++firstExpected)\n\t\t\t++numExpected;\n\t\tif (pName)\n\t\t\tEASTLTest_Printf(\"[%s] Too few elements: expected %u, found %u\\n\", pName, numExpected, numActual);\n\t\telse\n\t\t\tEASTLTest_Printf(\"Too few elements: expected %u, found %u\\n\", numExpected, numActual);\n\t\treturn false;\n\t}\n\telse // if (firstActual != lastActual && firstExpected != lastExpected)\n\t{\n\t\tif (pName)\n\t\t\tEASTLTest_Printf(\"[%s] Mismatch at index %u\\n\", pName, numMatching);\n\t\telse\n\t\t\tEASTLTest_Printf(\"Mismatch at index %u\\n\", numMatching);\n\t\treturn false;\n\t}\n}\n\ntemplate <typename InputIterator, typename T = typename InputIterator::value_type>\nbool VerifySequence(InputIterator firstActual, InputIterator lastActual, std::initializer_list<T> initList, const char* pName)\n{\n\treturn VerifySequence(firstActual, lastActual, initList.begin(), initList.end(), pName);\n}\n\ntemplate <typename Container, typename T = typename Container::value_type>\nbool VerifySequence(const Container& container, std::initializer_list<T> initList, const char* pName)\n{\n\treturn VerifySequence(container.begin(), container.end(), initList.begin(), initList.end(), pName);\n}\n\n\n/// VerifySequence\n///\n/// Allows the user to specify that a container has a given set of values.\n///\n/// Example usage:\n///    vector<int> v;\n///    v.push_back(1); v.push_back(3); v.push_back(5);\n///    VerifySequence(v.begin(), v.end(), int(), \"v.push_back\", 1, 3, 5, -1);\n///\n/// Note: The StackValue template argument is a hint to the compiler about what type\n///       the passed vararg sequence is.\n///\ntemplate <typename InputIterator, typename StackValue>\nbool VerifySequence(InputIterator first, InputIterator last, StackValue /*unused*/, const char* pName, ...)\n{\n\ttypedef typename eastl::iterator_traits<InputIterator>::value_type value_type;\n\n\tint        argIndex = 0;\n\tint        seqIndex = 0;\n\tbool       bReturnValue = true;\n\tStackValue next;\n\n\tva_list args;\n\tva_start(args, pName);\n\n\tfor( ; first != last; ++first, ++argIndex, ++seqIndex)\n\t{\n\t\tnext = va_arg(args, StackValue);\n\n\t\tif((next == StackValue(-1)) || !(value_type(next) == *first))\n\t\t{\n\t\t\tif(pName)\n\t\t\t\tEASTLTest_Printf(\"[%s] Mismatch at index %d\\n\", pName, argIndex);\n\t\t\telse\n\t\t\t\tEASTLTest_Printf(\"Mismatch at index %d\\n\", argIndex);\n\t\t\tbReturnValue = false;\n\t\t}\n\t}\n\n\tfor(; first != last; ++first)\n\t\t++seqIndex;\n\n\tif(bReturnValue)\n\t{\n\t\tnext = va_arg(args, StackValue);\n\n\t\tif(!(next == StackValue(-1)))\n\t\t{\n\t\t\tdo {\n\t\t\t\t++argIndex;\n\t\t\t\tnext = va_arg(args, StackValue);\n\t\t\t} while(!(next == StackValue(-1)));\n\n\t\t\tif(pName)\n\t\t\t\tEASTLTest_Printf(\"[%s] Too many elements: expected %d, found %d\\n\", pName, argIndex, seqIndex);\n\t\t\telse\n\t\t\t\tEASTLTest_Printf(\"Too many elements: expected %d, found %d\\n\", argIndex, seqIndex);\n\t\t\tbReturnValue = false;\n\t\t}\n\t}\n\n\tva_end(args);\n\n\treturn bReturnValue;\n}\n\n\n\n\n/// PrintSequence\n///\n/// Allows the user to print a sequence of values.\n///\n/// Example usage:\n///    vector<int> v;\n///    PrintSequence(v.begin(), v.end(), use_self<int>(), 100, \"vector\", 1, 3, 5, -1);\n///\n/// Example usage:\n///    template <typename T> struct use_mX { int operator()(const T& t) const { return t.mX; } };\n///    vector<TestObject> v;\n///    PrintSequence(v.begin(), v.end(), use_mX<TestObject>(), 100, \"vector\", 1, 3, 5, -1);\n///\ntemplate <typename InputIterator, typename ExtractInt>\nvoid PrintSequence(InputIterator first, InputIterator last, ExtractInt extractInt, int nMaxCount, const char* pName, ...)\n{\n\tif(pName)\n\t\tEASTLTest_Printf(\"[%s]\", pName);\n\n\tfor(int i = 0; (i < nMaxCount) && (first != last); ++i, ++first)\n\t{\n\t\tEASTLTest_Printf(\"%d \", (int)extractInt(*first));\n\t}\n\n\tEASTLTest_Printf(\"\\n\");\n}\n\n\n\n\n/// demoted_iterator\n///\n/// Converts an iterator into a demoted category. For example, you can convert\n/// an iterator of type bidirectional_iterator_tag to forward_iterator_tag.\n/// The following is a list of iterator types. A demonted iterator can be demoted\n/// only to a lower iterator category (earlier in the following list):\n///     input_iterator_tag\n///     forward_iterator_tag\n///     bidirectional_iterator_tag\n///     random_access_iterator_tag\n///     contiguous_iterator_tag\n///\n/// Converts something which can be iterated into a formal input iterator.\n/// This class is useful for testing functions and algorithms that expect\n/// InputIterators, which are the lowest and 'weakest' form of iterators.\n///\n/// Key traits of InputIterators:\n///    Algorithms on input iterators should never attempt to pass\n///    through the same iterator twice. They should be single pass\n///    algorithms. value_type T is not required to be an lvalue type.\n///\n/// Example usage:\n///     typedef demoted_iterator<int*, eastl::bidirectional_iterator_tag>         PointerAsBidirectionalIterator;\n///     typedef demoted_iterator<MyVector::iterator, eastl::forward_iterator_tag> VectorIteratorAsForwardIterator;\n///\n/// Example usage:\n///     IntVector v;\n///     comb_sort(to_forward_iterator(v.begin()), to_forward_iterator(v.end()));\n///\ntemplate <typename Iterator, typename IteratorCategory>\nclass demoted_iterator\n{\nprotected:\n\tIterator mIterator;\n\npublic:\n\ttypedef demoted_iterator<Iterator, IteratorCategory>                 this_type;\n\ttypedef Iterator                                                     iterator_type;\n\ttypedef IteratorCategory                                             iterator_category;\n\ttypedef typename eastl::iterator_traits<Iterator>::value_type        value_type;\n\ttypedef typename eastl::iterator_traits<Iterator>::difference_type   difference_type;\n\ttypedef typename eastl::iterator_traits<Iterator>::reference         reference;\n\ttypedef typename eastl::iterator_traits<Iterator>::pointer           pointer;\n\n\tdemoted_iterator()\n\t\t: mIterator() { }\n\n\texplicit demoted_iterator(const Iterator& i)\n\t\t: mIterator(i) { }\n\n\tdemoted_iterator(const this_type& x)\n\t\t: mIterator(x.mIterator) { }\n\n\tthis_type& operator=(const Iterator& i)\n\t\t{ mIterator = i; return *this; }\n\n\tthis_type& operator=(const this_type& x)\n\t\t{ mIterator = x.mIterator; return *this; }\n\n\treference operator*() const\n\t\t{ return *mIterator; }\n\n\tpointer operator->() const\n\t\t{ return mIterator; }\n\n\tthis_type& operator++()\n\t\t{ ++mIterator; return *this; }\n\n\tthis_type operator++(int)\n\t\t{ return this_type(mIterator++); }\n\n\tthis_type& operator--()\n\t\t{ --mIterator; return *this; }\n\n\tthis_type operator--(int)\n\t\t{ return this_type(mIterator--); }\n\n\treference operator[](const difference_type& n) const\n\t\t{ return mIterator[n]; }\n\n\tthis_type& operator+=(const difference_type& n)\n\t\t{ mIterator += n; return *this; }\n\n\tthis_type operator+(const difference_type& n) const\n\t\t{ return this_type(mIterator + n); }\n\n\tthis_type& operator-=(const difference_type& n)\n\t\t{ mIterator -= n; return *this; }\n\n\tthis_type operator-(const difference_type& n) const\n\t\t{ return this_type(mIterator - n); }\n\n\tconst iterator_type& base() const\n\t\t{ return mIterator; }\n\n}; // class demoted_iterator\n\ntemplate<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>\ninline bool\noperator==(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)\n\t{ return a.base() == b.base(); }\n\ntemplate<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>\ninline bool\noperator!=(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)\n\t{ return !(a == b); }\n\ntemplate<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>\ninline bool\noperator<(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)\n\t{ return a.base() < b.base(); }\n\ntemplate<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>\ninline bool\noperator<=(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)\n\t{ return !(b < a); }\n\ntemplate<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>\ninline bool\noperator>(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)\n\t{ return b < a; }\n\ntemplate<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>\ninline bool\noperator>=(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)\n\t{ return !(a < b); }\n\ntemplate<typename Iterator1, typename IteratorCategory1, typename Iterator2, typename IteratorCategory2>\ninline demoted_iterator<Iterator1, IteratorCategory1>\noperator-(const demoted_iterator<Iterator1, IteratorCategory1>& a, const demoted_iterator<Iterator2, IteratorCategory2>& b)\n\t{ return demoted_iterator<Iterator1, IteratorCategory1>(a.base() - b.base()); }\n\ntemplate<typename Iterator1, typename IteratorCategory1>\ninline demoted_iterator<Iterator1, IteratorCategory1>\noperator+(typename demoted_iterator<Iterator1, IteratorCategory1>::difference_type n, const demoted_iterator<Iterator1, IteratorCategory1>& a)\n\t{ return a + n; }\n\n\n// to_xxx_iterator\n//\n// Returns a demoted iterator\n//\ntemplate <typename Iterator>\ninline demoted_iterator<Iterator, eastl::input_iterator_tag>\nto_input_iterator(const Iterator& i)\n\t{ return demoted_iterator<Iterator, eastl::input_iterator_tag>(i); }\n\ntemplate <typename Iterator>\ninline demoted_iterator<Iterator, eastl::forward_iterator_tag>\nto_forward_iterator(const Iterator& i)\n\t{ return demoted_iterator<Iterator, eastl::forward_iterator_tag>(i); }\n\ntemplate <typename Iterator>\ninline demoted_iterator<Iterator, eastl::bidirectional_iterator_tag>\nto_bidirectional_iterator(const Iterator& i)\n\t{ return demoted_iterator<Iterator, eastl::bidirectional_iterator_tag>(i); }\n\ntemplate <typename Iterator>\ninline demoted_iterator<Iterator, eastl::random_access_iterator_tag>\nto_random_access_iterator(const Iterator& i)\n\t{ return demoted_iterator<Iterator, eastl::random_access_iterator_tag>(i); }\n\n\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// MallocAllocator\n//\n// Implements an EASTL allocator that uses malloc/free as opposed to\n// new/delete or PPMalloc Malloc/Free. This is useful for testing\n// allocator behaviour of code.\n//\n// Example usage:\n//      vector<int, MallocAllocator> intVector;\n//\nclass MallocAllocator\n{\npublic:\n\tMallocAllocator(const char* = EASTL_NAME_VAL(\"MallocAllocator\"))\n\t\t: mAllocCount(0), mFreeCount(0), mAllocVolume(0) {}\n\n\tMallocAllocator(const MallocAllocator& x)\n\t\t: mAllocCount(x.mAllocCount), mFreeCount(x.mFreeCount), mAllocVolume(x.mAllocVolume) {}\n\n\tMallocAllocator(const MallocAllocator& x, const char*) : MallocAllocator(x) {}\n\n\tMallocAllocator& operator=(const MallocAllocator& x)\n\t{\n\t\tmAllocCount = x.mAllocCount;\n\t\tmFreeCount = x.mFreeCount;\n\t\tmAllocVolume = x.mAllocVolume;\n\t\treturn *this;\n\t}\n\n\tvoid* allocate(size_t n, int = 0);\n\tvoid* allocate(size_t n, size_t, size_t, int = 0); // We don't support alignment, so you can't use this class where alignment is required.\n\tvoid deallocate(void* p, size_t n);\n\n\tconst char* get_name() const { return \"MallocAllocator\"; }\n\tvoid set_name(const char*) {}\n\n\tstatic void reset_all()\n\t{\n\t\tmAllocCountAll = 0;\n\t\tmFreeCountAll = 0;\n\t\tmAllocVolumeAll = 0;\n\t\tmpLastAllocation = NULL;\n\t}\n\npublic:\n\tint mAllocCount;\n\tint mFreeCount;\n\tsize_t mAllocVolume;\n\n\tstatic int mAllocCountAll;\n\tstatic int mFreeCountAll;\n\tstatic size_t mAllocVolumeAll;\n\tstatic void* mpLastAllocation;\n};\n\ninline bool operator==(const MallocAllocator&, const MallocAllocator&) { return true; }\ninline bool operator!=(const MallocAllocator&, const MallocAllocator&) { return false; }\n\n\n///////////////////////////////////////////////////////////////////////////////\n// CustomAllocator\n//\n// Implements an allocator that works just like eastl::allocator but is defined\n// within this test as opposed to within EASTL.\n//\n// Example usage:\n//      vector<int, CustomAllocator> intVector;\n//\nclass CustomAllocator\n{\npublic:\n\tCustomAllocator(const char* = NULL) {}\n\tCustomAllocator(const CustomAllocator&) {}\n\tCustomAllocator(const CustomAllocator&, const char*) {}\n\tCustomAllocator& operator=(const CustomAllocator&) { return *this; }\n\n\tvoid* allocate(size_t n, int flags = 0);\n\tvoid* allocate(size_t n, size_t, size_t, int flags = 0);\n\tvoid deallocate(void* p, size_t n);\n\n\tconst char* get_name() const { return \"CustomAllocator\"; }\n\tvoid set_name(const char*) {}\n};\n\ninline bool operator==(const CustomAllocator&, const CustomAllocator&) { return true; }\ninline bool operator!=(const CustomAllocator&, const CustomAllocator&) { return false; }\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// UnequalAllocator\n///\n/// Acts the same as eastl::allocator, but always compares as unequal to an\n/// instance of itself.\n///\nclass UnequalAllocator\n{\npublic:\n\tEASTL_ALLOCATOR_EXPLICIT UnequalAllocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME))\n\t    : mAllocator(pName) {}\n\n\tUnequalAllocator(const UnequalAllocator& x) : mAllocator(x.mAllocator) {}\n\tUnequalAllocator(const UnequalAllocator& x, const char* pName) : mAllocator(x.mAllocator) { set_name(pName); }\n\tUnequalAllocator& operator=(const UnequalAllocator& x)\n\t{\n\t\tmAllocator = x.mAllocator;\n\t\treturn *this;\n\t}\n\n\tvoid* allocate(size_t n, int flags = 0) { return mAllocator.allocate(n, flags); }\n\tvoid* allocate(size_t n, size_t alignment, size_t offset, int flags = 0) { return mAllocator.allocate(n, alignment, offset, flags); }\n\tvoid deallocate(void* p, size_t n) { return mAllocator.deallocate(p, n); }\n\n\tconst char* get_name() const { return mAllocator.get_name(); }\n\tvoid set_name(const char* pName) { mAllocator.set_name(pName); }\n\nprotected:\n\teastl::allocator mAllocator;\n};\n\ninline bool operator==(const UnequalAllocator&, const UnequalAllocator&) { return false; }\ninline bool operator!=(const UnequalAllocator&, const UnequalAllocator&) { return true; }\n\n\n///////////////////////////////////////////////////////////////////////////////\n/// CountingAllocator\n///\n/// Counts allocation events allowing unit tests to validate assumptions.\n///\nclass CountingAllocator : public eastl::allocator\n{\npublic:\n\tusing base_type = eastl::allocator;\n\n\tEASTL_ALLOCATOR_EXPLICIT CountingAllocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME))\n\t    : base_type(pName)\n\t{\n\t\ttotalCtorCount++;\n\t\tdefaultCtorCount++;\n\t}\n\n\tCountingAllocator(const CountingAllocator& x) : base_type(x)\n\t{\n\t\ttotalCtorCount++;\n\t\tcopyCtorCount++;\n\t}\n\n\tCountingAllocator(const CountingAllocator& x, const char* pName) : base_type(x)\n\t{\n\t\ttotalCtorCount++;\n\t\tcopyCtorCount++;\n\t\tset_name(pName);\n\t}\n\n\tCountingAllocator& operator=(const CountingAllocator& x)\n\t{\n\t\tbase_type::operator=(x);\n\t\tassignOpCount++;\n\t\treturn *this;\n\t}\n\n\tvirtual void* allocate(size_t n, int flags = 0)\n\t{\n\t\tactiveAllocCount++;\n\t\ttotalAllocCount++;\n\t\ttotalAllocatedMemory += n;\n\t\tactiveAllocatedMemory += n;\n\t\treturn base_type::allocate(n, flags);\n\t}\n\n\tvirtual void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0)\n\t{\n\t\tactiveAllocCount++;\n\t\ttotalAllocCount++;\n\t\ttotalAllocatedMemory += n;\n\t\tactiveAllocatedMemory += n;\n\t\treturn base_type::allocate(n, alignment, offset, flags);\n\t}\n\n\tvoid deallocate(void* p, size_t n)\n\t{\n\t\tactiveAllocCount--;\n\t\ttotalDeallocCount--;\n\t\tactiveAllocatedMemory -= n;\n\t\treturn base_type::deallocate(p, n);\n\t}\n\n\tconst char* get_name() const          { return base_type::get_name(); }\n\tvoid set_name(const char* pName)      { base_type::set_name(pName); }\n\n\tstatic auto getTotalAllocationCount()  { return totalAllocCount; }\n\tstatic auto getTotalAllocationSize()   { return totalAllocatedMemory; }\n\tstatic auto getActiveAllocationSize()  { return activeAllocatedMemory; }\n\tstatic auto getActiveAllocationCount() { return activeAllocCount; }\n\tstatic auto neverUsed()\t\t\t\t   { return totalAllocCount == 0; }\n\n\tstatic void resetCount()\n\t{\n\t\tactiveAllocCount      = 0;\n\t\ttotalAllocCount       = 0;\n\t\ttotalDeallocCount     = 0;\n\t\ttotalCtorCount        = 0;\n\t\tdefaultCtorCount      = 0;\n\t\tcopyCtorCount         = 0;\n\t\tassignOpCount         = 0;\n\t\ttotalAllocatedMemory  = 0;\n\t\tactiveAllocatedMemory = 0;\n\t}\n\n\tvirtual ~CountingAllocator() = default;\n\n\tstatic uint64_t activeAllocCount;\n\tstatic uint64_t totalAllocCount;\n\tstatic uint64_t totalDeallocCount;\n\tstatic uint64_t totalCtorCount;\n\tstatic uint64_t defaultCtorCount;\n\tstatic uint64_t copyCtorCount;\n\tstatic uint64_t assignOpCount;\n\tstatic uint64_t totalAllocatedMemory;  // the total amount of memory allocated\n\tstatic uint64_t activeAllocatedMemory; // currently allocated memory by allocator\n};\n\ninline bool operator==(const CountingAllocator& rhs, const CountingAllocator& lhs) { return operator==(CountingAllocator::base_type(rhs), CountingAllocator::base_type(lhs)); }\ninline bool operator!=(const CountingAllocator& rhs, const CountingAllocator& lhs) { return !(rhs == lhs); }\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// InstanceAllocator\n//\n// Implements an allocator which has a instance id that makes it different\n// from other InstanceAllocators of a different id. Allocations between\n// InstanceAllocators of different ids are incompatible. An allocation done\n// by an InstanceAllocator of id=0 cannot be freed by an InstanceAllocator\n// of id=1.\n//\n// Example usage:\n//         InstanceAllocator ia0((uint8_t)0);\n//         InstanceAllocator ia1((uint8_t)1);\n//\n//         eastl::list<int, InstanceAllocator> list0(1, ia0);\n//         eastl::list<int, InstanceAllocator> list1(1, ia1);\n//\n//         list0 = list1; // list0 cannot free it's current contents with list1's allocator, and InstanceAllocator's purpose is to detect if it mistakenly does so.\n//\nclass InstanceAllocator\n{\npublic:\n\tenum\n\t{\n\t\tkMultiplier = 16\n\t}; // Use 16 because it's the highest currently known platform alignment requirement.\n\n\tInstanceAllocator() : mInstanceId(0) {}\n\texplicit InstanceAllocator(const char*, uint8_t instanceId = 0) : mInstanceId(instanceId) {}\n\texplicit InstanceAllocator(uint8_t instanceId) : mInstanceId(instanceId) {}\n\tInstanceAllocator(const InstanceAllocator& x) : mInstanceId(x.mInstanceId) {}\n\tInstanceAllocator(const InstanceAllocator& x, const char*) : mInstanceId(x.mInstanceId) {}\n\n\tInstanceAllocator& operator=(const InstanceAllocator& x)\n\t{\n\t\tmInstanceId = x.mInstanceId;\n\t\treturn *this;\n\t}\n\n\tvoid* allocate(size_t n, int = 0)\n\t{ // +1 so that we always have space to write mInstanceId.\n\t\tuint8_t* p8 =\n\t\t    static_cast<uint8_t*>(malloc(n + (kMultiplier * (mInstanceId + 1)))); // We make allocations between\n\t\t                                                                          // different instances incompatible by\n\t\t                                                                          // tweaking their return values.\n\t\teastl::fill(p8, p8 + kMultiplier, 0xff);\n\t\tEA_ANALYSIS_ASSUME(p8 != NULL);\n\t\t*p8 = mInstanceId;\n\t\treturn p8 + (kMultiplier * (mInstanceId + 1));\n\t}\n\n\tvoid* allocate(size_t n, size_t, size_t, int = 0)\n\t{ // +1 so that we always have space to write mInstanceId.\n\t\tuint8_t* p8 =\n\t\t    static_cast<uint8_t*>(malloc(n + (kMultiplier * (mInstanceId + 1)))); // We make allocations between\n\t\t                                                                          // different instances incompatible by\n\t\t                                                                          // tweaking their return values.\n\t\teastl::fill(p8, p8 + kMultiplier, 0xff);\n\t\tEA_ANALYSIS_ASSUME(p8 != NULL);\n\t\t*p8 = mInstanceId;\n\t\treturn p8 + (kMultiplier * (mInstanceId + 1));\n\t}\n\n\tvoid deallocate(void* p, size_t /*n*/)\n\t{\n\t\tuint8_t* p8 = static_cast<uint8_t*>(p) - (kMultiplier * (mInstanceId + 1));\n\t\tEASTL_ASSERT(*p8 == mInstanceId); // mInstanceId must match the id used in allocate(), otherwise the behavior is\n\t\t                                  // undefined (probably a heap assert).\n\t\tif (*p8 == mInstanceId) // It's possible that *p8 coincidentally matches mInstanceId if p8 is offset into memory\n\t\t                        // we don't control.\n\t\t\tfree(p8);\n\t\telse\n\t\t\t++mMismatchCount;\n\t}\n\n\tconst char* get_name() const // required to be const because allocators such as fixed_vector_allocator assume that the get_name() member function can be called with a const allocator.\n\t{\n\t\tEA::StdC::Snprintf(mName, kNameBufferSize, \"InstanceAllocator %u\", mInstanceId);\n\t\treturn mName;\n\t}\n\n\tvoid set_name(const char*) {}\n\n\tEA_NODISCARD static bool reset_all()\n\t{\n\t\tconst bool noMismatches = (mMismatchCount == 0);\n\t\tmMismatchCount = 0;\n\t\treturn noMismatches;\n\t}\n\npublic:\n\tconst static int kNameBufferSize = 32;\n\tuint8_t mInstanceId;\n\tmutable char mName[kNameBufferSize]; // mutable so that we can create the string in get_name()\n\n\tstatic int mMismatchCount;\n};\n\ninline bool operator==(const InstanceAllocator& a, const InstanceAllocator& b) { return (a.mInstanceId == b.mInstanceId); }\ninline bool operator!=(const InstanceAllocator& a, const InstanceAllocator& b) { return (a.mInstanceId != b.mInstanceId); }\n\n\n///////////////////////////////////////////////////////////////////////////////\n// ThrowingAllocator\n//\n// Implements an EASTL allocator that uses malloc/free as opposed to\n// new/delete or PPMalloc Malloc/Free. This is useful for testing\n// allocator behaviour of code.\n//\n// Example usage:\n//      vector<int, ThrowingAllocator< false<> > intVector;\n//\ntemplate <bool initialShouldThrow = true>\nclass ThrowingAllocator\n{\npublic:\n\tThrowingAllocator(const char* = EASTL_NAME_VAL(\"ThrowingAllocator\")) : mbShouldThrow(initialShouldThrow) {}\n\tThrowingAllocator(const ThrowingAllocator& x) : mbShouldThrow(x.mbShouldThrow) {}\n\tThrowingAllocator(const ThrowingAllocator& x, const char*) : mbShouldThrow(x.mbShouldThrow) {}\n\n\tThrowingAllocator& operator=(const ThrowingAllocator& x)\n\t{\n\t\tmbShouldThrow = x.mbShouldThrow;\n\t\treturn *this;\n\t}\n\n\tvoid* allocate(size_t n, int = 0)\n\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\tif (mbShouldThrow)\n\t\t\tthrow std::bad_alloc();\n#endif\n\t\treturn malloc(n);\n\t}\n\n\tvoid* allocate(size_t n, size_t, size_t, int = 0)\n\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\tif (mbShouldThrow)\n\t\t\tthrow std::bad_alloc();\n#endif\n\t\treturn malloc(n); // We don't support alignment, so you can't use this class where alignment is required.\n\t}\n\n\tvoid deallocate(void* p, size_t) { free(p); }\n\n\tconst char* get_name() const { return \"ThrowingAllocator\"; }\n\tvoid set_name(const char*) {}\n\n\tvoid set_should_throw(bool shouldThrow) { mbShouldThrow = shouldThrow; }\n\tbool get_should_throw() const { return mbShouldThrow; }\n\nprotected:\n\tbool mbShouldThrow;\n};\n\ntemplate <bool initialShouldThrow>\ninline bool operator==(const ThrowingAllocator<initialShouldThrow>&, const ThrowingAllocator<initialShouldThrow>&)\n{\n\treturn true;\n}\n\ntemplate <bool initialShouldThrow>\ninline bool operator!=(const ThrowingAllocator<initialShouldThrow>&, const ThrowingAllocator<initialShouldThrow>&)\n{\n\treturn false;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Helper utility that does a case insensitive string comparsion with two sets of overloads\n//\nstruct TestStrCmpI_2\n{\n\tbool operator()(const char* pCStr, const eastl::string& str) const { return str.comparei(pCStr) == 0; }\n\tbool operator()(const eastl::string& str, const char* pCStr) const { return str.comparei(pCStr) == 0; }\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// StompDetectAllocator\n//\n// An allocator that has sentinal values surrounding its allocator in an\n// effort to detected if its internal memory has been stomped.\n//\nstatic uint64_t STOMP_MAGIC_V1 = 0x0101DEC1A551F1ED;\nstatic uint64_t STOMP_MAGIC_V2 = 0x12345C1A551F1ED5;\n\nstruct StompDetectAllocator\n{\n\tStompDetectAllocator() { Validate(); }\n\t~StompDetectAllocator() { Validate(); }\n\n\tStompDetectAllocator(const char*) { Validate(); }\n\n\tvoid* allocate(size_t n, int = 0) { return mMallocAllocator.allocate(n); }\n\tvoid* allocate(size_t n, size_t, size_t, int = 0) { return mMallocAllocator.allocate(n); }\n\tvoid deallocate(void* p, size_t n) { mMallocAllocator.deallocate(p, n); }\n\n\tconst char* get_name() const { return \"FatAllocator\"; }\n\tvoid set_name(const char*) {}\n\n\tvoid Validate() const\n\t{\n\t\tEASTL_ASSERT(mSentinal1 == STOMP_MAGIC_V1);\n\t\tEASTL_ASSERT(mSentinal2 == STOMP_MAGIC_V2);\n\t}\n\n\tuint64_t mSentinal1 = STOMP_MAGIC_V1;\n\tMallocAllocator mMallocAllocator;\n\tuint64_t mSentinal2 = STOMP_MAGIC_V2;\n};\n\ninline bool operator==(const StompDetectAllocator& a, const StompDetectAllocator& b)\n{\n\ta.Validate();\n\tb.Validate();\n\n\treturn (a.mMallocAllocator == b.mMallocAllocator);\n}\n\ninline bool operator!=(const StompDetectAllocator& a, const StompDetectAllocator& b)\n{\n\ta.Validate();\n\tb.Validate();\n\n\treturn (a.mMallocAllocator != b.mMallocAllocator);\n}\n\n\n// Commonly used free-standing functions to test callables\ninline int ReturnVal(int param) { return param; }\ninline int ReturnZero() { return 0; }\ninline int ReturnOne() { return 1; }\n\n\n// ValueInit\ntemplate<class T>\nstruct ValueInitOf\n{\n\tValueInitOf() : mV() {}\n\t~ValueInitOf() = default;\n\n\tValueInitOf(const ValueInitOf&) = default;\n\tValueInitOf(ValueInitOf&&) = default;\n\n\tValueInitOf& operator=(const ValueInitOf&) = default;\n\tValueInitOf& operator=(ValueInitOf&&) = default;\n\n\tT get() { return mV; }\n\n\tT mV;\n};\n\nstruct NoCopyMove\n{\n\tNoCopyMove() = default;\n\tNoCopyMove(const NoCopyMove&) = delete;\n\tNoCopyMove(NoCopyMove&&) = delete;\n\tNoCopyMove& operator=(const NoCopyMove&) = delete;\n\tNoCopyMove& operator=(NoCopyMove&&) = delete;\n};\nstatic_assert(!eastl::is_copy_constructible_v<NoCopyMove>, \"!copy constructible\");\nstatic_assert(!eastl::is_copy_assignable_v<NoCopyMove>, \"!copy assignable\");\nstatic_assert(!eastl::is_move_constructible_v<NoCopyMove>, \"!move constructible\");\nstatic_assert(!eastl::is_move_assignable_v<NoCopyMove>, \"!move assignable\");\n\nstruct NoCopyMoveNonEmpty\n{\n\tNoCopyMoveNonEmpty() = default;\n\tNoCopyMoveNonEmpty(const NoCopyMoveNonEmpty&) = delete;\n\tNoCopyMoveNonEmpty(NoCopyMoveNonEmpty&&) = delete;\n\tNoCopyMoveNonEmpty& operator=(const NoCopyMoveNonEmpty&) = delete;\n\tNoCopyMoveNonEmpty& operator=(NoCopyMoveNonEmpty&&) = delete;\n\n\tint mVal{};\n};\nstatic_assert(!eastl::is_copy_constructible_v<NoCopyMoveNonEmpty>, \"!copy constructible\");\nstatic_assert(!eastl::is_copy_assignable_v<NoCopyMoveNonEmpty>, \"!copy assignable\");\nstatic_assert(!eastl::is_move_constructible_v<NoCopyMoveNonEmpty>, \"!move constructible\");\nstatic_assert(!eastl::is_move_assignable_v<NoCopyMoveNonEmpty>, \"!move assignable\");\nstatic_assert(!eastl::is_empty_v<NoCopyMoveNonEmpty>, \"!empty\");\n\n// MoveOnlyType - useful for verifying containers that may hold, e.g., unique_ptrs to make sure move ops are implemented\nstruct MoveOnlyType\n{\n\tMoveOnlyType() = delete;\n\tMoveOnlyType(int val) : mVal(val) {}\n\tMoveOnlyType(const MoveOnlyType&) = delete;\n\tMoveOnlyType(MoveOnlyType&& x) noexcept : mVal(x.mVal) { x.mVal = 0; }\n\tMoveOnlyType& operator=(const MoveOnlyType&) = delete;\n\tMoveOnlyType& operator=(MoveOnlyType&& x)\n\t{\n\t\tmVal = x.mVal;\n\t\tx.mVal = 0;\n\t\treturn *this;\n\t}\n\tbool operator==(const MoveOnlyType& o) const { return mVal == o.mVal; }\n\n\tint mVal;\n};\n\n// MoveOnlyTypeDefaultCtor - useful for verifying containers that may hold, e.g., unique_ptrs to make sure move ops are implemented\nstruct MoveOnlyTypeDefaultCtor\n{\n\tMoveOnlyTypeDefaultCtor() = default;\n\tMoveOnlyTypeDefaultCtor(int val) : mVal(val) {}\n\tMoveOnlyTypeDefaultCtor(const MoveOnlyTypeDefaultCtor&) = delete;\n\tMoveOnlyTypeDefaultCtor(MoveOnlyTypeDefaultCtor&& x) noexcept : mVal(x.mVal) { x.mVal = 0; }\n\tMoveOnlyTypeDefaultCtor& operator=(const MoveOnlyTypeDefaultCtor&) = delete;\n\tMoveOnlyTypeDefaultCtor& operator=(MoveOnlyTypeDefaultCtor&& x)\n\t{\n\t\tmVal = x.mVal;\n\t\tx.mVal = 0;\n\t\treturn *this;\n\t}\n\tbool operator==(const MoveOnlyTypeDefaultCtor& o) const { return mVal == o.mVal; }\n\n\tint mVal;\n};\nstatic_assert(eastl::is_move_constructible_v<MoveOnlyTypeDefaultCtor>, \"move constructible\");\nstatic_assert(eastl::is_nothrow_move_constructible_v<MoveOnlyTypeDefaultCtor>, \"nothrow move constructible\");\n\nstruct NonTriviallyCopyable {\n\t// non-trivial special members (that is equivalent to the defaults)\n\tNonTriviallyCopyable(unsigned int v = 0) noexcept : mValue(v) {}\n\tNonTriviallyCopyable(NonTriviallyCopyable&& other) noexcept : mValue(other.mValue) {}\n\tNonTriviallyCopyable& operator=(NonTriviallyCopyable&& other) noexcept { mValue = other.mValue; return *this; }\n\tNonTriviallyCopyable(const NonTriviallyCopyable& other) noexcept : mValue(other.mValue) {}\n\tNonTriviallyCopyable& operator=(const NonTriviallyCopyable& other) noexcept { mValue = other.mValue; return *this; }\n\n\tfriend bool operator==(const NonTriviallyCopyable& lhs, const NonTriviallyCopyable& rhs) { return lhs.mValue == rhs.mValue; }\n\npublic:\n\tunsigned int mValue;\n};\nstatic_assert(eastl::is_default_constructible<NonTriviallyCopyable>::value, \"NonTriviallyCopyable\");\nstatic_assert(!eastl::is_trivially_copyable<NonTriviallyCopyable>::value, \"NonTriviallyCopyable\");\nstatic_assert(eastl::is_standard_layout<NonTriviallyCopyable>::value, \"NonTriviallyCopyable\");\n\nstruct TriviallyCopyableWithCopy {\n\t// non-trivial default ctor\n\tTriviallyCopyableWithCopy(unsigned int v = 0) noexcept : mValue(v) {}\n\n\t// all eligible (for trivial copyability) copy ctor/move ctor/copy assignment/move assignment are trivial\n\tTriviallyCopyableWithCopy(const TriviallyCopyableWithCopy&) = default;\n\tTriviallyCopyableWithCopy& operator=(const TriviallyCopyableWithCopy&) = default;\n\n\t// remaining copy ctor/move ctor/copy assignment/move assignment are deleted\n\tTriviallyCopyableWithCopy(TriviallyCopyableWithCopy&&) = delete;\n\tTriviallyCopyableWithCopy& operator=(TriviallyCopyableWithCopy&&) = delete;\n\n\tfriend bool operator==(const TriviallyCopyableWithCopy& lhs, const TriviallyCopyableWithCopy& rhs) { return lhs.mValue == rhs.mValue; }\n\npublic:\n\tunsigned int mValue;\n\n\t// intentionally not a standard-layout class:\n\t// standard-layout requires all non-static data members have the same access control.\nprivate:\n\tchar ch{ 'C' };\n};\nstatic_assert(eastl::is_default_constructible<TriviallyCopyableWithCopy>::value, \"TriviallyCopyableWithCopy\");\nstatic_assert(eastl::is_trivially_copyable<TriviallyCopyableWithCopy>::value, \"TriviallyCopyableWithCopy\");\nstatic_assert(!eastl::is_standard_layout<TriviallyCopyableWithCopy>::value, \"TriviallyCopyableWithCopy\");\nstatic_assert(!eastl::is_move_constructible_v<TriviallyCopyableWithCopy>, \"TriviallyCopyableWithCopy\");\n\nstruct TriviallyCopyableWithMove {\n\t// non-trivial default ctor\n\tTriviallyCopyableWithMove(unsigned int v = 0) noexcept : mValue(v) {}\n\n\t// all eligible (for trivial copyability) copy ctor/move ctor/copy assignment/move assignment are trivial\n\tTriviallyCopyableWithMove(TriviallyCopyableWithMove&&) = default;\n\tTriviallyCopyableWithMove& operator=(TriviallyCopyableWithMove&&) = default;\n\n\t// remaining copy ctor/move ctor/copy assignment/move assignment are deleted\n\tTriviallyCopyableWithMove(const TriviallyCopyableWithMove&) = delete;\n\tTriviallyCopyableWithMove& operator=(const TriviallyCopyableWithMove&) = delete;\n\n\tfriend bool operator==(const TriviallyCopyableWithMove& lhs, const TriviallyCopyableWithMove& rhs) { return lhs.mValue == rhs.mValue; }\n\npublic:\n\tunsigned int mValue;\n\n\t// intentionally not a standard-layout class:\n\t// standard-layout requires all non-static data members have the same access control.\nprivate:\n\tchar ch{ 'C' };\n};\nstatic_assert(eastl::is_default_constructible<TriviallyCopyableWithMove>::value, \"TriviallyCopyableWithMove\");\nstatic_assert(eastl::is_trivially_copyable<TriviallyCopyableWithMove>::value, \"TriviallyCopyableWithMove\");\nstatic_assert(!eastl::is_standard_layout<TriviallyCopyableWithMove>::value, \"TriviallyCopyableWithMove\");\n\nstruct TriviallyCopyableWithCopyCtor {\n\tTriviallyCopyableWithCopyCtor(unsigned int v) noexcept : mValue(v) {}\n\n\tTriviallyCopyableWithCopyCtor(const TriviallyCopyableWithCopyCtor&) = default;\n\n\tTriviallyCopyableWithCopyCtor() = delete;\n\tTriviallyCopyableWithCopyCtor(TriviallyCopyableWithCopyCtor&&) = delete;\n\tTriviallyCopyableWithCopyCtor& operator=(const TriviallyCopyableWithCopyCtor&) = delete;\n\tTriviallyCopyableWithCopyCtor& operator=(TriviallyCopyableWithCopyCtor&&) = delete;\n\n\tfriend bool operator==(const TriviallyCopyableWithCopyCtor& lhs, const TriviallyCopyableWithCopyCtor& rhs) { return lhs.mValue == rhs.mValue; }\n\n\tunsigned int mValue;\n};\nstatic_assert(eastl::is_trivially_copyable<TriviallyCopyableWithCopyCtor>::value, \"TriviallyCopyableWithCopyCtor\");\nstatic_assert(eastl::is_standard_layout<TriviallyCopyableWithCopyCtor>::value, \"TriviallyCopyableWithCopyCtor\");\nstatic_assert(eastl::is_trivially_copy_constructible<TriviallyCopyableWithCopyCtor>::value, \"TriviallyCopyableWithCopyCtor\");\n\nstruct TriviallyCopyableWithCopyAssign {\n\tTriviallyCopyableWithCopyAssign(unsigned int v) noexcept : mValue(v) {}\n\n\tTriviallyCopyableWithCopyAssign& operator=(const TriviallyCopyableWithCopyAssign&) = default;\n\n\tTriviallyCopyableWithCopyAssign() = delete;\n\tTriviallyCopyableWithCopyAssign(const TriviallyCopyableWithCopyAssign&) = delete;\n\tTriviallyCopyableWithCopyAssign(TriviallyCopyableWithCopyAssign&&) = delete;\n\tTriviallyCopyableWithCopyAssign& operator=(TriviallyCopyableWithCopyAssign&&) = delete;\n\n\tfriend bool operator==(const TriviallyCopyableWithCopyAssign& lhs, const TriviallyCopyableWithCopyAssign& rhs) { return lhs.mValue == rhs.mValue; }\n\n\tunsigned int mValue;\n};\nstatic_assert(eastl::is_trivially_copyable<TriviallyCopyableWithCopyAssign>::value, \"TriviallyCopyableWithCopyAssign\");\nstatic_assert(eastl::is_standard_layout<TriviallyCopyableWithCopyAssign>::value, \"TriviallyCopyableWithCopyAssign\");\nstatic_assert(eastl::is_trivially_copy_assignable<TriviallyCopyableWithCopyAssign>::value, \"TriviallyCopyableWithCopyAssign\");\n\nstruct TriviallyCopyableWithMoveCtor {\n\tTriviallyCopyableWithMoveCtor(unsigned int v) noexcept : mValue(v) {}\n\n\tTriviallyCopyableWithMoveCtor(TriviallyCopyableWithMoveCtor&&) = default;\n\n\tTriviallyCopyableWithMoveCtor() = delete;\n\tTriviallyCopyableWithMoveCtor(const TriviallyCopyableWithMoveCtor&) = delete;\n\tTriviallyCopyableWithMoveCtor& operator=(const TriviallyCopyableWithMoveCtor&) = delete;\n\tTriviallyCopyableWithMoveCtor& operator=(TriviallyCopyableWithMoveCtor&&) = delete;\n\n\tfriend bool operator==(const TriviallyCopyableWithMoveCtor& lhs, const TriviallyCopyableWithMoveCtor& rhs) { return lhs.mValue == rhs.mValue; }\n\n\tunsigned int mValue;\n};\nstatic_assert(eastl::is_trivially_copyable<TriviallyCopyableWithMoveCtor>::value, \"TriviallyCopyableWithMoveCtor\");\nstatic_assert(eastl::is_standard_layout<TriviallyCopyableWithMoveCtor>::value, \"TriviallyCopyableWithMoveCtor\");\nstatic_assert(eastl::is_trivially_move_constructible<TriviallyCopyableWithMoveCtor>::value, \"TriviallyCopyableWithMoveCtor\");\nstatic_assert(eastl::is_nothrow_move_constructible<TriviallyCopyableWithMoveCtor>::value, \"TriviallyCopyableWithMoveCtor\");\n\nstruct TriviallyCopyableWithMoveAssign {\n\tTriviallyCopyableWithMoveAssign(unsigned int v) noexcept : mValue(v) {}\n\n\tTriviallyCopyableWithMoveAssign& operator=(TriviallyCopyableWithMoveAssign&&) = default;\n\n\tTriviallyCopyableWithMoveAssign() = delete;\n\tTriviallyCopyableWithMoveAssign(const TriviallyCopyableWithMoveAssign&) = delete;\n\tTriviallyCopyableWithMoveAssign(TriviallyCopyableWithMoveAssign&&) = delete;\n\tTriviallyCopyableWithMoveAssign& operator=(const TriviallyCopyableWithMoveAssign&) = delete;\n\n\tfriend bool operator==(const TriviallyCopyableWithMoveAssign& lhs, const TriviallyCopyableWithMoveAssign& rhs) { return lhs.mValue == rhs.mValue; }\n\n\tunsigned int mValue;\n};\nstatic_assert(eastl::is_trivially_copyable<TriviallyCopyableWithMoveAssign>::value, \"TriviallyCopyableWithMoveAssign\");\nstatic_assert(eastl::is_standard_layout<TriviallyCopyableWithMoveAssign>::value, \"TriviallyCopyableWithMoveAssign\");\nstatic_assert(eastl::is_trivially_move_assignable<TriviallyCopyableWithMoveAssign>::value, \"TriviallyCopyableWithMoveAssign\");\n\n// useful for testing empty base optimization of types\nstruct NoDataMembers {};\nstatic_assert(eastl::is_empty<NoDataMembers>::value, \"empty\");\n\n\n//////////////////////////////////////////////////////////////////////////////\n// Utility RAII class that sets a new default allocator for the scope\n//\nstruct AutoDefaultAllocator\n{\n\teastl::allocator* mPrevAllocator = nullptr;\n\n\tAutoDefaultAllocator(eastl::allocator* nextAllocator) { mPrevAllocator = SetDefaultAllocator(nextAllocator); }\n\t~AutoDefaultAllocator()                               { SetDefaultAllocator(mPrevAllocator); }\n};\n\n//////////////////////////////////////////////////////////////////////////////\n// Define string types for heterogenous lookup.\n// \n// ExplicitString is to be used where we don't want any implicitly conversions to be available for the type.\n// This is relevant when calling container heterogenous lookup functions that we want to guarantee that there is no implicit conversion to the container key type.\n//\n// Note: less<void> is a transparent comparison type, less<ExplicitString> is not.\n\nstruct ExplicitString {\n\tstatic unsigned int sCtorFromStrCount;\n\n\teastl::string mString;\n\n\tExplicitString() = default;\n\n\texplicit ExplicitString(const char* str)\n\t\t: mString(str)\n\t{\n\t\t++sCtorFromStrCount;\n\t}\n\n\tstruct Additional {};\n\n\tExplicitString(Additional, const char* str)\n\t\t: mString(str) {}\n\n\t// to be called in test setup code where we don't want to count towards sCtorFromStrCount.\n\tstatic ExplicitString Create(const char* str)\n\t{\n\t\treturn ExplicitString{ Additional{}, str };\n\t}\n\n\tstatic void Reset()\n\t{\n\t\tsCtorFromStrCount = 0;\n\t}\n};\n\ninline bool operator <(const ExplicitString& lhs, const ExplicitString& rhs) { return lhs.mString < rhs.mString; }\ninline bool operator <(const ExplicitString& lhs, const char* rhs) { return lhs.mString < rhs; }\ninline bool operator <(const char* lhs, const ExplicitString& rhs) { return lhs < rhs.mString; }\n\ninline bool operator ==(const ExplicitString& lhs, const ExplicitString& rhs) { return lhs.mString == rhs.mString; }\ninline bool operator ==(const ExplicitString& lhs, const char* rhs) { return lhs.mString == rhs; }\ninline bool operator ==(const char* lhs, const ExplicitString& rhs) { return lhs == rhs.mString; }\n\nstruct ExplicitStringHash {\n\ttypedef int is_transparent;\n\n\tsize_t operator()(const ExplicitString& str) const\n\t{\n\t\treturn eastl::hash<char*>{}(str.mString.c_str());\n\t}\n\n\tsize_t operator()(const char* p) const\n\t{\n\t\treturn eastl::hash<char*>{}(p);\n\t}\n};\n\nnamespace detail\n{\n\n\ttemplate <class, class = void>\n\tstruct is_fixed_container : public eastl::false_type\n\t{\n\t};\n\n\ttemplate <class Container>\n\tstruct is_fixed_container<\n\t    Container,\n\t    eastl::void_t<decltype(bool(Container::can_overflow())),\n\t                  decltype(eastl::declval<Container>().get_allocator().get_overflow_allocator())>>\n\t    : public eastl::true_type\n\t{\n\t};\n\n\ttemplate <class Container>\n\tconstexpr bool is_fixed_container_v = is_fixed_container<Container>::value;\n\n} // namespace detail\n\n// Only needed because fixed containers essentially leak their implementation details into the public interface.\n//\n// Ideally fixed containers should be an allocator-aware container only if overflow is enabled. Specifically,\n// allocator_type, Container::get_allocator(), constructors with a allocator parameter and all other functionality that\n// expose an allocator should only exist if overflow is enabled. The fixed allocator types (eg. fixed_vector_allocator)\n// are an implementation detail and shouldn't be part of the public interface. Instead, Container::allocator_type should\n// be the user specified overflow allocator and Container::get_allocator() should return this allocator, not the fixed\n// allocator. This function essentially implements this design fix for Container::get_allocator() as a non-member\n// function.\ntemplate <typename Container, eastl::enable_if_t<!detail::is_fixed_container_v<Container>, bool> = true>\nauto get_allocator(const Container& c)\n{\n\treturn c.get_allocator();\n}\n\ntemplate <typename Container, eastl::enable_if_t<detail::is_fixed_container_v<Container>, bool> = true>\nauto get_allocator(const Container& c)\n{\n\t// fixed containers without overflow don't have a meaningful allocator, ie. treat them as a non-allocator aware container.\n\tstatic_assert(Container::can_overflow());\n\treturn c.get_allocator().get_overflow_allocator();\n}\n\n#endif // Header include guard\n"
  },
  {
    "path": "test/source/EASTLTestAllocator.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTLTEST_ALLOCATOR_H\n#define EASTLTEST_ALLOCATOR_H\n\n#include <EABase/eabase.h>\n#include <EASTL/atomic.h>\n#include <EASTL/internal/config.h>\n#include <new>\n#include <stdio.h>\n\n#if !EASTL_OPENSOURCE\n\n\t#include <PPMalloc/EAGeneralAllocator.h>\n\t#include <PPMalloc/EAGeneralAllocatorDebug.h>\n\n\t#include <coreallocator/icoreallocator_interface.h>\n\n\t#if defined(EA_COMPILER_MSVC)\n\t\t#include <math.h>       // VS2008 has an acknowledged bug that requires math.h (and possibly also string.h) to be #included before intrin.h.\n\t\t#include <intrin.h>\n\t\t#pragma intrinsic(_ReturnAddress)\n\t#endif\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// EASTLTest_GetGeneralAllocator()\n\t//\n\tnamespace EA\n\t{\n\t\tnamespace Allocator\n\t\t{\n\t\t\t#ifdef EA_DEBUG\n\t\t\t\textern PPM_API GeneralAllocatorDebug* gpEAGeneralAllocatorDebug;\n\t\t\t#else\n\t\t\t\textern PPM_API GeneralAllocator*      gpEAGeneralAllocator;\n\t\t\t#endif\n\n\t\t\tstatic inline auto& EASTLTest_GetGeneralAllocator()\n\t\t\t{\n\t\t\t#ifdef EA_DEBUG\n\t\t\t\tusing GeneralAllocatorType = GeneralAllocatorDebug;\n\t\t\t#else\n\t\t\t\tusing GeneralAllocatorType = GeneralAllocator;\n\t\t\t#endif\n\n\t\t\t\tstatic GeneralAllocatorType sGeneralAllocator;\n\t\t\t\treturn sGeneralAllocator;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// allocator counts for debugging purposes\n\t//\n\teastl::atomic<int> gEASTLTest_AllocationCount = 0;\n\teastl::atomic<int> gEASTLTest_TotalAllocationCount = 0;\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// EASTLTest_ValidateHeap\n\t//\n\tbool EASTLTest_ValidateHeap()\n\t{\n\t#ifdef EA_DEBUG\n\t\treturn EA::Allocator::EASTLTest_GetGeneralAllocator().ValidateHeap(EA::Allocator::GeneralAllocator::kHeapValidationLevelBasic);\n\t#else\n\t\treturn true;\n\t#endif\n\t}\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// Microsoft function parameter annotations\n\t// https://msdn.microsoft.com/en-CA/library/hh916382.aspx\n\t//\n\t#ifndef _Ret_maybenull_\n\t#define _Ret_maybenull_\n\t#endif\n\n\t#ifndef _Post_writable_byte_size_\n\t#define _Post_writable_byte_size_(x)\n\t#endif\n\n\t#ifndef _Ret_notnull_\n\t#define _Ret_notnull_\n\t#endif\n\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// operator new extensions\n\t//\n\tnamespace\n\t{\n\t\t#ifdef EA_DEBUG\n\t\t\tconst char gUnattributedNewTag[] = \"Anonymous new\";\n\t\t#endif\n\n\t\t#if defined(EA_COMPILER_MSVC)\n\t\t\t#define UNATTRIBUTED_NEW_FILE   \"raw_return_address\"\n\t\t\t#define UNATTRIBUTED_NEW_LINE   ((int)(uintptr_t)_ReturnAddress())\n\t\t#else\n\t\t\t#define UNATTRIBUTED_NEW_FILE   NULL\n\t\t\t#define UNATTRIBUTED_NEW_LINE   0\n\t\t#endif\n\t}\n\n\t///////////////////////////////////////////////////////////////////////////////\n\t// system memory allocation helpers\n\t//\n\tnamespace\n\t{\n\t\tvoid* PlatformMalloc(size_t size, size_t alignment = 16)\n\t\t{\n\t\t#ifdef EA_PLATFORM_MICROSOFT\n\t\t\treturn _aligned_malloc(size, alignment);\n\t\t#else\n\t\t\tvoid *p = nullptr;\n\t\t\talignment = alignment < sizeof( void *) ? sizeof( void *) : alignment;\n\t\t\tposix_memalign(&p, alignment, size);\n\t\t\treturn p;\n\t\t#endif\n\t\t}\n\n\t\tvoid PlatformFree(void* p)\n\t\t{\n\t\t#ifdef EA_PLATFORM_MICROSOFT\n\t\t\t_aligned_free(p);\n\t\t#else\n\t\t\tfree(p);\n\t\t#endif\n\t\t}\n\n\t\tvoid* InternalMalloc(size_t size)\n\t\t{\n\t\t\tauto& allocator = EA::Allocator::EASTLTest_GetGeneralAllocator();\n\n\t\t#ifdef EA_DEBUG\n\t\t\tvoid* mem = allocator.MallocAlignedDebug(size, alignof(std::max_align_t), 0, 0, 0, gUnattributedNewTag, UNATTRIBUTED_NEW_FILE, UNATTRIBUTED_NEW_LINE);\n\t\t#else\n\t\t\tvoid* mem = allocator.MallocAligned(size, alignof(std::max_align_t));;\n\t\t#endif\n\n\t\t\tif(mem == nullptr)\n\t\t\t\tmem = PlatformMalloc(size);\n\n\t\t\treturn mem;\n\t\t}\n\n\t\tvoid* InternalMalloc(size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line)\n\t\t{\n\t\t\tauto& allocator = EA::Allocator::EASTLTest_GetGeneralAllocator();\n\n\t\t#ifdef EA_DEBUG\n\t\t\tvoid* mem = allocator.MallocAlignedDebug(size, alignof(std::max_align_t), 0, flags, debugFlags, name, file, line);\n\t\t#else\n\t\t\tvoid* mem = allocator.MallocAligned(size, alignof(std::max_align_t), 0, flags);;\n\t\t\tEA_UNUSED(debugFlags);\n\t\t\tEA_UNUSED(file);\n\t\t\tEA_UNUSED(line);\n\t\t\tEA_UNUSED(name);\n\t\t#endif\n\n\t\t\tif(mem == nullptr)\n\t\t\t\tmem = PlatformMalloc(size);\n\n\t\t\treturn mem;\n\t\t}\n\n\t\tvoid* InternalMalloc(size_t size, size_t alignment, const char* name, int flags, unsigned debugFlags, const char* file, int line)\n\t\t{\n\t\t    void* mem = nullptr;\n\n\t\t\tauto& allocator = EA::Allocator::EASTLTest_GetGeneralAllocator();\n\n\t\t#ifdef EA_DEBUG\n\t\t\tmem = allocator.MallocAlignedDebug(size, alignment, 0, flags, debugFlags, name, file, line);\n\t\t#else\n\t\t\tmem = allocator.MallocAligned(size, alignment, flags);\n\t\t\tEA_UNUSED(debugFlags);\n\t\t\tEA_UNUSED(file);\n\t\t\tEA_UNUSED(line);\n\t\t\tEA_UNUSED(name);\n\t\t#endif\n\n\t\t\tif(mem == nullptr)\n\t\t\t\tmem = PlatformMalloc(size, alignment);\n\n\t\t\treturn mem;\n\t\t}\n\n\t\tvoid* InternalMalloc(size_t size, size_t alignment)\n\t\t{\n\t\t\tvoid* mem = nullptr;\n\n\t\t\tauto& allocator = EA::Allocator::EASTLTest_GetGeneralAllocator();\n\n\t\t#ifdef EA_DEBUG\n\t\t\tmem = allocator.MallocAlignedDebug(size, alignment, 0, 0, 0, gUnattributedNewTag, UNATTRIBUTED_NEW_FILE, UNATTRIBUTED_NEW_LINE);\n\t\t#else\n\t\t\tmem = allocator.MallocAligned(size, alignment);\n\t\t#endif\n\n\t\t\tif(mem == nullptr)\n\t\t\t\tmem = PlatformMalloc(size, alignment);\n\n\t\t\treturn mem;\n\t\t}\n\n\t\tvoid InternalFree(void* p)\n\t\t{\n\t\t\tauto& allocator = EA::Allocator::EASTLTest_GetGeneralAllocator();\n\n\t\t\tif(allocator.ValidateAddress(p, EA::Allocator::GeneralAllocator::kAddressTypeOwned) == p)\n\t\t\t{\n\t\t\t\tallocator.Free(p);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tPlatformFree(p);\n\t\t\t}\n\t\t}\n\t}\n\n\tclass EASTLTestICA : public EA::Allocator::ICoreAllocator\n\t{\n\tpublic:\n\t\tEASTLTestICA()\n\t\t{\n\t\t}\n\n\t\tvirtual ~EASTLTestICA()\n\t\t{\n\t\t}\n\n\t\tvirtual void* Alloc(size_t size, const char* name, unsigned int flags)\n\t\t{\n\t\t\treturn ::InternalMalloc(size, name, (int)flags, 0, NULL, 0);\n\t\t}\n\n\t\tvirtual void* Alloc(size_t size, const char* name, unsigned int flags,\n\t\t\t\t\t\t\tunsigned int align, unsigned int)\n\t\t{\n\t\t\treturn ::InternalMalloc(size, (size_t)align, name, (int)flags, 0, NULL, 0);\n\t\t}\n\n\t\tvirtual void Free(void* pData, size_t /*size*/)\n\t\t{\n\t\t\treturn ::InternalFree(pData);\n\t\t}\n\t};\n\n\tEA::Allocator::ICoreAllocator* EA::Allocator::ICoreAllocator::GetDefaultAllocator()\n\t{\n\t\tstatic EASTLTestICA sEASTLTestICA;\n\n\t\treturn &sEASTLTestICA;\n\t}\n\n\t///////////////////////////////////////////////////////////////////////////\n\t// operator new/delete implementations\n\t//\n\t_Ret_maybenull_ _Post_writable_byte_size_(size) void* operator new(size_t size, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE()\n\t{\n\t\treturn InternalMalloc(size);\n\t}\n\n\n\tvoid operator delete(void* p, const std::nothrow_t&) EA_THROW_SPEC_DELETE_NONE()\n\t{\n\t\tif(p) // The standard specifies that 'delete NULL' is a valid operation.\n\t\t{\n\t\t\tgEASTLTest_AllocationCount.fetch_add(-1, eastl::memory_order_relaxed);\n\t\t\tInternalFree(p);\n\t\t}\n\t}\n\n\n\t_Ret_maybenull_ _Post_writable_byte_size_(size) void* operator new[](size_t size, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE()\n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\tvoid* p = InternalMalloc(size);\n\t\treturn p;\n\t}\n\n\n\tvoid operator delete[](void* p, const std::nothrow_t&) EA_THROW_SPEC_DELETE_NONE()\n\t{\n\t\tif(p)\n\t\t{\n\t\t\tgEASTLTest_AllocationCount.fetch_add(-1, eastl::memory_order_relaxed);\n\t\t\tInternalFree(p);\n\t\t}\n\t}\n\n\n\t_Ret_notnull_ _Post_writable_byte_size_(size) void* operator new(size_t size) \n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\tvoid* mem = InternalMalloc(size);\n\n\t#if !defined(EA_COMPILER_NO_EXCEPTIONS)\n\t\tif (mem == NULL)\n\t\t{\n\t\t\tthrow std::bad_alloc();\n\t\t}\n\t#endif\n\n\t\treturn mem;\n\t}\n\n\n\t_Ret_notnull_ _Post_writable_byte_size_(size) void* operator new[](size_t size) \n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\tvoid* mem = InternalMalloc(size);\n\n\t#if !defined(EA_COMPILER_NO_EXCEPTIONS)\n\t\tif (mem == NULL)\n\t\t{\n\t\t\tthrow std::bad_alloc();\n\t\t}\n\t#endif\n\n\t\treturn mem;\n\t}\n\n\n\tvoid* operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line)\n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\treturn InternalMalloc(size, name, flags, debugFlags, file, line);\n\t}\n\n\n\tvoid* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* name, int flags, unsigned debugFlags, const char* file, int line)\n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\treturn InternalMalloc(size, alignment, name, flags, debugFlags, file, line);\n\t}\n\n\t// Used by GCC when you make new objects of classes with >= N bit alignment (with N depending on the compiler).\n\tvoid* operator new(size_t size, size_t alignment)\n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\treturn InternalMalloc(size, alignment);\n\t}\n\n\t// Used by GCC when you make new objects of classes with >= N bit alignment (with N depending on the compiler).\n\tvoid* operator new(size_t size, size_t alignment, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE()\n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\treturn InternalMalloc(size, alignment);\n\t}\n\n\t// Used by GCC when you make new objects of classes with >= N bit alignment (with N depending on the compiler).\n\tvoid* operator new[](size_t size, size_t alignment)\n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\treturn InternalMalloc(size, alignment);\n\t}\n\n\t// Used by GCC when you make new objects of classes with >= N bit alignment (with N depending on the compiler).\n\tvoid* operator new[](size_t size, size_t alignment, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE()\n\t{\n\t\tgEASTLTest_AllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tgEASTLTest_TotalAllocationCount.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\treturn InternalMalloc(size, alignment);\n\t}\n\n\tvoid operator delete(void* p) EA_THROW_SPEC_DELETE_NONE()\n\t{\n\t\tif(p) // The standard specifies that 'delete NULL' is a valid operation.\n\t\t{\n\t\t\tgEASTLTest_AllocationCount.fetch_add(-1, eastl::memory_order_relaxed);\n\t\t\tInternalFree(p);\n\t\t}\n\t}\n\n\n\tvoid operator delete[](void* p) EA_THROW_SPEC_DELETE_NONE()\n\t{\n\t\tif(p)\n\t\t{\n\t\t\tgEASTLTest_AllocationCount.fetch_add(-1, eastl::memory_order_relaxed);\n\t\t\tInternalFree(p);\n\t\t}\n\t}\n\n\tvoid EASTLTest_SetGeneralAllocator()\n\t{\n\t\tEA::Allocator::SetGeneralAllocator(&EA::Allocator::EASTLTest_GetGeneralAllocator());\n\t\t#ifdef EA_DEBUG\n\t\t\tEA::Allocator::gpEAGeneralAllocatorDebug->SetDefaultDebugDataFlag(EA::Allocator::GeneralAllocatorDebug::kDebugDataIdGuard);\n\t\t#endif\n\t}\n\n#else\n\t#if !defined(EA_PLATFORM_MICROSOFT) || defined(EA_PLATFORM_MINGW)\n\t\t#include <stdlib.h>\n\t#endif\n\n\tnamespace Internal\n\t{\n\t\tvoid* EASTLAlignedAlloc(size_t size, size_t alignment)\n\t\t{\n\t\t#ifdef EA_PLATFORM_MICROSOFT\n\t\t\treturn _aligned_malloc(size, alignment);\n\t\t#else\n\t\t\tvoid *p = nullptr;\n\t\t\talignment = alignment < sizeof( void *) ? sizeof( void *) : alignment;\n\t\t\tposix_memalign(&p, alignment, size);\n\t\t\treturn p;\n\t\t#endif\n\t\t}\n\n\t\tvoid EASTLAlignedFree(void* p)\n\t\t{\n\t\t#ifdef EA_PLATFORM_MICROSOFT\n\t\t\t_aligned_free(p);\n\t\t#else\n\t\t\tfree(p);\n\t\t#endif\n\t\t}\n\t}\n\n\tvoid* operator new(size_t size)\n\t\t{ return Internal::EASTLAlignedAlloc(size, 16); }\n\n\tvoid* operator new[](size_t size)\n\t\t{ return Internal::EASTLAlignedAlloc(size, 16); }\n\n\tvoid* operator new[](size_t size, const char* /*name*/, int /*flags*/, unsigned /*debugFlags*/, const char* /*file*/, int /*line*/)\n\t\t{ return Internal::EASTLAlignedAlloc(size, 16); }\n\n\tvoid* operator new[](size_t size, size_t alignment, size_t /*alignmentOffset*/, const char* /*name*/, int /*flags*/, unsigned /*debugFlags*/, const char* /*file*/, int /*line*/)\n\t\t{ return Internal::EASTLAlignedAlloc(size, alignment); }\n\n\tvoid* operator new(size_t size, size_t alignment)\n\t\t{ return Internal::EASTLAlignedAlloc(size, alignment); }\n\n\tvoid* operator new(size_t size, size_t alignment, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE()\n\t\t{ return Internal::EASTLAlignedAlloc(size, alignment); }\n\n\tvoid* operator new[](size_t size, size_t alignment)\n\t\t{ return Internal::EASTLAlignedAlloc(size, alignment); }\n\n\tvoid* operator new[](size_t size, size_t alignment, const std::nothrow_t&)EA_THROW_SPEC_NEW_NONE()\n\t\t{ return Internal::EASTLAlignedAlloc(size, alignment); }\n\n\t// C++14 deleter\n\tvoid operator delete(void* p, std::size_t sz ) EA_THROW_SPEC_DELETE_NONE()\n\t\t{ Internal::EASTLAlignedFree(p); EA_UNUSED(sz); }\n\n\tvoid operator delete[](void* p, std::size_t sz ) EA_THROW_SPEC_DELETE_NONE()\n\t\t{ Internal::EASTLAlignedFree(p); EA_UNUSED(sz); }\n\n\tvoid operator delete(void* p) EA_THROW_SPEC_DELETE_NONE()\n\t\t{ Internal::EASTLAlignedFree(p); }\n\n\tvoid operator delete[](void* p) EA_THROW_SPEC_DELETE_NONE()\n\t\t{ Internal::EASTLAlignedFree(p); }\n\n\tvoid EASTLTest_SetGeneralAllocator() { /* intentionally blank */ }\n\tbool EASTLTest_ValidateHeap() { return true; }\n\n#endif // !EASTL_OPENSOURCE\n\n#endif // Header include guard\n"
  },
  {
    "path": "test/source/EASTLTestAllocator.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef EASTLTEST_ALLOCATOR_H\n#define EASTLTEST_ALLOCATOR_H\n\n#include <EABase/eabase.h>\n#include <new>\n\n    void* operator new(size_t size);\n    void* operator new[](size_t size);\n    void* operator new[](size_t size, const char* /*name*/, int /*flags*/, unsigned /*debugFlags*/, const char* /*file*/, int /*line*/);\n    void* operator new[](size_t size, size_t alignment, size_t /*alignmentOffset*/, const char* /*name*/, int /*flags*/, unsigned /*debugFlags*/, const char* /*file*/, int /*line*/);\n    void* operator new(size_t size, size_t alignment);\n    void* operator new(size_t size, size_t alignment, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE();\n    void* operator new[](size_t size, size_t alignment);\n    void* operator new[](size_t size, size_t alignment, const std::nothrow_t&)EA_THROW_SPEC_NEW_NONE();\n    void operator delete(void* p) EA_THROW_SPEC_DELETE_NONE();\n    void operator delete[](void* p) EA_THROW_SPEC_DELETE_NONE();\n    void EASTLTest_SetGeneralAllocator();\n    bool EASTLTest_ValidateHeap();\n\n\n#endif // Header include guard\n"
  },
  {
    "path": "test/source/EASTLTestIterators.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n///////////////////////////////////////////////////////////////////////////////\n// Input concepts (see https://en.cppreference.com/w/cpp/named_req#Iterator):\n//  - input, eg. std::istream_iterator, not part of EASTL.\n//  - forward, eg. hash_map<K, V>::iterator\n//  - bidirectional, eg. list<T>::iterator\n//  - random access, eg. deque<T>::iterator\n//  - contiguous, eg. vector<T>::iterator\n// \n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef EASTL_TEST_ITERATORS_H\n#define EASTL_TEST_ITERATORS_H\n\n#include <EASTL/internal/config.h>\n#include <EASTL/iterator.h>\n\n#if defined(EA_PRAGMA_ONCE_SUPPORTED)\n#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.\n#endif\n\nstruct EndSentinel {};\n\n// a LegacyInputIterator that increments a referenced Integer.\n// this iterator cannot be made a forward iterator or stronger because it is a single pass iterator.\ntemplate <typename Integer>\nclass InputIterator\n{\nprotected:\n\tInteger* mInt{nullptr};\n\tInteger mEnd{0};\n\npublic:\n\ttypedef ptrdiff_t\t\t\t\t\t\t\tdifference_type;\n\ttypedef Integer\t\t\t\t\t\t\t\tvalue_type;\n\ttypedef Integer* pointer;\n\ttypedef Integer& reference;\n\ttypedef eastl::input_iterator_tag\titerator_category;\n\n\texplicit InputIterator(Integer* i) noexcept\n\t\t: mInt(i), mEnd(0) { }\n\n\texplicit InputIterator(EndSentinel, Integer end) noexcept\n\t\t: mInt(nullptr), mEnd(end) { }\n\n\tInputIterator() = default;\n\tInputIterator(const InputIterator& x) = default;\n\tInputIterator(InputIterator&& x) = default;\n\tInputIterator& operator=(const InputIterator& x) = default;\n\tInputIterator& operator=(InputIterator&& x) = default;\n\n\treference operator*() const\n\t{\n\t\treturn *mInt;\n\t}\n\n\tpointer operator->() const\n\t{\n\t\treturn mInt;\n\t}\n\n\tInputIterator& operator++()\n\t{\n\t\t++(*mInt);\n\t\treturn *this;\n\t}\n\n\tInputIterator operator++(int) const\n\t{\n\t\t// seeing as this is a single pass iterator, ie. the iterator modifies the source, pre- and post- increment are equivalent.\n\t\t// we iterate the copy, and even though this member function is const, the modification is visible by this object.\n\t\tInputIterator temp(*this);\n\t\t++temp;\n\t\treturn temp;\n\t}\n\n\ttemplate<typename Iterator>\n\tfriend inline bool operator==(const InputIterator<Iterator>& a, const InputIterator<Iterator>& b);\n\n}; // class InputIterator\n\ntemplate<typename Iterator>\ninline bool operator==(const InputIterator<Iterator>& a, const InputIterator<Iterator>& b)\n{\n\treturn /* is iterator == sentinel? */ (a.mInt && !b.mInt && *a.mInt == b.mEnd) ||\n\t\t/* are iterators equal? */ (a.mInt && b.mInt && a.mInt == b.mInt) ||\n\t\t/* are sentinels equal? */ (!a.mInt && !b.mInt && a.mEnd == b.mEnd);\n}\n\n// LegacyInputIterator\ntemplate<typename Iterator>\ninline bool operator!=(const InputIterator<Iterator>& a, const InputIterator<Iterator>& b)\n{\n\treturn !(a == b);\n}\n\n#endif // Header include guard\n"
  },
  {
    "path": "test/source/GetTypeName.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef GETTYPENAME_H\n#define GETTYPENAME_H\n\n\n#include <EABase/eabase.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/string.h>\n#include <stdlib.h>\n#include <typeinfo>\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE\n//\n// Defined as 0 or 1. The value depends on the compilation environment.\n// Indicates if we can use system-provided abi::__cxa_demangle() at runtime.\n//\n#if !defined(EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE)\n\t#if (defined(EA_PLATFORM_LINUX) || defined(EA_PLATFORM_APPLE)) && defined(EA_PLATFORM_DESKTOP)\n\t\t#define EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE 1\n\t#else\n\t\t#define EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE 0\n\t#endif\n#endif\n\n\n#if EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE\n\t#include <cxxabi.h>\n#elif EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP)\n\tEA_DISABLE_ALL_VC_WARNINGS();\n\t#include <Windows.h>\n\t#include <DbgHelp.h>\n\t#pragma comment(lib, \"dbghelp.lib\")\n\tEA_RESTORE_ALL_VC_WARNINGS();\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EASTLTEST_GETTYPENAME_AVAILABLE\n//\n// Defined as 0 or 1. The value depends on the compilation environment.\n// Indicates if we can use system-provided abi::__cxa_demangle() at runtime.\n//\n#if !defined(EASTLTEST_GETTYPENAME_AVAILABLE)\n\t#if (EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE || EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP)) && (!defined(EA_COMPILER_NO_RTTI) || defined(_MSC_VER)) // VC++ works without RTTI enabled.\n\t\t#define EASTLTEST_GETTYPENAME_AVAILABLE 1\n\t#else\n\t\t#define EASTLTEST_GETTYPENAME_AVAILABLE 0\n\t#endif\n#endif\n\n\n/// GetTypeName\n///\n/// Returns the type name of a templated type.\n///\ntemplate <typename T>\neastl::string GetTypeName()\n{\n\teastl::string result;\n\n\t#if !defined(EA_COMPILER_NO_RTTI) || defined(_MSC_VER) // VC++ works without RTTI enabled.\n\t\ttypedef typename eastl::remove_reference<T>::type TR;\n\n\t\tconst char* pName = typeid(TR).name();\n\n\t\t#if EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE\n\t\t\tconst char* pDemangledName = abi::__cxa_demangle(pName, NULL, NULL, NULL);\n\n\t\t#elif EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP)\n\t\t\tchar pDemangledName[1024];\n\t\t\tDWORD count = UnDecorateSymbolName(pName, pDemangledName, (DWORD)EAArrayCount(pDemangledName), UNDNAME_NO_THISTYPE | UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_MEMBER_TYPE);\n\t\t\tif(count == 0)\n\t\t\t\tpDemangledName[0] = 0;\n\t\t#else\n\t\t\tconst char* pDemangledName = NULL;\n\t\t#endif\n\n\t\tif(pDemangledName && pDemangledName[0])\n\t\t\tresult = pDemangledName;\n\t\telse\n\t\t\tresult = pName;\n\n\t\tif(eastl::is_const<TR>::value)\n\t\t\tresult += \" const\";\n\n\t\tif(eastl::is_volatile<TR>::value)\n\t\t\tresult += \" volatile\";\n\n\t\tif(eastl::is_lvalue_reference<T>::value)\n\t\t\tresult += \"&\";\n\t\telse if(eastl::is_rvalue_reference<T>::value)\n\t\t\tresult += \"&&\";\n\n\t\tif(pDemangledName)\n\t\t{\n\t\t\t#if EASTL_LIBSTDCPP_DEMANGLE_AVAILABLE\n\t\t\t\tfree((void*)(pDemangledName));\n\t\t\t#endif\n\t\t}\n\t#endif\n\n\treturn result;\n}\n\n\n#endif // Header include guard\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestAlgorithm.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#if defined(_MSC_VER)\n\t// We have little choice but to disable this warning. See the FAQ for why.\n\t#pragma warning(disable: 4244) // conversion from '___' to '___', possible loss of data\n#endif\n\n\n#include <EASTL/algorithm.h>\n#include <EASTL/functional.h>\n#include <EASTL/unique_ptr.h>\n#include <EASTL/vector.h>\n#include <EASTL/array.h>\n#include <EASTL/deque.h>\n#include <EASTL/list.h>\n#include <EASTL/slist.h>\n#include <EASTL/string.h>\n#include <EASTL/set.h>\n#include <EASTL/sort.h>\n#include \"ConceptImpls.h\"\n#include <EAStdC/EAMemory.h>\n#include \"EASTLTest.h\"  // Put this after the above so that it doesn't block any warnings from the includes above.\n\nnamespace eastl\n{\n\t#if 0\n\t// These are some tests of altermative implementations of branch-free min/max functions.\n\t/*\n\tunion FloatInt32Union\n\t{\n\t\tfloat   f;\n\t\tint32_t i;\n\t};\n\n\tinline float min_alt2(float a, float b)\n\t{\n\t\tFloatInt32Union uc;\n\t\tuc.f = a - b;\n\n\t\tconst float choices[2] = { a, b };\n\t\treturn (choices + 1)[uc.i >> 31];\n\t}\n\n\tinline float min_alt3(float a, float b)\n\t{\n\t\tFloatInt32Union uc, ua, ub, ur;\n\n\t\tuc.f   = a - b;\n\t\tuc.i >>= 31;\n\t\tua.f   = a;\n\t\tub.f   = b;\n\t\tur.i   = (ua.i & uc.i) | (ub.i & ~uc.i);\n\n\t\treturn ur.f;\n\t}\n\t*/\n\t#endif\n}\n\n\nnamespace\n{\n\tstruct A{\n\t\tA(int n) : a(n){}\n\t\tint a;\n\t};\n\tstruct LessStruct{ bool operator()(const A& a1, const A& a2){ return a1.a < a2.a; } };\n\n\n\tstruct B{\n\t\tB(int n) : b(n){}\n\t\tint b;\n\t};\n\tinline bool LessFunction(const B& b1, const B& b2){ return b1.b < b2.b; }\n}\n\nenum TestMinMaxEnum\n{\n\tteX = 0,\n\tteY = 3\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Greater\n//\n// A version of greater that uses operator < instead of operator >.\n//\ntemplate <typename T>\nstruct Greater\n{\n\tbool operator()(const T& a, const T& b) const\n\t\t{ return (b < a); }\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// DivisibleBy\n//\nstruct DivisibleBy\n{\n\tint d;\n\tDivisibleBy(int n = 1) : d(n) {}\n\tbool operator()(int n) const { return ((n % d) == 0); }\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestObjectNegate\n//\nstruct TestObjectNegate\n{\n\tTestObject operator()(const TestObject& a) const\n\t\t{ return TestObject(-a.mX); }\n};\n\nstatic int TestMinMax()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t{\n\t\t// NOTE(rparolin): This compiles but it should not.  We provide explicit eastl::max overloads for float, double,\n\t\t// and long double which enable this behaviour.  It is not standards compliant and it will be removed in a\n\t\t// future release.\n\t\t{\n\t\t\tstruct Foo\n\t\t\t{\n\t\t\t\toperator float() const { return 0; }\n\t\t\t};\n\n\t\t\tFoo f1;\n\t\t\tfloat f2{};\n\t\t\teastl::max(f1, f2);\n\t\t}\n\n\t\t// NOTE(rparolin): This will not compile because we lack explicit eastl::max overloads for 'int'.\n\t\t// {\n\t\t//\t struct Foo\n\t\t//\t {\n\t\t//\t\t operator int() const { return 0; }\n\t\t//\t };\n\n\t\t//\t Foo f1;\n\t\t//\t int f2{};\n\t\t//\t eastl::max(f1, f2);\n\t\t// }\n\t}\n\n\t{\n\t\t// const T& min(const T& a, const T& b);\n\t\t// const T& min(const T& a, const T& b, Compare compare)\n\t\t// const T& max(const T& a, const T& b);\n\t\t// const T& max(const T& a, const T& b, Compare compare)\n\n\t\tA a1(1), a2(2), a3(3);\n\t\ta3 = min(a1, a2, LessStruct());\n\t\tEATEST_VERIFY(a3.a == 1);\n\t\ta3 = max(a1, a2, LessStruct());\n\t\tEATEST_VERIFY(a3.a == 2);\n\n\t\tB b1(1), b2(2), b3(3);\n\t\tb3 = min(b2, b1, LessFunction);\n\t\tEATEST_VERIFY(b3.b == 1);\n\t\tb3 = max(b2, b1, LessFunction);\n\t\tEATEST_VERIFY(b3.b == 2);\n\n\n\t\tTestObject t1(1), t2(2), t3(3);\n\t\tt3 = min(t2, t1);\n\t\tEATEST_VERIFY(t3.mX == 1);\n\t\tt3 = max(t2, t1);\n\t\tEATEST_VERIFY(t3.mX == 2);\n\n\n\t\tint i1, i2(-1), i3(1);\n\t\ti1 = min(i2, i3);\n\t\tEATEST_VERIFY(i1 == -1);\n\t\ti1 = min(i3, i2);\n\t\tEATEST_VERIFY(i1 == -1);\n\t\ti1 = max(i2, i3);\n\t\tEATEST_VERIFY(i1 == 1);\n\t\ti1 = max(i3, i2);\n\t\tEATEST_VERIFY(i1 == 1);\n\n\t\tconst volatile int i2cv(-1), i3cv(1);\n\t\ti1 = min(i2cv, i3cv);\n\t\tEATEST_VERIFY(i1 == -1);\n\t\ti1 = min(i3cv, i2cv);\n\t\tEATEST_VERIFY(i1 == -1);\n\t\ti1 = max(i2cv, i3cv);\n\t\tEATEST_VERIFY(i1 == 1);\n\t\ti1 = max(i3cv, i2cv);\n\t\tEATEST_VERIFY(i1 == 1);\n\n\t\tfloat f1, f2(-1), f3(1);\n\t\tf1 = min(f2, f3);\n\t\tEATEST_VERIFY(f1 == -1);\n\t\tf1 = min(f3, f2);\n\t\tEATEST_VERIFY(f1 == -1);\n\t\tf1 = max(f2, f3);\n\t\tEATEST_VERIFY(f1 == 1);\n\t\tf1 = max(f3, f2);\n\t\tEATEST_VERIFY(f1 == 1);\n\n\t\tdouble d1, d2(-1), d3(1);\n\t\td1 = min(d2, d3);\n\t\tEATEST_VERIFY(d1 == -1);\n\t\td1 = min(d3, d2);\n\t\tEATEST_VERIFY(d1 == -1);\n\t\td1 = max(d2, d3);\n\t\tEATEST_VERIFY(d1 == 1);\n\t\td1 = max(d3, d2);\n\t\tEATEST_VERIFY(d1 == 1);\n\n\t\tvoid* p1, *p2 = &d2, *p3 = &d3;\n\t\tp1 = min(p2, p3);\n\t\tEATEST_VERIFY((uintptr_t)p1 == min((uintptr_t)p2, (uintptr_t)p3));\n\n\t\tdouble* pd1, *pd2 = &d2, *pd3 = &d3;\n\t\tpd1 = min(pd2, pd3);\n\t\tEATEST_VERIFY((uintptr_t)pd1 == min((uintptr_t)pd2, (uintptr_t)pd3));\n\n\n\t\t// initializer_list tests\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\tEATEST_VERIFY(min({ 3, 1, 2}) == 1);\n\t\t\tEATEST_VERIFY(max({ 3, 1, 2}) == 3);\n\t\t#endif\n\n\n\t\t// Test scalar specializations\n\t\tEATEST_VERIFY(min((char)1, (char)1) == 1);\n\t\tEATEST_VERIFY(min((char)1, (char)2) == 1);\n\t\tEATEST_VERIFY(min((char)2, (char)1) == 1);\n\n\t\tEATEST_VERIFY(min((signed char)1, (signed char)1) == 1);\n\t\tEATEST_VERIFY(min((signed char)1, (signed char)2) == 1);\n\t\tEATEST_VERIFY(min((signed char)2, (signed char)1) == 1);\n\n\t\tEATEST_VERIFY(min((unsigned char)1, (unsigned char)1) == 1);\n\t\tEATEST_VERIFY(min((unsigned char)1, (unsigned char)2) == 1);\n\t\tEATEST_VERIFY(min((unsigned char)2, (unsigned char)1) == 1);\n\n\t\tEATEST_VERIFY(min((signed short)1, (signed short)1) == 1);\n\t\tEATEST_VERIFY(min((signed short)1, (signed short)2) == 1);\n\t\tEATEST_VERIFY(min((signed short)2, (signed short)1) == 1);\n\n\t\tEATEST_VERIFY(min((unsigned short)1, (unsigned short)1) == 1);\n\t\tEATEST_VERIFY(min((unsigned short)1, (unsigned short)2) == 1);\n\t\tEATEST_VERIFY(min((unsigned short)2, (unsigned short)1) == 1);\n\n\t\tEATEST_VERIFY(min((signed int)1, (signed int)1) == 1);\n\t\tEATEST_VERIFY(min((signed int)1, (signed int)2) == 1);\n\t\tEATEST_VERIFY(min((signed int)2, (signed int)1) == 1);\n\n\t\tEATEST_VERIFY(min((unsigned int)1, (unsigned int)1) == 1);\n\t\tEATEST_VERIFY(min((unsigned int)1, (unsigned int)2) == 1);\n\t\tEATEST_VERIFY(min((unsigned int)2, (unsigned int)1) == 1);\n\n\t\tEATEST_VERIFY(min((signed long)1, (signed long)1) == 1);\n\t\tEATEST_VERIFY(min((signed long)1, (signed long)2) == 1);\n\t\tEATEST_VERIFY(min((signed long)2, (signed long)1) == 1);\n\n\t\tEATEST_VERIFY(min((unsigned long)1, (unsigned long)1) == 1);\n\t\tEATEST_VERIFY(min((unsigned long)1, (unsigned long)2) == 1);\n\t\tEATEST_VERIFY(min((unsigned long)2, (unsigned long)1) == 1);\n\n\t\tEATEST_VERIFY(min((signed long long)1, (signed long long)1) == 1);\n\t\tEATEST_VERIFY(min((signed long long)1, (signed long long)2) == 1);\n\t\tEATEST_VERIFY(min((signed long long)2, (signed long long)1) == 1);\n\n\t\tEATEST_VERIFY(min((unsigned long long)1, (unsigned long long)1) == 1);\n\t\tEATEST_VERIFY(min((unsigned long long)1, (unsigned long long)2) == 1);\n\t\tEATEST_VERIFY(min((unsigned long long)2, (unsigned long long)1) == 1);\n\n\t\tEATEST_VERIFY(min((float)1, (float)1) == 1);\n\t\tEATEST_VERIFY(min((float)1, (float)2) == 1);\n\t\tEATEST_VERIFY(min((float)2, (float)1) == 1);\n\n\t\tEATEST_VERIFY(min((double)1, (double)1) == 1);\n\t\tEATEST_VERIFY(min((double)1, (double)2) == 1);\n\t\tEATEST_VERIFY(min((double)2, (double)1) == 1);\n\n\t\tEATEST_VERIFY(min((long double)1, (long double)1) == 1);\n\t\tEATEST_VERIFY(min((long double)1, (long double)2) == 1);\n\t\tEATEST_VERIFY(min((long double)2, (long double)1) == 1);\n\n\n\t\t// Test max specializations\n\t\tEATEST_VERIFY(max((char)1, (char)1) == 1);\n\t\tEATEST_VERIFY(max((char)1, (char)2) == 2);\n\t\tEATEST_VERIFY(max((char)2, (char)1) == 2);\n\n\t\tEATEST_VERIFY(max((signed char)1, (signed char)1) == 1);\n\t\tEATEST_VERIFY(max((signed char)1, (signed char)2) == 2);\n\t\tEATEST_VERIFY(max((signed char)2, (signed char)1) == 2);\n\n\t\tEATEST_VERIFY(max((unsigned char)1, (unsigned char)1) == 1);\n\t\tEATEST_VERIFY(max((unsigned char)1, (unsigned char)2) == 2);\n\t\tEATEST_VERIFY(max((unsigned char)2, (unsigned char)1) == 2);\n\n\t\tEATEST_VERIFY(max((signed short)1, (signed short)1) == 1);\n\t\tEATEST_VERIFY(max((signed short)1, (signed short)2) == 2);\n\t\tEATEST_VERIFY(max((signed short)2, (signed short)1) == 2);\n\n\t\tEATEST_VERIFY(max((unsigned short)1, (unsigned short)1) == 1);\n\t\tEATEST_VERIFY(max((unsigned short)1, (unsigned short)2) == 2);\n\t\tEATEST_VERIFY(max((unsigned short)2, (unsigned short)1) == 2);\n\n\t\tEATEST_VERIFY(max((signed int)1, (signed int)1) == 1);\n\t\tEATEST_VERIFY(max((signed int)1, (signed int)2) == 2);\n\t\tEATEST_VERIFY(max((signed int)2, (signed int)1) == 2);\n\n\t\tEATEST_VERIFY(max((unsigned int)1, (unsigned int)1) == 1);\n\t\tEATEST_VERIFY(max((unsigned int)1, (unsigned int)2) == 2);\n\t\tEATEST_VERIFY(max((unsigned int)2, (unsigned int)1) == 2);\n\n\t\tEATEST_VERIFY(max((signed long)1, (signed long)1) == 1);\n\t\tEATEST_VERIFY(max((signed long)1, (signed long)2) == 2);\n\t\tEATEST_VERIFY(max((signed long)2, (signed long)1) == 2);\n\n\t\tEATEST_VERIFY(max((unsigned long)1, (unsigned long)1) == 1);\n\t\tEATEST_VERIFY(max((unsigned long)1, (unsigned long)2) == 2);\n\t\tEATEST_VERIFY(max((unsigned long)2, (unsigned long)1) == 2);\n\n\t\tEATEST_VERIFY(max((signed long long)1, (signed long long)1) == 1);\n\t\tEATEST_VERIFY(max((signed long long)1, (signed long long)2) == 2);\n\t\tEATEST_VERIFY(max((signed long long)2, (signed long long)1) == 2);\n\n\t\tEATEST_VERIFY(max((unsigned long long)1, (unsigned long long)1) == 1);\n\t\tEATEST_VERIFY(max((unsigned long long)1, (unsigned long long)2) == 2);\n\t\tEATEST_VERIFY(max((unsigned long long)2, (unsigned long long)1) == 2);\n\n\t\tEATEST_VERIFY(max((float)1, (float)1) == 1);\n\t\tEATEST_VERIFY(max((float)1, (float)2) == 2);\n\t\tEATEST_VERIFY(max((float)2, (float)1) == 2);\n\n\t\tEATEST_VERIFY(max((double)1, (double)1) == 1);\n\t\tEATEST_VERIFY(max((double)1, (double)2) == 2);\n\t\tEATEST_VERIFY(max((double)2, (double)1) == 2);\n\n\t\tEATEST_VERIFY(max((long double)1, (long double)1) == 1);\n\t\tEATEST_VERIFY(max((long double)1, (long double)2) == 2);\n\t\tEATEST_VERIFY(max((long double)2, (long double)1) == 2);\n\n\n\t\t// Test min_alt specializations\n\t\tEATEST_VERIFY(min_alt((char)1, (char)1) == 1);\n\t\tEATEST_VERIFY(min_alt((char)1, (char)2) == 1);\n\t\tEATEST_VERIFY(min_alt((char)2, (char)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((signed char)1, (signed char)1) == 1);\n\t\tEATEST_VERIFY(min_alt((signed char)1, (signed char)2) == 1);\n\t\tEATEST_VERIFY(min_alt((signed char)2, (signed char)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((unsigned char)1, (unsigned char)1) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned char)1, (unsigned char)2) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned char)2, (unsigned char)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((signed short)1, (signed short)1) == 1);\n\t\tEATEST_VERIFY(min_alt((signed short)1, (signed short)2) == 1);\n\t\tEATEST_VERIFY(min_alt((signed short)2, (signed short)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((unsigned short)1, (unsigned short)1) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned short)1, (unsigned short)2) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned short)2, (unsigned short)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((signed int)1, (signed int)1) == 1);\n\t\tEATEST_VERIFY(min_alt((signed int)1, (signed int)2) == 1);\n\t\tEATEST_VERIFY(min_alt((signed int)2, (signed int)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((unsigned int)1, (unsigned int)1) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned int)1, (unsigned int)2) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned int)2, (unsigned int)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((signed long)1, (signed long)1) == 1);\n\t\tEATEST_VERIFY(min_alt((signed long)1, (signed long)2) == 1);\n\t\tEATEST_VERIFY(min_alt((signed long)2, (signed long)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((unsigned long)1, (unsigned long)1) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned long)1, (unsigned long)2) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned long)2, (unsigned long)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((signed long long)1, (signed long long)1) == 1);\n\t\tEATEST_VERIFY(min_alt((signed long long)1, (signed long long)2) == 1);\n\t\tEATEST_VERIFY(min_alt((signed long long)2, (signed long long)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((unsigned long long)1, (unsigned long long)1) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned long long)1, (unsigned long long)2) == 1);\n\t\tEATEST_VERIFY(min_alt((unsigned long long)2, (unsigned long long)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((float)1, (float)1) == 1);\n\t\tEATEST_VERIFY(min_alt((float)1, (float)2) == 1);\n\t\tEATEST_VERIFY(min_alt((float)2, (float)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((double)1, (double)1) == 1);\n\t\tEATEST_VERIFY(min_alt((double)1, (double)2) == 1);\n\t\tEATEST_VERIFY(min_alt((double)2, (double)1) == 1);\n\n\t\tEATEST_VERIFY(min_alt((long double)1, (long double)1) == 1);\n\t\tEATEST_VERIFY(min_alt((long double)1, (long double)2) == 1);\n\t\tEATEST_VERIFY(min_alt((long double)2, (long double)1) == 1);\n\n\n\t\t// Test max_alt specializations\n\t\tEATEST_VERIFY(max_alt((char)1, (char)1) == 1);\n\t\tEATEST_VERIFY(max_alt((char)1, (char)2) == 2);\n\t\tEATEST_VERIFY(max_alt((char)2, (char)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((signed char)1, (signed char)1) == 1);\n\t\tEATEST_VERIFY(max_alt((signed char)1, (signed char)2) == 2);\n\t\tEATEST_VERIFY(max_alt((signed char)2, (signed char)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((unsigned char)1, (unsigned char)1) == 1);\n\t\tEATEST_VERIFY(max_alt((unsigned char)1, (unsigned char)2) == 2);\n\t\tEATEST_VERIFY(max_alt((unsigned char)2, (unsigned char)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((signed short)1, (signed short)1) == 1);\n\t\tEATEST_VERIFY(max_alt((signed short)1, (signed short)2) == 2);\n\t\tEATEST_VERIFY(max_alt((signed short)2, (signed short)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((unsigned short)1, (unsigned short)1) == 1);\n\t\tEATEST_VERIFY(max_alt((unsigned short)1, (unsigned short)2) == 2);\n\t\tEATEST_VERIFY(max_alt((unsigned short)2, (unsigned short)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((signed int)1, (signed int)1) == 1);\n\t\tEATEST_VERIFY(max_alt((signed int)1, (signed int)2) == 2);\n\t\tEATEST_VERIFY(max_alt((signed int)2, (signed int)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((unsigned int)1, (unsigned int)1) == 1);\n\t\tEATEST_VERIFY(max_alt((unsigned int)1, (unsigned int)2) == 2);\n\t\tEATEST_VERIFY(max_alt((unsigned int)2, (unsigned int)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((signed long)1, (signed long)1) == 1);\n\t\tEATEST_VERIFY(max_alt((signed long)1, (signed long)2) == 2);\n\t\tEATEST_VERIFY(max_alt((signed long)2, (signed long)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((unsigned long)1, (unsigned long)1) == 1);\n\t\tEATEST_VERIFY(max_alt((unsigned long)1, (unsigned long)2) == 2);\n\t\tEATEST_VERIFY(max_alt((unsigned long)2, (unsigned long)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((signed long long)1, (signed long long)1) == 1);\n\t\tEATEST_VERIFY(max_alt((signed long long)1, (signed long long)2) == 2);\n\t\tEATEST_VERIFY(max_alt((signed long long)2, (signed long long)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((unsigned long long)1, (unsigned long long)1) == 1);\n\t\tEATEST_VERIFY(max_alt((unsigned long long)1, (unsigned long long)2) == 2);\n\t\tEATEST_VERIFY(max_alt((unsigned long long)2, (unsigned long long)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((float)1, (float)1) == 1);\n\t\tEATEST_VERIFY(max_alt((float)1, (float)2) == 2);\n\t\tEATEST_VERIFY(max_alt((float)2, (float)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((double)1, (double)1) == 1);\n\t\tEATEST_VERIFY(max_alt((double)1, (double)2) == 2);\n\t\tEATEST_VERIFY(max_alt((double)2, (double)1) == 2);\n\n\t\tEATEST_VERIFY(max_alt((long double)1, (long double)1) == 1);\n\t\tEATEST_VERIFY(max_alt((long double)1, (long double)2) == 2);\n\t\tEATEST_VERIFY(max_alt((long double)2, (long double)1) == 2);\n\t}\n\n\t{\n\t\t// const T& min_alt(const T& a, const T& b);\n\t\t// const T& min_alt(const T& a, const T& b, Compare compare)\n\t\t// const T& max_alt(const T& a, const T& b);\n\t\t// const T& max_alt(const T& a, const T& b, Compare compare)\n\n\t\tA a1(1), a2(2), a3(3);\n\t\ta3 = min_alt(a1, a2, LessStruct());\n\t\tEATEST_VERIFY(a3.a == 1);\n\t\ta3 = max_alt(a1, a2, LessStruct());\n\t\tEATEST_VERIFY(a3.a == 2);\n\n\t\tB b1(1), b2(2), b3(3);\n\t\tb3 = min_alt(b2, b1, LessFunction);\n\t\tEATEST_VERIFY(b3.b == 1);\n\t\tb3 = max_alt(b2, b1, LessFunction);\n\t\tEATEST_VERIFY(b3.b == 2);\n\n\n\t\tTestObject t1(1), t2(2), t3(3);\n\t\tt3 = min_alt(t2, t1);\n\t\tEATEST_VERIFY(t3.mX == 1);\n\t\tt3 = max_alt(t2, t1);\n\t\tEATEST_VERIFY(t3.mX == 2);\n\n\n\t\tint i1, i2(-1), i3(1);\n\t\ti1 = min_alt(i2, i3);\n\t\tEATEST_VERIFY(i1 == -1);\n\t\ti1 = min_alt(i3, i2);\n\t\tEATEST_VERIFY(i1 == -1);\n\t\ti1 = max_alt(i2, i3);\n\t\tEATEST_VERIFY(i1 == 1);\n\t\ti1 = max_alt(i3, i2);\n\t\tEATEST_VERIFY(i1 == 1);\n\n\t\tfloat f1, f2(-1), f3(1);\n\t\tf1 = min_alt(f2, f3);\n\t\tEATEST_VERIFY(f1 == -1);\n\t\tf1 = min_alt(f3, f2);\n\t\tEATEST_VERIFY(f1 == -1);\n\t\tf1 = max_alt(f2, f3);\n\t\tEATEST_VERIFY(f1 == 1);\n\t\tf1 = max_alt(f3, f2);\n\t\tEATEST_VERIFY(f1 == 1);\n\n\t\tdouble d1, d2(-1), d3(1);\n\t\td1 = min_alt(d2, d3);\n\t\tEATEST_VERIFY(d1 == -1);\n\t\td1 = min_alt(d3, d2);\n\t\tEATEST_VERIFY(d1 == -1);\n\t\td1 = max_alt(d2, d3);\n\t\tEATEST_VERIFY(d1 == 1);\n\t\td1 = max_alt(d3, d2);\n\t\tEATEST_VERIFY(d1 == 1);\n\n\t\t// Make sure enums work\n\t\tstatic_assert(eastl::is_enum<TestMinMaxEnum>::value, \"is_enum failure\");\n\t\tEATEST_VERIFY(eastl::min(teX, teY) == teX);\n\n\t\t// Make sure pointers work\n\t\tTestObject testObjectArray[2];\n\t\tEATEST_VERIFY(eastl::min(&testObjectArray[0], &testObjectArray[1]) == &testObjectArray[0]);\n\n\t\t// Regression for Microsoft warning C4347 (http://msdn.microsoft.com/en-us/library/x7wb5te0.aspx)\n\t\tint32_t value  = rng.RandRange(17, 18);\n\t\tint32_t result = eastl::max_alt<int32_t>(0, value); // warning C4347: behavior change: 'const T &eastl::max_alt<int32_t>(const T &,const T &)' is called instead of 'int eastl::max_alt(int,int)'\n\t\tEATEST_VERIFY(result == 17);\n\n\t\t// Regression for Microsoft error C2666 (http://msdn.microsoft.com/en-us/library/dyafzty4%28v=vs.110%29.aspx)\n\t\tuint32_t value2a  = 17;\n\t\tuint32_t value2b  = 2;\n\t\tuint32_t result2 = eastl::min_alt<uint32_t>(value2a - value2b, 4); // error C2666: 'eastl::min_alt' : 12 overloads have similar conversions\n\t\tEATEST_VERIFY(result2 == 4);\n\n\t\t// Regression for volatile arguments + literals\n\t\t// This test is disabled until we come up with a solution for this. std::min gives the same result as below, so we aren't necessarily obligated to resolve this.\n\t\t// volatile uint32_t value3  = 17;\n\t\t// uint32_t result3 = eastl::min_alt<uint32_t>(value3, 4); // error C2664: 'const T &eastl::min_alt<unsigned int>(const T &,const T &)' : cannot convert parameter 1 from 'volatile uint32_t' to 'const unsigned int &'\n\t\t// EATEST_VERIFY(result3 == 4);\n\t}\n\n\n\t{\n\t\t// ForwardIterator min_element(ForwardIterator first, ForwardIterator last)\n\t\t// ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare compare)\n\n\t\tint intArray[] = { -5, 2, 1, 5, 4, 5 };\n\t\tint* pInt = min_element(intArray, intArray + 6);\n\t\tEATEST_VERIFY(pInt && (*pInt == -5));\n\n\t\tpInt = min_element(intArray, intArray + 6, Greater<int>());\n\t\tEATEST_VERIFY(pInt && (*pInt == 5));\n\n\n\t\tTestObject toArray[] = { TestObject(7), TestObject(2), TestObject(8), TestObject(5), TestObject(4), TestObject(-12) };\n\t\tTestObject* pTO = min_element(toArray, toArray + 6);\n\t\tEATEST_VERIFY(pTO && (*pTO == TestObject(-12)));\n\n\t\tpTO = min_element(toArray, toArray + 6, Greater<TestObject>());\n\t\tEATEST_VERIFY(pTO && (*pTO == TestObject(8)));\n\t}\n\n\n\t{\n\t\t// ForwardIterator max_element(ForwardIterator first, ForwardIterator last)\n\t\t// ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare compare)\n\n\t\tint intArray[] = { -5, 2, 1, 5, 4, 5 };\n\t\tint* pInt = max_element(intArray, intArray + 6);\n\t\tEATEST_VERIFY(pInt && (*pInt == 5));\n\n\t\tpInt = max_element(intArray, intArray + 6, less<int>());\n\t\tEATEST_VERIFY(pInt && (*pInt == 5));\n\n\n\t\tTestObject toArray[] = { TestObject(7), TestObject(2), TestObject(8), TestObject(5), TestObject(4), TestObject(-12) };\n\t\tTestObject* pTO = max_element(toArray, toArray + 6);\n\t\tEATEST_VERIFY(pTO && (*pTO == TestObject(8)));\n\n\t\tpTO = max_element(toArray, toArray + 6, less<TestObject>());\n\t\tEATEST_VERIFY(pTO && (*pTO == TestObject(8)));\n\t}\n\n\t{\n\t\t// template <class ForwardIterator, class Compare>\n\t\t// eastl::pair<ForwardIterator, ForwardIterator>\n\t\t// minmax_element(ForwardIterator first, ForwardIterator last)\n\t\t//\n\t\t// template <class ForwardIterator, class Compare>\n\t\t// eastl::pair<ForwardIterator, ForwardIterator>\n\t\t// minmax_element(ForwardIterator first, ForwardIterator last, Compare compare)\n\n\t\tint intArray[] = { 5, -2, 1, 5, 6, 5 };\n\n\t\teastl::pair<int*, int*> result = eastl::minmax_element(intArray, intArray + 6);\n\t\tEATEST_VERIFY((*result.first == -2) && (*result.second == 6));\n\n\n\t\t// template <typename T>\n\t\t// eastl::pair<const T&, const T&>\n\t\t// minmax(const T& a, const T& b)\n\t\t//\n\t\t// template <typename T, typename Compare>\n\t\t// eastl::pair<const T&, const T&>\n\t\t// minmax(const T& a, const T& b, Compare comp)\n\n\t\t// The VC++ compiler is broken in such a way that it can't compile the following without generating a warning:\n\t\t//     warning C4413: 'eastl::pair<T1,T2>::first' : reference member is initialized to a temporary that doesn't persist after the constructor exits.\n\t\t// The Microsoft standard library definition of minmax doesn't generate this warning... because that minmax is broken and non-conforming. I think they\n\t\t// made it the way they did because of the aforementioned compiler bug.\n\t\t// Recent versions of clang seem to generate a warning of its own. To do: we need to address this.\n\t\t// GCC 4.8 for x86 has a compiler bug in optimized builds for this code, so we currently enable this for non-optimized builds only.\n\t\t#if defined(EA_COMPILER_CPP11_ENABLED) && ((defined(EA_COMPILER_CLANG) && EA_COMPILER_VERSION < 302) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007)) && !defined(__OPTIMIZE__))\n\n\t\t\tint i3(3), i2(2);\n\t\t\teastl::pair<const int&, const int&> resulti = eastl::minmax(i3, i2);\n\t\t\tEATEST_VERIFY_F((resulti.first == 2) && (resulti.second == 3), \"minmax failure. %d %d\", resulti.first, resulti.second);\n\n\t\t\tchar c3(3), c2(2);\n\t\t\teastl::pair<const char&, const char&> resultc = eastl::minmax(c3, c2);\n\t\t\tEATEST_VERIFY_F((resultc.first == 2) && (resultc.second == 3), \"minmax failure. %d %d\", (int)resultc.first, (int)resultc.second);\n\n\t\t\tfloat f3(3), f2(2);\n\t\t\teastl::pair<const float&, const float&> resultf = eastl::minmax(f3, f2);\n\t\t\tEATEST_VERIFY_F((resultf.first == 2) && (resultf.second == 3), \"minmax failure. %f %f\", resultf.first, resultf.second);\n\t\t#endif\n\n\n\t\t// template <typename T>\n\t\t// eastl::pair<T, T>\n\t\t// minmax(std::initializer_list<T> ilist)\n\t\t//\n\t\t// template <typename T, class Compare>\n\t\t// eastl::pair<T, T>\n\t\t// minmax(std::initializer_list<T> ilist, Compare compare)\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\teastl::pair<int, int> result3 = eastl::minmax({3, 2});\n\t\t\tEATEST_VERIFY((result3.first == 2) && (result3.second == 3));\n\t\t#endif\n\t}\n\n\n\treturn nErrorCount;\n}\n\n\nstatic int TestClamp()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::clamp(42, 1, 100) == 42);\n\tEATEST_VERIFY(eastl::clamp(-42, 1, 100) == 1);\n\tEATEST_VERIFY(eastl::clamp(420, 1, 100) == 100);\n\tEATEST_VERIFY(eastl::clamp(1, 1, 100) == 1);\n\tEATEST_VERIFY(eastl::clamp(100, 1, 100) == 100);\n\n\tEATEST_VERIFY(eastl::clamp(42.f, 1.f, 100.f, less<float>()) == 42.f);\n\tEATEST_VERIFY(eastl::clamp(-42.f, 1.f, 100.f, less<float>()) == 1.f);\n\tEATEST_VERIFY(eastl::clamp(420.f, 1.f, 100.f, less<float>()) == 100.f);\n\tEATEST_VERIFY(eastl::clamp(1.f, 1.f, 100.f, less<float>()) == 1.f);\n\tEATEST_VERIFY(eastl::clamp(100.f, 1.f, 100.f, less<float>()) == 100.f);\n\n\tEATEST_VERIFY(eastl::clamp(42., 1., 100., less<double>()) == 42.);\n\tEATEST_VERIFY(eastl::clamp(-42., 1., 100., less<double>()) == 1.);\n\tEATEST_VERIFY(eastl::clamp(420., 1., 100., less<double>()) == 100.);\n\tEATEST_VERIFY(eastl::clamp(1., 1., 100., less<double>()) == 1.);\n\tEATEST_VERIFY(eastl::clamp(100., 1., 100., less<double>()) == 100.);\n\n\tEATEST_VERIFY(eastl::clamp(A(42), A(1), A(100), LessStruct()).a == A(42).a);\n\tEATEST_VERIFY(eastl::clamp(A(-42), A(1), A(100), LessStruct()).a == A(1).a);\n\tEATEST_VERIFY(eastl::clamp(A(420), A(1), A(100), LessStruct()).a == A(100).a);\n\tEATEST_VERIFY(eastl::clamp(A(1), A(1), A(100), LessStruct()).a == A(1).a);\n\tEATEST_VERIFY(eastl::clamp(A(100), A(1), A(100), LessStruct()).a == A(100).a);\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestAlgorithm\n//\nint TestAlgorithm()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\tTestObject::Reset();\n\n\tnErrorCount += TestMinMax();\n\tnErrorCount += TestClamp();\n\n\n\t// bool all_of (InputIterator first, InputIterator last, Predicate p);\n\t// bool any_of (InputIterator first, InputIterator last, Predicate p);\n\t// bool none_of(InputIterator first, InputIterator last, Predicate p);\n\t{\n\n\t\teastl::vector<int> v;\n\t\tv.push_back(2);\n\t\tv.push_back(4);\n\t\tv.push_back(6);\n\t\tv.push_back(8);\n\n\t\tEATEST_VERIFY(eastl::all_of( v.begin(), v.end(), DivisibleBy(2)));\n\t\tEATEST_VERIFY(eastl::any_of( v.begin(), v.end(), DivisibleBy(3)));\n\t\tEATEST_VERIFY(eastl::none_of(v.begin(), v.end(), DivisibleBy(5)));\n\t}\n\n\n\t{\n\t\t// pair mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)\n\t\t// pair mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Predicate predicate)\n\n\t\tint intArray1[] = { -5, 2, 1, 5, 4, 8888 };\n\t\tint intArray2[] = { -5, 2, 1, 5, 4, 9999 };\n\t\tint intArray3[] = { -5, 2, 1, 5, 4, 9999 };\n\n\t\teastl::pair<int*, int*> pairInt = mismatch(intArray1, intArray1, intArray2);\n\t\tEATEST_VERIFY(pairInt.first  == intArray1 + 0);\n\t\tEATEST_VERIFY(pairInt.second == intArray2 + 0);\n\n\t\tpairInt = mismatch(intArray1, intArray1 + 6, intArray2);\n\t\tEATEST_VERIFY(pairInt.first  == intArray1 + 5);\n\t\tEATEST_VERIFY(pairInt.second == intArray2 + 5);\n\t\tpairInt = mismatch(intArray2, intArray2 + 6, intArray3);\n\n\t\tEATEST_VERIFY(pairInt.first  == intArray2 + 6);\n\t\tEATEST_VERIFY(pairInt.second == intArray3 + 6);\n\n\n\t\tpairInt = mismatch(intArray1, intArray1, intArray2, equal_to<int>());\n\t\tEATEST_VERIFY(pairInt.first  == intArray1 + 0);\n\t\tEATEST_VERIFY(pairInt.second == intArray2 + 0);\n\n\t\tpairInt = mismatch(intArray1, intArray1 + 6, intArray2, equal_to<int>());\n\t\tEATEST_VERIFY(pairInt.first  == intArray1 + 5);\n\t\tEATEST_VERIFY(pairInt.second == intArray2 + 5);\n\n\t\tpairInt = mismatch(intArray2, intArray2 + 6, intArray3, equal_to<int>());\n\t\tEATEST_VERIFY(pairInt.first  == intArray2 + 6);\n\t\tEATEST_VERIFY(pairInt.second == intArray3 + 6);\n\t}\n\n\n\t{\n\t\t// void swap(T& a, T& b)\n\t\t// void iter_swap(ForwardIterator1 a, ForwardIterator2 b)\n\n\t\tint intArray[] = { -5, 2, 1, 5, 4, 5 };\n\n\t\tswap(intArray[0], intArray[4]);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"swap\", 4, 2, 1, 5, -5, 5, -1));\n\n\t\titer_swap(intArray + 2, intArray + 3);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"iter_swap\", 4, 2, 5, 1, -5, 5, -1));\n\n\n\t\tTestObject toArray[] = { TestObject(-5), TestObject(2), TestObject(1), TestObject(5), TestObject(4), TestObject(5) };\n\n\t\tswap(toArray[0], toArray[4]);\n\t\tEATEST_VERIFY(toArray[0] == TestObject(4));\n\t\tEATEST_VERIFY(toArray[4] == TestObject(-5));\n\n\t\titer_swap(toArray + 2, toArray + 3);\n\t\tEATEST_VERIFY(toArray[2] == TestObject(5));\n\t\tEATEST_VERIFY(toArray[3] == TestObject(1));\n\t}\n\n\n\t{\n\t\t// ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 0, 0, 0, 0, 0, 0 };\n\n\t\tswap_ranges(intArray1, intArray1 + 6, intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"swap_ranges\", 0, 0, 0, 0, 0, 0, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"swap_ranges\", 3, 2, 6, 5, 4, 1, -1));\n\n\n\t\tTestObject toArray1[] = { TestObject(3), TestObject(2), TestObject(6), TestObject(5), TestObject(4), TestObject(1) };\n\t\tTestObject toArray2[] = { TestObject(0), TestObject(0), TestObject(0), TestObject(0), TestObject(0), TestObject(0) };\n\n\t\tswap_ranges(toArray1, toArray1 + 6, toArray2);\n\t\tEATEST_VERIFY(toArray1[0] == TestObject(0));\n\t\tEATEST_VERIFY(toArray1[5] == TestObject(0));\n\t\tEATEST_VERIFY(toArray2[0] == TestObject(3));\n\t\tEATEST_VERIFY(toArray2[5] == TestObject(1));\n\t}\n\n\n\t{\n\t\t// ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last)\n\t\t// ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate predicate)\n\n\t\tint intArray[] = { 3, 2, 5, 5, 4, 1 };\n\n\t\tint* pInt = adjacent_find(intArray + 0, intArray + 6);\n\t\tEATEST_VERIFY(pInt == (intArray + 2));\n\n\t\tpInt = adjacent_find(intArray + 3, intArray + 6);\n\t\tEATEST_VERIFY(pInt == (intArray + 6)); // Verify not found\n\n\n\t\tTestObject toArray[] = { TestObject(3), TestObject(2), TestObject(5), TestObject(5), TestObject(4), TestObject(1) };\n\n\t\tTestObject* pTO = adjacent_find(toArray + 0, toArray + 6);\n\t\tEATEST_VERIFY(pTO == (toArray + 2));\n\n\t\tpTO = adjacent_find(toArray + 3, toArray + 6);\n\t\tEATEST_VERIFY(pTO == (toArray + 6)); // Verify not found\n\t}\n\n\n\t{\n\t\t// OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 0, 0, 0, 0, 0, 0 };\n\n\t\tmove(intArray1, intArray1 + 0, intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"move\", 0, 0, 0, 0, 0, 0, -1));\n\n\t\tmove(intArray1, intArray1 + 6, intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"move\", 3, 2, 6, 5, 4, 1, -1));\n\n\t\tmove(intArray1 + 1, intArray1 + 6, intArray1 + 0); // Copy over self.\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"move\", 2, 6, 5, 4, 1, 1, -1));\n\t}\n\n\n\t{\n\t\t// OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 0, 0, 0, 0, 0, 0 };\n\n\t\tcopy(intArray1, intArray1 + 0, intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"copy\", 0, 0, 0, 0, 0, 0, -1));\n\n\t\tcopy(intArray1, intArray1 + 6, intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"copy\", 3, 2, 6, 5, 4, 1, -1));\n\n\t\tcopy(intArray1 + 1, intArray1 + 6, intArray1 + 0); // Copy over self.\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"copy\", 2, 6, 5, 4, 1, 1, -1));\n\t}\n\n\n\t{\n\t\t// OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate)\n\n\t\tint intArray1[] = { 9, 1, 9, 9, 9, 9, 1, 1, 9, 9 };\n\t\tint intArray2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\n\n\t\tauto equal_to_1 = [](int i) { return i == 1; };\n\t\tcopy_if(intArray1, intArray1 + 0, intArray2, equal_to_1);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 10, int(), \"copy_if\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1));\n\n\t\tcopy_if(intArray1, intArray1 + 9, intArray2, equal_to_1);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 10, int(), \"copy_if\", 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1));\n\n\t\tcopy_if(intArray1 + 1, intArray1 + 9, intArray1 + 0, equal_to_1); // Copy over self.\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 10, int(), \"copy_if\", 1, 1, 1, 9, 9, 9, 1, 1, 9, 9, -1));\n\t}\n\n\n\t{\n\t\t// OutputIterator copy_n(InputIterator first, Size count, OutputIterator result)\n\n\t\teastl::string in = \"123456\";\n\t\teastl::string out;\n\n\t\teastl::copy_n(in.begin(), 4, eastl::back_inserter(out));\n\t\tEATEST_VERIFY(out == \"1234\");\n\t}\n\n\n\t{\n\t\t// BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result)\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 0, 0, 0, 0, 0, 0 };\n\n\t\tcopy_backward(intArray1, intArray1 + 0, (int*) nullptr);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"copy_backward\", 0, 0, 0, 0, 0, 0, -1));\n\n\t\tcopy_backward(intArray1, intArray1 + 0, intArray2 + 0);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"copy_backward\", 0, 0, 0, 0, 0, 0, -1));\n\n\t\tcopy_backward(intArray1, intArray1 + 6, intArray2 + 6);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 6, int(), \"copy_backward\", 3, 2, 6, 5, 4, 1, -1));\n\n\t\tcopy_backward(intArray1, intArray1 + 5, intArray1 + 6); // Copy over self.\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"copy_backward\", 3, 3, 2, 6, 5, 4, -1));\n\t}\n\n\n\t{\n\t\t// OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)\n\t\t{\n\t\t\teastl::vector<eastl::string> src;\n\t\t\tfor(eastl_size_t i = 0; i < 4; i++)\n\t\t\t\tsrc.push_back(eastl::string(1, (char8_t)('0' + i)));\n\t\t\teastl::vector<eastl::string> dest(src.size());\n\n\t\t\teastl::move(src.begin(), src.end(), dest.begin());\n\t\t\tEATEST_VERIFY((dest[0] == \"0\") && (dest[3] == \"3\"));\n\t\t\tEATEST_VERIFY(src[0].empty() && src[3].empty());\n\t\t}\n\n\t\t{\n\t\t\t// BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result)\n\t\t\teastl::vector<eastl::string> src;\n\t\t\tfor(eastl_size_t i = 0; i < 4; i++)\n\t\t\t\tsrc.push_back(eastl::string(1, (char8_t)('0' + i)));\n\t\t\teastl::vector<eastl::string> dest(src.size());\n\n\t\t\teastl::move_backward(src.begin(), src.end(), dest.end());\n\t\t\tEATEST_VERIFY((dest[0] == \"0\") && (dest[3] == \"3\"));\n\t\t\tEATEST_VERIFY(src[0].empty() && src[3].empty());\n\t\t}\n\t}\n\n\n\t{\n\t\t// difference_type count(InputIterator first, InputIterator last, const T& value)\n\n\t\tint intArray[] = { 1, 2, 1, 5, 4, 1 };\n\t\tptrdiff_t n = count(intArray, intArray + 6, 1);\n\t\tEATEST_VERIFY(n == 3);\n\n\t\tTestObject toArray[] = { TestObject(1), TestObject(2), TestObject(1), TestObject(5), TestObject(4), TestObject(1) };\n\t\tn = count(toArray, toArray + 6, TestObject(1));\n\t\tEATEST_VERIFY(n == 3);\n\t}\n\n\n\t{\n\t\t// difference_type count_if(InputIterator first, InputIterator last, Predicate predicate)\n\n\t\tint intArray[] = { 3, 2, 6, 5, 4, 1, 2, 4, 5, 4, 1, 2 };\n\n\t\t// Count all items whose value is less than three.\n\t\tauto less_than_3 = [](int i) { return i < 3; };\n\t\tptrdiff_t n = count_if(intArray, intArray, less_than_3); // No-op\n\t\tEATEST_VERIFY(n == 0);\n\t\tn = count_if(intArray, intArray + 12, less_than_3);\n\t\tEATEST_VERIFY(n == 5);\n\n\n\t\t// Count all items whose value is less than three.\n\t\tTestObject toArray[] = { TestObject(1), TestObject(3), TestObject(1), TestObject(4), TestObject(2), TestObject(5) };\n\n\t\tauto less_than_testobject_3 = [](const TestObject& lhs) { return lhs < TestObject(3); };\n\t\tn = count_if(toArray, toArray, less_than_testobject_3); // No-op\n\t\tEATEST_VERIFY(n == 0);\n\t\tn = count_if(toArray, toArray + 6, less_than_testobject_3);\n\t\tEATEST_VERIFY(n == 3);\n\n\n\t\t// Count all items whose value is less than three.\n\t\tslist<int> intList;\n\t\tintList.push_front(1);\n\t\tintList.push_front(3);\n\t\tintList.push_front(1);\n\t\tintList.push_front(4);\n\t\tintList.push_front(2);\n\t\tintList.push_front(5);\n\n\t\tn = count_if(intList.begin(), intList.begin(), less_than_3); // No-op\n\t\tEATEST_VERIFY(n == 0);\n\t\tn = count_if(intList.begin(), intList.end(), less_than_3);\n\t\tEATEST_VERIFY(n == 3);\n\t}\n\n\n\t{\n\t\t// void fill(ForwardIterator first, ForwardIterator last, const T& value)\n\n\t\tvector<int> intArray(10);\n\n\t\tEATEST_VERIFY(VerifySequence(intArray.begin(), intArray.end(), int(), \"fill\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1));\n\t\tfill(intArray.begin() + 3, intArray.begin() + 7, 4);\n\t\tEATEST_VERIFY(VerifySequence(intArray.begin(), intArray.end(), int(), \"fill\", 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, -1));\n\n\n\t\tslist<int> intList(10);\n\t\tslist<int>::iterator first = intList.begin();\n\t\tslist<int>::iterator last = intList.begin();\n\n\t\tadvance(first, 3);\n\t\tadvance(last, 7);\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fill\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1));\n\t\tfill(first, last, 4);\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fill\", 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, -1));\n\n\n\t\t// Exercise specializations we have for some platform/compiler combinations\n\t\t// void fill(uint64_t* first, uint64_t* last, uint64_t c);\n\t\t// void fill( int64_t* first,  int64_t* last,  int64_t c);\n\t\t// void fill(uint32_t* first, uint32_t* last, uint32_t c);\n\t\t// void fill( int32_t* first,  int32_t* last,  int32_t c);\n\t\t// void fill(uint16_t* first, uint16_t* last, uint16_t c);\n\t\t// void fill( int16_t* first,  int16_t* last,  int16_t c);\n\t\tconst eastl_size_t kMaxSize = 300;\n\t\teastl::vector<uint64_t> vU64(kMaxSize, 0);\n\t\teastl::vector< int64_t> vI64(kMaxSize, 0);\n\t\teastl::vector<uint32_t> vU32(kMaxSize, 0);\n\t\teastl::vector< int32_t> vI32(kMaxSize, 0);\n\t\teastl::vector<uint16_t> vU16(kMaxSize, 0);\n\t\teastl::vector< int16_t> vI16(kMaxSize, 0);\n\n\t\tfor(eastl_size_t i = 0; i < kMaxSize; ++i)\n\t\t{\n\t\t\teastl::fill(vU64.begin(), vU64.begin() + i, UINT64_C(0x0123456789abcdef));\n\t\t\tEATEST_VERIFY(EA::StdC::Memcheck64(&vU64[0], UINT64_C(0x0123456789abcdef), i) == NULL);\n\t\t\tEA::StdC::Memset64(&vU64[0], 0, i);\n\n\t\t\teastl::fill(vI64.begin(), vI64.begin() + i, UINT64_C(0x0123456789abcdef));\n\t\t\tEATEST_VERIFY(EA::StdC::Memcheck64(&vI64[0], UINT64_C(0x0123456789abcdef), i) == NULL);\n\t\t\tEA::StdC::Memset64(&vI64[0], 0, i);\n\n\t\t\teastl::fill(vU32.begin(), vU32.begin() + i, UINT32_C(0x01234567));\n\t\t\tEATEST_VERIFY(EA::StdC::Memcheck32(&vU32[0], UINT32_C(0x01234567), i) == NULL);\n\t\t\tEA::StdC::Memset32(&vU32[0], 0, i);\n\n\t\t\teastl::fill(vI32.begin(), vI32.begin() + i, UINT32_C(0x01234567));\n\t\t\tEATEST_VERIFY(EA::StdC::Memcheck32(&vI32[0], UINT32_C(0x01234567), i) == NULL);\n\t\t\tEA::StdC::Memset32(&vI32[0], 0, i);\n\n\t\t\teastl::fill(vU16.begin(), vU16.begin() + i, UINT16_C(0x0123));\n\t\t\tEATEST_VERIFY(EA::StdC::Memcheck16(&vU16[0], UINT16_C(0x0123), i) == NULL);\n\t\t\tEA::StdC::Memset16(&vU16[0], 0, i);\n\n\t\t\teastl::fill(vI16.begin(), vI16.begin() + i, UINT16_C(0x0123));\n\t\t\tEATEST_VERIFY(EA::StdC::Memcheck16(&vI16[0], UINT16_C(0x0123), i) == NULL);\n\t\t\tEA::StdC::Memset16(&vI16[0], 0, i);\n\t\t}\n\n\t\t{   // Regression for user-reported compile failure.\n\t\t\tenum TestEnum { eTestValue = -1 };\n\t\t\teastl::vector<int32_t> intArrayEnum;\n\n\t\t\teastl::fill<eastl::vector<int32_t>::iterator, int32_t>(intArrayEnum.begin(), intArrayEnum.end(), eTestValue);\n\t\t\tEATEST_VERIFY(intArrayEnum.size() == 0);\n\t\t}\n\t}\n\n\n\t{\n\t\t// OutputIterator fill_n(OutputIterator first, Size n, const T& value)\n\n\t\tvector<int> intArray(10);\n\n\t\tEATEST_VERIFY(VerifySequence(intArray.begin(), intArray.end(), int(), \"fill_n\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1));\n\t\tfill_n(intArray.begin() + 3, 4, 4);\n\t\tEATEST_VERIFY(VerifySequence(intArray.begin(), intArray.end(), int(), \"fill_n\", 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, -1));\n\n\n\t\tlist<int> intList(10);\n\t\tlist<int>::iterator first = intList.begin();\n\n\t\tadvance(first, 3);\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fill_n\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1));\n\t\tfill_n(first, 4, 4);\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fill_n\", 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, -1));\n\n\t\t// Exercise specializations we have for some platform/compiler combinations\n\t\t// template<typename Size>\n\t\t// uint64_t* fill_n(uint64_t* first, Size n, uint64_t c);\n\t\t//  int64_t* fill_n( int64_t* first, Size n,  int64_t c);\n\t\t// uint32_t* fill_n(uint32_t* first, Size n, uint32_t c);\n\t\t//  int32_t* fill_n( int32_t* first, Size n,  int32_t c);\n\t\t// uint16_t* fill_n(uint16_t* first, Size n, uint16_t c);\n\t\t//  int16_t* fill_n( int16_t* first, Size n,  int16_t c);\n\t\tconst eastl_size_t kMaxSize = 17;\n\t\teastl::vector<uint64_t> vU64(kMaxSize, 0);\n\t\teastl::vector< int64_t> vI64(kMaxSize, 0);\n\t\teastl::vector<uint32_t> vU32(kMaxSize, 0);\n\t\teastl::vector< int32_t> vI32(kMaxSize, 0);\n\t\teastl::vector<uint16_t> vU16(kMaxSize, 0);\n\t\teastl::vector< int16_t> vI16(kMaxSize, 0);\n\n\t\teastl::vector<uint64_t>::iterator itU64 = eastl::fill_n(vU64.begin(), kMaxSize, UINT64_C(0x0123456789abcdef));\n\t\tEATEST_VERIFY(EA::StdC::Memcheck64(&vU64[0], UINT64_C(0x0123456789abcdef), kMaxSize) == NULL);\n\t\tEATEST_VERIFY(itU64 == (vU64.begin() + kMaxSize));\n\t\tEA::StdC::Memset64(&vU64[0], 0, kMaxSize);\n\n\t\teastl::vector<int64_t>::iterator itI64 = eastl::fill_n(vI64.begin(), kMaxSize, UINT64_C(0x0123456789abcdef));\n\t\tEATEST_VERIFY(EA::StdC::Memcheck64(&vI64[0], UINT64_C(0x0123456789abcdef), kMaxSize) == NULL);\n\t\tEATEST_VERIFY(itI64 == (vI64.begin() + kMaxSize));\n\t\tEA::StdC::Memset64(&vI64[0], 0, kMaxSize);\n\n\t\teastl::vector<uint32_t>::iterator itU32 = eastl::fill_n(vU32.begin(), kMaxSize, UINT32_C(0x01234567));\n\t\tEATEST_VERIFY(EA::StdC::Memcheck32(&vU32[0], UINT32_C(0x01234567), kMaxSize) == NULL);\n\t\tEATEST_VERIFY(itU32 == (vU32.begin() + kMaxSize));\n\t\tEA::StdC::Memset32(&vU32[0], 0, kMaxSize);\n\n\t\teastl::vector<int32_t>::iterator itI32 = eastl::fill_n(vI32.begin(), kMaxSize, UINT32_C(0x01234567));\n\t\tEATEST_VERIFY(EA::StdC::Memcheck32(&vI32[0], UINT32_C(0x01234567), kMaxSize) == NULL);\n\t\tEATEST_VERIFY(itI32 == (vI32.begin() + kMaxSize));\n\t\tEA::StdC::Memset32(&vI32[0], 0, kMaxSize);\n\n\t\teastl::vector<uint16_t>::iterator itU16 = eastl::fill_n(vU16.begin(), kMaxSize, UINT16_C(0x0123));\n\t\tEATEST_VERIFY(EA::StdC::Memcheck16(&vU16[0], UINT16_C(0x0123), kMaxSize) == NULL);\n\t\tEATEST_VERIFY(itU16 == (vU16.begin() + kMaxSize));\n\t\tEA::StdC::Memset16(&vU16[0], 0, kMaxSize);\n\n\t\teastl::vector<int16_t>::iterator itI16 = eastl::fill_n(vI16.begin(), kMaxSize, UINT16_C(0x0123));\n\t\tEATEST_VERIFY(EA::StdC::Memcheck16(&vI16[0], UINT16_C(0x0123), kMaxSize) == NULL);\n\t\tEATEST_VERIFY(itI16 == (vI16.begin() + kMaxSize));\n\t\tEA::StdC::Memset16(&vI16[0], 0, kMaxSize);\n\t}\n\n\n\t{\n\t\t// InputIterator find(InputIterator first, InputIterator last, const T& value)\n\t\tvector<int> intArray;\n\t\tintArray.push_back(0);\n\t\tintArray.push_back(1);\n\t\tintArray.push_back(2);\n\t\tintArray.push_back(3);\n\n\t\tvector<int>::iterator it = find(intArray.begin(), intArray.end(), 2);\n\t\tEATEST_VERIFY(it == (intArray.begin() + 2));\n\t\tEATEST_VERIFY(*it == 2);\n\n\t\tit = find(intArray.begin(), intArray.end(), 7);\n\t\tEATEST_VERIFY(it == intArray.end());\n\t}\n\n\n\t{\n\t\t// InputIterator find_if(InputIterator first, InputIterator last, Predicate predicate)\n\t\t// InputIterator find_if_not(InputIterator first, InputIterator last, Predicate predicate)\n\n\t\tint intArray[] = { 3, 2, 6, 5, 4, 1, 2, 4, 5, 4, 1, 2 };\n\n\t\t// Find an item which is equal to 1.\n\t\tint* pInt = find_if(intArray, intArray, [](int i) { return i == 1; }); // No-op\n\t\tEATEST_VERIFY(pInt == (intArray));\n\t\tpInt = find_if(intArray, intArray + 12, [](int i) { return i == 1; });\n\t\tEATEST_VERIFY(pInt == (intArray + 5));\n\t\tpInt = find_if(intArray, intArray + 12, [](int i) { return i == 99; });\n\t\tEATEST_VERIFY(pInt == (intArray + 12));\n\n\t\tpInt = find_if_not(intArray, intArray + 12, [](int i) { return i == 3; });\n\t\tEATEST_VERIFY(pInt == (intArray + 1));\n\n\t\t// Find an item which is equal to 1.\n\t\tTestObject toArray[] = { TestObject(4), TestObject(3), TestObject(2), TestObject(1), TestObject(2), TestObject(5) };\n\n\t\tTestObject* pTO = find_if(toArray, toArray, [](const TestObject& lhs) { return lhs == TestObject(1); }); // No-op\n\t\tEATEST_VERIFY(pTO == (toArray));\n\t\tpTO = find_if(toArray, toArray + 6, [](const TestObject& lhs) { return lhs == TestObject(1); });\n\t\tEATEST_VERIFY(pTO == (toArray + 3));\n\t\tpTO = find_if(toArray, toArray + 6, [](const TestObject& lhs) { return lhs == TestObject(99); });\n\t\tEATEST_VERIFY(pTO == (toArray + 6));\n\n\t\tpTO = find_if_not(toArray, toArray + 6, [](const TestObject& lhs) { return lhs == TestObject(4); });\n\t\tEATEST_VERIFY(pTO == (toArray + 1));\n\n\t\t// Find an item which is equal to 1.\n\t\tslist<int> intList;\n\t\tintList.push_front(4);\n\t\tintList.push_front(3);\n\t\tintList.push_front(2);\n\t\tintList.push_front(1);\n\t\tintList.push_front(2);\n\t\tintList.push_front(5);\n\n\t\t// The list is now: { 5, 2, 1, 2, 3, 4 }\n\t\tslist<int>::iterator it = find_if(intList.begin(), intList.begin(), [](int i) { return i == 1; }); // No-op\n\t\tEATEST_VERIFY(it == intList.begin());\n\t\tit = find_if(intList.begin(), intList.end(), [](int i) { return i == 1; });\n\t\tEATEST_VERIFY(*it == 1);\n\t\tit = find_if(intList.begin(), intList.end(), [](int i) { return i == 99; });\n\t\tEATEST_VERIFY(it == intList.end());\n\n\t\tit = find_if_not(intList.begin(), intList.end(), [](int i) { return i == 5; });\n\t\tEATEST_VERIFY(*it == 2);\n\t}\n\n\n\t{\n\t\t// ForwardIterator1 find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)\n\t\t// ForwardIterator1 find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate predicate)\n\n\t\tint intArray1[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\t\tint intArray2[3]  = { 7, 6, 5 };\n\n\t\tint* pInt = find_first_of(intArray1, intArray1, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_first_of(intArray1, intArray1 + 10, intArray2, intArray2);\n\t\tEATEST_VERIFY(pInt == intArray1 + 10);\n\t\tpInt = find_first_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1 + 5);\n\n\t\tpInt = find_first_of(intArray1, intArray1, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_first_of(intArray1, intArray1 + 10, intArray2, intArray2, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 10);\n\t\tpInt = find_first_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 5);\n\t}\n\n\n\t{\n\t\t// ForwardIterator1 find_first_not_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)\n\t\t// ForwardIterator1 find_first_not_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2), BinaryPredicate predicate)\n\n\t\tint intArray1[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\t\tint intArray2[3]  = { 0, 1, 2 };\n\n\t\tint* pInt = find_first_not_of(intArray1, intArray1, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_first_not_of(intArray1, intArray1 + 10, intArray2, intArray2);\n\t\tEATEST_VERIFY(pInt == intArray1 + 0);\n\t\tpInt = find_first_not_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1 + 3);\n\n\t\tpInt = find_first_not_of(intArray1, intArray1, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_first_not_of(intArray1, intArray1 + 10, intArray2, intArray2, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 0);\n\t\tpInt = find_first_not_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 3);\n\t}\n\n\n\t{\n\t\t// ForwardIterator1 find_last_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)\n\t\t// ForwardIterator1 find_last_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate predicate)\n\n\t\tint intArray1[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\t\tint intArray2[3]  = { 3, 4, 5 };\n\n\t\tint* pInt = find_last_of(intArray1, intArray1, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_last_of(intArray1, intArray1 + 10, intArray2, intArray2);\n\t\tEATEST_VERIFY(pInt == intArray1 + 10);\n\t\tpInt = find_last_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1 + 5);\n\n\t\tpInt = find_last_of(intArray1, intArray1, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_last_of(intArray1, intArray1 + 10, intArray2, intArray2, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 10);\n\t\tpInt = find_last_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 5);\n\t}\n\n\n\t{\n\t\t// ForwardIterator1 find_last_not_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)\n\t\t// ForwardIterator1 find_last_not_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2), BinaryPredicate predicate)\n\n\t\tint intArray1[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\t\tint intArray2[3]  = { 7, 8, 9 };\n\n\t\tint* pInt = find_last_not_of(intArray1, intArray1, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_last_not_of(intArray1, intArray1 + 10, intArray2, intArray2);\n\t\tEATEST_VERIFY(pInt == intArray1 + 10);\n\t\tpInt = find_last_not_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3);\n\t\tEATEST_VERIFY(pInt == intArray1 + 6);\n\n\t\tpInt = find_last_not_of(intArray1, intArray1, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tpInt = find_last_not_of(intArray1, intArray1 + 10, intArray2, intArray2, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 10);\n\t\tpInt = find_last_not_of(intArray1, intArray1 + 10, intArray2, intArray2 + 3, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray1 + 6);\n\t}\n\n\n\t{\n\t\t// Function for_each(InputIterator first, InputIterator last, Function function)\n\n\t\tdeque<int> intDeque(1000);\n\t\tSetIncrementalIntegers<int> sii; // We define this class at the top of this file.\n\t\teastl_size_t i;\n\n\t\tsii = for_each(intDeque.begin(), intDeque.end(), sii);\n\t\tEATEST_VERIFY(sii.mX == 1000);\n\t\tfor(i = 0; i < 1000; i++)\n\t\t{\n\t\t\tif(intDeque[i] != (int)i)\n\t\t\t\tbreak;\n\t\t}\n\t\tEATEST_VERIFY(i == 1000);\n\n\n\t\tarray<int, 1000> intArray;\n\t\tsii.reset();\n\n\t\tsii = for_each(intArray.begin(), intArray.end(), sii);\n\t\tEATEST_VERIFY(sii.mX == 1000);\n\t\tfor(i = 0; i < 1000; i++)\n\t\t{\n\t\t\tif(intArray[i] != (int)i)\n\t\t\t\tbreak;\n\t\t}\n\t\tEATEST_VERIFY(i == 1000);\n\t}\n\n\t// for_each_n\n\t{\n\t\t{\n\t\t\tvector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tfor_each_n(v.begin(), 5, [](auto& e) { e += 10; });\n\n\t\t\tvector<int> expected = {10, 11, 12, 13, 14, 5, 6, 7, 8, 9};\n\t\t\tEATEST_VERIFY(v == expected);\n\t\t}\n\n\t\t// verify lambda can return a result that is ignored.\n\t\t{\n\t\t\tvector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tfor_each_n(v.begin(), 5, [](auto& e) { e += 10; return 42; });\n\n\t\t\tvector<int> expected = {10, 11, 12, 13, 14, 5, 6, 7, 8, 9};\n\t\t\tEATEST_VERIFY(v == expected);\n\t\t}\n\t}\n\n\t{\n\t\t// void generate(ForwardIterator first, ForwardIterator last, Generator generator)\n\t\t// OutputIterator generate_n(OutputIterator first, Size n, Generator generator)\n\n\t\tdeque<int> intDeque((eastl_size_t)rng.RandRange(100, 1000));\n\t\tGenerateIncrementalIntegers<int> gii(0); // We define this class at the top of this file.\n\t\tint i, iEnd;\n\n\t\tgenerate(intDeque.begin(), intDeque.end(), gii);\n\t\tfor(i = 0, iEnd = (int)intDeque.size(); i < iEnd; i++)\n\t\t{\n\t\t\tif(intDeque[(eastl_size_t)i] != i)\n\t\t\t\tbreak;\n\t\t}\n\t\tEATEST_VERIFY(i == iEnd);\n\n\n\t\tarray<int, 1000> intArray;\n\t\tgii.reset(0);\n\n\t\tgenerate(intArray.begin(), intArray.end(), gii);\n\t\tfor(i = 0; i < 1000; i++)\n\t\t{\n\t\t\tif(intArray[(eastl_size_t)i] != i)\n\t\t\t\tbreak;\n\t\t}\n\t\tEATEST_VERIFY(i == 1000);\n\t}\n\n\n\t{\n\t\t// OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unaryOperation)\n\n\t\tdeque<int> intDeque((eastl_size_t)rng.RandRange(1, 1000));\n\t\tint i, iEnd;\n\n\t\tfor(i = 0, iEnd = (int)intDeque.size(); i < iEnd; i++)\n\t\t\tintDeque[(eastl_size_t)i] = 1;\n\t\ttransform(intDeque.begin(), intDeque.begin(), intDeque.begin(), negate<int>()); // No-op\n\t\tEATEST_VERIFY(intDeque[0] == 1); // Verify nothing happened\n\t\ttransform(intDeque.begin(), intDeque.end(), intDeque.begin(), negate<int>());\n\t\tfor(i = 0, iEnd = (int)intDeque.size(); i < iEnd; i++)\n\t\t{\n\t\t\tif(intDeque[(eastl_size_t)i] != -1)\n\t\t\t\tbreak;\n\t\t}\n\t\tEATEST_VERIFY(i == iEnd);\n\n\n\t\tslist<TestObject> sList;\n\t\tfor(i = 0, iEnd = rng.RandRange(1, 100); i < iEnd; i++)\n\t\t\tsList.push_front(TestObject(1));\n\t\ttransform(sList.begin(), sList.begin(), sList.begin(), TestObjectNegate()); // No-op\n\t\tEATEST_VERIFY(sList.front() == TestObject(1));\n\t\ttransform(sList.begin(), sList.end(), sList.begin(), TestObjectNegate()); // TestObjectNegate is a custom function we define for this test.\n\t\tslist<TestObject>::iterator it = sList.begin();\n\t\tfor(; it != sList.end(); it++)\n\t\t{\n\t\t\tif(!(*it == TestObject(-1)))\n\t\t\t\tbreak;\n\t\t}\n\t\tEATEST_VERIFY(it == sList.end());\n\t}\n\n\n\t{\n\t\t// OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binaryOperation)\n\n\t\tint intArray1[12] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 };\n\t\tint intArray2[12] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };\n\n\t\tint* pInt = transform(intArray1, intArray1, intArray2, intArray2, plus<int>());\n\t\tEATEST_VERIFY(pInt == intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"transform\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"transform\", 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1));\n\n\t\tpInt = transform(intArray1, intArray1 + 12, intArray2, intArray2, plus<int>());\n\t\tEATEST_VERIFY(pInt == intArray2 + 12);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"transform\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"transform\", 3, 3, 4, 4, 3, 3, 4, 4, 3, 3, 4, 4, -1));\n\t}\n\n\n\t{\n\t\t// bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)\n\t\t// bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate predicate)\n\n\t\tvector<eastl_size_t> intArray(100);\n\t\tlist<eastl_size_t>   intList(100);\n\t\tgenerate(intArray.begin(), intArray.end(), rng);\n\t\tcopy(intArray.begin(), intArray.end(), intList.begin());\n\n\t\tbool b = equal(intArray.begin(), intArray.begin(), (eastl_size_t*)NULL);\n\t\tEATEST_VERIFY(b);\n\t\tb = equal(intArray.begin(), intArray.end(), intList.begin());\n\t\tEATEST_VERIFY(b);\n\t\tintArray[50] += 1;\n\t\tb = equal(intArray.begin(), intArray.end(), intList.begin());\n\t\tEATEST_VERIFY(!b);\n\n\t\tintArray[50] -= 1; // resulttore its original value so the containers are equal again.\n\t\tb = equal(intArray.begin(), intArray.begin(), (eastl_size_t*)NULL, equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(b);\n\t\tb = equal(intArray.begin(), intArray.end(), intList.begin(), equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(b);\n\t\tintArray[50] += 1;\n\t\tb = equal(intArray.begin(), intArray.end(), intList.begin(), equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(!b);\n\t}\n\n\n\t{\n\t\t// bool identical(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)\n\t\t// bool identical(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate predicate)\n\n\t\tvector<eastl_size_t> intArray(100);\n\t\tlist<eastl_size_t>   intList(100);\n\t\tgenerate(intArray.begin(), intArray.end(), rng);\n\t\tcopy(intArray.begin(), intArray.end(), intList.begin());\n\n\n\t\tbool b = identical(intArray.begin(), intArray.begin(), (eastl_size_t*)NULL, (eastl_size_t*)NULL);\n\t\tEATEST_VERIFY(b);\n\t\tb = identical(intArray.begin(), intArray.end(), intList.begin(), intList.end());\n\t\tEATEST_VERIFY(b);\n\t\tb = identical(intArray.begin(), intArray.end() - 10, intList.begin(), intList.end());\n\t\tEATEST_VERIFY(!b);\n\t\tb = identical(intList.begin(), intList.end(), intArray.begin() + 10, intArray.end());\n\t\tEATEST_VERIFY(!b);\n\t\tintArray[50] += 1;\n\t\tb = identical(intArray.begin(), intArray.end(), intList.begin(), intList.end());\n\t\tEATEST_VERIFY(!b);\n\n\n\t\tintArray[50] -= 1; // resulttore its original value so the containers are equal again.\n\t\tb = identical(intArray.begin(), intArray.begin(), (eastl_size_t*)NULL, (eastl_size_t*)NULL, equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(b);\n\t\tb = identical(intArray.begin(), intArray.end(), intList.begin(), intList.end(), equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(b);\n\t\tb = identical(intArray.begin(), intArray.end() - 10, intList.begin(), intList.end(), equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(!b);\n\t\tb = identical(intList.begin(), intList.end(), intArray.begin() + 10, intArray.end(), equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(!b);\n\t\tintArray[50] += 1;\n\t\tb = identical(intArray.begin(), intArray.end(), intList.begin(), intList.end(), equal_to<eastl_size_t>());\n\t\tEATEST_VERIFY(!b);\n\t}\n\n\n\t{\n\t\t// bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)\n\t\t// bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare compare)\n\n\t\tint intArray1[6] = { 0, 1, 2, 3, 4, 5 };\n\t\tint intArray2[6] = { 0, 1, 2, 3, 4, 6 };\n\t\tint intArray3[5] = { 0, 1, 2, 3, 4    };\n\n\t\tbool b = lexicographical_compare(intArray1, intArray1, intArray2, intArray2); // Test empty range.\n\t\tEATEST_VERIFY(!b);\n\t\tb = lexicographical_compare(intArray1, intArray1 + 6, intArray2, intArray2 + 6);\n\t\tEATEST_VERIFY( b);\n\t\tb = lexicographical_compare(intArray2, intArray2 + 6, intArray1, intArray1 + 6);\n\t\tEATEST_VERIFY(!b);\n\t\tb = lexicographical_compare(intArray1, intArray1 + 6, intArray3, intArray3 + 5);\n\t\tEATEST_VERIFY(!b);\n\n\t\tb = lexicographical_compare(intArray1, intArray1, intArray2, intArray2, greater<int>()); // Test empty range.\n\t\tEATEST_VERIFY(!b);\n\t\tb = lexicographical_compare(intArray1, intArray1 + 6, intArray2, intArray2 + 6, greater<int>());\n\t\tEATEST_VERIFY(!b);\n\t\tb = lexicographical_compare(intArray2, intArray2 + 6, intArray1, intArray1 + 6, greater<int>());\n\t\tEATEST_VERIFY( b);\n\t\tb = lexicographical_compare(intArray3, intArray3 + 5, intArray1, intArray1 + 6, less<int>());\n\t\tEATEST_VERIFY( b);\n\t}\n\n\t{\n\t\t// bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)\n\t\t// bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare compare)\n\n\t\tchar* cstr = nullptr;\n\n\t\tbool b = lexicographical_compare(cstr, cstr, cstr, cstr);\n\t\tEATEST_VERIFY(!b);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{\n\t\t// <compairison_category> lexicographical_compare_three_way(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare compare)\n\n\t\tint intArray1[6] = {0, 1, 2, 3, 4, 5};\n\t\tint intArray2[6] = {0, 1, 2, 3, 4, 6};\n\t\tint intArray3[5] = {0, 1, 2, 3, 4};\n\t\tint intArray4[5] = {4, 3, 2, 1, 0};\n\n\t\t// strong ordering\n\t\tauto compare_strong = [](int first, int second)\n\t\t{\n\t\t\treturn (first < second) ? std::strong_ordering::less :\n\t\t\t\t(first > second) ? std::strong_ordering::greater :\n\t\t\t\tstd::strong_ordering::equal;\n\t\t};\n\n\t\tauto b = lexicographical_compare_three_way(intArray1, intArray1 + 6, intArray2, intArray2 + 6, compare_strong);\n\t\tEATEST_VERIFY(b == std::strong_ordering::less);\n\t\tb = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray2, intArray2 + 6, compare_strong);\n\t\tEATEST_VERIFY(b == std::strong_ordering::less);\n\t\tb = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray2, intArray2 + 6, synth_three_way{});\n\t\tEATEST_VERIFY(b == std::strong_ordering::less);\n\n\t\tb = lexicographical_compare_three_way(intArray2, intArray2 + 6, intArray1, intArray1 + 6, compare_strong);\n\t\tEATEST_VERIFY(b == std::strong_ordering::greater);\n\t\tb = lexicographical_compare_three_way(intArray2, intArray2 + 6, intArray1, intArray1 + 6, synth_three_way{});\n\t\tEATEST_VERIFY(b == std::strong_ordering::greater);\n\n\t\tb = lexicographical_compare_three_way(intArray1, intArray1 + 6, intArray3, intArray3 + 5, compare_strong);\n\t\tEATEST_VERIFY(b == std::strong_ordering::greater);\n\t\tb = lexicographical_compare_three_way(intArray1, intArray1 + 6, intArray3, intArray3 + 5, synth_three_way{});\n\t\tEATEST_VERIFY(b == std::strong_ordering::greater);\n\n\t\tb = lexicographical_compare_three_way(intArray1, intArray1, intArray2, intArray2, compare_strong); // Test empty range.\n\t\tEATEST_VERIFY(b == std::strong_ordering::equal);\n\t\tb = lexicographical_compare_three_way(intArray1, intArray1, intArray2, intArray2, synth_three_way{}); // Test empty range.\n\t\tEATEST_VERIFY(b == std::strong_ordering::equal);\n\n\t\t// weak ordering\n\t\tauto compare_weak = [](int first, int second)\n\t\t{\n\t\t    return (first < second) ? std::weak_ordering::less :\n\t\t\t    (first > second) ? std::weak_ordering::greater :\n\t\t\t    std::weak_ordering::equivalent;\n\t\t};\n\n\t\tauto c = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray4, intArray4 + 5, compare_weak);\n\t\tEATEST_VERIFY(c == std::weak_ordering::less);\n\t\tc = lexicographical_compare_three_way(intArray4, intArray4 + 5, intArray3, intArray3 + 5, compare_weak);\n\t\tEATEST_VERIFY(c == std::weak_ordering::greater);\n\t\tc = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray4, intArray4 + 5, synth_three_way{});\n\t\tEATEST_VERIFY(c == std::weak_ordering::less);\n\t\tc = lexicographical_compare_three_way(intArray4, intArray4 + 5, intArray3, intArray3 + 5, synth_three_way{});\n\t\tEATEST_VERIFY(c == std::weak_ordering::greater);\n\t}\n\n\t{\n\t\tEATEST_VERIFY(synth_three_way{}(1, 1) == std::strong_ordering::equal);\n\t\tEATEST_VERIFY(synth_three_way{}(2, 1) == std::strong_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(1, 2) == std::strong_ordering::less);\n\n\t\tstruct weak_struct\n\t\t{\n\t\t\tint val;\n\t\t\tinline std::weak_ordering operator<=>(const weak_struct& b) const\n\t\t\t{\n\t\t\t\treturn val <=> b.val;\n\t\t\t}\n\t\t};\n\n\t\tEATEST_VERIFY(synth_three_way{}(weak_struct{1}, weak_struct{2}) == std::weak_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_struct{2}, weak_struct{1}) == std::weak_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_struct{1}, weak_struct{1}) == std::weak_ordering::equivalent);\n\t}\n#endif\n\n\t{\n\t\t// ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\n\t\tint i;\n\n\t\tint* pInt = lower_bound((int*)NULL, (int*)NULL, 100);\n\t\tEATEST_VERIFY(pInt == NULL);\n\n\n\t\tfor(i = 0; i < 20 + (gEASTL_TestLevel * 20); i++)\n\t\t{\n\t\t\tdeque<int> intDeque((eastl_size_t)rng.RandRange(1, 500));\n\n\t\t\tfor(int j = 0, jEnd = (int)intDeque.size(); j < jEnd; j++)\n\t\t\t\tintDeque[(eastl_size_t)j] = (int)rng.RandLimit(jEnd / 2); // This will result in both gaps and duplications.\n\n\t\t\tfor(int k = 0, kEnd = (int)intDeque.size(); k < kEnd; k++)\n\t\t\t{\n\t\t\t\tdeque<int>::iterator it = lower_bound(intDeque.begin(), intDeque.end(), k);\n\n\t\t\t\tif(it != intDeque.begin())\n\t\t\t\t\tEATEST_VERIFY(*(it - 1) < k);\n\n\t\t\t\tif(it != intDeque.end())\n\t\t\t\t\tEATEST_VERIFY((k < *it) || !(*it < k)); // Verify tha k <= *it by using only operator<\n\t\t\t}\n\t\t}\n\n\n\t\tfor(i = 0; i < 20 + (gEASTL_TestLevel * 20); i++)\n\t\t{\n\t\t\tlist<TestObject> toList;\n\t\t\tint              nSize = (int)rng.RandRange(1, 500);\n\n\t\t\tfor(int j = 0, jEnd = nSize; j < jEnd; j++)\n\t\t\t\ttoList.push_back(TestObject((int)rng.RandLimit(jEnd / 2))); // This will result in both gaps and duplications.\n\n\t\t\tfor(int k = 0; k < nSize; k++)\n\t\t\t{\n\t\t\t\tTestObject toK(k);\n\t\t\t\tlist<TestObject>::iterator it = lower_bound(toList.begin(), toList.end(), toK);\n\n\t\t\t\tif(it != toList.begin())\n\t\t\t\t{\n\t\t\t\t\t--it;\n\t\t\t\t\tEATEST_VERIFY(*it < toK);\n\t\t\t\t\t++it;\n\t\t\t\t}\n\n\t\t\t\tif(it != toList.end())\n\t\t\t\t\tEATEST_VERIFY((toK < *it) || !(*it < toK)); // Verify tha k <= *it by using only operator<\n\t\t\t}\n\t\t}\n\t}\n\n\n\t{\n\t\t// ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\n\t\tint i;\n\n\t\tint* pInt = upper_bound((int*)NULL, (int*)NULL, 100);\n\t\tEATEST_VERIFY(pInt == NULL);\n\n\n\t\tfor(i = 0; i < 20 + (gEASTL_TestLevel * 20); i++)\n\t\t{\n\t\t\tdeque<int> intDeque((eastl_size_t)rng.RandRange(1, 500));\n\n\t\t\tfor(eastl_size_t j = 0, jEnd = intDeque.size(); j < jEnd; j++)\n\t\t\t\tintDeque[j] = (int)rng.RandLimit((uint32_t)jEnd / 2); // This will result in both gaps and duplications.\n\n\t\t\tfor(int k = 0, kEnd = (int)intDeque.size(); k < kEnd; k++)\n\t\t\t{\n\t\t\t\tdeque<int>::iterator it = upper_bound(intDeque.begin(), intDeque.end(), k);\n\n\t\t\t\tif(it != intDeque.begin())\n\t\t\t\t\tEATEST_VERIFY((*(it - 1) < k) || !(k < *(it - 1))); // Verify tha *it <= k by using only operator<\n\n\t\t\t\tif(it != intDeque.end())\n\t\t\t\t\tEATEST_VERIFY(k < *it);\n\t\t\t}\n\t\t}\n\n\n\t\tfor(i = 0; i < 20 + (gEASTL_TestLevel * 20); i++)\n\t\t{\n\t\t\tlist<TestObject> toList;\n\t\t\tint              nSize = (int)rng.RandRange(1, 500);\n\n\t\t\tfor(int j = 0, jEnd = nSize; j < jEnd; j++)\n\t\t\t\ttoList.push_back(TestObject((int)rng.RandLimit(jEnd / 2))); // This will result in both gaps and duplications.\n\n\t\t\tfor(int k = 0; k < nSize; k++)\n\t\t\t{\n\t\t\t\tTestObject toK(k);\n\t\t\t\tlist<TestObject>::iterator it = upper_bound(toList.begin(), toList.end(), toK);\n\n\t\t\t\tif(it != toList.begin())\n\t\t\t\t{\n\t\t\t\t\t--it;\n\t\t\t\t\tEATEST_VERIFY((*it < toK) || !(toK < *it)); // Verify tha *it <= k by using only operator<\n\t\t\t\t\t++it;\n\t\t\t\t}\n\n\t\t\t\tif(it != toList.end())\n\t\t\t\t\tEATEST_VERIFY(toK < *it);\n\t\t\t}\n\t\t}\n\t}\n\n\n\t{\n\t\t// pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\n\t\tint i;\n\n\t\tpair<int*, int*> pInt = equal_range((int*)NULL, (int*)NULL, 100);\n\t\tEATEST_VERIFY(pInt.first  == NULL);\n\t\tEATEST_VERIFY(pInt.second == NULL);\n\n\n\t\tfor(i = 0; i < 20 + (gEASTL_TestLevel * 20); i++)\n\t\t{\n\t\t\tdeque<int> intDeque((eastl_size_t)rng.RandRange(1, 500));\n\n\t\t\tfor(int j = 0, jEnd = (int)intDeque.size(); j < jEnd; j++)\n\t\t\t\tintDeque[(eastl_size_t)j] = (int)rng.RandLimit(jEnd / 2); // This will result in both gaps and duplications.\n\n\t\t\tfor(int k = 0, kEnd = (int)intDeque.size(); k < kEnd; k++)\n\t\t\t{\n\t\t\t\tpair<deque<int>::iterator, deque<int>::iterator> it = equal_range(intDeque.begin(), intDeque.end(), k);\n\n\t\t\t\t// Test it.first as lower_bound.\n\t\t\t\tif(it.first != intDeque.begin())\n\t\t\t\t\tEATEST_VERIFY(*(it.first - 1) < k);\n\n\t\t\t\tif(it.first != intDeque.end())\n\t\t\t\t\tEATEST_VERIFY((k < *it.first) || !(*it.first < k)); // Verify tha k <= *it by using only operator<\n\n\t\t\t\t// Test it.second as upper_bound.\n\t\t\t\tif(it.second != intDeque.begin())\n\t\t\t\t\tEATEST_VERIFY((*(it.second - 1) < k) || !(k < *(it.second - 1))); // Verify tha *it <= k by using only operator<\n\n\t\t\t\tif(it.second != intDeque.end())\n\t\t\t\t\tEATEST_VERIFY(k < *it.second);\n\t\t\t}\n\t\t}\n\n\n\t\tfor(i = 0; i < 20 + (gEASTL_TestLevel * 20); i++)\n\t\t{\n\t\t\tlist<TestObject> toList;\n\t\t\tint              nSize = (int)rng.RandRange(1, 500);\n\n\t\t\tfor(int j = 0, jEnd = nSize; j < jEnd; j++)\n\t\t\t\ttoList.push_back(TestObject((int)rng.RandLimit(jEnd / 2))); // This will result in both gaps and duplications.\n\n\t\t\tfor(int k = 0; k < nSize; k++)\n\t\t\t{\n\t\t\t\tTestObject toK(k);\n\t\t\t\tpair<list<TestObject>::iterator, list<TestObject>::iterator> it = equal_range(toList.begin(), toList.end(), toK);\n\n\t\t\t\t// Test it.first as lower_bound\n\t\t\t\tif(it.first != toList.begin())\n\t\t\t\t{\n\t\t\t\t\t--it.first;\n\t\t\t\t\tEATEST_VERIFY(*it.first < toK);\n\t\t\t\t\t++it.first;\n\t\t\t\t}\n\n\t\t\t\tif(it.first != toList.end())\n\t\t\t\t\tEATEST_VERIFY((toK < *it.first) || !(*it.first < toK)); // Verify tha k <= *it by using only operator<\n\n\t\t\t\t// Test it.second as upper_bound\n\t\t\t\tif(it.second != toList.begin())\n\t\t\t\t{\n\t\t\t\t\t--it.second;\n\t\t\t\t\tEATEST_VERIFY((*it.second < toK) || !(toK < *it.second)); // Verify tha *it <= k by using only operator<\n\t\t\t\t\t++it.second;\n\t\t\t\t}\n\n\t\t\t\tif(it.second != toList.end())\n\t\t\t\t\tEATEST_VERIFY(toK < *it.second);\n\t\t\t}\n\t\t}\n\t}\n\n\n\t{\n\t\t// void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value)\n\t\t// void replace_if(ForwardIterator first, ForwardIterator last, Predicate predicate, const T& new_value)\n\n\t\tint intArray[8] = { 0, 3, 2, 7, 5, 4, 5, 3, };\n\n\t\t// Convert 3s to 99s.\n\t\treplace(intArray, intArray,     3, 99); // No-op\n\t\tEATEST_VERIFY((intArray[1] == 3) && (intArray[7] == 3));\n\t\treplace(intArray, intArray + 8, 3, 99); // No-op\n\t\tEATEST_VERIFY((intArray[1] == 99) && (intArray[7] == 99));\n\n\t\t// Convert 99s to 88s.\n\t\treplace_if(intArray, intArray, [](int i) { return i == 99; }, 88); // No-op\n\t\tEATEST_VERIFY((intArray[1] == 99) && (intArray[7] == 99));\n\t\treplace_if(intArray, intArray + 8, [](int i) { return i == 99; }, 88);\n\t\tEATEST_VERIFY((intArray[1] == 88) && (intArray[7] == 88));\n\n\n\t\tslist<TestObject> toList;\n\t\tslist<TestObject>::iterator it;\n\t\ttoList.push_front(TestObject(3));\n\t\ttoList.push_front(TestObject(5));\n\t\ttoList.push_front(TestObject(4));\n\t\ttoList.push_front(TestObject(5));\n\t\ttoList.push_front(TestObject(7));\n\t\ttoList.push_front(TestObject(2));\n\t\ttoList.push_front(TestObject(3));\n\t\ttoList.push_front(TestObject(0));\n\n\t\t// Convert 3s to 99s.\n\t\treplace(toList.begin(), toList.begin(), TestObject(3), TestObject(99)); // No-op\n\t\tit = toList.begin();\n\t\tadvance(it, 1);\n\t\tEATEST_VERIFY(*it == TestObject(3));\n\t\tadvance(it, 6);\n\t\tEATEST_VERIFY(*it == TestObject(3));\n\t\treplace(toList.begin(), toList.end(), TestObject(3), TestObject(99));\n\t\tit = toList.begin();\n\t\tadvance(it, 1);\n\t\tEATEST_VERIFY(*it == TestObject(99));\n\t\tadvance(it, 6);\n\t\tEATEST_VERIFY(*it == TestObject(99));\n\n\t\t// Convert 99s to 88s.\n\t\treplace_if(toList.begin(), toList.begin(), [](const TestObject& lhs) { return lhs == TestObject(99); }, TestObject(88)); // No-op\n\t\tit = toList.begin();\n\t\tadvance(it, 1);\n\t\tEATEST_VERIFY(*it == TestObject(99));\n\t\tadvance(it, 6);\n\t\tEATEST_VERIFY(*it == TestObject(99));\n\t\treplace_if(toList.begin(), toList.end(), [](const TestObject& lhs) { return lhs == TestObject(99); }, TestObject(88));\n\t\tit = toList.begin();\n\t\tadvance(it, 1);\n\t\tEATEST_VERIFY(*it == TestObject(88));\n\t\tadvance(it, 6);\n\t\tEATEST_VERIFY(*it == TestObject(88));\n\t}\n\n\n\t{\n\t\t// OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)\n\t\t// OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate)\n\n\t\tint intArray1[12] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 };\n\t\tint intArray2[12] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };\n\n\t\tint* pInt = remove_copy(intArray1, intArray1, intArray2, 1); // No-op\n\t\tEATEST_VERIFY(pInt == intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"remove_copy\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"remove_copy\", 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1));\n\n\t\tpInt = remove_copy(intArray1, intArray1 + 12, intArray2, 1);\n\t\tEATEST_VERIFY(pInt == intArray2 + 6);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"remove_copy\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"remove_copy\", 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, -1));\n\n\n\t\tpInt = remove_copy_if(intArray1, intArray1, intArray2, [](int i) { return i == 0; }); // No-op\n\t\tEATEST_VERIFY(pInt == intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"remove_copy_if\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"remove_copy_if\", 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, -1));\n\n\t\tpInt = remove_copy_if(intArray1, intArray1 + 12, intArray2, [](int i) { return i == 0; });\n\t\tEATEST_VERIFY(pInt == intArray2 + 6);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"remove_copy_if\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"remove_copy_if\", 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, -1));\n\t}\n\n\n\t{\n\t\t// ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate predicate)\n\n\t\tint intArray1[12] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 };\n\t\tint intArray2[12] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };\n\n\t\tint* pInt = remove(intArray1, intArray1, 1);\n\t\tEATEST_VERIFY(pInt == intArray1);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"remove\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tpInt = remove(intArray1, intArray1 + 12, 1);\n\t\tEATEST_VERIFY(pInt == intArray1 + 6);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"remove\", 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\n\t\tpInt = remove_if(intArray2, intArray2, [](int i) { return i == 1; });\n\t\tEATEST_VERIFY(pInt == intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"remove\", 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1));\n\t\tpInt = remove_if(intArray2, intArray2 + 12, [](int i) { return i == 1; });\n\t\tEATEST_VERIFY(pInt == intArray2 + 12);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"remove\", 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1));\n\t}\n\n\t{\n\t\t// ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// OutputIterator  remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)\n\n\t\t// We use the TestObject to explictly check how many times move assignment and copy assignment has been performed\n\t\tTestObject::Reset();\n\t\tTestObject dataArray1[5] { TestObject(1), TestObject(2), TestObject(3), TestObject(4), TestObject(5) };\n\t\tTestObject dataArray2[5] { TestObject(1), TestObject(2), TestObject(3), TestObject(4), TestObject(5) };\n\n\t\t// remove() should invoke eastl::move, leaving our last element swapped with our removed element (3)\n\t\t// { 1 , 2 , 4 , 5 , 3 }\n\t\tTestObject* end1 = remove(dataArray1, dataArray1 + 5, TestObject(3));\n\t\tEATEST_VERIFY(end1 == dataArray1 + 4);\n\t\tEATEST_VERIFY(TestObject::sTOMoveAssignCount == 2); // we move 4 into 3, then 5 into 4\n\t\tEATEST_VERIFY(TestObject::sTOCopyAssignCount == 0); // no copies\n\t\tEATEST_VERIFY(dataArray1[4].mX == 3);\n\n\t\t// remove_copy() should use copy assignment, leaving our last two elements with a duplicate value of (5)\n\t\t// { 1 , 2 , 4 , 5 , 5 }\n\t\tTestObject* target = find(dataArray2, dataArray2 + 5, TestObject(3));\n\t\tTestObject* end2 = remove_copy(target + 1, dataArray2 + 5, target, TestObject(3));\n\t\tEATEST_VERIFY(end2 == dataArray2 + 4);\n\t\tEATEST_VERIFY(TestObject::sTOMoveAssignCount == 2); // the two moves from the previous test\n\t\tEATEST_VERIFY(TestObject::sTOCopyAssignCount == 2); // we copy 4 into 3, and then 5 into 4\n\t\tEATEST_VERIFY(dataArray2[4].mX == 5);\n\t}\n\n\t{\n\t\t// ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// OutputIterator  remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, const T& value)\n\n\t\t// We use the TestObject to explictly check how many times move assignment and copy assignment has been performed\n\t\tTestObject::Reset();\n\t\tTestObject dataArray1[5] { TestObject(1), TestObject(2), TestObject(3), TestObject(4), TestObject(5) };\n\t\tTestObject dataArray2[5] { TestObject(1), TestObject(2), TestObject(3), TestObject(4), TestObject(5) };\n\n\t\t// remove_if() should invoke eastl::move, leaving our last element swapped with our removed element (3)\n\t\t// { 1 , 2 , 4 , 5 , 3 }\n\t\tTestObject* end1 = remove_if(dataArray1, dataArray1 + 5, [](const TestObject& t) { return t.mX == 3; });\n\t\tEATEST_VERIFY(end1 == dataArray1 + 4);\n\t\tEATEST_VERIFY(TestObject::sTOMoveAssignCount == 2); // we move 4 into 3, then 5 into 4\n\t\tEATEST_VERIFY(TestObject::sTOCopyAssignCount == 0); // no copies\n\t\tEATEST_VERIFY(dataArray1[4].mX == 3);\n\n\t\t// remove_copy_if() should use copy assignment, leaving our last two elements with a duplicate value of (5)\n\t\t// { 1 , 2 , 4 , 5 , 5 }\n\t\tTestObject* target = find(dataArray2, dataArray2 + 5, TestObject(3));\n\t\tTestObject* end2 = remove_copy_if(target + 1, dataArray2 + 5, target, [](const TestObject& t) { return t.mX == 3; });\n\t\tEATEST_VERIFY(end2 == dataArray2 + 4);\n\t\tEATEST_VERIFY(TestObject::sTOMoveAssignCount == 2); // the two moves from the previous test\n\t\tEATEST_VERIFY(TestObject::sTOCopyAssignCount == 2); // we copy 4 into 3, and then 5 into 4\n\t\tEATEST_VERIFY(dataArray2[4].mX == 5);\n\t}\n\n\n    {\n\t    // ForwardIterator apply_and_remove(ForwardIterator first, ForwardIterator last, Function function, const T&\n\t    // value) ForwardIterator apply_and_remove_if(ForwardIterator first, ForwardIterator last, Function function,\n\t    // Predicate predicate)\n\n\t    // Test for empty range and full container range\n\t    {\n\t\t    int intArray[12] = {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    int* pInt = apply_and_remove(intArray, intArray, func, 1);\n\t\t    EATEST_VERIFY(pInt == intArray);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), \"apply_and_remove\", 0, 0, 1, 1, 0, 0, 1, 1, 0,\n\t\t                                 0, 1, 1, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", -1));\n\t\t    pInt = apply_and_remove(intArray, intArray + 12, func, 1);\n\t\t    EATEST_VERIFY(pInt == intArray + 6);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"apply_and_remove\", 0, 0, 0, 0, 0, 0, -1));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", 1, 1, 1, 1, 1, 1, -1));\n\t    }\n\n\t    // Test for no match on empty range and full container range\n\t    {\n\t\t    int intArray[12] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    int* pInt = apply_and_remove(intArray, intArray, func, 1);\n\t\t    EATEST_VERIFY(pInt == intArray);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), \"apply_and_remove\", 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t\t                                 3, 3, 3, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", -1));\n\t\t    pInt = apply_and_remove(intArray, intArray + 12, func, 1);\n\t\t    EATEST_VERIFY(pInt == intArray + 12);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), \"apply_and_remove\", 3, 3, 3, 3, 3, 3, 3, 3, 3,\n\t\t                                 3, 3, 3, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", -1));\n\t    }\n\n\t    // Test for empty range and full container range\n\t    {\n\t\t    int intArray[12] = {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    int* pInt = apply_and_remove_if(intArray, intArray, func, [](int i) { return i == 1; });\n\t\t    EATEST_VERIFY(pInt == intArray);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), \"apply_and_remove_if\", 0, 0, 1, 1, 0, 0, 1, 1,\n\t\t                                 0, 0, 1, 1, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", -1));\n\t\t    pInt = apply_and_remove_if(intArray, intArray + 12, func, [](int i) { return i == 1; });\n\t\t    EATEST_VERIFY(pInt == intArray + 6);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"apply_and_remove_if\", 0, 0, 0, 0, 0, 0, -1));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", 1, 1, 1, 1, 1, 1, -1));\n\t    }\n\n\t    // Test for no match on empty range and full container range\n\t    {\n\t\t    int intArray[12] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    int* pInt = apply_and_remove_if(intArray, intArray, func, [](int i) { return i == 1; });\n\t\t    EATEST_VERIFY(pInt == intArray);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), \"apply_and_remove_if\", 3, 3, 3, 3, 3, 3, 3, 3,\n\t\t                                 3, 3, 3, 3, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", -1));\n\t\t    pInt = apply_and_remove_if(intArray, intArray + 12, func, [](int i) { return i == 1; });\n\t\t    EATEST_VERIFY(pInt == intArray + 12);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), \"apply_and_remove_if\", 3, 3, 3, 3, 3, 3, 3, 3,\n\t\t                                 3, 3, 3, 3, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", -1));\n\t    }\n\n\t    auto even = [](int a) { return (a % 2) == 0; };\n\t    // Test to verify that the remaining element have stable ordering\n\t    {\n\t\t    int intArray[12] = {7, 8, 2, 3, 4, 5, 6, 0, 1, 9, 10, 11};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    int* pInt = apply_and_remove_if(intArray, intArray + 12, func, even);\n\t\t    EATEST_VERIFY(pInt == intArray + 6);\n\t\t    EATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"apply_and_remove_if\", 7, 3, 5, 1, 9, 11, -1));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", 8, 2, 4, 6, 0, 10, -1));\n\t    }\n\t    {\n\t\t    int intArray[12] = {7, 8, 0, 0, 4, 5, 6, 0, 1, 9, 0, 11};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    int* pInt = apply_and_remove(intArray, intArray + 12, func, 0);\n\t\t    EATEST_VERIFY(pInt == intArray + 8);\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(intArray, intArray + 8, int(), \"apply_and_remove\", 7, 8, 4, 5, 6, 1, 9, 11, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", 0, 0, 0, 0, -1));\n\t    }\n\n\t    // Tests on a list (i.e. non-contiguous memory container)\n\t    {\n\t\t    list<int> intList = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    auto listIter = apply_and_remove_if(intList.begin(), intList.begin(), func, even);\n\t\t    EATEST_VERIFY(listIter == intList.begin());\n\t\t    EATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"apply_and_remove_if\", 0, 1, 2, 3, 4, 5,\n\t\t                                 6, 7, 8, 9, 10, 11, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", -1));\n\t\t    listIter = apply_and_remove_if(intList.begin(), intList.end(), func, even);\n\t\t    EATEST_VERIFY(listIter == next(intList.begin(), 6));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(intList.begin(), listIter, int(), \"apply_and_remove_if\", 1, 3, 5, 7, 9, 11, -1));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", 0, 2, 4, 6, 8, 10, -1));\n\t    }\n\t    {\n\t\t    list<int> intList = {0, 4, 2, 3, 4, 5, 6, 4, 4, 4, 10, 11};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    auto listIter = apply_and_remove(intList.begin(), intList.begin(), func, 4);\n\t\t    EATEST_VERIFY(listIter == intList.begin());\n\t\t    EATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"apply_and_remove\", 0, 4, 2, 3, 4, 5, 6,\n\t\t                                 4, 4, 4, 10, 11, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", -1));\n\t\t    listIter = apply_and_remove(intList.begin(), intList.end(), func, 4);\n\t\t    EATEST_VERIFY(listIter == next(intList.begin(), 7));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(intList.begin(), listIter, int(), \"apply_and_remove\", 0, 2, 3, 5, 6, 10, 11, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", 4, 4, 4, 4, 4, -1));\n\t    }\n\n\t    // Tests on a part of a container\n\t    {\n\t\t    vector<int> intVector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    auto vectorIter = apply_and_remove_if(next(intVector.begin(), 3), prev(intVector.end(), 2), func, even);\n\t\t    EATEST_VERIFY(vectorIter == next(intVector.begin(), 7));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(intVector.begin(), vectorIter, int(), \"apply_and_remove_if\", 0, 1, 2, 3, 5, 7, 9, -1));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(prev(intVector.end(), 2), intVector.end(), int(), \"apply_and_remove_if\", 10, 11, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove_if\", 4, 6, 8, -1));\n\t    }\n\t    {\n\t\t    vector<int> intVector = {5, 1, 5, 3, 4, 5, 5, 7, 8, 5, 10, 5};\n\t\t    vector<int> output;\n\t\t    auto func = [&output](int a) { output.push_back(a); };\n\t\t    auto vectorIter = apply_and_remove(next(intVector.begin(), 2), prev(intVector.end(), 3), func, 5);\n\t\t    EATEST_VERIFY(vectorIter == next(intVector.begin(), 6));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(intVector.begin(), vectorIter, int(), \"apply_and_remove\", 5, 1, 3, 4, 7, 8, -1));\n\t\t    EATEST_VERIFY(\n\t\t        VerifySequence(prev(intVector.end(), 3), intVector.end(), int(), \"apply_and_remove\", 5, 10, 5, -1));\n\t\t    EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), \"apply_and_remove\", 5, 5, 5, -1));\n\t    }\n    }\n\n\n    {\n\t\t// OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)\n\t\t// OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate, const T& new_value)\n\n\t\tint intArray1[12] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 };\n\t\tint intArray2[12] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };\n\n\t\tint* pInt = replace_copy(intArray1, intArray1, intArray2, 1, 4);\n\t\tEATEST_VERIFY(pInt == intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"replace_copy\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"replace_copy\", 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1));\n\n\t\tpInt = replace_copy(intArray1, intArray1 + 12, intArray2, 1, 4);\n\t\tEATEST_VERIFY(pInt == intArray2 + 12);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 12, int(), \"replace_copy\", 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, -1));\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 12, int(), \"replace_copy\", 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, -1));\n\t}\n\n\n\t{\n\t\t// void reverse(BidirectionalIterator first, BidirectionalIterator last)\n\n\t\tvector<int> intArray;\n\t\tfor(int i = 0; i < 10; i++)\n\t\t\tintArray.push_back(i);\n\n\t\treverse(intArray.begin(), intArray.begin()); // No-op\n\t\tEATEST_VERIFY(VerifySequence(intArray.begin(), intArray.end(), int(), \"reverse\", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));\n\n\t\treverse(intArray.begin(), intArray.end());\n\t\tEATEST_VERIFY(VerifySequence(intArray.begin(), intArray.end(), int(), \"reverse\", 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1));\n\n\n\t\tlist<TestObject> toList;\n\t\tfor(int j = 0; j < 10; j++)\n\t\t\ttoList.push_back(TestObject(j));\n\n\t\treverse(toList.begin(), toList.begin()); // No-op\n\t\tEATEST_VERIFY(toList.front() == TestObject(0));\n\t\tEATEST_VERIFY(toList.back() == TestObject(9));\n\n\t\treverse(toList.begin(), toList.end());\n\t\tEATEST_VERIFY(toList.front() == TestObject(9));\n\t\tEATEST_VERIFY(toList.back() == TestObject(0));\n\n\t\t// Verify that reversing an empty range executes without exception.\n\t\treverse(toList.begin(), toList.begin());\n\t}\n\n\n\t{\n\t\t// reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result)\n\n\t\tvector<int> intArray1;\n\t\tint         intArray2[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };\n\n\t\tfor(int i = 0; i < 10; i++)\n\t\t\tintArray1.push_back(i);\n\n\t\tint* pInt = reverse_copy(intArray1.begin(), intArray1.begin(), intArray2); // No-op\n\t\tEATEST_VERIFY(pInt == intArray2);\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 10, int(), \"reverse_copy\", 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1));\n\n\t\tpInt = reverse_copy(intArray1.begin(), intArray1.end(), intArray2);\n\t\tEATEST_VERIFY(pInt == intArray2 + intArray1.size());\n\t\tEATEST_VERIFY(VerifySequence(intArray2, intArray2 + 10, int(), \"reverse_copy\", 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1));\n\n\n\t\tlist<TestObject> toList;\n\t\tTestObject       toArray2[10];\n\n\t\tfor(int j = 0; j < 10; j++)\n\t\t{\n\t\t\ttoList.push_back(TestObject(j));\n\t\t\ttoArray2[j] = TestObject(5);\n\t\t}\n\n\t\tTestObject* pTO = reverse_copy(toList.begin(), toList.begin(), toArray2); // No-op\n\t\tEATEST_VERIFY(pTO == toArray2);\n\t\tEATEST_VERIFY(toArray2[0] == TestObject(5));\n\t\tEATEST_VERIFY(toArray2[9] == TestObject(5));\n\n\t\tpTO = reverse_copy(toList.begin(), toList.end(), toArray2);\n\t\tEATEST_VERIFY(pTO == toArray2 + 10);\n\t}\n\n\n\t{\n\t\t// ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)\n\t\t// ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate predicate)\n\n\t\t// Test via bidirectional/random_access iterator.\n\t\tbasic_string<char> sTest(\"abcdefg abcdefg abcdefg\");\n\t\tconst char* pSubstring1 = \" abcd\";\n\t\tconst char* pSubstring2 = \"1234\";\n\n\t\tbasic_string<char>::iterator iString = search(sTest.begin(), sTest.end(), pSubstring1, pSubstring1 + strlen(pSubstring1));\n\t\tEATEST_VERIFY(&*iString == &sTest[7]);\n\n\t\tiString = search(sTest.begin(), sTest.end(), pSubstring1, pSubstring1 + 1); // Search for sequence of 1.\n\t\tEATEST_VERIFY(&*iString == &sTest[7]);\n\n\t\tiString = search(sTest.begin(), sTest.end(), pSubstring2, pSubstring2 + strlen(pSubstring2));\n\t\tEATEST_VERIFY(&*iString == sTest.end());\n\n\t\tiString = search(sTest.begin(), sTest.end(), pSubstring2, pSubstring2); // Search with empty search pattern.\n\t\tEATEST_VERIFY(&*iString == sTest.begin());\n\n\t\t// Test via forward iterator.\n\t\tslist<char> sListTest;\n\t\tfor(slist<char>::size_type i = sTest.size(); i > 0; --i)\n\t\t\tsListTest.push_front(sTest[i - 1]);\n\n\t\tslist<char>::iterator iSlist = search(sListTest.begin(), sListTest.end(), pSubstring1, pSubstring1 + 5);\n\t\tslist<char>::iterator i7 = sListTest.begin();\n\t\tadvance(i7, 7);\n\t\tEATEST_VERIFY(iSlist == i7);\n\n\t\tiSlist = search(sListTest.begin(), sListTest.end(), pSubstring2, pSubstring2 + strlen(pSubstring2));\n\t\tEATEST_VERIFY(iSlist == sListTest.end());\n\n\t\tiSlist = search(sListTest.begin(), sListTest.end(), pSubstring2, pSubstring2); // Search with empty search pattern.\n\t\tEATEST_VERIFY(iSlist == sListTest.begin());\n\t}\n\n\n\t{\n\t\t// ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value)\n\n\t\tconst char* pString1 = \"Hello wwworld\";\n\t\tconst char* presultult  = search_n(pString1, pString1 + strlen(pString1), 1, 'w');\n\t\tEATEST_VERIFY(presultult == pString1 + 6);\n\t}\n\n\n\t{\n\t\t// bool binary_search(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\n\t\t// ForwardIterator binary_search_i(ForwardIterator first, ForwardIterator last, const T& value)\n\t\t// ForwardIterator binary_search_i(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)\n\n\t\tvector<int> intArray;\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tintArray.push_back(i);\n\n\t\tbool b = binary_search(intArray.begin(), intArray.begin(), 0);\n\t\tEATEST_VERIFY(b == false);\n\n\t\tb = binary_search(intArray.begin(), intArray.begin() + 1, 0);\n\t\tEATEST_VERIFY(b == true);\n\n\t\tb = binary_search(intArray.begin(), intArray.end(), 733, less<int>());\n\t\tEATEST_VERIFY(b == true);\n\n\n\t\tvector<int>::iterator it = binary_search_i(intArray.begin(), intArray.begin(), 0);\n\t\tEATEST_VERIFY(it == intArray.begin());\n\n\t\tit = binary_search_i(intArray.begin(), intArray.begin() + 1, 0, less<int>());\n\t\tEATEST_VERIFY(it == intArray.begin());\n\n\t\tit = binary_search_i(intArray.begin(), intArray.end(), 733);\n\t\tEATEST_VERIFY(it == intArray.begin() + 733);\n\n\n\t\tlist<TestObject> toList;\n\t\tlist<TestObject>::iterator toI;\n\t\tfor(int j = 0; j < 1000; j++)\n\t\t\ttoList.push_back(TestObject(j));\n\n\t\tb = binary_search(toList.begin(), toList.begin(), TestObject(0), less<TestObject>());\n\t\tEATEST_VERIFY(b == false);\n\n\t\ttoI = toList.begin();\n\t\ttoI++;\n\t\tb = binary_search(toList.begin(), toI, TestObject(0));\n\t\tEATEST_VERIFY(b == true);\n\n\t\tb = binary_search(toList.begin(), toList.end(), TestObject(733));\n\t\tEATEST_VERIFY(b == true);\n\n\n\t\ttoI = binary_search_i(toList.begin(), toList.begin(), TestObject(0), less<TestObject>()); // No-op\n\t\tEATEST_VERIFY(toI == toList.begin());\n\n\t\ttoI = toList.begin();\n\t\ttoI++;\n\t\ttoI = binary_search_i(toList.begin(), toI, TestObject(0));\n\t\tEATEST_VERIFY(*toI == TestObject(0));\n\n\t\ttoI = binary_search_i(toList.begin(), toList.end(), TestObject(733));\n\t\tEATEST_VERIFY(*toI == TestObject(733));\n\t}\n\n\n\t{\n\t\t// ForwardIterator unique(ForwardIterator first, ForwardIterator last)\n\t\t// ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate predicate)\n\n\t\tint intArray[] = { 1, 2, 3, 3, 4, 4 };\n\n\t\tint* pInt = unique(intArray, intArray + 0);\n\t\tEATEST_VERIFY(pInt == intArray);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"unique\", 1, 2, 3, 3, 4, 4, -1));\n\n\t\tpInt = unique(intArray, intArray + 6, equal_to<int>());\n\t\tEATEST_VERIFY(pInt == intArray + 4);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"unique\", 1, 2, 3, 4, 4, 4, -1));\n\n\n\t\tTestObject toArray[] = { TestObject(1), TestObject(2), TestObject(3), TestObject(3), TestObject(4), TestObject(4) };\n\n\t\tTestObject* pTO = unique(toArray, toArray + 6);\n\t\tEATEST_VERIFY(pTO == toArray + 4);\n\t\tEATEST_VERIFY(toArray[3] == TestObject(4));\n\t}\n\n\n\t{\n\t\t// ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)\n\t\t// ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate predicate)\n\n\t\t// Test via bidirectional/random_access iterator.\n\t\tbasic_string<char> sTest(\"abcdefg abcdefg abcdefg\");\n\t\tconst char* pSubstring1 = \"abcd\";\n\t\tconst char* pSubstring2 = \"1234\";\n\n\t\tbasic_string<char>::iterator iString = find_end(sTest.begin(), sTest.end(), pSubstring1, pSubstring1 + 4);\n\t\tEATEST_VERIFY(&*iString == &sTest[16]);\n\n\t\tiString = find_end(sTest.begin(), sTest.end(), pSubstring1, pSubstring1 + 4, equal_to<char>());\n\t\tEATEST_VERIFY(&*iString == &sTest[16]);\n\n\t\tiString = find_end(sTest.begin(), sTest.end(), pSubstring2, pSubstring2 + strlen(pSubstring2));\n\t\tEATEST_VERIFY(iString == sTest.end());\n\n\t\tiString = find_end(sTest.begin(), sTest.end(), pSubstring2, pSubstring2 + strlen(pSubstring2), equal_to<char>());\n\t\tEATEST_VERIFY(iString == sTest.end());\n\n\t\t// Test via forward iterator.\n\t\tslist<char> sListTest;\n\t\tfor(slist<char>::size_type i = sTest.size(); i > 0; --i)\n\t\t\tsListTest.push_front(sTest[i - 1]);\n\n\t\tslist<char>::iterator iSlist = find_end(sListTest.begin(), sListTest.end(), pSubstring1, pSubstring1 + strlen(pSubstring1));\n\t\tslist<char>::iterator i16 = sListTest.begin();\n\t\tadvance(i16, 16);\n\t\tEATEST_VERIFY(iSlist == i16);\n\n\t\tiSlist = find_end(sListTest.begin(), sListTest.end(), pSubstring1, pSubstring1 + strlen(pSubstring1), equal_to<char>());\n\t\ti16 = sListTest.begin();\n\t\tadvance(i16, 16);\n\t\tEATEST_VERIFY(iSlist == i16);\n\n\t\tiSlist = find_end(sListTest.begin(), sListTest.end(), pSubstring2, pSubstring2 + strlen(pSubstring2));\n\t\tEATEST_VERIFY(iSlist == sListTest.end());\n\n\t\tiSlist = find_end(sListTest.begin(), sListTest.end(), pSubstring2, pSubstring2 + strlen(pSubstring2), equal_to<char>());\n\t\tEATEST_VERIFY(iSlist == sListTest.end());\n\t}\n\n\n\t{\n\t\t// OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)\n\t\t// OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,  OutputIterator result, Compare compare)\n\n\t\tint intArray1[] = { 0, 0, 2, 5, 8, 8, 12, 24, 26, 43 };\n\t\tint intArray2[] = { 0, 0, 0, 5, 7, 8, 11, 24, 25, 43 };\n\t\tint intArray3[] = { 9, 9, 9, 9, 9, 9,  9,  9,  9,  9 };\n\n\t\tset_difference(intArray1, intArray1 + 0, intArray2, intArray2 + 0, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_difference\", 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1));\n\n\t\tset_difference(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_difference\", 2, 8, 12, 26, 9, 9, 9, 9, 9, 9, -1));\n\n\t\tintArray3[0] = intArray3[1] = intArray3[2] = 9;\n\n\t\tset_difference(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3, less<int>());\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_difference\", 2, 8, 12, 26, 9, 9, 9, 9, 9, 9, -1));\n\t}\n\n\n\t{\n\t\t// OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)\n\t\t// OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,  OutputIterator result, Compare compare)\n\n\t\tint intArray1[] = { 0, 0, 2, 5, 8, 8, 12, 24, 26, 43 };\n\t\tint intArray2[] = { 0, 0, 0, 5, 7, 8, 11, 24, 25, 43 };\n\t\tint intArray3[] = { 9, 9, 9, 9, 9, 9,  9,  9,  9,  9 };\n\n\t\tset_symmetric_difference(intArray1, intArray1 + 0, intArray2, intArray2 + 0, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_symmetric_difference\", 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1));\n\n\t\tset_symmetric_difference(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_symmetric_difference\", 0, 2, 7, 8, 11, 12, 25, 26, 9, 9, -1));\n\n\t\tintArray3[0] = intArray3[1] = intArray3[2] = intArray3[4] = intArray3[5] = intArray3[6] = 9;\n\n\t\tset_symmetric_difference(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3, less<int>());\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_symmetric_difference\", 0, 2, 7, 8, 11, 12, 25, 26, 9, 9, -1));\n\t}\n\n\n\t{\n\t\t// OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)\n\t\t// OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare compare)\n\n\t\tint intArray1[] = { 0, 0, 2, 5, 8, 8, 12, 24, 26, 43 };\n\t\tint intArray2[] = { 0, 0, 0, 5, 7, 8, 11, 24, 25, 43 };\n\t\tint intArray3[] = { 9, 9, 9, 9, 9, 9,  9,  9,  9,  9 };\n\n\t\tset_intersection(intArray1, intArray1 + 0, intArray2, intArray2 + 0, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_intersection\", 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1));\n\n\t\tset_intersection(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_intersection\", 0, 0, 5, 8, 24, 43, 9, 9, 9, 9, -1));\n\n\t\tintArray3[0] = intArray3[1] = intArray3[2] = intArray3[4] = intArray3[5] = intArray3[6] = 9;\n\n\t\tset_intersection(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3, less<int>());\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 10, int(), \"set_intersection\", 0, 0, 5, 8, 24, 43, 9, 9, 9, 9, -1));\n\t}\n\n\n\t{\n\t\t// OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)\n\t\t// OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare compare)\n\n\t\tint intArray1[] = { 0, 0, 2, 5, 8, 8, 12, 24, 26, 43 };\n\t\tint intArray2[] = { 0, 0, 0, 5, 7, 8, 11, 24, 25, 43 };\n\t\tint intArray3[] = { 9, 9, 9, 9, 9, 9,  9,  9,  9,  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };\n\n\t\tset_union(intArray1, intArray1 + 0, intArray2, intArray2 + 0, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 20, int(), \"set_union\", 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1));\n\n\t\tset_union(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3);\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 20, int(), \"set_union\", 0, 0, 0, 2, 5, 7, 8, 8, 11, 12, 24, 25, 26, 43, 9, 9, 9, 9, 9, 9, -1));\n\n\t\tintArray3[0] = intArray3[1] = intArray3[2] = intArray3[3] = intArray3[4] = intArray3[5] = intArray3[6] = intArray3[7] = intArray3[8] = intArray3[9] = intArray3[10] = intArray3[11] = 9;\n\n\t\tset_union(intArray1, intArray1 + 10, intArray2, intArray2 + 10, intArray3, less<int>());\n\t\tEATEST_VERIFY(VerifySequence(intArray3, intArray3 + 20, int(), \"set_union\", 0, 0, 0, 2, 5, 7, 8, 8, 11, 12, 24, 25, 26, 43, 9, 9, 9, 9, 9, 9, -1));\n\t}\n\n\n\t// set_difference_2\n\t{\n\t\t// template <typename InputIterator1, typename InputIterator2, typename OutputIterator>\n\t\t// void set_difference_2(InputIterator1 first1, InputIterator1 last1,\n\t\t//                       InputIterator2 first2, InputIterator2 last2,\n\t\t//                       OutputIterator result1, OutputIterator result2)\n\t\t{\n\t\t\tconst eastl::vector<int> v1 = {1, 2, 4, 5,   7, 7, 9};\n\t\t\tconst eastl::vector<int> v2 = {   2,       6,      9};\n\t\t\teastl::vector<int> only_v1, only_v2;\n\n\t\t\teastl::set_difference_2(v1.begin(), v1.end(), v2.begin(), v2.end(),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v1, only_v1.begin()),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v2, only_v2.begin()));\n\n\t\t\tEATEST_VERIFY((only_v1 == eastl::vector<int>{1, 4, 5, 7, 7}));\n\t\t\tEATEST_VERIFY((only_v2 == eastl::vector<int>{6}));\n\t\t}\n\n        // template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>\n        // void set_difference_2(InputIterator1 first1, InputIterator1 last1,\n        //                       InputIterator2 first2, InputIterator2 last2,\n        //                       OutputIterator result1, OutputIterator result2, Compare compare)\n        {\n\t\t\tstruct local\n\t\t\t{\n\t\t\t\tint data = -1;\n\t\t\t\tbool operator==(const local& other) const\n\t\t\t\t\t{ return data == other.data; }\n\t\t\t};\n\n\t\t\tconst eastl::vector<local> v1 = {{1}, {2}, {4}, {5},      {7}, {7}, {9}};\n\t\t\tconst eastl::vector<local> v2 = {     {2},           {6},           {9}};\n\t\t\teastl::vector<local> only_v1, only_v2;\n\n\t\t\teastl::set_difference_2(v1.begin(), v1.end(), v2.begin(), v2.end(),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v1, only_v1.begin()),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v2, only_v2.begin()),\n\t\t\t\t\t\t\t\t\t[](const local& lhs, const local& rhs) { return lhs.data < rhs.data; });\n\n\t\t\tEATEST_VERIFY((only_v1 == eastl::vector<local>{{1}, {4}, {5}, {7}, {7}}));\n\t\t\tEATEST_VERIFY((only_v2 == eastl::vector<local>{{6}}));\n\t\t}\n\t}\n\n\n\t// set_decomposition\n\t{\n\t\t// OutputIterator3 set_decomposition(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,\n\t\t//                           OutputIterator1 result1, OutputIterator2 result2, OutputIterator3 result3)\n\t\t{\n\t\t\tconst eastl::vector<int> v1 = {1, 2, 4, 5,   7, 7, 9};\n\t\t\tconst eastl::vector<int> v2 = {   2,       6,      9};\n\t\t\teastl::vector<int> only_v1, only_v2, intersection;\n\n\t\t\teastl::set_decomposition(v1.begin(), v1.end(), v2.begin(), v2.end(),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v1, only_v1.begin()),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v2, only_v2.begin()),\n\t\t\t\t\t\t\t\t\teastl::inserter(intersection, intersection.begin()));\n\n\t\t\tEATEST_VERIFY((only_v1 == eastl::vector<int>{1, 4, 5, 7, 7}));\n\t\t\tEATEST_VERIFY((only_v2 == eastl::vector<int>{6}));\n\t\t\tEATEST_VERIFY((intersection == eastl::vector<int>{2, 9}));\n\t\t}\n\n\t\t// OutputIterator3 set_decomposition(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,\n\t\t//                           OutputIterator1 result1, OutputIterator2 result2, OutputIterator3 result3, Compare compare)\n\t\t{\n\t\t\tstruct local\n\t\t\t{\n\t\t\t\tint data = -1;\n\t\t\t\tbool operator==(const local& other) const\n\t\t\t\t\t{ return data == other.data; }\n\t\t\t};\n\n\t\t\tconst eastl::vector<local> v1 = {{1}, {2}, {4}, {5},      {7}, {7}, {9}};\n\t\t\tconst eastl::vector<local> v2 = {     {2},           {6},           {9}};\n\t\t\teastl::vector<local> only_v1, only_v2, intersection;\n\n\t\t\teastl::set_decomposition(v1.begin(), v1.end(), v2.begin(), v2.end(),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v1, only_v1.begin()),\n\t\t\t\t\t\t\t\t\teastl::inserter(only_v2, only_v2.begin()),\n\t\t\t\t\t\t\t\t\teastl::inserter(intersection, intersection.begin()),\n\t\t\t\t\t\t\t\t\t[](const local& lhs, const local& rhs) { return lhs.data < rhs.data; });\n\n\t\t\tEATEST_VERIFY((only_v1 == eastl::vector<local>{{1}, {4}, {5}, {7}, {7}}));\n\t\t\tEATEST_VERIFY((only_v2 == eastl::vector<local>{{6}}));\n\t\t\tEATEST_VERIFY((intersection == eastl::vector<local>{{2}, {9}}));\n\t\t}\n\t}\n\n\t// includes\n\t{\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {1, 2, 3, 4, 5};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {1, 3, 4};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {2};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {2, 3, 4, 5};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {2, 4};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {1};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {5};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {6};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {0};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {1, 2, 3, 4, 5, 6};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {2, 6};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\t\teastl::vector<int> w = {-1, 2, 3, 4, 5};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end()));\n\t\t}\n\n\t\tconst auto& to_lower_cmp = [](auto a, auto b) { return tolower(a) < tolower(b);};\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w = {'A', 'b', 'C', 'd', 'E'};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w = {'B', 'C', 'd', 'E'};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w = {'A', 'C', 'E'};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w = {'A'};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w = {'E'};\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w = {'A', 'b', 'C', 'd', 'F'};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w = {'A', 'b', 'C', 'd', 'E', 'f'};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<char> v;\n\t\t\teastl::vector<char> w = {'A', 'b', 'C', 'd', 'E', 'f'};\n\t\t\tEATEST_VERIFY(!eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<char> v = {'a', 'b', 'c', 'd', 'e'};\n\t\t\teastl::vector<char> w;\n\t\t\tEATEST_VERIFY(eastl::includes(v.begin(), v.end(), w.begin(), w.end(), to_lower_cmp));\n\t\t}\n\t}\n\n    {\n\t\t// template<typename ForwardIterator1, typename ForwardIterator2>\n\t\t// bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)\n\n\t\t// template<typename ForwardIterator1, typename ForwardIterator2, class BinaryPredicate>\n\t\t// bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate predicate)\n\t\tEASTLTest_Rand eastlRNG(EA::UnitTest::GetRandSeed());\n\n\t\t{\n\t\t\tint intArray1[] = { 0, 1, 2, 3, 4 };\n\t\t\tint intArray2[] = { 0, 1, 2, 3, 4 };\n\n\t\t\t// Test an empty set.\n\t\t\tEATEST_VERIFY(eastl::is_permutation(intArray1, intArray1 + 0, intArray2));\n\n\t\t\t// Test two identical sets.\n\t\t\tEATEST_VERIFY(eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\t\t\teastl::random_shuffle(intArray1, intArray1 + EAArrayCount(intArray1), eastlRNG);\n\n\t\t\t// Test order randomization.\n\t\t\tEATEST_VERIFY(eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\t\t\teastl::random_shuffle(intArray2, intArray2 + EAArrayCount(intArray2), eastlRNG);\n\t\t\tEATEST_VERIFY(eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\n\t\t\t// Test the case where there's a difference.\n\t\t\tintArray2[4] = intArray2[3]; // This change guarantees is_permutation will return false.\n\t\t\tEATEST_VERIFY(!eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\t\t}\n\n\t\t{\n\t\t\tint intArray1[] = { 0, 0, 0, 1, 1 };\n\t\t\tint intArray2[] = { 0, 0, 0, 1, 1 };\n\n\t\t\t// Test two identical sets.\n\t\t\tEATEST_VERIFY(eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\t\t\teastl::random_shuffle(intArray1, intArray1 + EAArrayCount(intArray1), eastlRNG);\n\n\t\t\t// Test order randomization.\n\t\t\tEATEST_VERIFY(eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\t\t\teastl::random_shuffle(intArray2, intArray2 + EAArrayCount(intArray2), eastlRNG);\n\t\t\tEATEST_VERIFY(eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\n\t\t\t// Test the case where there's a difference.\n\t\t\tintArray2[4] = (intArray2[4] == 0) ? 1 : 0;\n\t\t\tEATEST_VERIFY(!eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2));\n\t\t}\n\n\t\tfor(int n = 0; n < 100000; n++)\n\t\t{\n\t\t\teastl_size_t intArray1[6];\n\t\t\teastl_size_t intArray2[6];\n\n\t\t\tfor(size_t i = 0; i < EAArrayCount(intArray1); i++)\n\t\t\t{\n\t\t\t\tintArray1[i] = eastlRNG.RandLimit(6);\n\t\t\t\tintArray2[i] = eastlRNG.RandLimit(6);\n\t\t\t}\n\n\t\t\tbool isPermutation = eastl::is_permutation(intArray1, intArray1 + EAArrayCount(intArray1), intArray2);\n\n\t\t\t// If is_permutation returned true, then sorted versions of the two arrays should be identical.\n\t\t\teastl::sort(intArray1, intArray1 + EAArrayCount(intArray1));\n\t\t\teastl::sort(intArray2, intArray2 + EAArrayCount(intArray2));\n\n\t\t\teastl::pair<eastl_size_t*, eastl_size_t*> mismatchResult = eastl::mismatch(intArray1, intArray1 + EAArrayCount(intArray1), intArray2);\n\t\t\tbool isIdentical = (mismatchResult.first == (intArray1 + EAArrayCount(intArray1)));\n\n\t\t\tEATEST_VERIFY(isPermutation == isIdentical); // With an array size of 6, isPermutation ends up being true about 1 in 400 times here.\n\t\t}\n\t}\n\n    {\n\t    // template <class InputIterator, class UnaryPredicate>\n\t    // bool is_partitioned(InputIterator first, InputIterator last, UnaryPredicate predicate)\n\n\t    // template <class ForwardIterator, class UnaryPredicate>\n\t    // ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, UnaryPredicate predicate)\n\n\t    const auto isEven = [](int i) { return i % 2 == 0; };\n\n\t    // These are all partitioned, even first and then odd.\n\t    vector<int> v1 = {0, 2, 4, 5, 7, 9, 11};\n\t    vector<int> v2 = {1, 3, 5, 7, 9};\n\t    vector<int> v3 = {2, 4, 8, 100, 102};\n\t    vector<int> v4 = {2, 4, 8, 100, 103};\n\t    EATEST_VERIFY(is_partitioned(v1.begin(), v1.end(), isEven));\n\t    EATEST_VERIFY(is_partitioned(v2.begin(), v2.end(), isEven));\n\t    EATEST_VERIFY(is_partitioned(v3.begin(), v3.end(), isEven));\n\t    EATEST_VERIFY(is_partitioned(v4.begin(), v4.end(), isEven));\n\n\t    EATEST_VERIFY(distance(v1.begin(), partition_point(v1.begin(), v1.end(), isEven)) == 3);\n\t    EATEST_VERIFY(distance(v2.begin(), partition_point(v2.begin(), v2.end(), isEven)) == 0);\n\t    EATEST_VERIFY(distance(v3.begin(), partition_point(v3.begin(), v3.end(), isEven)) == 5);\n\t    EATEST_VERIFY(distance(v4.begin(), partition_point(v4.begin(), v4.end(), isEven)) == 4);\n\n\t    // These are all not partitioned:\n\t    vector<int> v5 = {0, 2, 3, 4, 5, 7, 9, 11};\n\t    vector<int> v6 = {1, 3, 5, 7, 9, 2};\n\t    vector<int> v7 = {2, 4, 3, 8, 100, 102};\n\t    vector<int> v8 = {2, 4, 8, 5, 100, 103};\n\t    EATEST_VERIFY(!is_partitioned(v5.begin(), v5.end(), isEven));\n\t    EATEST_VERIFY(!is_partitioned(v6.begin(), v6.end(), isEven));\n\t    EATEST_VERIFY(!is_partitioned(v7.begin(), v7.end(), isEven));\n\t    EATEST_VERIFY(!is_partitioned(v8.begin(), v8.end(), isEven));\n    }\n\n    {\n\t\t//template<typename BidirectionalIterator>\n\t\t//bool next_permutation(BidirectionalIterator first, BidirectionalIterator last);\n\n\t\t//template<typename BidirectionalIterator, typename Compare>\n\t\t//bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare compare);\n\n\t\tuint64_t    count;\n\t\tvector<int> intArray;\n\t\tfor(int i = 0; i < 8; i++)\n\t\t\tintArray.push_back(i);\n\n\t\tcount = 0;\n\t\tdo {\n\t\t\t++count;\n\t\t} while(next_permutation(intArray.begin(), intArray.end()));\n\t\tEATEST_VERIFY(count == 40320); // count = n!\n\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\n\t\tcount = 0;\n\t\tdo {\n\t\t\t++count;\n\t\t} while(next_permutation(intArray.begin(), intArray.end(), eastl::less<int>()));\n\t\tEATEST_VERIFY(count == 40320); // count = n!\n\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t}\n\n\n\t{\n\t\t// template <typename ForwardIterator>\n\t\t// ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last);\n\n\t\t// eastl::array (ContiguousIterator/Pointer)\n\t\tconst eastl_size_t kRotateArraySize = 10;\n\t\ttypedef eastl::array<int, kRotateArraySize> IntArray;\n\n\t\t{   // This type is templated, so we can't run a loop over various sizes.\n\t\t\tIntArray intArray;\n\n\t\t\tfor(eastl_size_t i = 0; i < kRotateArraySize; i++)\n\t\t\t{\n\t\t\t\teastl::generate_n(intArray.begin(), kRotateArraySize, GenerateIncrementalIntegers<int>());\n\t\t\t\tIntArray::iterator intArrayItMiddle = eastl::next(intArray.begin(), i);\n\t\t\t\tIntArray::iterator intArrayIt = eastl::rotate(intArray.begin(), intArrayItMiddle, intArray.end());\n\n\t\t\t\tfor(eastl_size_t j = 0; j < kRotateArraySize; j++)\n\t\t\t\t{\n\t\t\t\t\tif(intArrayIt == intArray.end())\n\t\t\t\t\t\tintArrayIt = intArray.begin();\n\t\t\t\t\tEATEST_VERIFY(*intArrayIt++ == (int)j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// eastl::vector (ContiguousIterator)\n\t\ttypedef eastl::vector<int> IntVector;\n\n\t\tfor(eastl_size_t s = 10; s < 500; s += (eastl_size_t)rng.RandRange(50, 100))\n\t\t{\n\t\t\tIntVector intVector(s, 0);\n\n\t\t\tfor(eastl_size_t i = 0; i < s; i++)\n\t\t\t{\n\t\t\t\teastl::generate_n(intVector.begin(), s, GenerateIncrementalIntegers<int>());\n\t\t\t\tIntVector::iterator intVectorItMiddle = eastl::next(intVector.begin(), i);\n\t\t\t\tIntVector::iterator intVectorIt = eastl::rotate(intVector.begin(), intVectorItMiddle, intVector.end());\n\n\t\t\t\tfor(eastl_size_t j = 0; j < s; j++)\n\t\t\t\t{\n\t\t\t\t\tif(intVectorIt == intVector.end())\n\t\t\t\t\t\tintVectorIt = intVector.begin();\n\t\t\t\t\tEATEST_VERIFY(*intVectorIt++ == (int)j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// eastl::deque (RandomAccessIterator)\n\t\ttypedef eastl::deque<int> IntDeque;\n\n\t\tfor(eastl_size_t s = 10; s < 500; s += (eastl_size_t)rng.RandRange(50, 100))\n\t\t{\n\t\t\tIntDeque intDeque(s, 0);\n\n\t\t\tfor(eastl_size_t i = 0; i < s; i++)\n\t\t\t{\n\t\t\t\teastl::generate_n(intDeque.begin(), s, GenerateIncrementalIntegers<int>());\n\t\t\t\tIntDeque::iterator intDequeItMiddle = eastl::next(intDeque.begin(), i);\n\t\t\t\tIntDeque::iterator intDequeIt = eastl::rotate(intDeque.begin(), intDequeItMiddle, intDeque.end());\n\n\t\t\t\tfor(eastl_size_t j = 0; j < s; j++)\n\t\t\t\t{\n\t\t\t\t\tif(intDequeIt == intDeque.end())\n\t\t\t\t\t\tintDequeIt = intDeque.begin();\n\t\t\t\t\tEATEST_VERIFY(*intDequeIt++ == (int)j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// eastl::list (BidirectionalIterator)\n\t\ttypedef eastl::list<int> IntList;\n\n\t\tfor(eastl_size_t s = 10; s < 500; s += (eastl_size_t)rng.RandRange(50, 100))\n\t\t{\n\t\t\tIntList intList(s, 0);\n\n\t\t\tfor(eastl_size_t i = 0; i < s; i++)\n\t\t\t{\n\t\t\t\teastl::generate_n(intList.begin(), s, GenerateIncrementalIntegers<int>());\n\t\t\t\tIntList::iterator intListItMiddle = eastl::next(intList.begin(), i);\n\t\t\t\tIntList::iterator intListIt = eastl::rotate(intList.begin(), intListItMiddle, intList.end());\n\n\t\t\t\tfor(eastl_size_t j = 0; j < s; j++)\n\t\t\t\t{\n\t\t\t\t\tif(intListIt == intList.end())\n\t\t\t\t\t\tintListIt = intList.begin();\n\t\t\t\t\tEATEST_VERIFY(*intListIt++ == (int)j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// eastl::slist (ForwardIterator)\n\t\ttypedef eastl::slist<int> IntSlist;\n\n\t\tfor(eastl_size_t s = 10; s < 500; s += (eastl_size_t)rng.RandRange(50, 100))\n\t\t{\n\t\t\tIntSlist intSlist(s, 0);\n\n\t\t\tfor(eastl_size_t i = 0; i < s; i++)\n\t\t\t{\n\t\t\t\teastl::generate_n(intSlist.begin(), s, GenerateIncrementalIntegers<int>());\n\t\t\t\tIntSlist::iterator intSlistItMiddle = eastl::next(intSlist.begin(), i);\n\t\t\t\tIntSlist::iterator intSlistIt = eastl::rotate(intSlist.begin(), intSlistItMiddle, intSlist.end());\n\n\t\t\t\tfor(eastl_size_t j = 0; j < s; j++)\n\t\t\t\t{\n\t\t\t\t\tif(intSlistIt == intSlist.end())\n\t\t\t\t\t\tintSlistIt = intSlist.begin();\n\t\t\t\t\tEATEST_VERIFY(*intSlistIt++ == (int)j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// test eastl::sort with move-only type\n\t{\n\t\t{\n\t\t\teastl::vector<eastl::unique_ptr<int>> vec;\n\t\t\teastl::sort(vec.begin(), vec.end(), [](const eastl::unique_ptr<int>& lhs, const eastl::unique_ptr<int>& rhs) { return *lhs < *rhs; });\n\t\t}\n\t\t{\n\t\t\teastl::vector<eastl::unique_ptr<int>> vec;\n\t\t\teastl::sort(vec.begin(), vec.end());\n\t\t}\n\t\t{\n\t\t\teastl::vector<MissingMoveConstructor> vec;\n\t\t\teastl::sort(vec.begin(), vec.end(), [](const MissingMoveConstructor& lhs, const MissingMoveConstructor& rhs) { return lhs < rhs; });\n\t\t}\n\t\t{\n\t\t\teastl::vector<MissingMoveConstructor> vec;\n\t\t\teastl::sort(vec.begin(), vec.end());\n\t\t}\n\t\t{\n\t\t\teastl::vector<MissingMoveAssignable> vec;\n\t\t\teastl::sort(vec.begin(), vec.end(), [](const MissingMoveAssignable& lhs, const MissingMoveAssignable& rhs) { return lhs < rhs; });\n\t\t}\n\t\t{\n\t\t\teastl::vector<MissingMoveAssignable> vec;\n\t\t\teastl::sort(vec.begin(), vec.end());\n\t\t}\n\t\t{\n\t\t\teastl::vector<eastl::unique_ptr<int>> vec;\n\t\t\tvec.emplace_back(new int(7));\n\t\t\tvec.emplace_back(new int(-42));\n\t\t\tvec.emplace_back(new int(5));\n\t\t\teastl::sort(vec.begin(), vec.end(),  [](const eastl::unique_ptr<int>& lhs, const eastl::unique_ptr<int>& rhs) { return *lhs < *rhs; });\n\t\t\tEATEST_VERIFY(*vec[0] == -42);\n\t\t\tEATEST_VERIFY(*vec[1] == 5);\n\t\t\tEATEST_VERIFY(*vec[2] == 7);\n\t\t}\n\t\t{\n\t\t\tfor (unsigned tests = 0; tests < 50; ++tests)\n\t\t\t{\n\t\t\t\teastl::vector<eastl::unique_ptr<int>> vec1;\n\n\t\t\t\tfor (int i = 0; i < 100; ++i)\n\t\t\t\t{\n\t\t\t\t\tint randomNumber = rng();\n\t\t\t\t\tvec1.emplace_back(new int(randomNumber));\n\t\t\t\t}\n\n\t\t\t\tauto vec1Cmp = [](const eastl::unique_ptr<int>& lhs, const eastl::unique_ptr<int>& rhs) { return *lhs < *rhs; };\n\t\t\t\teastl::sort(vec1.begin(), vec1.end(), vec1Cmp);\n\t\t\t\tEATEST_VERIFY(eastl::is_sorted(vec1.begin(), vec1.end(), vec1Cmp));\n\t\t\t}\n\t\t}\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestAllocator.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/allocator.h>\n#include <EASTL/allocator_malloc.h>\n#include <EASTL/fixed_allocator.h>\n#include <EASTL/core_allocator_adapter.h>\n#include <EASTL/list.h>\n#include <EAStdC/EAString.h>\n#include <EAStdC/EAAlignment.h>\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// fixed_pool_reference\n//\nstruct fixed_pool_reference\n{\npublic:\n\tfixed_pool_reference(const char* = NULL)\n\t{\n\t\tmpFixedPool = NULL;\n\t}\n\n\tfixed_pool_reference(eastl::fixed_pool& fixedPool)\n\t{\n\t\tmpFixedPool = &fixedPool;\n\t}\n\n\tfixed_pool_reference(const fixed_pool_reference& x)\n\t{\n\t\tmpFixedPool = x.mpFixedPool;\n\t}\n\n\tfixed_pool_reference& operator=(const fixed_pool_reference& x)\n\t{\n\t\tmpFixedPool = x.mpFixedPool;\n\t\treturn *this;\n\t}\n\n\tvoid* allocate(size_t /*n*/, int /*flags*/ = 0)\n\t{\n\t\treturn mpFixedPool->allocate();\n\t}\n\n\tvoid* allocate(size_t /*n*/, size_t /*alignment*/, size_t /*offset*/, int /*flags*/ = 0)\n\t{\n\t\treturn mpFixedPool->allocate();\n\t}\n\n\tvoid deallocate(void* p, size_t /*n*/)\n\t{\n\t\treturn mpFixedPool->deallocate(p);\n\t}\n\n\tconst char* get_name() const\n\t{\n\t\treturn \"fixed_pool_reference\";\n\t}\n\n\tvoid set_name(const char* /*pName*/)\n\t{\n\t}\n\nprotected:\n\tfriend bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b);\n\tfriend bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b);\n\n\teastl::fixed_pool* mpFixedPool;\n};\n\n\ninline bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b)\n{\n\treturn (a.mpFixedPool == b.mpFixedPool);\n}\n\ninline bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b)\n{\n\treturn (a.mpFixedPool != b.mpFixedPool);\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedAllocator\n//\nEA_DISABLE_VC_WARNING(6262)\nstatic int TestFixedAllocator()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{  // fixed_allocator\n\t\ttypedef eastl::list<int, fixed_allocator> IntList;\n\t\ttypedef IntList::node_type                IntListNode;\n\n\t\tconst size_t  kBufferCount = 200;\n\t\tIntListNode   buffer1[kBufferCount];\n\t\tIntList       intList1;\n\t\tconst size_t  kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);\n\n\t\tintList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);\n\n\t\tfor(size_t i = 0; i < kBufferCount; i++)\n\t\t\tintList1.push_back(0);\n\n\t\tEATEST_VERIFY(intList1.size() == kBufferCount);\n\n\t\t// Try making a copy.\n\t\tIntListNode buffer2[kBufferCount];\n\t\tIntList intList2;\n\t\tintList2.get_allocator().init(buffer2, sizeof(buffer2), sizeof(IntListNode), kAlignOfIntListNode);\n\t\tintList2 = intList1;\n\t\tEATEST_VERIFY(intList2.size() == kBufferCount);\n\t}\n\n\t// fixed_allocator_with_overflow, ensure allocations are coming from fixed buffer. This is to\n\t// prevent a reported user regression where all allocations were being routed to the overflow\n\t// allocator.\n\t{\n\t\tconst int DEFAULT_VALUE = 0xbaadf00d;\n\t\tconst int TEST_VALUE = 0x12345689;\n\t\tconst size_t kBufferCount = 10;\n\n\t\ttypedef eastl::list<int, fixed_allocator_with_overflow> IntList;\n\t\ttypedef IntList::node_type IntListNode;\n\n\t\tconst size_t kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);\n\n\t\t// ensure the fixed buffer contains the default value that will be replaced\n\t\tIntListNode buffer1[kBufferCount];\n\t\tfor (int i = 0; i < kBufferCount; i++)\n\t\t{\n\t\t\tbuffer1[i].mValue = DEFAULT_VALUE;\n\t\t\tEATEST_VERIFY(buffer1[i].mValue == DEFAULT_VALUE);\n\t\t}\n\n\t\tIntList intList1;\n\n\t\t// replace all the values in the local buffer with the test value\n\t\tintList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);\n\t\tfor (size_t i = 0; i < kBufferCount; i++)\n\t\t\tintList1.push_back(TEST_VALUE);\n\n\t\t// ensure the local buffer has been altered with the contents of the list::push_back\n\t\tfor (int i = 0; i < kBufferCount; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(buffer1[i].mValue == TEST_VALUE);\n\t\t}\n\n\t\tintList1.clear();\n\t}\n\n\t{  // fixed_allocator_with_overflow\n\t\ttypedef eastl::list<int, fixed_allocator_with_overflow> IntList;\n\t\ttypedef IntList::node_type                              IntListNode;\n\n\t\tconst size_t  kBufferCount = 200;\n\t\tIntListNode   buffer1[kBufferCount];\n\t\tIntList       intList1;\n\t\tconst size_t  kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);\n\n\t\tintList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);\n\n\t\tfor(size_t i = 0; i < kBufferCount * 2; i++)\n\t\t\tintList1.push_back(0);\n\n\t\tEATEST_VERIFY(intList1.size() == (kBufferCount * 2));\n\n\t\t// Try making a copy.\n\t\tIntListNode buffer2[kBufferCount];\n\t\tIntList intList2;\n\t\tintList2.get_allocator().init(buffer2, sizeof(buffer2), sizeof(IntListNode), kAlignOfIntListNode);\n\t\tintList2 = intList1;\n\t\tEATEST_VERIFY(intList2.size() == (kBufferCount * 2));\n\t}\n\n\t{\n\t\t// fixed_pool_reference\n\t\ttypedef eastl::list<int, fixed_pool_reference> WidgetList;\n\t \n\t\tWidgetList::node_type buffer[16];\n\t\teastl::fixed_pool myPool(buffer, sizeof(buffer), sizeof(WidgetList::node_type), 16);\n\n\t\tWidgetList myList1(myPool);\n\t\tWidgetList myList2(myPool);\n\t \n\t\tmyList1.push_back(1);\n\t\tmyList2.push_back(1);\n\t\tEATEST_VERIFY(myList1 == myList2);\n\n\t\tmyList1.push_back(2);\n\t\tmyList1.sort();\n\t\tmyList2.push_front(2);\n\t\tmyList2.sort();\n\t\tEATEST_VERIFY(myList1 == myList2);\n\t}\n\n\treturn nErrorCount;\n}\nEA_RESTORE_VC_WARNING()\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestAllocatorMalloc\n//\nstatic int TestAllocatorMalloc()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\ttypedef eastl::list<int, eastl::allocator_malloc> WidgetList;\n\t \n\t\tWidgetList myList1;\n\t\tWidgetList myList2;\n\t \n\t\tmyList1.push_back(1);\n\t\tmyList2.push_back(1);\n\t\tEATEST_VERIFY(myList1 == myList2);\n\n\t\tmyList1.push_back(2);\n\t\tmyList1.sort();\n\t\tmyList2.push_front(2);\n\t\tmyList2.sort();\n\t\tEATEST_VERIFY(myList1 == myList2);\n\n\t\t#if EASTL_ALIGNED_MALLOC_AVAILABLE\n\t\t\t\n\t\t#endif\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n#if EASTL_DLL\n\tvoid* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\n\tvoid* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line);\n#endif\n\n\nstruct EASTLTestCoreAllocator\n{\npublic:\n\tvoid* Alloc(size_t size, const char* name, unsigned int flags)\n\t{\n\t\treturn ::operator new[](size, name, flags, 0, __FILE__, __LINE__);\n\t}\n\n\tvoid* Alloc(size_t size, const char* name, unsigned int flags,\n\t\t\t\t unsigned int alignment, unsigned int alignOffset = 0)\n\t{\n\t\treturn ::operator new[](size, alignment, alignOffset, name, flags, 0, __FILE__, __LINE__);\n\t}\n\n\tvoid Free(void* p, size_t /*size*/ = 0)\n\t{\n\t\t::operator delete((char*)p);\n\t}\n\n\tstatic EASTLTestCoreAllocator* GetDefaultAllocator();\n};\n\nEASTLTestCoreAllocator gEASTLTestCoreAllocator;\n\nEASTLTestCoreAllocator* EASTLTestCoreAllocator::GetDefaultAllocator()\n{\n\treturn &gEASTLTestCoreAllocator;\n}\n\n\n\nstruct TestClass\n{\n\tmutable int mX;\n\n\tTestClass() : mX(37) { }\n\n\tvoid Increment()\n\t\t{ mX++; }\n\n\tvoid IncrementConst() const\n\t\t{ mX++; }\n\n\tint MultiplyBy(int x)\n\t\t{ return mX * x; }\n\n\tint MultiplyByConst(int x) const\n\t\t{ return mX * x; }\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// TestCoreAllocatorAdapter\n//\nstatic int TestCoreAllocatorAdapter()\n{\n\tint nErrorCount = 0;\n\t\n#if EASTL_CORE_ALLOCATOR_ENABLED\n\ttypedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter;\n\n\teastl::list<TestClass, Adapter> widgetList(Adapter(\"UI/WidgetList\", &gEASTLTestCoreAllocator));\n\twidgetList.push_back(TestClass());\n\tEATEST_VERIFY(widgetList.size() == 1);\n\n\teastl::vector<TestClass, Adapter> widgetVector(100, Adapter(\"UI/WidgetVector\", &gEASTLTestCoreAllocator));\n\twidgetVector.push_back(TestClass());\n\tEATEST_VERIFY(widgetVector.size() == 101);\n\n\teastl::vector<TestClass, Adapter> widgetVector2(widgetVector);\n\twidgetVector2.resize(400);\n\tEATEST_VERIFY(widgetVector2.size() == 400);\n#endif\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestSwapAllocator\n//\nstatic int TestSwapAllocator()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tInstanceAllocator a(nullptr, (uint8_t)111), b(nullptr, (uint8_t)222);\n\t\teastl::swap(a, b);\n\t\t\n\t\tEATEST_VERIFY(a.mInstanceId == 222);\n\t\tEATEST_VERIFY(b.mInstanceId == 111);\n\n\t\tEATEST_VERIFY(EA::StdC::Strcmp(a.get_name(), \"InstanceAllocator 222\") == 0);\n\t\tEATEST_VERIFY(EA::StdC::Strcmp(b.get_name(), \"InstanceAllocator 111\") == 0);\n\t}\n\n\treturn nErrorCount;\n}\n\nstatic int TestAllocationOffsetAndAlignment()\n{\n\tint nErrorCount = 0;\n\n\tauto testAllocatorAlignment = [&nErrorCount](int requestedSize, int requestedAlignment, int requestedOffset)\n\t{\n\t\tCountingAllocator::resetCount();\n\t\tCountingAllocator a;\n\n\t\tvoid* p = allocate_memory(a, requestedSize, requestedAlignment, requestedOffset);\n\n\t\tEATEST_VERIFY(p != nullptr);\n\t\tEATEST_VERIFY(EA::StdC::IsAligned(p, requestedAlignment));\n\n\t\ta.deallocate(p, requestedSize);\n\t\tEATEST_VERIFY(CountingAllocator::getActiveAllocationSize() == 0);\n\t};\n\n\ttestAllocatorAlignment(100, 1, 0);\n\ttestAllocatorAlignment(100, 2, 0);\n\ttestAllocatorAlignment(100, 4, 0);\n\ttestAllocatorAlignment(100, 8, 0);\n\ttestAllocatorAlignment(100, 16, 0);\n\n\ttestAllocatorAlignment(100, 1, 16);\n\ttestAllocatorAlignment(100, 2, 16);\n\ttestAllocatorAlignment(100, 4, 16);\n\ttestAllocatorAlignment(100, 8, 16);\n\ttestAllocatorAlignment(100, 16, 16);\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestAllocator\n//\nint TestAllocator()\n{\n\tint nErrorCount = 0;\n\t\n\tnErrorCount += TestAllocationOffsetAndAlignment();\n\tnErrorCount += TestFixedAllocator();\n\tnErrorCount += TestAllocatorMalloc();\n\tnErrorCount += TestCoreAllocatorAdapter();\n\tnErrorCount += TestSwapAllocator();\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestAllocatorPropagate.cpp",
    "content": "// (c) 2023 Electronic Arts Inc.\n\n#include \"EASTLTest.h\"\n#include <EASTL/list.h>\n#include <EASTL/slist.h>\n#include <EASTL/vector.h>\n#include <EASTL/deque.h>\n#include <EASTL/map.h>\n#include <EASTL/set.h>\n#include <EASTL/string.h>\n#include <EASTL/hash_map.h>\n#include <EASTL/hash_set.h>\n#include <EASTL/segmented_vector.h>\n#include <EASTL/fixed_list.h>\n#include <EASTL/fixed_slist.h>\n#include <EASTL/fixed_vector.h>\n#include <EASTL/fixed_map.h>\n#include <EASTL/fixed_set.h>\n#include <EASTL/fixed_hash_map.h>\n#include <EASTL/fixed_hash_set.h>\n#include <EASTL/fixed_string.h>\n\ntemplate<typename Container, typename Elem>\nint TestPropagateOnContainerCopyAssignment(std::initializer_list<Elem> ilist1, std::initializer_list<Elem> ilist2, const char* containerName)\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tContainer c1(ilist1, InstanceAllocator(1));\n\t\tContainer c2(ilist2, InstanceAllocator(2));\n\n\t\tEATEST_VERIFY(get_allocator(c1).mInstanceId == 1);\n\t\tEATEST_VERIFY(get_allocator(c2).mInstanceId == 2);\n\t\tEATEST_VERIFY(get_allocator(c1) != get_allocator(c2));\n\n\t\tc1 = c2;\n\t\tEATEST_VERIFY(c1 == c2);\n\n\t\t// eastl containers have propagate_on_container_copy_assignment behaviour iff EASTL_ALLOCATOR_COPY_ENABLED.\n\t\tbool allocatorsEqual = (get_allocator(c1) == get_allocator(c2));\n\t\tEATEST_VERIFY(allocatorsEqual == (bool)EASTL_ALLOCATOR_COPY_ENABLED);\n\n\t\t// destroying containers to invoke InstanceAllocator::deallocate() checks\n\t}\n\n\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t                  \"Container elements should be deallocated by the allocator that allocated it.\");\n\n\tif(nErrorCount > 0)\n\t\tEASTLTest_Printf(\"Propagate on %s copy assignment: failure\\n\", containerName);\n\n\treturn nErrorCount;\n}\n\ntemplate<typename Container, typename Elem>\nint TestPropagateOnContainerMoveAssignment(std::initializer_list<Elem> ilist1, std::initializer_list<Elem> ilist2, const char* containerName)\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tContainer c1(ilist1, InstanceAllocator(1));\n\t\tContainer c2(ilist2, InstanceAllocator(2));\n\t\t\n\t\tEATEST_VERIFY(get_allocator(c1).mInstanceId == 1);\n\t\tEATEST_VERIFY(get_allocator(c2).mInstanceId == 2);\n\t\tEATEST_VERIFY(get_allocator(c1) != get_allocator(c2));\n\n\t\tc1 = eastl::move(c2);\n\n\t\t// eastl containers have propagate_on_container_move_assignment behaviour.\n\t\tEATEST_VERIFY(get_allocator(c1).mInstanceId == 2);\n\n\t\t// destroying containers to invoke InstanceAllocator::deallocate() checks\n\t}\n\n\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t                  \"Container elements should be deallocated by the allocator that allocated it.\");\n\n\tif (nErrorCount > 0)\n\t\tEASTLTest_Printf(\"Propagate on %s move assignment: failure\\n\", containerName);\n\n\treturn nErrorCount;\n}\n\ntemplate<typename Container, typename Elem>\nint TestPropagateOnContainerSwap(std::initializer_list<Elem> ilist1, std::initializer_list<Elem> ilist2, const char* containerName)\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tContainer c1(ilist1, InstanceAllocator(1));\n\t\tContainer c2(ilist2, InstanceAllocator(2));\n\t\t\n\t\tEATEST_VERIFY(get_allocator(c1).mInstanceId == 1);\n\t\tEATEST_VERIFY(get_allocator(c2).mInstanceId == 2);\n\t\tEATEST_VERIFY(get_allocator(c1) != get_allocator(c2));\n\n\t\teastl::swap(c1, c2);\n\n\t\t// eastl containers have propagate_on_container_swap behaviour.\n\t\tEATEST_VERIFY(get_allocator(c1).mInstanceId == 2);\n\t\tEATEST_VERIFY(get_allocator(c2).mInstanceId == 1);\n\t\tEATEST_VERIFY(get_allocator(c1) != get_allocator(c2));\n\n\t\t// destroying containers to invoke InstanceAllocator::deallocate() checks\n\t}\n\n\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t                  \"Container elements should be deallocated by the allocator that allocated it.\");\n\n\tif (nErrorCount > 0)\n\t\tEASTLTest_Printf(\"Propagate on %s swap: failure\\n\", containerName);\n\n\treturn nErrorCount;\n}\n\nint TestAllocatorPropagate()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<list<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"list\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<slist<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"slist\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<vector<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"vector\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<deque<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"deque\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<segmented_vector<int, 32, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"segmented_vector\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<map<int, int, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"map\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<multimap<int, int, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"multimap\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<set<int, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"set\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<multiset<int, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"multiset\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<hash_map<int, int, hash<int>, equal_to<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"hash_map\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<hash_multimap<int, int, hash<int>, equal_to<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"hash_multimap\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<hash_set<int, hash<int>, equal_to<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"hash_set\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<hash_multiset<int, hash<int>, equal_to<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"hash_multiset\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<basic_string<char, InstanceAllocator>>({ 'a', 'b', 'c' }, { 'd', 'e', 'f' }, \"basic_string\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_list<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_list\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_slist<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_slist\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_vector<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_vector\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_map<int, int, 8, true, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_map\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_multimap<int, int, 8, true, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_multimap\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_set<int, 8, true, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_set\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_multiset<int, 8, true, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_multiset\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_hash_map<int, int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_hash_map\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_hash_multimap<int, int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_hash_multimap\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_hash_set<int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_hash_set\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_hash_multiset<int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_hash_multiset\");\n\tnErrorCount += TestPropagateOnContainerCopyAssignment<fixed_string<char, 8, true, InstanceAllocator>>({ 'a', 'b', 'c' }, { 'd', 'e', 'f' }, \"fixed_string\");\n\n\t// commenting out containers with irregular propagation behaviour:\n\t// nErrorCount += TestPropagateOnContainerMoveAssignment<list<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"list\");\n\t// nErrorCount += TestPropagateOnContainerMoveAssignment<slist<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"slist\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<vector<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"vector\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<deque<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"deque\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<segmented_vector<int, 32, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"segmented_vector\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<map<int, int, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"map\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<multimap<int, int, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"multimap\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<set<int, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"set\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<multiset<int, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"multiset\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<hash_map<int, int, hash<int>, equal_to<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"hash_map\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<hash_multimap<int, int, hash<int>, equal_to<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"hash_multimap\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<hash_set<int, hash<int>, equal_to<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"hash_set\");\n\tnErrorCount += TestPropagateOnContainerMoveAssignment<hash_multiset<int, hash<int>, equal_to<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"hash_multiset\");\n\t// nErrorCount += TestPropagateOnContainerMoveAssignment<basic_string<char, InstanceAllocator>>({ 'a', 'b', 'c' }, { 'd', 'e', 'f' }, \"basic_string\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_list<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_list\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_slist<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_slist\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_vector<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_vector\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_map<int, int, 8, true, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_map\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_multimap<int, int, 8, true, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_multimap\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_set<int, 8, true, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_set\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_multiset<int, 8, true, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_multiset\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_hash_map<int, int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_hash_map\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_hash_multimap<int, int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_hash_multimap\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_hash_set<int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_hash_set\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_hash_multiset<int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_hash_multiset\");\n\t//nErrorCount += TestPropagateOnContainerMoveAssignment<fixed_string<char, 8, true, InstanceAllocator>>({ 'a', 'b', 'c' }, { 'd', 'e', 'f' }, \"fixed_string\");\n\n\t// nErrorCount += TestPropagateOnContainerSwap<list<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"list\");\n\t// nErrorCount += TestPropagateOnContainerSwap<slist<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"slist\");\n\tnErrorCount += TestPropagateOnContainerSwap<vector<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"vector\");\n\tnErrorCount += TestPropagateOnContainerSwap<deque<int, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"deque\");\n\tnErrorCount += TestPropagateOnContainerSwap<segmented_vector<int, 32, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"segmented_vector\");\n\tnErrorCount += TestPropagateOnContainerSwap<map<int, int, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"map\");\n\tnErrorCount += TestPropagateOnContainerSwap<multimap<int, int, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"multimap\");\n\tnErrorCount += TestPropagateOnContainerSwap<set<int, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"set\");\n\tnErrorCount += TestPropagateOnContainerSwap<multiset<int, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"multiset\");\n\tnErrorCount += TestPropagateOnContainerSwap<hash_map<int, int, hash<int>, equal_to<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"hash_map\");\n\tnErrorCount += TestPropagateOnContainerSwap<hash_multimap<int, int, hash<int>, equal_to<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"hash_multimap\");\n\tnErrorCount += TestPropagateOnContainerSwap<hash_set<int, hash<int>, equal_to<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"hash_set\");\n\tnErrorCount += TestPropagateOnContainerSwap<hash_multiset<int, hash<int>, equal_to<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"hash_multiset\");\n\t// nErrorCount += TestPropagateOnContainerSwap<basic_string<char, InstanceAllocator>>({ 'a', 'b', 'c' }, { 'd', 'e', 'f' }, \"basic_string\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_list<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_list\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_slist<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_slist\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_vector<int, 8, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_vector\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_map<int, int, 8, true, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_map\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_multimap<int, int, 8, true, less<int>, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_multimap\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_set<int, 8, true, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_set\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_multiset<int, 8, true, less<int>, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_multiset\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_hash_map<int, int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_hash_map\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_hash_multimap<int, int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ pair<const int, int>(1, 1) }, { pair<const int, int>(2, 2) }, \"fixed_hash_multimap\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_hash_set<int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_hash_set\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_hash_multiset<int, 8, 9, true, hash<int>, equal_to<int>, true, InstanceAllocator>>({ 1, 2, 3 }, { 4, 5, 6 }, \"fixed_hash_multiset\");\n\t//nErrorCount += TestPropagateOnContainerSwap<fixed_string<char, 8, true, InstanceAllocator>>({ 'a', 'b', 'c' }, { 'd', 'e', 'f' }, \"fixed_string\");\n\n\t// container adaptors are not tested because their behaviour should be the same as their underlying container:\n\t// queue\n\t// priority_queue\n\t// stack\n\t// vector_map\n\t// vector_multimap\n\t// vector_set\n\t// vector_multiset\n\t// ring_buffer\n\t// lru_cache\n\n\t// other containers not tested:\n\t// string_hash_map - doesn't have appropriate constructor.\n\t// string_map - doesn't have appropriate constructor.\n\t// list_map - doesn't have appropriate constructor.\n\t// tuple_vector_alloc - what is this type?\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestAny.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/any.h>\n#include <EASTL/vector.h>\n#include <EASTL/string.h>\n#include <EASTL/numeric.h>\n#include <EAStdC/EAString.h>\n\n\n// SmallTestObject\n//\nstruct SmallTestObject\n{\n\tstatic int mCtorCount;\n\n\tSmallTestObject() EA_NOEXCEPT { mCtorCount++; }\n\tSmallTestObject(const SmallTestObject&) EA_NOEXCEPT { mCtorCount++; }\n\tSmallTestObject(SmallTestObject&&) EA_NOEXCEPT { mCtorCount++; }\n\tSmallTestObject& operator=(const SmallTestObject&) EA_NOEXCEPT { mCtorCount++; return *this; }\n\t~SmallTestObject() EA_NOEXCEPT { mCtorCount--; }\n\n\tstatic void Reset() { mCtorCount = 0; }\n\tstatic bool IsClear() { return mCtorCount == 0; }\n};\n\nint SmallTestObject::mCtorCount = 0;\n\n\n// RequiresInitList\n//\nstruct RequiresInitList\n{\n\tRequiresInitList(std::initializer_list<int> ilist)\n\t: sum(eastl::accumulate(begin(ilist), end(ilist), 0)) {}\n\n\tint sum;\n};\n\n\nint TestAny()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t// NOTE(rparolin): Ensure 'any' is at least the size of an eastl::string and an eastl::vector to prevent heap\n\t// allocation of handle objects (objects that point to a heap allocation).  This will reduce memory pressure since\n\t// eastl::string will be a commonly used type.  We could also test with a vector.\n\t{\n\t\tstatic_assert(sizeof(eastl::string) <= sizeof(eastl::any), \"ensure that 'any' has enough local memory to store a string\");\n\t\tstatic_assert(sizeof(eastl::vector<int>) <= sizeof(eastl::any), \"ensure that 'any' has enough local memory to store a vector\");\n\t}\n\n\t{\n\t  // default construct\n\t\tany a;\n\t\tVERIFY(a.has_value() == false);\n\t}\n\n\t{\n\t\t// test object ctors & dtors are called for a large object\n\t\tTestObject::Reset();\n\t\t{ any a{TestObject()}; }\n\t\tVERIFY(TestObject::IsClear());\n\t}\n\n\t{\n\t\t// test object ctors & dtors are called for a small object\n\t\tSmallTestObject::Reset();\n\t\t{ any a{SmallTestObject()}; }\n\t\tVERIFY(SmallTestObject::IsClear());\n\t}\n\n\t{\n\t\tany a(42);\n\t\tVERIFY(a.has_value() == true);\n\n\t\tVERIFY(any_cast<int>(a) == 42);\n\t\tVERIFY(any_cast<int>(a) != 1337);\n\t\tany_cast<int&>(a) = 10;\n\t\tVERIFY(any_cast<int>(a) == 10);\n\n\t\ta = 1.f;\n\t\tany_cast<float&>(a) = 1337.f;\n\t\tVERIFY(any_cast<float>(a) == 1337.f);\n\n\t\ta = 4343;\n\t\tVERIFY(any_cast<int>(a) == 4343);\n\n\t\ta = string(\"hello world\");\n\t\tVERIFY(any_cast<string>(a) == \"hello world\");\n\t\tVERIFY(any_cast<string&>(a) == \"hello world\");\n\t}\n\n\t{\n\t\tstruct custom_type { int data; };\n\n\t\tany a = custom_type{};\n\t\tany_cast<custom_type&>(a).data = 42;\n\t\tVERIFY(any_cast<custom_type>(a).data == 42);\n\t}\n\n\t{\n\t\tany a = 42;\n\t\tVERIFY(any_cast<int>(a) == 42);\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tint throwCount = 0;\n\t\t\ttry { VERIFY(any_cast<short>(a) == 42); }\n\t\t\tcatch (bad_any_cast) { throwCount++;  }\n\t\t\tVERIFY(throwCount != 0);\n\t\t#endif\n\t}\n\n\t{\n\t\tvector<any> va = {42, 'a', 42.f, 3333u, 4444ul, 5555ull, 6666.0};\n\n\t\tVERIFY(any_cast<int>(va[0]) == 42);\n\t\tVERIFY(any_cast<char>(va[1]) == 'a');\n\t\tVERIFY(any_cast<float>(va[2]) == 42.f);\n\t\tVERIFY(any_cast<unsigned>(va[3]) == 3333u);\n\t\tVERIFY(any_cast<unsigned long>(va[4]) == 4444ul);\n\t\tVERIFY(any_cast<unsigned long long>(va[5]) == 5555ull);\n\t\tVERIFY(any_cast<double>(va[6]) == 6666.0);\n\t}\n\n\t{\n\t\tany a(string(\"test string\"));\n\t\tVERIFY(a.has_value());\n\t\tVERIFY(any_cast<string>(a) == \"test string\");\n\t}\n\n\t{\n\t\tvector<any> va = {42, string(\"rob\"), 'a', 42.f};\n\t\tVERIFY(any_cast<int>(va[0]) == 42);\n\t\tVERIFY(any_cast<string>(va[1]) == \"rob\");\n\t\tVERIFY(any_cast<char>(va[2]) == 'a');\n\t\tVERIFY(any_cast<float>(va[3]) == 42.f);\n\t}\n\n\t{\n\t\tvector<any> va;\n\t\tva.push_back(42);\n\t\tva.push_back(string(\"rob\"));\n\t\tva.push_back('a');\n\t\tva.push_back(42.f);\n\n\t\tVERIFY(any_cast<int>(va[0]) == 42);\n\t\tVERIFY(any_cast<string>(va[1]) == \"rob\");\n\t\tVERIFY(any_cast<char>(va[2]) == 'a');\n\t\tVERIFY(any_cast<float>(va[3]) == 42.f);\n\t}\n\n\t// NOTE(rparolin):  Replaces a small 'any' object with a large one and make sure it doesn't corrupt\n\t// the surrounding memory in the vector.\n\t{\n\t\tTestObject::Reset();\n\t\t{\n\t\t\tvector<any> va = {42, 'a', 42.f, 3333u, 4444ul, 5555ull, 6666.0};\n\n\t\t\tVERIFY(any_cast<int>(va[0]) == 42);\n\t\t\tVERIFY(any_cast<char>(va[1]) == 'a');\n\t\t\tVERIFY(any_cast<float>(va[2]) == 42.f);\n\t\t\tVERIFY(any_cast<unsigned>(va[3]) == 3333u);\n\t\t\tVERIFY(any_cast<unsigned long>(va[4]) == 4444ul);\n\t\t\tVERIFY(any_cast<unsigned long long>(va[5]) == 5555ull);\n\t\t\tVERIFY(any_cast<double>(va[6]) == 6666.0);\n\n\t\t\tva[3] = TestObject(3333); // replace a small integral with a large heap allocated object.\n\n\t\t\tVERIFY(any_cast<int>(va[0]) == 42);\n\t\t\tVERIFY(any_cast<char>(va[1]) == 'a');\n\t\t\tVERIFY(any_cast<float>(va[2]) == 42.f);\n\t\t\tVERIFY(any_cast<TestObject>(va[3]).mX == 3333); // not 3333u because TestObject ctor takes a signed type.\n\t\t\tVERIFY(any_cast<unsigned long>(va[4]) == 4444ul);\n\t\t\tVERIFY(any_cast<unsigned long long>(va[5]) == 5555ull);\n\t\t\tVERIFY(any_cast<double>(va[6]) == 6666.0);\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t}\n\n\t{\n\t\tany a(string(\"test string\"));\n\t\tVERIFY(a.has_value());\n\t\ta.reset();\n\t\tVERIFY(!a.has_value());\n\t}\n\n\t{\n\t\tany a1 = 42;\n\t\tany a2 = a1;\n\n\t\tVERIFY(a1.has_value());\n\t\tVERIFY(a2.has_value());\n\t\tVERIFY(any_cast<int>(a1) == any_cast<int>(a2));\n\t}\n\n\t{\n\t\tany a1;\n\t\tVERIFY(!a1.has_value());\n\t\t{\n\t\t\tany a2(string(\"test string\"));\n\t\t\ta1 = any_cast<string>(a2);\n\n\t\t\tVERIFY(a1.has_value());\n\t\t}\n\t\tVERIFY(any_cast<string>(a1) == \"test string\");\n\t\tVERIFY(a1.has_value());\n\t}\n\n\t{\n\t\tany a1;\n\t\tVERIFY(!a1.has_value());\n\t\t{\n\t\t\tany a2(string(\"test string\"));\n\t\t\ta1 = a2;\n\t\t\tVERIFY(a1.has_value());\n\t\t}\n\t\tVERIFY(any_cast<string&>(a1) == \"test string\");\n\t\tVERIFY(a1.has_value());\n\t}\n\n\t// swap tests\n\t{\n\t\t{\n\t\t\tany a1 = 42;\n\t\t\tany a2 = 24;\n\t\t\tVERIFY(any_cast<int>(a1) == 42);\n\t\t\tVERIFY(any_cast<int>(a2) == 24);\n\n\t\t\ta1.swap(a2);\n\t\t\tVERIFY(any_cast<int>(a1) == 24);\n\t\t\tVERIFY(any_cast<int>(a2) == 42);\n\n\t\t\teastl::swap(a1, a2);\n\t\t\tVERIFY(any_cast<int>(a1) == 42);\n\t\t\tVERIFY(any_cast<int>(a2) == 24);\n\t\t}\n\t\t{\n\t\t\tany a1 = string(\"hello\");\n\t\t\tany a2 = string(\"world\");\n\t\t\tVERIFY(any_cast<string>(a1) == \"hello\");\n\t\t\tVERIFY(any_cast<string>(a2) == \"world\");\n\n\t\t\ta1.swap(a2);\n\t\t\tVERIFY(any_cast<string>(a1) == \"world\");\n\t\t\tVERIFY(any_cast<string>(a2) == \"hello\");\n\n\t\t\teastl::swap(a1, a2);\n\t\t\tVERIFY(any_cast<string>(a1) == \"hello\");\n\t\t\tVERIFY(any_cast<string>(a2) == \"world\");\n\t\t}\n\t}\n\n\t#if EASTL_RTTI_ENABLED\n\t{\n\t\t#if defined(EA_COMPILER_MSVC)\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42).type().name(), \"int\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42.f).type().name(), \"float\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42u).type().name(), \"unsigned int\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42ul).type().name(), \"unsigned long\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42l).type().name(), \"long\") == 0);\n\n\t\t#elif defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_GNUC)\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42).type().name(), \"i\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42.f).type().name(), \"f\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42u).type().name(), \"j\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42ul).type().name(), \"m\") == 0);\n\t\t\tVERIFY(EA::StdC::Strcmp(any(42l).type().name(), \"l\") == 0);\n\t\t#endif\n\t}\n\t#endif\n\n\t// emplace, small object tests\n\t{\n\t\tany a;\n\n\t\tVERIFY(a.emplace<int>(42) == 42);\n\t\tVERIFY(a.has_value());\n\t\tVERIFY(any_cast<int>(a) == 42);\n\n\t\tVERIFY(a.emplace<short>((short)8) == (short)8); // no way to define a short literal we must cast here.\n\t\tVERIFY(any_cast<short>(a) == 8);\n\t\tVERIFY(a.has_value());\n\n\t\ta.reset();\n\t\tVERIFY(!a.has_value());\n\t}\n\n\t// emplace, large object tests\n\t{\n\t\tTestObject::Reset();\n\t\t{\n\t\t\tany a;\n\t\t\tVERIFY(a.emplace<TestObject>() == TestObject());\n\t\t\tVERIFY(a.has_value());\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t}\n\n\t// emplace, initializer_list\n\t{\n\t\t{\n\t\t\tany a;\n\t\t\tVERIFY((a.emplace<RequiresInitList>(std::initializer_list<int>{1, 2, 3, 4, 5, 6}).sum == RequiresInitList{ 1, 2, 3, 4, 5, 6 }.sum));\n\n\t\t\tVERIFY(a.has_value());\n\t\t\tVERIFY(any_cast<RequiresInitList>(a).sum == 21);\n\t\t}\n\t}\n\n\t// emplace, types that decay\n\t{\n\t\t// T[] decays to T*\n\t\t{\n\t\t\tany a;\n\t\t\tint arr[] = { 1, 2, 3 };\n\t\t\tauto emplaced = a.emplace<int[]>(arr);\n\t\t\tstatic_assert(eastl::is_same_v<decltype(emplaced), int*>, \"decay-ed emplace\");\n\t\t\tVERIFY(VerifySequence(emplaced, emplaced + 3, { 1, 2, 3 }, \"any::emplace()\"));\n\t\t}\n\n\t\t// function decays to pointer to function\n\t\t{\n\t\t\tint(*func) (char, char) = [](char, char) { return 0; };\n\n\t\t\tany a;\n\t\t\tauto emplaced = a.emplace<int(char, char)>(func);\n\t\t\tstatic_assert(eastl::is_same_v<decltype(emplaced), int(*)(char, char)>, \"decay-ed emplace\");\n\t\t\tVERIFY(emplaced == func);\n\t\t}\n\n\t\t// const T decays to T\n\t\t{\n\t\t\tany a;\n\t\t\tauto emplaced = a.emplace<const int>(10);\n\t\t\tstatic_assert(eastl::is_same_v<decltype(emplaced), int>, \"decay-ed emplace\");\n\t\t\tVERIFY(emplaced == 10);\n\t\t}\n\t}\n\n\t// equivalence tests\n\t{\n\t\tany a, b;\n\t\tVERIFY(!a.has_value() == !b.has_value());\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tint bad_any_cast_thrown = 0;\n\t\t\ttry\n\t\t\t{\n\t\t\t\tVERIFY(any_cast<int>(a) == any_cast<int>(b));\n\t\t\t}\n\t\t\tcatch (eastl::bad_any_cast)\n\t\t\t{\n\t\t\t\tbad_any_cast_thrown++;\n\t\t\t}\n\t\t\tVERIFY(bad_any_cast_thrown != 0);\n\t\t#endif\n\n\n\t\ta = 42; b = 24;\n\t\tVERIFY(any_cast<int>(a) != any_cast<int>(b));\n\t\tVERIFY(a.has_value() == b.has_value());\n\n\t\ta = 42; b = 42;\n\t\tVERIFY(any_cast<int>(a) == any_cast<int>(b));\n\t\tVERIFY(a.has_value() == b.has_value());\n\t}\n\n\t// move tests\n\t{\n\t\tany a = string(\"hello world\"); \n\t\tVERIFY(any_cast<string&>(a) == \"hello world\");\n\n\t\tauto s = move(any_cast<string&>(a)); // move string out\n\t\tVERIFY(s == \"hello world\");\n\t\tVERIFY(any_cast<string&>(a).empty());\n\n\t\tany_cast<string&>(a) = move(s); // move string in\n\t\tVERIFY(any_cast<string&>(a) == \"hello world\");\n\t}\n\n\t// nullptr tests\n\t{\n\t\tany* a = nullptr;\n\t\tVERIFY(any_cast<int>(a) == nullptr);\n\t\tVERIFY(any_cast<short>(a) == nullptr);\n\t\tVERIFY(any_cast<long>(a) == nullptr);\n\t\tVERIFY(any_cast<string>(a) == nullptr);\n\n\t\tany b;\n\t\tVERIFY(any_cast<short>(&b) == nullptr);\n\t\tVERIFY(any_cast<const short>(&b) == nullptr);\n\t\tVERIFY(any_cast<volatile short>(&b) == nullptr);\n\t\tVERIFY(any_cast<const volatile short>(&b) == nullptr);\n\n\t\tVERIFY(any_cast<short*>(&b) == nullptr);\n\t\tVERIFY(any_cast<const short*>(&b) == nullptr);\n\t\tVERIFY(any_cast<volatile short*>(&b) == nullptr);\n\t\tVERIFY(any_cast<const volatile short*>(&b) == nullptr);\n\t}\n\n\t// Aligned type tests\n\t{\n\t\t{\n\t\t   any a = Align16(1337);\n\t\t   VERIFY(any_cast<Align16>(a) == Align16(1337));\n\t\t}\n\t\t\n\t\t{\n\t\t\tany a = Align32(1337);\n\t\t\tVERIFY(any_cast<Align32>(a) == Align32(1337));\n\t\t}\n\t\t\n\t\t{\n\t\t\tany a = Align64(1337);\n\t\t\tVERIFY(any_cast<Align64>(a) == Align64(1337));\n\t\t}\n\t}\n\n\t// make_any\n\t{\n\t\t{\n\t\t\tauto a = make_any<int>(42);\n\t\t\tVERIFY(any_cast<int>(a) == 42);\n\t\t}\n\n\t\t{\n\t\t\tauto a = make_any<RequiresInitList>(std::initializer_list<int>{1,2,3,4,5,6,7,8});\n\t\t\tVERIFY(any_cast<RequiresInitList&>(a).sum == 36);\n\t\t}\n\t}\n\n\t// user reported regression that eastl::any constructor was not decaying the deduced type correctly.\n\t{\n\t\tfloat f = 42.f;\n\t\teastl::any a(f);\n\t\tVERIFY(any_cast<float>(a) == 42.f);\n\t}\n\n\t//testing unsafe operations\n\t{\n\t\teastl::any a = 1;\n\t\tint* i = eastl::any_cast<int>(&a);\n\t\tVERIFY((*i) == 1);\n\n\t\ta = 2;\n\t\tint *j = (int*)eastl::unsafe_any_cast<void>(&a);\n\t\tVERIFY((*j) == 2);\n\n\t\tconst eastl::any b = 3;\n\t\tconst void * p = eastl::unsafe_any_cast<void>(&b);\n\t\tvoid *q = const_cast<void *>(p);\n\t\tint *r = static_cast<int *>(q);\n\t\tVERIFY((*r) == 3);\n\t}\n\n\t// user regression when calling the assignment operator\n\t{\n\t\t{\n\t\t\teastl::any a1;\n\t\t\teastl::any a2;\n\t\t\tVERIFY(a1.has_value() == false);\n\t\t\tVERIFY(a2.has_value() == false);\n\n\t\t\ta1 = a2;\n\t\t\tVERIFY(a1.has_value() == false);\n\t\t\tVERIFY(a2.has_value() == false);\n\t\t}\n\n\t\t{\n\t\t\teastl::any a1 = 42;\n\t\t\teastl::any a2;\n\t\t\tVERIFY(a1.has_value() == true);\n\t\t\tVERIFY(a2.has_value() == false);\n\n\t\t\ta1 = a2;\n\t\t\tVERIFY(a1.has_value() == false);\n\t\t\tVERIFY(a2.has_value() == false);\n\t\t}\n\n\t\t{\n\t\t\teastl::any a1;\n\t\t\teastl::any a2 = 42;\n\t\t\tVERIFY(a1.has_value() == false);\n\t\t\tVERIFY(a2.has_value() == true);\n\n\t\t\ta1 = a2;\n\t\t\tVERIFY(a1.has_value() == true);\n\t\t\tVERIFY(a2.has_value() == true);\n\t\t\tVERIFY(any_cast<int>(a1) == 42);\n\t\t\tVERIFY(any_cast<int>(a2) == 42);\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\n\n"
  },
  {
    "path": "test/source/TestArray.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/array.h>\n#include <EABase/eabase.h>\n\n\n\nusing namespace eastl;\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate struct eastl::array<int, 0>;\ntemplate struct eastl::array<int, 5>;\ntemplate struct eastl::array<Align32, 5>; // VC++ fails to compile due to error generated by the swap function. C2718: http://msdn.microsoft.com/en-us/library/vstudio/sxe76d9e.aspx\n\ntemplate<typename T> class TP;\n\n// test whether typename tuple_element<I, T>::type is defined:\ntemplate<size_t I, typename T, typename = void>\nstruct has_tuple_element_type : false_type {};\n\ntemplate<size_t I, typename T>\nstruct has_tuple_element_type<I, T, void_t<typename tuple_element<I, T>::type>> : true_type {};\n\nstatic_assert(eastl::is_aggregate<eastl::array<int, 0>>::value, \"must be an aggregate\");\nstatic_assert(eastl::is_aggregate<eastl::array<int, 5>>::value, \"must be an aggregate\");\n\nint TestArray()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tarray<int, 5> a = { { 0, 1, 2, 3, 4 } };\n\t\tarray<int, 5> b = { { 0, 1, 2, 3    } };\n\t\tarray<int, 5> c = { { 4, 3, 2, 1, 0 } };\n\t\tarray<int, 0> d = {};\n\n\t\tVERIFY(!a.empty());\n\t\tVERIFY(a.size() == 5);\n\t\tVERIFY(a[0] == 0);\n\t\tVERIFY(a[4] == 4);\n\n\t\tVERIFY(!b.empty());\n\t\tVERIFY(b.size() == 5);\n\t\tVERIFY(b[0] == 0);\n\t\tVERIFY(b[3] == 3);\n\n\t\tVERIFY(d.empty());\n\t\tVERIFY(d.size() == 0);\n\n\t\t// swap\n\t\ta.swap(c);\n\t\tVERIFY(a[0] == 4);\n\t\tVERIFY(c[0] == 0);\n\n\t\t// begin, end\n\t\tarray<int, 5>::iterator it = a.begin();\n\t\tVERIFY((a.validate_iterator(it) & (isf_valid | isf_can_dereference)) != 0);\n\t\tVERIFY(*it == 4);\n\n\t\t++it;\n\t\tVERIFY(*it == 3);\n\n\t\t++it;\n\t\tVERIFY(*it == 2);\n\n\t\t--it;\n\t\tVERIFY(*it == 3);\n\n\t\tit += 3;\n\t\tVERIFY((a.validate_iterator(it) & (isf_valid | isf_can_dereference)) != 0);\n\t\tVERIFY(*it == 0);\n\n\t\t++it;\n\t\tVERIFY(it == a.end());\n\t\tVERIFY((a.validate_iterator(it) & isf_valid) != 0);\n\t\tVERIFY(a.validate());\n\n\t\t// rbegin, rend\n\t\tarray<int, 5>::reverse_iterator itr = a.rbegin();\n\t\tVERIFY((a.validate_iterator(itr.base()) & (isf_valid | isf_can_dereference)) != 0);\n\t\tVERIFY(*itr == 0);\n\n\t\titr++;\n\t\tVERIFY(*itr == 1);\n\n\t\t// data\n\t\tint* pArray = a.data();\n\t\tVERIFY(pArray == a.mValue);\n\n\t\t// front\n\t\tint& nFront = a.front();\n\t\tVERIFY(nFront == 4);\n\n\t\t// back\n\t\tint& nBack = a.back();\n\t\tVERIFY(nBack == 0);\n\n\t\t// at\n\t\tVERIFY(a[0] == a.at(0));\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tbool bExceptionOccurred = false;\n\t\t\ttry{\n\t\t\t\tint x = a.at(100);\n\t\t\t\tVERIFY(x != -1);\n\t\t\t}\n\t\t\tcatch(...){\n\t\t\t\tbExceptionOccurred = true;\n\t\t\t}\n\t\t\tVERIFY(bExceptionOccurred);\n\t\t#endif\n\n\t\t// global operators\n\t\ta[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3; a[4] = 4;  // 01234\n\t\tb[0] = 0; b[1] = 1; b[2] = 2; b[3] = 3; b[4] = 4;  // 01234\n\t\tc[0] = 0; c[1] = 1; c[2] = 2; c[3] = 3; c[4] = 9;  // 01239\n\n\t\tVERIFY( (a == b));\n\t\tVERIFY(!(a != b));\n\t\tVERIFY(!(a  < b));\n\t\tVERIFY( (a <= b));\n\t\tVERIFY( (a >= b));\n\t\tVERIFY(!(a  > b));\n\n\t\tVERIFY(!(a == c));\n\t\tVERIFY( (a != c));\n\t\tVERIFY( (a  < c));\n\t\tVERIFY( (a <= c));\n\t\tVERIFY(!(a >= c));\n\t\tVERIFY(!(a  > c));\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\tVERIFY( (a <=> b) == 0);\n\t\tVERIFY(!((a <=> b) != 0));\n\t\tVERIFY(!((a <=> b) < 0));\n\t\tVERIFY( (a <=> b) <= 0);\n\t\tVERIFY( (a <=> b) >= 0);\n\t\tVERIFY(!((a <=> b) > 0));\n\n\t\tVERIFY(!((a <=> c) == 0));\n\t\tVERIFY( (a <=> c) != 0);\n\t\tVERIFY( (a <=> c) < 0);\n\t\tVERIFY( (a <=> c) <= 0);\n\t\tVERIFY(!((a <=> c) >= 0));\n\t\tVERIFY(!((a <=> c) > 0));\n#endif\n\n\t\t// deduction guides\n\t\t#ifdef __cpp_deduction_guides\n\t\t\tarray deduced {1,2,3,4,5};\n\n\t\t\tstatic_assert(eastl::is_same_v<decltype(deduced)::value_type, int>, \"deduced array value_type mismatch\");\n\t\t\tVERIFY(deduced.size() == 5);\n\t\t#endif\n\n\t\teastl::array<int, 0> empty_array;\n\t\tVERIFY(empty_array.size() == 0); // array with 0 elements is empty\n\n\t\t// structured binding\n\n\t\t{\n\t\t\teastl::array<int, 5> aCopy = a;\n\t\t\tauto&& [a0, a1, a2, a3, a4] = aCopy;\n\n\t\t\tVERIFY(a1 == aCopy[1]);\n\t\t\tVERIFY(a2 == aCopy[2]);\n\t\t\tVERIFY(a3 == aCopy[3]);\n\t\t\tVERIFY(a4 == aCopy[4]);\n\n\t\t\ta0 = 100;\n\t\t\tVERIFY(aCopy[0] == 100);\n\n\t\t\ta4 = 0;\n\t\t\tVERIFY(aCopy[4] == 0);\n\n\t\t\t// The deduced type may or may not be a reference type; it is an aliased type,\n\t\t\t//  as per https://en.cppreference.com/w/cpp/language/structured_binding:\n\t\t\t//  > Like a reference, a structured binding is an alias to an existing object. Unlike a reference,\n\t\t\t//    the type of a structured binding does not have to be a reference type.\n\t\t\t// Any reference specifier is thus removed to check only the type & its const qualifier\n\t\t\tstatic_assert(eastl::is_same_v<eastl::remove_reference_t<decltype(a0)>, int>);\n\n\t\t\tconst eastl::array<int, 5> aConstCopy = a;\n\t\t\tauto&& [aConst0, aConst1, aConst2, aConst3, aConst4] = aConstCopy;\n\n\t\t\tstatic_assert(eastl::is_same_v<eastl::remove_reference_t<decltype(aConst0)>, const int>);\n\t\t}\n\t}\n\n\t// constexpr tests\n\t{\n\t#ifndef EA_NO_CPP14_CONSTEXPR\n\t\tEA_CPP14_CONSTEXPR eastl::array<int, 4> a = {{ 0, 1, 2, 3 }};\n\n\t\tstatic_assert(a == eastl::array<int, 4>{{ 0, 1, 2, 3 }}, \"array constexpr failure\");\n\n\t\tstatic_assert(a[0] == 0, \"array constexpr failure\");\n\t\tstatic_assert(a[1] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a[2] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a[3] == 3, \"array constexpr failure\");\n\n\t\tstatic_assert(a.at(0) == 0, \"array constexpr failure\");\n\t\tstatic_assert(a.at(1) == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.at(2) == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.at(3) == 3, \"array constexpr failure\");\n\n\t\tstatic_assert(a.data()[0] == 0, \"array constexpr failure\");\n\t\tstatic_assert(a.data()[1] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.data()[2] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.data()[3] == 3, \"array constexpr failure\");\n\n\t\tstatic_assert(a.empty() == false, \"array constexpr failure\");\n\t\tstatic_assert(a.size() == 4, \"array constexpr failure\");\n\t\tstatic_assert(a.max_size() == 4, \"array constexpr failure\");\n\n\t\tstatic_assert(a.front() == 0, \"array constexpr failure\");\n\t\tstatic_assert(a.back() == 3, \"array constexpr failure\");\n\n\t\tstatic_assert(a.begin()[0] == 0, \"array constexpr failure\");\n\t\tstatic_assert(a.begin()[1] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.begin()[2] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.begin()[3] == 3, \"array constexpr failure\");\n\n\t\tstatic_assert(a.cbegin()[0] == 0, \"array constexpr failure\");\n\t\tstatic_assert(a.cbegin()[1] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.cbegin()[2] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.cbegin()[3] == 3, \"array constexpr failure\");\n\n\t\tstatic_assert(a.crbegin()[0] == 3, \"array constexpr failure\");\n\t\tstatic_assert(a.crbegin()[1] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.crbegin()[2] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.crbegin()[3] == 0, \"array constexpr failure\");\n\n\t\tstatic_assert(a.end()[-1] == 3, \"array constexpr failure\");\n\t\tstatic_assert(a.end()[-2] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.end()[-3] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.end()[-4] == 0, \"array constexpr failure\");\n\n\t\tstatic_assert(a.cend()[-1] == 3, \"array constexpr failure\");\n\t\tstatic_assert(a.cend()[-2] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.cend()[-3] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.cend()[-4] == 0, \"array constexpr failure\");\n\n\t\tstatic_assert(a.crend()[-1] == 0, \"array constexpr failure\");\n\t\tstatic_assert(a.crend()[-2] == 1, \"array constexpr failure\");\n\t\tstatic_assert(a.crend()[-3] == 2, \"array constexpr failure\");\n\t\tstatic_assert(a.crend()[-4] == 3, \"array constexpr failure\");\n\t#endif\n\t}\n\n\t// tuple_size / tuple_element\n\t{\n\t\tstatic_assert(tuple_size_v<array<int, 0>> == 0, \"tuple_size\");\n\t\tstatic_assert(tuple_size_v<array<int, 1>> == 1, \"tuple_size\");\n\t\tstatic_assert(tuple_size_v<array<int, 2>> == 2, \"tuple_size\");\n\t\tstatic_assert(tuple_size_v<array<int, 3>> == 3, \"tuple_size\");\n\n\t\tstatic_assert(is_same_v<tuple_element_t<2, array<int, 3>>, int>, \"tuple_element_t\");\n\t\tstatic_assert(is_same_v<tuple_element_t<0, array<int, 5>>, int>, \"tuple_element_t\");\n\t\tstatic_assert(is_same_v<tuple_element_t<3, array<int, 5>>, int>, \"tuple_element_t\");\n\n\t\tstatic_assert(has_tuple_element_type<3, array<int, 5>>::value, \"tuple_element_t\");\n\n\t\t// tuple_element_t with the following parameters is a compile error:\n\t\tstatic_assert(!has_tuple_element_type<0, array<int, 0>>::value, \"tuple_element_t\");\n\t\tstatic_assert(!has_tuple_element_type<1, array<int, 1>>::value, \"tuple_element_t\");\n\t\tstatic_assert(!has_tuple_element_type<10, array<int, 8>>::value, \"tuple_element_t\");\n\t}\n\n\t// get<I>()\n\t{\n\t\t{\n\t\t\teastl::array<int, 2> arr{ 1, 3 };\n\t\t\tget<0>(arr) = 4;\n\t\t\tVERIFY(arr[0] == 4);\n\t\t}\n\n\t\t{\n\t\t\tconst eastl::array<int, 3> arr{ 5, 6, -10 };\n\t\t\tVERIFY(get<2>(arr) == -10);\n\t\t\tVERIFY(get<0>(eastl::array<int, 2>{7, 8}) == 7);\n\t\t\tVERIFY(get<1>(eastl::array<int, 2>{7, 8}) == 8);\n\t\t}\n\t}\n\n#ifndef EA_COMPILER_NO_STRUCTURED_BINDING\n\t// C++17 structured binding\n\t{\n\t\t{\n\t\t\teastl::array<int, 2> arr{ 1, 3 };\n\t\t\tauto [a, b] = arr; // get(array<T,N>&&)\n\t\t\tVERIFY(a == 1);\n\t\t\tVERIFY(b == 3);\n\t\t\tauto& [c, d] = arr; // get(array<T,N>&)\n\t\t\tVERIFY(c == 1);\n\t\t\tVERIFY(d == 3);\n\t\t\tc = 5;\n\t\t\td = 6;\n\t\t\tVERIFY(arr[0] == 5);\n\t\t\tVERIFY(arr[1] == 6);\n\t\t}\n\n\t\t{\n\t\t\teastl::array<int, 5> arr{ 0, 2, 4, 6, 8 };\n\t\t\tconst auto [a, b, c, d, e] = arr; // get(const array<T,N>&&)\n\t\t\tVERIFY(a == 0);\n\t\t\tVERIFY(b == 2);\n\t\t\tVERIFY(c == 4);\n\t\t\tVERIFY(d == 6);\n\t\t\tVERIFY(e == 8);\n\t\t\tconst auto& [f,g,h,i,j] = arr; // get(const array<T,N>&)\n\t\t\tVERIFY(f == 0);\n\t\t\tVERIFY(g == 2);\n\t\t\tVERIFY(h == 4);\n\t\t\tVERIFY(i == 6);\n\t\t\tVERIFY(j == 8);\n\t\t\tarr[0] = 5;\n\t\t\tarr[1] = 6;\n\t\t\tVERIFY(f == 5);\n\t\t\tVERIFY(g == 6);\n\t\t}\n\t}\n#endif\n\n\t// to_array\n\t{\n\t\t{\n\t\t\tconstexpr int c_array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tconstexpr auto arr = to_array(c_array);\n\n\t\t\tstatic_assert(is_same_v<remove_cv_t<decltype(arr)>, eastl::array<int, 10>>, \"unexpected return type\");\n\n\t\t\tstatic_assert(arr[0] == 0, \"unexpected array value\");\n\t\t\tstatic_assert(arr[1] == 1, \"unexpected array value\");\n\t\t\tstatic_assert(arr[2] == 2, \"unexpected array value\");\n\t\t\tstatic_assert(arr[3] == 3, \"unexpected array value\");\n\t\t\tstatic_assert(arr[4] == 4, \"unexpected array value\");\n\t\t\tstatic_assert(arr[5] == 5, \"unexpected array value\");\n\t\t\tstatic_assert(arr[6] == 6, \"unexpected array value\");\n\t\t\tstatic_assert(arr[7] == 7, \"unexpected array value\");\n\t\t\tstatic_assert(arr[8] == 8, \"unexpected array value\");\n\t\t\tstatic_assert(arr[9] == 9, \"unexpected array value\");\n\t\t}\n\n\t\t{\n\t\t\tconstexpr auto arr = to_array({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});\n\n\t\t\tstatic_assert(is_same_v<remove_cv_t<decltype(arr)>, eastl::array<int, 10>>, \"unexpected return type\");\n\n\t\t\tstatic_assert(arr[0] == 0, \"unexpected array value\");\n\t\t\tstatic_assert(arr[1] == 1, \"unexpected array value\");\n\t\t\tstatic_assert(arr[2] == 2, \"unexpected array value\");\n\t\t\tstatic_assert(arr[3] == 3, \"unexpected array value\");\n\t\t\tstatic_assert(arr[4] == 4, \"unexpected array value\");\n\t\t\tstatic_assert(arr[5] == 5, \"unexpected array value\");\n\t\t\tstatic_assert(arr[6] == 6, \"unexpected array value\");\n\t\t\tstatic_assert(arr[7] == 7, \"unexpected array value\");\n\t\t\tstatic_assert(arr[8] == 8, \"unexpected array value\");\n\t\t\tstatic_assert(arr[9] == 9, \"unexpected array value\");\n\t\t}\n\n\t\t{\n\t\t\tconstexpr auto arr = to_array<long>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});\n\n\t\t\tstatic_assert(is_same_v<remove_cv_t<decltype(arr)>, eastl::array<long, 10>>, \"unexpected return type\");\n\n\t\t\tstatic_assert(arr[0] == 0l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[1] == 1l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[2] == 2l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[3] == 3l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[4] == 4l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[5] == 5l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[6] == 6l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[7] == 7l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[8] == 8l, \"unexpected array value\");\n\t\t\tstatic_assert(arr[9] == 9l, \"unexpected array value\");\n\t\t}\n\n\t\t{\n\t\t\tconstexpr auto arr = to_array<unsigned long>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});\n\n\t\t\tstatic_assert(is_same_v<remove_cv_t<decltype(arr)>, eastl::array<unsigned long, 10>>, \"unexpected return type\");\n\n\t\t\tstatic_assert(arr[0] == 0ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[1] == 1ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[2] == 2ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[3] == 3ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[4] == 4ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[5] == 5ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[6] == 6ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[7] == 7ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[8] == 8ul, \"unexpected array value\");\n\t\t\tstatic_assert(arr[9] == 9ul, \"unexpected array value\");\n\t\t}\n\n\t\t{\n\t\t\tconstexpr auto arr = to_array(\"EASTL\");\n\n\t\t\tstatic_assert(is_same_v<remove_cv_t<decltype(arr)>, eastl::array<char, 6>>, \"unexpected return type\");\n\n\t\t\tstatic_assert(arr[0] == 'E', \"unexpected value in array\");\n\t\t\tstatic_assert(arr[1] == 'A', \"unexpected value in array\");\n\t\t\tstatic_assert(arr[2] == 'S', \"unexpected value in array\");\n\t\t\tstatic_assert(arr[3] == 'T', \"unexpected value in array\");\n\t\t\tstatic_assert(arr[4] == 'L', \"unexpected value in array\");\n\t\t}\n\n\t\t// Older Microsoft compilers don't implement guaranteed copy ellision which is problematic when dealing with\n\t\t// non-copyable types. We disable this test unless we are on a version of MSVC with those features.\n\t\t#if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1920) // VS2019 16.0+\n\t\t{\n\t\t\tstruct LocalNonCopyable\n\t\t\t{\n\t\t\t\tLocalNonCopyable() = default;\n\t\t\t\t~LocalNonCopyable() = default;\n\n\t\t\t\tLocalNonCopyable(LocalNonCopyable&&) = default;\n\t\t\t\tLocalNonCopyable& operator=(LocalNonCopyable&&) = default;\n\n\t\t\t\tLocalNonCopyable(const LocalNonCopyable&) = delete;\n\t\t\t\tLocalNonCopyable& operator=(const LocalNonCopyable&) = delete;\n\t\t\t};\n\n\t\t\tconstexpr auto arr = to_array({LocalNonCopyable{}});\n\t\t\tstatic_assert(arr.size() == 1, \"unexpected error\");\n\t\t}\n\t\t#endif\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestAssociativeContainers.h",
    "content": "// (c) 2024 Electronic Arts Inc.\n\n#include \"EASTLTest.h\"\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestAssociativeContainerHeterogeneousLookup\n//\n// This function is designed to work with map, multimap, set, multiset, fixed_*, hash_map (unordered_map), hash_multimap, hash_set, hash_multihash, fixed_hash_*.\n//\n// Requires container has a key_type of ExplicitString and has a single element with key \"found\".\n// \n// Tests for heterogeneous element lookup: find(), count(), contains(), equal_range()\ntemplate <typename T>\nint TestAssociativeContainerHeterogeneousLookup(T&& container)\n{\n\tint nErrorCount = 0;\n\n\tExplicitString::Reset();\n\n\tVERIFY(container.find(\"not found\") == container.end());\n\tVERIFY(container.find(\"found\") == container.begin());\n\n\tVERIFY(container.count(\"not found\") == 0);\n\tVERIFY(container.count(\"found\") == 1);\n\n\tVERIFY(container.contains(\"found\"));\n\tVERIFY(!container.contains(\"not found\"));\n\n\tVERIFY(container.equal_range(\"not found\") == eastl::make_pair(container.end(), container.end()));\n\n\tauto it_found = container.find(\"found\");\n\tauto it_found_next = it_found;\n\t++it_found_next;\n\tVERIFY(container.equal_range(\"found\") == eastl::make_pair(it_found, it_found_next));\n\n\tVERIFY(ExplicitString::sCtorFromStrCount == 0);\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestOrderedAssociativeContainerHeterogeneousLookup\n//\n// This function is designed to work with map, fixed_map, vector_map.\n//\n// Requires container has a key_type of ExplicitString and has a single element with key \"found\".\n//\n// Tests for heterogeneous element lookup: lower_bound(), upper_bound()\ntemplate <typename T>\nint TestOrderedAssociativeContainerHeterogeneousLookup(T&& container)\n{\n\tint nErrorCount = 0;\n\n\tExplicitString::Reset();\n\n\tVERIFY(container.lower_bound(\"not found\") == container.upper_bound(\"not found\"));\n\tVERIFY(container.lower_bound(\"found\") != container.upper_bound(\"found\"));\n\n\tVERIFY(ExplicitString::sCtorFromStrCount == 0);\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMapHeterogeneousInsertion\n//\n// This function is designed to work with map, fixed_map, hash_map (unordered_map), fixed_hash_map, vector_map.\n//\n// Requires container has a key_type of ExplicitString and mapped_type of int.\n// \n// Tests for heterogeneous element insertion: try_emplace(), insert_or_assign(), at(), operator[]\ntemplate <typename T>\nint TestMapHeterogeneousInsertion()\n{\n\tint nErrorCount = 0;\n\n\tExplicitString::Reset();\n\n\tT container;\n\n\t// all of these statements cause the container to construct key_type, due to the insertion.\n\tEATEST_VERIFY(container.try_emplace(\"0\", 1).second);\n\tEATEST_VERIFY(container.insert_or_assign(\"1\", 1).second);\n\tcontainer[\"3\"] = 3;\n\n\tEATEST_VERIFY(ExplicitString::sCtorFromStrCount == 3);\n\n\tExplicitString::Reset();\n\n\t// no construction of key_type:\n\n\tEATEST_VERIFY(!container.try_emplace(\"0\").second);\n\tEATEST_VERIFY(!container.try_emplace(\"1\").second);\n\tEATEST_VERIFY(!container.try_emplace(\"3\").second);\n\n\tEATEST_VERIFY(container[\"0\"] == 1);\n\tEATEST_VERIFY(container[\"1\"] == 1);\n\tEATEST_VERIFY(container[\"3\"] == 3);\n\n\tEATEST_VERIFY(!container.insert_or_assign(\"1\", 2).second);\n\n\tEATEST_VERIFY(container.at(\"0\") == 1);\n\tEATEST_VERIFY(container.at(\"1\") == 2);\n\tEATEST_VERIFY(container.at(\"3\") == 3);\n\n\tVERIFY(ExplicitString::sCtorFromStrCount == 0);\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestSetHeterogeneousInsertion\n//\n// This function is designed to work with set, fixed_set, hash_set (unordered_set), fixed_hash_set, vector_set.\n//\n// Requires container has a key_type of ExplicitString.\n//\n// Tests for heterogeneous element insertion: insert()\ntemplate <typename T>\nint TestSetHeterogeneousInsertion()\n{\n\tint nErrorCount = 0;\n\n\tExplicitString::Reset();\n\n\tT container;\n\n\t// all of these statements cause the container to construct key_type, due to the insertion.\n\tEATEST_VERIFY(container.insert(\"0\").second);\n\tEATEST_VERIFY(container.insert(\"1\").second);\n\tEATEST_VERIFY(container.insert(\"3\").second);\n\n\tEATEST_VERIFY(ExplicitString::sCtorFromStrCount == 3);\n\n\tExplicitString::Reset();\n\n\t// no construction of key_type:\n\n\tauto insert_result0 = container.insert(\"0\");\n\tEATEST_VERIFY(insert_result0.first == container.find(\"0\"));\n\tEATEST_VERIFY(!insert_result0.second);\n\n\tauto insert_result1 = container.insert(\"1\");\n\tEATEST_VERIFY(insert_result1.first == container.find(\"1\"));\n\tEATEST_VERIFY(!insert_result1.second);\n\n\tauto insert_result3 = container.insert(\"3\");\n\tEATEST_VERIFY(insert_result3.first == container.find(\"3\"));\n\tEATEST_VERIFY(!insert_result3.second);\n\n\tVERIFY(ExplicitString::sCtorFromStrCount == 0);\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestAssociativeContainerHeterogeneousErasure\n//\n// This function is designed to work with map, multimap, set, multiset, fixed_*, hash_map (unordered_map), hash_multimap, hash_set, hash_multihash, fixed_hash_*.\n//\n// Requires container has a key_type of ExplicitString and has a single element with key \"found\".\n//\n// Tests for heterogeneous element insertion: erase()\ntemplate <typename T>\nint TestAssociativeContainerHeterogeneousErasure(T&& container)\n{\n\tint nErrorCount = 0;\n\n\tExplicitString::Reset();\n\n\tVERIFY(container.erase(\"found\") == 1);\n\tVERIFY(container.erase(\"not found\") == 0);\n\n\tVERIFY(ExplicitString::sCtorFromStrCount == 0);\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestAtomicAsm.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n\n#include <EASTL/atomic.h>\n\n#include <cstddef>\n\n\nstruct UserType128\n{\n\tuint32_t a,b,c,d;\n\n\tfriend bool operator==(const UserType128& a, const UserType128& b)\n\t{\n\t\treturn (a.a == b.a) && (a.b == b.b) && (a.c == b.c) && (a.d == b.d);\n\t}\n};\n\n\n/**\n * There is no nice way to verify the emitted asm for each of the given operations.\n * This test file is meant to put each operation into its own function so its easy\n * to verify in a disassembler for manual inspection.\n */\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32StoreRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tatomic.store(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU32StoreRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tatomic.store(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU32StoreSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tatomic.store(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU32Store()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tatomic.store(1);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU32StoreOrders()\n{\n\tTestAtomicU32StoreRelaxed();\n\n\tTestAtomicU32StoreRelease();\n\n\tTestAtomicU32StoreSeqCst();\n\n\tTestAtomicU32Store();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64StoreRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tatomic.store(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU64StoreRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tatomic.store(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU64StoreSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tatomic.store(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU64Store()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tatomic.store(1);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomicU64StoreOrders()\n{\n\tTestAtomicU64StoreRelaxed();\n\n\tTestAtomicU64StoreRelease();\n\n\tTestAtomicU64StoreSeqCst();\n\n\tTestAtomicU64Store();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128StoreRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tatomic.store(UserType128{1, 1, 1, 1}, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomic128StoreRelease()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tatomic.store(UserType128{1, 1, 1, 1}, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomic128StoreSeqCst()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tatomic.store(UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomic128Store()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tatomic.store(UserType128{1, 1, 1, 1});\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\nEA_NO_INLINE static void TestAtomic128StoreOrders()\n{\n\tTestAtomic128StoreRelaxed();\n\n\tTestAtomic128StoreRelease();\n\n\tTestAtomic128StoreSeqCst();\n\n\tTestAtomic128Store();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32LoadRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t load = atomic.load(eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU32LoadAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t load = atomic.load(eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU32LoadSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t load = atomic.load(eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU32Load()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t load = atomic.load();\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU32LoadOrders()\n{\n\tTestAtomicU32LoadRelaxed();\n\n\tTestAtomicU32LoadAcquire();\n\n\tTestAtomicU32LoadSeqCst();\n\n\tTestAtomicU32Load();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64LoadRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t load = atomic.load(eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU64LoadAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t load = atomic.load(eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU64LoadSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t load = atomic.load(eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU64Load()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t load = atomic.load();\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomicU64LoadOrders()\n{\n\tTestAtomicU64LoadRelaxed();\n\n\tTestAtomicU64LoadAcquire();\n\n\tTestAtomicU64LoadSeqCst();\n\n\tTestAtomicU64Load();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128LoadRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 load = atomic.load(eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomic128LoadAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 load = atomic.load(eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomic128LoadSeqCst()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 load = atomic.load(eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomic128Load()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 load = atomic.load();\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\nEA_NO_INLINE static void TestAtomic128LoadOrders()\n{\n\tTestAtomic128LoadRelaxed();\n\n\tTestAtomic128LoadAcquire();\n\n\tTestAtomic128LoadSeqCst();\n\n\tTestAtomic128Load();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32ExchangeRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t exchange = atomic.exchange(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU32ExchangeAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t exchange = atomic.exchange(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU32ExchangeRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t exchange = atomic.exchange(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU32ExchangeAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t exchange = atomic.exchange(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU32ExchangeSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t exchange = atomic.exchange(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU32Exchange()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t exchange = atomic.exchange(1);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU32ExchangeOrders()\n{\n\tTestAtomicU32ExchangeRelaxed();\n\n\tTestAtomicU32ExchangeAcquire();\n\n\tTestAtomicU32ExchangeRelease();\n\n\tTestAtomicU32ExchangeAcqRel();\n\n\tTestAtomicU32ExchangeSeqCst();\n\n\tTestAtomicU32Exchange();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64ExchangeRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t exchange = atomic.exchange(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU64ExchangeAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t exchange = atomic.exchange(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU64ExchangeRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t exchange = atomic.exchange(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU64ExchangeAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t exchange = atomic.exchange(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU64ExchangeSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t exchange = atomic.exchange(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU64Exchange()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t exchange = atomic.exchange(1);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomicU64ExchangeOrders()\n{\n\tTestAtomicU64ExchangeRelaxed();\n\n\tTestAtomicU64ExchangeAcquire();\n\n\tTestAtomicU64ExchangeRelease();\n\n\tTestAtomicU64ExchangeAcqRel();\n\n\tTestAtomicU64ExchangeSeqCst();\n\n\tTestAtomicU64Exchange();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128ExchangeRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 exchange = atomic.exchange(UserType128{1, 1, 1, 1}, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomic128ExchangeAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 exchange = atomic.exchange(UserType128{1, 1, 1, 1}, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomic128ExchangeRelease()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 exchange = atomic.exchange(UserType128{1, 1, 1, 1}, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomic128ExchangeAcqRel()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 exchange = atomic.exchange(UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomic128ExchangeSeqCst()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 exchange = atomic.exchange(UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomic128Exchange()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 exchange = atomic.exchange(UserType128{1, 1, 1, 1});\n\n\teastl::compiler_barrier_data_dependency(exchange);\n}\n\nEA_NO_INLINE static void TestAtomic128ExchangeOrders()\n{\n\tTestAtomic128ExchangeRelaxed();\n\n\tTestAtomic128ExchangeAcquire();\n\n\tTestAtomic128ExchangeRelease();\n\n\tTestAtomic128ExchangeAcqRel();\n\n\tTestAtomic128ExchangeSeqCst();\n\n\tTestAtomic128Exchange();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorT()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t load = atomic;\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorT()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t load = atomic;\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128OperatorT()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 load = atomic;\n\n\teastl::compiler_barrier_data_dependency(load);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorEqual()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tatomic = 1;\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorEqual()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tatomic = 1;\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128OperatorEqual()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tatomic = UserType128{1, 1, 1, 1};\n\n\teastl::compiler_barrier_data_dependency(atomic);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongRelaxedRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongAcquireRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongAcquireAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongReleaseRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongAcqRelRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongAcqRelAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongSeqCstRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongSeqCstAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongSeqCstSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrong()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeStrongOrders()\n{\n\tTestAtomicU32CompareExchangeStrongRelaxedRelaxed();\n\n\tTestAtomicU32CompareExchangeStrongAcquireRelaxed();\n\n\tTestAtomicU32CompareExchangeStrongAcquireAcquire();\n\n\tTestAtomicU32CompareExchangeStrongReleaseRelaxed();\n\n\tTestAtomicU32CompareExchangeStrongAcqRelRelaxed();\n\n\tTestAtomicU32CompareExchangeStrongAcqRelAcquire();\n\n\tTestAtomicU32CompareExchangeStrongSeqCstRelaxed();\n\n\tTestAtomicU32CompareExchangeStrongSeqCstAcquire();\n\n\tTestAtomicU32CompareExchangeStrongSeqCstSeqCst();\n\n\tTestAtomicU32CompareExchangeStrongRelaxed();\n\n\tTestAtomicU32CompareExchangeStrongAcquire();\n\n\tTestAtomicU32CompareExchangeStrongRelease();\n\n\tTestAtomicU32CompareExchangeStrongAcqRel();\n\n\tTestAtomicU32CompareExchangeStrongSeqCst();\n\n\tTestAtomicU32CompareExchangeStrong();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongRelaxedRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongAcquireRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongAcquireAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongReleaseRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongAcqRelRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongAcqRelAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongSeqCstRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongSeqCstAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongSeqCstSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrong()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_strong(expected, 1);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeStrongOrders()\n{\n\tTestAtomicU64CompareExchangeStrongRelaxedRelaxed();\n\n\tTestAtomicU64CompareExchangeStrongAcquireRelaxed();\n\n\tTestAtomicU64CompareExchangeStrongAcquireAcquire();\n\n\tTestAtomicU64CompareExchangeStrongReleaseRelaxed();\n\n\tTestAtomicU64CompareExchangeStrongAcqRelRelaxed();\n\n\tTestAtomicU64CompareExchangeStrongAcqRelAcquire();\n\n\tTestAtomicU64CompareExchangeStrongSeqCstRelaxed();\n\n\tTestAtomicU64CompareExchangeStrongSeqCstAcquire();\n\n\tTestAtomicU64CompareExchangeStrongSeqCstSeqCst();\n\n\tTestAtomicU64CompareExchangeStrongRelaxed();\n\n\tTestAtomicU64CompareExchangeStrongAcquire();\n\n\tTestAtomicU64CompareExchangeStrongRelease();\n\n\tTestAtomicU64CompareExchangeStrongAcqRel();\n\n\tTestAtomicU64CompareExchangeStrongSeqCst();\n\n\tTestAtomicU64CompareExchangeStrong();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongRelaxedRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongAcquireRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongAcquireAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongReleaseRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongAcqRelRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongAcqRelAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongSeqCstRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongSeqCstAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongSeqCstSeqCst()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongRelease()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongAcqRel()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongSeqCst()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrong()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_strong(expected, UserType128{1, 1, 1, 1});\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeStrongOrders()\n{\n\tTestAtomic128CompareExchangeStrongRelaxedRelaxed();\n\n\tTestAtomic128CompareExchangeStrongAcquireRelaxed();\n\n\tTestAtomic128CompareExchangeStrongAcquireAcquire();\n\n\tTestAtomic128CompareExchangeStrongReleaseRelaxed();\n\n\tTestAtomic128CompareExchangeStrongAcqRelRelaxed();\n\n\tTestAtomic128CompareExchangeStrongAcqRelAcquire();\n\n\tTestAtomic128CompareExchangeStrongSeqCstRelaxed();\n\n\tTestAtomic128CompareExchangeStrongSeqCstAcquire();\n\n\tTestAtomic128CompareExchangeStrongSeqCstSeqCst();\n\n\tTestAtomic128CompareExchangeStrongRelaxed();\n\n\tTestAtomic128CompareExchangeStrongAcquire();\n\n\tTestAtomic128CompareExchangeStrongRelease();\n\n\tTestAtomic128CompareExchangeStrongAcqRel();\n\n\tTestAtomic128CompareExchangeStrongSeqCst();\n\n\tTestAtomic128CompareExchangeStrong();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakRelaxedRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakAcquireRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakAcquireAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakReleaseRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakAcqRelRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakAcqRelAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakSeqCstRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakSeqCstAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakSeqCstSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeak()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU32CompareExchangeWeakOrders()\n{\n\tTestAtomicU32CompareExchangeWeakRelaxedRelaxed();\n\n\tTestAtomicU32CompareExchangeWeakAcquireRelaxed();\n\n\tTestAtomicU32CompareExchangeWeakAcquireAcquire();\n\n\tTestAtomicU32CompareExchangeWeakReleaseRelaxed();\n\n\tTestAtomicU32CompareExchangeWeakAcqRelRelaxed();\n\n\tTestAtomicU32CompareExchangeWeakAcqRelAcquire();\n\n\tTestAtomicU32CompareExchangeWeakSeqCstRelaxed();\n\n\tTestAtomicU32CompareExchangeWeakSeqCstAcquire();\n\n\tTestAtomicU32CompareExchangeWeakSeqCstSeqCst();\n\n\tTestAtomicU32CompareExchangeWeakRelaxed();\n\n\tTestAtomicU32CompareExchangeWeakAcquire();\n\n\tTestAtomicU32CompareExchangeWeakRelease();\n\n\tTestAtomicU32CompareExchangeWeakAcqRel();\n\n\tTestAtomicU32CompareExchangeWeakSeqCst();\n\n\tTestAtomicU32CompareExchangeWeak();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakRelaxedRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakAcquireRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakAcquireAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakReleaseRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakAcqRelRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakAcqRelAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakSeqCstRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakSeqCstAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakSeqCstSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeak()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t expected = 0;\n\tbool ret = atomic.compare_exchange_weak(expected, 1);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomicU64CompareExchangeWeakOrders()\n{\n\tTestAtomicU64CompareExchangeWeakRelaxedRelaxed();\n\n\tTestAtomicU64CompareExchangeWeakAcquireRelaxed();\n\n\tTestAtomicU64CompareExchangeWeakAcquireAcquire();\n\n\tTestAtomicU64CompareExchangeWeakReleaseRelaxed();\n\n\tTestAtomicU64CompareExchangeWeakAcqRelRelaxed();\n\n\tTestAtomicU64CompareExchangeWeakAcqRelAcquire();\n\n\tTestAtomicU64CompareExchangeWeakSeqCstRelaxed();\n\n\tTestAtomicU64CompareExchangeWeakSeqCstAcquire();\n\n\tTestAtomicU64CompareExchangeWeakSeqCstSeqCst();\n\n\tTestAtomicU64CompareExchangeWeakRelaxed();\n\n\tTestAtomicU64CompareExchangeWeakAcquire();\n\n\tTestAtomicU64CompareExchangeWeakRelease();\n\n\tTestAtomicU64CompareExchangeWeakAcqRel();\n\n\tTestAtomicU64CompareExchangeWeakSeqCst();\n\n\tTestAtomicU64CompareExchangeWeak();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakRelaxedRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakAcquireRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakAcquireAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakReleaseRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakAcqRelRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakAcqRelAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakSeqCstRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakSeqCstAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakSeqCstSeqCst()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakRelaxed()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakAcquire()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakRelease()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakAcqRel()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakSeqCst()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1}, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeak()\n{\n\teastl::atomic<UserType128> atomic;\n\n\tUserType128 expected = UserType128{0, 0, 0, 0};\n\tbool ret = atomic.compare_exchange_weak(expected, UserType128{1, 1, 1, 1});\n\n\teastl::compiler_barrier_data_dependency(ret);\n}\n\nEA_NO_INLINE static void TestAtomic128CompareExchangeWeakOrders()\n{\n\tTestAtomic128CompareExchangeWeakRelaxedRelaxed();\n\n\tTestAtomic128CompareExchangeWeakAcquireRelaxed();\n\n\tTestAtomic128CompareExchangeWeakAcquireAcquire();\n\n\tTestAtomic128CompareExchangeWeakReleaseRelaxed();\n\n\tTestAtomic128CompareExchangeWeakAcqRelRelaxed();\n\n\tTestAtomic128CompareExchangeWeakAcqRelAcquire();\n\n\tTestAtomic128CompareExchangeWeakSeqCstRelaxed();\n\n\tTestAtomic128CompareExchangeWeakSeqCstAcquire();\n\n\tTestAtomic128CompareExchangeWeakSeqCstSeqCst();\n\n\tTestAtomic128CompareExchangeWeakRelaxed();\n\n\tTestAtomic128CompareExchangeWeakAcquire();\n\n\tTestAtomic128CompareExchangeWeakRelease();\n\n\tTestAtomic128CompareExchangeWeakAcqRel();\n\n\tTestAtomic128CompareExchangeWeakSeqCst();\n\n\tTestAtomic128CompareExchangeWeak();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32FetchAddRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_add(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAddAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_add(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAddRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_add(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAddAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_add(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAddSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_add(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAdd()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_add(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAddOrders()\n{\n\tTestAtomicU32FetchAddRelaxed();\n\n\tTestAtomicU32FetchAddAcquire();\n\n\tTestAtomicU32FetchAddRelease();\n\n\tTestAtomicU32FetchAddAcqRel();\n\n\tTestAtomicU32FetchAddSeqCst();\n\n\tTestAtomicU32FetchAdd();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64FetchAddRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_add(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAddAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_add(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAddRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_add(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAddAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_add(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAddSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_add(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAdd()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_add(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAddOrders()\n{\n\tTestAtomicU64FetchAddRelaxed();\n\n\tTestAtomicU64FetchAddAcquire();\n\n\tTestAtomicU64FetchAddRelease();\n\n\tTestAtomicU64FetchAddAcqRel();\n\n\tTestAtomicU64FetchAddSeqCst();\n\n\tTestAtomicU64FetchAdd();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128FetchAddRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_add(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAddAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_add(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAddRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_add(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAddAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_add(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAddSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_add(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAdd()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_add(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAddOrders()\n{\n\tTestAtomic128FetchAddRelaxed();\n\n\tTestAtomic128FetchAddAcquire();\n\n\tTestAtomic128FetchAddRelease();\n\n\tTestAtomic128FetchAddAcqRel();\n\n\tTestAtomic128FetchAddSeqCst();\n\n\tTestAtomic128FetchAdd();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32AddFetchRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.add_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AddFetchAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.add_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AddFetchRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.add_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AddFetchAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.add_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AddFetchSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.add_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AddFetch()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.add_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AddFetchOrders()\n{\n\tTestAtomicU32AddFetchRelaxed();\n\n\tTestAtomicU32AddFetchAcquire();\n\n\tTestAtomicU32AddFetchRelease();\n\n\tTestAtomicU32AddFetchAcqRel();\n\n\tTestAtomicU32AddFetchSeqCst();\n\n\tTestAtomicU32AddFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64AddFetchRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.add_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AddFetchAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.add_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AddFetchRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.add_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AddFetchAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.add_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AddFetchSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.add_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AddFetch()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.add_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AddFetchOrders()\n{\n\tTestAtomicU64AddFetchRelaxed();\n\n\tTestAtomicU64AddFetchAcquire();\n\n\tTestAtomicU64AddFetchRelease();\n\n\tTestAtomicU64AddFetchAcqRel();\n\n\tTestAtomicU64AddFetchSeqCst();\n\n\tTestAtomicU64AddFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128AddFetchRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.add_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AddFetchAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.add_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AddFetchRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.add_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AddFetchAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.add_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AddFetchSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.add_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AddFetch()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.add_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AddFetchOrders()\n{\n\tTestAtomic128AddFetchRelaxed();\n\n\tTestAtomic128AddFetchAcquire();\n\n\tTestAtomic128AddFetchRelease();\n\n\tTestAtomic128AddFetchAcqRel();\n\n\tTestAtomic128AddFetchSeqCst();\n\n\tTestAtomic128AddFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32FetchSubRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_sub(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchSubAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_sub(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchSubRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_sub(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchSubAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_sub(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchSubSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_sub(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchSub()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_sub(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchSubOrders()\n{\n\tTestAtomicU32FetchSubRelaxed();\n\n\tTestAtomicU32FetchSubAcquire();\n\n\tTestAtomicU32FetchSubRelease();\n\n\tTestAtomicU32FetchSubAcqRel();\n\n\tTestAtomicU32FetchSubSeqCst();\n\n\tTestAtomicU32FetchSub();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64FetchSubRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_sub(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchSubAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_sub(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchSubRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_sub(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchSubAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_sub(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchSubSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_sub(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchSub()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_sub(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchSubOrders()\n{\n\tTestAtomicU64FetchSubRelaxed();\n\n\tTestAtomicU64FetchSubAcquire();\n\n\tTestAtomicU64FetchSubRelease();\n\n\tTestAtomicU64FetchSubAcqRel();\n\n\tTestAtomicU64FetchSubSeqCst();\n\n\tTestAtomicU64FetchSub();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128FetchSubRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_sub(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchSubAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_sub(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchSubRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_sub(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchSubAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_sub(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchSubSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_sub(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchSub()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_sub(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchSubOrders()\n{\n\tTestAtomic128FetchSubRelaxed();\n\n\tTestAtomic128FetchSubAcquire();\n\n\tTestAtomic128FetchSubRelease();\n\n\tTestAtomic128FetchSubAcqRel();\n\n\tTestAtomic128FetchSubSeqCst();\n\n\tTestAtomic128FetchSub();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32SubFetchRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.sub_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32SubFetchAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.sub_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32SubFetchRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.sub_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32SubFetchAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.sub_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32SubFetchSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.sub_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32SubFetch()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.sub_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32SubFetchOrders()\n{\n\tTestAtomicU32SubFetchRelaxed();\n\n\tTestAtomicU32SubFetchAcquire();\n\n\tTestAtomicU32SubFetchRelease();\n\n\tTestAtomicU32SubFetchAcqRel();\n\n\tTestAtomicU32SubFetchSeqCst();\n\n\tTestAtomicU32SubFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64SubFetchRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.sub_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64SubFetchAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.sub_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64SubFetchRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.sub_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64SubFetchAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.sub_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64SubFetchSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.sub_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64SubFetch()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.sub_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64SubFetchOrders()\n{\n\tTestAtomicU64SubFetchRelaxed();\n\n\tTestAtomicU64SubFetchAcquire();\n\n\tTestAtomicU64SubFetchRelease();\n\n\tTestAtomicU64SubFetchAcqRel();\n\n\tTestAtomicU64SubFetchSeqCst();\n\n\tTestAtomicU64SubFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128SubFetchRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.sub_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128SubFetchAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.sub_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128SubFetchRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.sub_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128SubFetchAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.sub_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128SubFetchSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.sub_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128SubFetch()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.sub_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128SubFetchOrders()\n{\n\tTestAtomic128SubFetchRelaxed();\n\n\tTestAtomic128SubFetchAcquire();\n\n\tTestAtomic128SubFetchRelease();\n\n\tTestAtomic128SubFetchAcqRel();\n\n\tTestAtomic128SubFetchSeqCst();\n\n\tTestAtomic128SubFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32FetchAndRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_and(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAndAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_and(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAndRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_and(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAndAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_and(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAndSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_and(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAnd()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_and(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchAndOrders()\n{\n\tTestAtomicU32FetchAndRelaxed();\n\n\tTestAtomicU32FetchAndAcquire();\n\n\tTestAtomicU32FetchAndRelease();\n\n\tTestAtomicU32FetchAndAcqRel();\n\n\tTestAtomicU32FetchAndSeqCst();\n\n\tTestAtomicU32FetchAnd();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64FetchAndRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_and(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAndAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_and(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAndRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_and(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAndAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_and(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAndSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_and(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAnd()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_and(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchAndOrders()\n{\n\tTestAtomicU64FetchAndRelaxed();\n\n\tTestAtomicU64FetchAndAcquire();\n\n\tTestAtomicU64FetchAndRelease();\n\n\tTestAtomicU64FetchAndAcqRel();\n\n\tTestAtomicU64FetchAndSeqCst();\n\n\tTestAtomicU64FetchAnd();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128FetchAndRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_and(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAndAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_and(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAndRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_and(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAndAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_and(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAndSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_and(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAnd()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_and(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchAndOrders()\n{\n\tTestAtomic128FetchAndRelaxed();\n\n\tTestAtomic128FetchAndAcquire();\n\n\tTestAtomic128FetchAndRelease();\n\n\tTestAtomic128FetchAndAcqRel();\n\n\tTestAtomic128FetchAndSeqCst();\n\n\tTestAtomic128FetchAnd();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32AndFetchRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.and_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AndFetchAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.and_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AndFetchRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.and_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AndFetchAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.and_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AndFetchSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.and_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AndFetch()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.and_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32AndFetchOrders()\n{\n\tTestAtomicU32AndFetchRelaxed();\n\n\tTestAtomicU32AndFetchAcquire();\n\n\tTestAtomicU32AndFetchRelease();\n\n\tTestAtomicU32AndFetchAcqRel();\n\n\tTestAtomicU32AndFetchSeqCst();\n\n\tTestAtomicU32AndFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64AndFetchRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.and_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AndFetchAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.and_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AndFetchRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.and_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AndFetchAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.and_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AndFetchSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.and_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AndFetch()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.and_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64AndFetchOrders()\n{\n\tTestAtomicU64AndFetchRelaxed();\n\n\tTestAtomicU64AndFetchAcquire();\n\n\tTestAtomicU64AndFetchRelease();\n\n\tTestAtomicU64AndFetchAcqRel();\n\n\tTestAtomicU64AndFetchSeqCst();\n\n\tTestAtomicU64AndFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128AndFetchRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.and_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AndFetchAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.and_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AndFetchRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.and_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AndFetchAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.and_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AndFetchSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.and_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AndFetch()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.and_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128AndFetchOrders()\n{\n\tTestAtomic128AndFetchRelaxed();\n\n\tTestAtomic128AndFetchAcquire();\n\n\tTestAtomic128AndFetchRelease();\n\n\tTestAtomic128AndFetchAcqRel();\n\n\tTestAtomic128AndFetchSeqCst();\n\n\tTestAtomic128AndFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OrFetchRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.or_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32OrFetchAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.or_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32OrFetchRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.or_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32OrFetchAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.or_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32OrFetchSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.or_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32OrFetch()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.or_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32OrFetchOrders()\n{\n\tTestAtomicU32OrFetchRelaxed();\n\n\tTestAtomicU32OrFetchAcquire();\n\n\tTestAtomicU32OrFetchRelease();\n\n\tTestAtomicU32OrFetchAcqRel();\n\n\tTestAtomicU32OrFetchSeqCst();\n\n\tTestAtomicU32OrFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OrFetchRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.or_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64OrFetchAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.or_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64OrFetchRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.or_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64OrFetchAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.or_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64OrFetchSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.or_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64OrFetch()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.or_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64OrFetchOrders()\n{\n\tTestAtomicU64OrFetchRelaxed();\n\n\tTestAtomicU64OrFetchAcquire();\n\n\tTestAtomicU64OrFetchRelease();\n\n\tTestAtomicU64OrFetchAcqRel();\n\n\tTestAtomicU64OrFetchSeqCst();\n\n\tTestAtomicU64OrFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OrFetchRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.or_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128OrFetchAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.or_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128OrFetchRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.or_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128OrFetchAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.or_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128OrFetchSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.or_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128OrFetch()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.or_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128OrFetchOrders()\n{\n\tTestAtomic128OrFetchRelaxed();\n\n\tTestAtomic128OrFetchAcquire();\n\n\tTestAtomic128OrFetchRelease();\n\n\tTestAtomic128OrFetchAcqRel();\n\n\tTestAtomic128OrFetchSeqCst();\n\n\tTestAtomic128OrFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32FetchOrRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_or(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchOrAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_or(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchOrRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_or(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchOrAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_or(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchOrSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_or(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchOr()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_or(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchOrOrders()\n{\n\tTestAtomicU32FetchOrRelaxed();\n\n\tTestAtomicU32FetchOrAcquire();\n\n\tTestAtomicU32FetchOrRelease();\n\n\tTestAtomicU32FetchOrAcqRel();\n\n\tTestAtomicU32FetchOrSeqCst();\n\n\tTestAtomicU32FetchOr();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64FetchOrRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_or(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchOrAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_or(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchOrRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_or(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchOrAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_or(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchOrSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_or(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchOr()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_or(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchOrOrders()\n{\n\tTestAtomicU64FetchOrRelaxed();\n\n\tTestAtomicU64FetchOrAcquire();\n\n\tTestAtomicU64FetchOrRelease();\n\n\tTestAtomicU64FetchOrAcqRel();\n\n\tTestAtomicU64FetchOrSeqCst();\n\n\tTestAtomicU64FetchOr();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128FetchOrRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_or(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchOrAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_or(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchOrRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_or(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchOrAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_or(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchOrSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_or(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchOr()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_or(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchOrOrders()\n{\n\tTestAtomic128FetchOrRelaxed();\n\n\tTestAtomic128FetchOrAcquire();\n\n\tTestAtomic128FetchOrRelease();\n\n\tTestAtomic128FetchOrAcqRel();\n\n\tTestAtomic128FetchOrSeqCst();\n\n\tTestAtomic128FetchOr();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32FetchXorRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_xor(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchXorAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_xor(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchXorRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_xor(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchXorAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_xor(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchXorSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_xor(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchXor()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.fetch_xor(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32FetchXorOrders()\n{\n\tTestAtomicU32FetchXorRelaxed();\n\n\tTestAtomicU32FetchXorAcquire();\n\n\tTestAtomicU32FetchXorRelease();\n\n\tTestAtomicU32FetchXorAcqRel();\n\n\tTestAtomicU32FetchXorSeqCst();\n\n\tTestAtomicU32FetchXor();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64FetchXorRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_xor(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchXorAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_xor(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchXorRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_xor(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchXorAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_xor(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchXorSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_add(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchXor()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.fetch_xor(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64FetchXorOrders()\n{\n\tTestAtomicU64FetchXorRelaxed();\n\n\tTestAtomicU64FetchXorAcquire();\n\n\tTestAtomicU64FetchXorRelease();\n\n\tTestAtomicU64FetchXorAcqRel();\n\n\tTestAtomicU64FetchXorSeqCst();\n\n\tTestAtomicU64FetchXor();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128FetchXorRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_xor(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchXorAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_xor(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchXorRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_xor(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchXorAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_xor(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchXorSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_xor(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchXor()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.fetch_xor(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128FetchXorOrders()\n{\n\tTestAtomic128FetchXorRelaxed();\n\n\tTestAtomic128FetchXorAcquire();\n\n\tTestAtomic128FetchXorRelease();\n\n\tTestAtomic128FetchXorAcqRel();\n\n\tTestAtomic128FetchXorSeqCst();\n\n\tTestAtomic128FetchXor();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32XorFetchRelaxed()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.xor_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32XorFetchAcquire()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.xor_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32XorFetchRelease()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.xor_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32XorFetchAcqRel()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.xor_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32XorFetchSeqCst()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.xor_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32XorFetch()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic.xor_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU32XorFetchOrders()\n{\n\tTestAtomicU32XorFetchRelaxed();\n\n\tTestAtomicU32XorFetchAcquire();\n\n\tTestAtomicU32XorFetchRelease();\n\n\tTestAtomicU32XorFetchAcqRel();\n\n\tTestAtomicU32XorFetchSeqCst();\n\n\tTestAtomicU32XorFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64XorFetchRelaxed()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.xor_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64XorFetchAcquire()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.xor_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64XorFetchRelease()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.xor_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64XorFetchAcqRel()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.xor_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64XorFetchSeqCst()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.xor_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64XorFetch()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic.xor_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomicU64XorFetchOrders()\n{\n\tTestAtomicU64XorFetchRelaxed();\n\n\tTestAtomicU64XorFetchAcquire();\n\n\tTestAtomicU64XorFetchRelease();\n\n\tTestAtomicU64XorFetchAcqRel();\n\n\tTestAtomicU64XorFetchSeqCst();\n\n\tTestAtomicU64XorFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128XorFetchRelaxed()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.xor_fetch(1, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128XorFetchAcquire()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.xor_fetch(1, eastl::memory_order_acquire);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128XorFetchRelease()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.xor_fetch(1, eastl::memory_order_release);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128XorFetchAcqRel()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.xor_fetch(1, eastl::memory_order_acq_rel);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128XorFetchSeqCst()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.xor_fetch(1, eastl::memory_order_seq_cst);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128XorFetch()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic.xor_fetch(1);\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\nEA_NO_INLINE static void TestAtomic128XorFetchOrders()\n{\n\tTestAtomic128XorFetchRelaxed();\n\n\tTestAtomic128XorFetchAcquire();\n\n\tTestAtomic128XorFetchRelease();\n\n\tTestAtomic128XorFetchAcqRel();\n\n\tTestAtomic128XorFetchSeqCst();\n\n\tTestAtomic128XorFetch();\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorPlusPlus()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic++;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorPlusPlus()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic++;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OperatorPlusPlus()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic++;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32PlusPlusOperator()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = ++atomic;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64PlusPlusOperator()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = ++atomic;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128PlusPlusOperator()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = ++atomic;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorMinusMinus()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic--;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorMinusMinus()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic--;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OperatorMinusMinus()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic--;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32MinusMinusOperator()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = --atomic;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64MinusMinusOperator()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = --atomic;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128MinusMinusOperator()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = --atomic;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorPlusAssignment()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic += 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorPlusAssignment()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic += 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OperatorPlusAssignment()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic += 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorMinusAssignment()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic -= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorMinusAssignment()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic -= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OperatorMinusAssignment()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic -= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorAndAssignment()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic &= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorAndAssignment()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic &= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OperatorAndAssignment()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic &= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorOrAssignment()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic |= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorOrAssignment()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic |= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OperatorOrAssignment()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic |= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomicU32OperatorXorAssignment()\n{\n\teastl::atomic<uint32_t> atomic;\n\n\tuint32_t val = atomic ^= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_64BIT)\n\nEA_NO_INLINE static void TestAtomicU64OperatorXorAssignment()\n{\n\teastl::atomic<uint64_t> atomic;\n\n\tuint64_t val = atomic ^= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\nEA_NO_INLINE static void TestAtomic128OperatorXorAssignment()\n{\n\teastl::atomic<__uint128_t> atomic;\n\n\t__uint128_t val = atomic ^= 1;\n\n\teastl::compiler_barrier_data_dependency(val);\n}\n\n#endif\n\nEA_NO_INLINE static void TestAtomicSignalFenceRelaxed()\n{\n\teastl::atomic_signal_fence(eastl::memory_order_relaxed);\n}\n\nEA_NO_INLINE static void TestAtomicSignalFenceAcquire()\n{\n\teastl::atomic_signal_fence(eastl::memory_order_acquire);\n}\n\nEA_NO_INLINE static void TestAtomicSignalFenceRelease()\n{\n\teastl::atomic_signal_fence(eastl::memory_order_release);\n}\n\nEA_NO_INLINE static void TestAtomicSignalFenceAcqRel()\n{\n\teastl::atomic_signal_fence(eastl::memory_order_acq_rel);\n}\n\nEA_NO_INLINE static void TestAtomicSignalFenceSeqCst()\n{\n\teastl::atomic_signal_fence(eastl::memory_order_seq_cst);\n}\n\nEA_NO_INLINE static void TestAtomicThreadFenceRelaxed()\n{\n\teastl::atomic_thread_fence(eastl::memory_order_relaxed);\n}\n\nEA_NO_INLINE static void TestAtomicThreadFenceAcquire()\n{\n\teastl::atomic_thread_fence(eastl::memory_order_acquire);\n}\n\nEA_NO_INLINE static void TestAtomicThreadFenceRelease()\n{\n\teastl::atomic_thread_fence(eastl::memory_order_release);\n}\n\nEA_NO_INLINE static void TestAtomicThreadFenceAcqRel()\n{\n\teastl::atomic_thread_fence(eastl::memory_order_acq_rel);\n}\n\nEA_NO_INLINE static void TestAtomicThreadFenceSeqCst()\n{\n\teastl::atomic_thread_fence(eastl::memory_order_seq_cst);\n}\n\nEA_NO_INLINE static void TestAtomicPointerReadDepends()\n{\n\teastl::atomic<void*> atomic;\n\n\tvoid* p = atomic.load(eastl::memory_order_read_depends);\n\n\teastl::compiler_barrier_data_dependency(p);\n}\n\nstruct ReadDependsStruct\n{\n\tint a;\n\tint b;\n};\n\neastl::atomic<ReadDependsStruct*> gAtomicPtr;\n\nEA_NO_INLINE int TestAtomicReadDependsStruct()\n{\n\tReadDependsStruct* p = gAtomicPtr.load(eastl::memory_order_read_depends);\n\n\tint a = p->a;\n\tint b = p->b;\n\n\treturn a + b;\n}\n\nEA_NO_INLINE static void TestCompilerBarrierDataDependency()\n{\n\t{\n\t\tUserType128 t{4, 5, 7, 8};\n\n\t\teastl::compiler_barrier_data_dependency(t);\n\t}\n\n\t{\n\t\tvoid* p = (void*)(uintptr_t)0xdeadbeef;\n\n\t\teastl::compiler_barrier_data_dependency(p);\n\t}\n\n\t{\n\t\tbool b = false;\n\n\t\teastl::compiler_barrier_data_dependency(b);\n\t}\n}\n\nstruct ReadDependsIntrusive\n{\n\tint a;\n\tint b;\n\tstruct ReadDependsIntrusive* next;\n\tint c;\n\tint d;\n};\n\neastl::atomic<ReadDependsIntrusive**> gListHead;\n\nEA_NO_INLINE static int TestAtomicReadDependsIntrusive()\n{\n\tReadDependsIntrusive** intrusivePtr = gListHead.load(eastl::memory_order_read_depends);\n\tReadDependsIntrusive* ptr = ((ReadDependsIntrusive*)(((char*)intrusivePtr) - offsetof(ReadDependsIntrusive, next)));\n\n\tint a = ptr->a;\n\tint b = ptr->b;\n\tint c = ptr->c;\n\tint d = ptr->d;\n\n\treturn a + b + c + d;\n}\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\nEA_NO_INLINE static void TestAtomic32LoadStoreSameAddressSeqCst()\n{\n\teastl::atomic<uint32_t> atomic{0};\n\n\tuint32_t ret1 = atomic.load(eastl::memory_order_relaxed);\n\n\tatomic.store(4, eastl::memory_order_relaxed);\n\n\tuint32_t ret2 = atomic.load(eastl::memory_order_relaxed);\n\n\tuint32_t ret3 = atomic.load(eastl::memory_order_relaxed);\n\n\tatomic.store(5, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret1);\n\teastl::compiler_barrier_data_dependency(ret2);\n\teastl::compiler_barrier_data_dependency(ret3);\n}\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nEA_NO_INLINE static void TestAtomic128LoadStoreSameAddressSeqCst()\n{\n\teastl::atomic<UserType128> atomic{UserType128{0, 0, 0, 0}};\n\n\tUserType128 ret1 = atomic.load(eastl::memory_order_relaxed);\n\n\tatomic.store(UserType128{1, 0, 2, 4}, eastl::memory_order_relaxed);\n\n\tUserType128 ret2 = atomic.load(eastl::memory_order_relaxed);\n\n\tUserType128 ret3 = atomic.load(eastl::memory_order_relaxed);\n\n\tatomic.store(UserType128{1, 1, 2, 4}, eastl::memory_order_relaxed);\n\n\teastl::compiler_barrier_data_dependency(ret1);\n\teastl::compiler_barrier_data_dependency(ret2);\n\teastl::compiler_barrier_data_dependency(ret3);\n}\n\n#endif\n\nint TestAtomicAsm()\n{\n\tint nErrorCount = 0;\n\n\t// Stores\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32StoreOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64StoreOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\tTestAtomic128StoreOrders();\n\t#endif\n\t}\n\n\t// Loads\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32LoadOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64LoadOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\tTestAtomic128LoadOrders();\n\t#endif\n\t}\n\n\t// exchange\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32ExchangeOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64ExchangeOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\tTestAtomic128ExchangeOrders();\n\t#endif\n\t}\n\n\t// operator T\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorT();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorT();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\tTestAtomic128OperatorT();\n\t#endif\n\t}\n\n\t// operator=\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorEqual();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorEqual();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\tTestAtomic128OperatorEqual();\n\t#endif\n\t}\n\n\t// compare_exchange_weak\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32CompareExchangeWeakOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64CompareExchangeWeakOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\tTestAtomic128CompareExchangeWeakOrders();\n\t#endif\n\t}\n\n\t// compare_exchange_strong\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32CompareExchangeStrongOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64CompareExchangeStrongOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\tTestAtomic128CompareExchangeStrongOrders();\n\t#endif\n\t}\n\n\t// fetch_add\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32FetchAddOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64FetchAddOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128FetchAddOrders();\n\t#endif\n\t}\n\n\t// add_fetch\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32AddFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64AddFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128AddFetchOrders();\n\t#endif\n\t}\n\n\t// fetch_sub\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32FetchSubOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64FetchSubOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128FetchSubOrders();\n\t#endif\n\t}\n\n\t// sub_fetch\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32SubFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64SubFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128SubFetchOrders();\n\t#endif\n\t}\n\n\t// fetch_and\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32FetchAndOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64FetchAndOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128FetchAndOrders();\n\t#endif\n\t}\n\n\t// and_fetch\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32AndFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64AndFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128AndFetchOrders();\n\t#endif\n\t}\n\n\t// fetch_or\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32FetchOrOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64FetchOrOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\t\tTestAtomic128FetchOrOrders();\n\t#endif\n\t}\n\n\t// or_fetch\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OrFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OrFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OrFetchOrders();\n\t#endif\n\t}\n\n\t// fetch_xor\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32FetchXorOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64FetchXorOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128FetchXorOrders();\n\t#endif\n\t}\n\n\t// xor_fetch\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32XorFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64XorFetchOrders();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128XorFetchOrders();\n\t#endif\n\t}\n\n\t// operator++/++operator\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorPlusPlus();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorPlusPlus();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OperatorPlusPlus();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32PlusPlusOperator();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64PlusPlusOperator();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128PlusPlusOperator();\n\t#endif\n\t}\n\n\t// operator--/--operator\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorMinusMinus();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorMinusMinus();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OperatorMinusMinus();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32MinusMinusOperator();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64MinusMinusOperator();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128MinusMinusOperator();\n\t#endif\n\t}\n\n\t// operator+=\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorPlusAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorPlusAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OperatorPlusAssignment();\n\t#endif\n\t}\n\n\t// operator-=\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorMinusAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorMinusAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OperatorMinusAssignment();\n\t#endif\n\t}\n\n\t// operator&=\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorAndAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorAndAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OperatorAndAssignment();\n\t#endif\n\t}\n\n\t// operator|=\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorOrAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorOrAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OperatorOrAssignment();\n\t#endif\n\t}\n\n\t// operator^=\n\t{\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\tTestAtomicU32OperatorXorAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\tTestAtomicU64OperatorXorAssignment();\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG))\n\t\tTestAtomic128OperatorXorAssignment();\n\t#endif\n\t}\n\n\t// atomic_signal_fence\n\t{\n\t\tTestAtomicSignalFenceRelaxed();\n\n\t\tTestAtomicSignalFenceAcquire();\n\n\t\tTestAtomicSignalFenceRelease();\n\n\t\tTestAtomicSignalFenceAcqRel();\n\n\t\tTestAtomicSignalFenceSeqCst();\n\t}\n\n\t// atomic_thread_fence\n\t{\n\t\tTestAtomicThreadFenceRelaxed();\n\n\t\tTestAtomicThreadFenceAcquire();\n\n\t\tTestAtomicThreadFenceRelease();\n\n\t\tTestAtomicThreadFenceAcqRel();\n\n\t\tTestAtomicThreadFenceSeqCst();\n\t}\n\n\t// atomic pointer read depends\n\t{\n\t\tTestAtomicPointerReadDepends();\n\t}\n\n\t// atomic pointer read depends\n\t{\n\t\tReadDependsStruct rds {3, 2};\n\n\t\tgAtomicPtr.store(&rds, eastl::memory_order_release);\n\n\t\tint ret = TestAtomicReadDependsStruct();\n\t\teastl::compiler_barrier_data_dependency(ret);\n\t}\n\n\t{\n\t\tReadDependsIntrusive rdi {3, 2, &rdi, 1, 0};\n\n\t\tgListHead.store(&(rdi.next), eastl::memory_order_release);\n\n\t\tint ret = TestAtomicReadDependsIntrusive();\n\t\teastl::compiler_barrier_data_dependency(ret);\n\t}\n\n\t{\n\t\tTestCompilerBarrierDataDependency();\n\t}\n\n#if defined(EASTL_ATOMIC_HAS_32BIT)\n\n\tTestAtomic32LoadStoreSameAddressSeqCst();\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\n\tTestAtomic128LoadStoreSameAddressSeqCst();\n\n#endif\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestAtomicBasic.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n\n#include <EASTL/atomic.h>\n\n\n/**\n * This is a basic test suite that tests all functionality is implemented\n * and that all operations do as expected.\n * I.E. fetch_add returns the previous value and add_fetch returns the current value\n */\n\nstatic eastl::atomic<int> sAtomicInt{ 4 };\nstatic eastl::atomic<void*> sAtomicPtr{ nullptr };\n\nstatic int TestAtomicConstantInitialization()\n{\n\tint nErrorCount;\n\n\tEATEST_VERIFY(sAtomicInt.load() == 4);\n\tEATEST_VERIFY(sAtomicPtr == nullptr);\n\n\treturn 0;\n}\n\nclass AtomicStandaloneBasicTest\n{\npublic:\n\n\tint RunTest()\n\t{\n\t\tAtomicSignalFence();\n\n\t\tAtomicThreadFence();\n\n\t\tAtomicCpuPause();\n\n\t\tAtomicCompilerBarrier();\n\n\t\treturn nErrorCount;\n\t}\n\nprivate:\n\n\tvoid AtomicSignalFence();\n\n\tvoid AtomicThreadFence();\n\n\tvoid AtomicCpuPause();\n\n\tvoid AtomicCompilerBarrier();\n\nprivate:\n\n\tint nErrorCount = 0;\n};\n\nvoid AtomicStandaloneBasicTest::AtomicSignalFence()\n{\n\teastl::atomic_signal_fence(eastl::memory_order_relaxed);\n\n\teastl::atomic_signal_fence(eastl::memory_order_acquire);\n\n\teastl::atomic_signal_fence(eastl::memory_order_release);\n\n\teastl::atomic_signal_fence(eastl::memory_order_acq_rel);\n\n\teastl::atomic_signal_fence(eastl::memory_order_seq_cst);\n}\n\nvoid AtomicStandaloneBasicTest::AtomicThreadFence()\n{\n\teastl::atomic_thread_fence(eastl::memory_order_relaxed);\n\n\teastl::atomic_thread_fence(eastl::memory_order_acquire);\n\n\teastl::atomic_thread_fence(eastl::memory_order_release);\n\n\teastl::atomic_thread_fence(eastl::memory_order_acq_rel);\n\n\teastl::atomic_thread_fence(eastl::memory_order_seq_cst);\n}\n\nvoid AtomicStandaloneBasicTest::AtomicCpuPause()\n{\n\teastl::cpu_pause();\n}\n\nvoid AtomicStandaloneBasicTest::AtomicCompilerBarrier()\n{\n\teastl::compiler_barrier();\n\n\t{\n\t\tbool ret = false;\n\t\teastl::compiler_barrier_data_dependency(ret);\n\t}\n}\n\nclass AtomicFlagBasicTest\n{\npublic:\n\n\tusing AtomicType = eastl::atomic_flag;\n\tusing BoolType = bool;\n\n\tint RunTest()\n\t{\n\t\tTestAtomicFlagCtor();\n\n\t\tTestAtomicFlagClear();\n\n\t\tTestAtomicFlagTestAndSet();\n\n\t\tTestAtomicFlagTest();\n\n\t\tTestAllMemoryOrders();\n\n\t\tTestAtomicFlagStandalone();\n\n\t\treturn nErrorCount;\n\t}\n\nprivate:\n\n\tvoid TestAtomicFlagCtor();\n\n\tvoid TestAtomicFlagClear();\n\n\tvoid TestAtomicFlagTestAndSet();\n\n\tvoid TestAtomicFlagTest();\n\n\tvoid TestAllMemoryOrders();\n\n\tvoid TestAtomicFlagStandalone();\n\nprivate:\n\n\tint nErrorCount = 0;\n};\n\nvoid AtomicFlagBasicTest::TestAtomicFlagCtor()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{ true };\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == true);\n\t}\n}\n\nvoid AtomicFlagBasicTest::TestAtomicFlagClear()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic.clear(eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{ true };\n\n\t\tatomic.clear(eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == false);\n\t}\n}\n\nvoid AtomicFlagBasicTest::TestAtomicFlagTestAndSet()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic.test_and_set(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == true);\n\t}\n\n\t{\n\t\tAtomicType atomic{ true };\n\n\t\tBoolType ret = atomic.test_and_set(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == true);\n\t}\n}\n\nvoid AtomicFlagBasicTest::TestAtomicFlagTest()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{ true };\n\n\t\tVERIFY(atomic.test(eastl::memory_order_relaxed) == true);\n\t}\n}\n\nvoid AtomicFlagBasicTest::TestAllMemoryOrders()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic.clear();\n\n\t\tatomic.clear(eastl::memory_order_relaxed);\n\n\t\tatomic.clear(eastl::memory_order_release);\n\n\t\tatomic.clear(eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic.test_and_set();\n\n\t\tatomic.test_and_set(eastl::memory_order_relaxed);\n\n\t\tatomic.test_and_set(eastl::memory_order_acquire);\n\n\t\tatomic.test_and_set(eastl::memory_order_release);\n\n\t\tatomic.test_and_set(eastl::memory_order_acq_rel);\n\n\t\tatomic.test_and_set(eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic.test();\n\n\t\tret = atomic.test(eastl::memory_order_relaxed);\n\n\t\tret = atomic.test(eastl::memory_order_acquire);\n\n\t\tret = atomic.test(eastl::memory_order_seq_cst);\n\t}\n}\n\nvoid AtomicFlagBasicTest::TestAtomicFlagStandalone()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic_flag_test_and_set(&atomic);\n\n\t\tret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_relaxed);\n\n\t\tret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_acquire);\n\n\t\tret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_release);\n\n\t\tret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_acq_rel);\n\n\t\tret = atomic_flag_test_and_set_explicit(&atomic, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic_flag_clear(&atomic);\n\n\t\tatomic_flag_clear_explicit(&atomic, eastl::memory_order_relaxed);\n\n\t\tatomic_flag_clear_explicit(&atomic, eastl::memory_order_release);\n\n\t\tatomic_flag_clear_explicit(&atomic, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t    BoolType ret = atomic_flag_test(&atomic);\n\n\t\tret = atomic_flag_test_explicit(&atomic, eastl::memory_order_relaxed);\n\n\t\tret = atomic_flag_test_explicit(&atomic, eastl::memory_order_acquire);\n\n\t\tret = atomic_flag_test_explicit(&atomic, eastl::memory_order_seq_cst);\n\t}\n}\n\nclass AtomicVoidPointerBasicTest\n{\npublic:\n\n\tusing AtomicType = eastl::atomic<void*>;\n\tusing PtrType = void*;\n\n\tint RunTest()\n\t{\n\t\tTestAtomicCtor();\n\n\t\tTestAssignmentOperators();\n\n\t\tTestIsLockFree();\n\n\t\tTestStore();\n\n\t\tTestLoad();\n\n\t\tTestExchange();\n\n\t\tTestCompareExchangeWeak();\n\n\t\tTestCompareExchangeStrong();\n\n\t\tTestAllMemoryOrders();\n\n\t\treturn nErrorCount;\n\t}\n\nprivate:\n\n\tvoid TestAtomicCtor();\n\n\tvoid TestAssignmentOperators();\n\n\tvoid TestIsLockFree();\n\n\tvoid TestStore();\n\n\tvoid TestLoad();\n\n\tvoid TestExchange();\n\n\tvoid TestCompareExchangeWeak();\n\n\tvoid TestCompareExchangeStrong();\n\n\tvoid TestAllMemoryOrders();\n\nprivate:\n\n\tint nErrorCount = 0;\n};\n\nvoid AtomicVoidPointerBasicTest::TestAtomicCtor()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ (PtrType)0x04 };\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x04);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestAssignmentOperators()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic = (PtrType)0x04;\n\n\t\tVERIFY(ret == (PtrType)0x04);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x04);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic = (PtrType)0x0;\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestIsLockFree()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic.is_lock_free() == true);\n\n\t\tVERIFY(atomic.is_always_lock_free == true);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestStore()\n{\n\t{\n\t\tPtrType val = (PtrType)0x0;\n\t\tAtomicType atomic;\n\n\t\tatomic.store(val, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == val);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic;\n\n\t\tatomic.store(val, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == val);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestLoad()\n{\n\t{\n\t\tAtomicType atomic{ (PtrType)0x4 };\n\n\t\tPtrType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestExchange()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestCompareExchangeWeak()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\t\t\tVERIFY(observed == (PtrType)0x0);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x4;\n\t\tbool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestCompareExchangeStrong()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\t\tVERIFY(observed == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x4;\n\t\tbool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n}\n\nvoid AtomicVoidPointerBasicTest::TestAllMemoryOrders()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType val = (PtrType)0x4;\n\n\t\tatomic.store(val);\n\n\t\tatomic.store(val, eastl::memory_order_relaxed);\n\n\t\tatomic.store(val, eastl::memory_order_release);\n\n\t\tatomic.store(val, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.load();\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tret = atomic.load(eastl::memory_order_acquire);\n\n\t\tret = atomic.load(eastl::memory_order_seq_cst);\n\n\t\tret = atomic.load(eastl::memory_order_read_depends);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.exchange((PtrType)0x4);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_acquire);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\n\t\tbool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\n\t\tbool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n}\n\nclass AtomicPointerBasicTest\n{\npublic:\n\n\tusing AtomicType = eastl::atomic<uint32_t*>;\n\tusing PtrType = uint32_t*;\n\n\tint RunTest()\n\t{\n\t\tTestAtomicCtor();\n\n\t\tTestAssignmentOperators();\n\n\t\tTestIsLockFree();\n\n\t\tTestStore();\n\n\t\tTestLoad();\n\n\t\tTestExchange();\n\n\t\tTestCompareExchangeWeak();\n\n\t\tTestCompareExchangeStrong();\n\n\t\tTestAllMemoryOrders();\n\n\t\tTestFetchAdd();\n\t\tTestAddFetch();\n\n\t\tTestFetchSub();\n\t\tTestSubFetch();\n\n\t\tTestAtomicPointerStandalone();\n\n\t\treturn nErrorCount;\n\t}\n\nprivate:\n\n\tvoid TestAtomicCtor();\n\n\tvoid TestAssignmentOperators();\n\n\tvoid TestIsLockFree();\n\n\tvoid TestStore();\n\n\tvoid TestLoad();\n\n\tvoid TestExchange();\n\n\tvoid TestCompareExchangeWeak();\n\n\tvoid TestCompareExchangeStrong();\n\n\tvoid TestAllMemoryOrders();\n\n\tvoid TestFetchAdd();\n\tvoid TestAddFetch();\n\n\tvoid TestFetchSub();\n\tvoid TestSubFetch();\n\n\tvoid TestAtomicPointerStandalone();\n\nprivate:\n\n\tint nErrorCount = 0;\n};\n\nvoid AtomicPointerBasicTest::TestAtomicCtor()\n{\n\t{\n\t\tAtomicType atomic{};\n\n\t\tPtrType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == nullptr);\n\t}\n\n\t{\n\t\tAtomicType atomic{ (PtrType)0x4 };\n\n\t\tPtrType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestAssignmentOperators()\n{\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{val};\n\n\t\tPtrType expected = (PtrType)0x8;\n\n\t\tPtrType ret = atomic = expected;\n\n\t\tVERIFY(ret == expected);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x0;\n\t\tAtomicType atomic{val};\n\n\t\tPtrType ret = atomic = val;\n\n\t\tVERIFY(ret == val);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == val);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{val};\n\n\t\tPtrType expected = (PtrType)0x8;\n\t\tPtrType ret = ++atomic;\n\n\t\tVERIFY(ret == expected);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\n\t\tAtomicType atomic{val};\n\n\t\tPtrType expected = (PtrType)0x8;\n\t\tPtrType ret = atomic++;\n\n\t\tVERIFY(ret == val);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{val};\n\n\t\tPtrType expected = (PtrType)0x10;\n\t\tPtrType ret = atomic += 3;\n\n\t\tVERIFY(ret == expected);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{val};\n\n\t\tPtrType expected = (PtrType)0x4;\n\t\tPtrType ret = atomic += 0;\n\n\t\tVERIFY(ret == expected);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{val};\n\n\t\tPtrType expected = (PtrType)0x0;\n\t\tPtrType ret = atomic -= 1;\n\n\t\tVERIFY(ret == expected);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{val};\n\n\t\tPtrType expected = (PtrType)0x4;\n\t\tPtrType ret = atomic -= 0;\n\n\t\tVERIFY(ret == expected);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestIsLockFree()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic.is_lock_free() == true);\n\n\t\tVERIFY(atomic.is_always_lock_free == true);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestStore()\n{\n\t{\n\t\tPtrType val = (PtrType)0x0;\n\t\tAtomicType atomic;\n\n\t\tatomic.store(val, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == val);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic;\n\n\t\tatomic.store(val, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == val);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestLoad()\n{\n\t{\n\t\tAtomicType atomic{ (PtrType)0x4 };\n\n\t\tPtrType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestCompareExchangeWeak()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\t\t\tVERIFY(observed == (PtrType)0x0);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x4;\n\t\tbool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestCompareExchangeStrong()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\t\tVERIFY(observed == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType observed = (PtrType)0x4;\n\t\tbool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestExchange()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestAllMemoryOrders()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType val = (PtrType)0x4;\n\n\t\tatomic.store(val);\n\n\t\tatomic.store(val, eastl::memory_order_relaxed);\n\n\t\tatomic.store(val, eastl::memory_order_release);\n\n\t\tatomic.store(val, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.load();\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tret = atomic.load(eastl::memory_order_acquire);\n\n\t\tret = atomic.load(eastl::memory_order_seq_cst);\n\n\t\tret = atomic.load(eastl::memory_order_read_depends);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.fetch_add(0);\n\n\t\tret = atomic.fetch_add(0, eastl::memory_order_relaxed);\n\n\t\tret = atomic.fetch_add(0, eastl::memory_order_acquire);\n\n\t\tret = atomic.fetch_add(0, eastl::memory_order_release);\n\n\t\tret = atomic.fetch_add(0, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.fetch_add(0, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.fetch_sub(0);\n\n\t\tret = atomic.fetch_sub(0, eastl::memory_order_relaxed);\n\n\t\tret = atomic.fetch_sub(0, eastl::memory_order_acquire);\n\n\t\tret = atomic.fetch_sub(0, eastl::memory_order_release);\n\n\t\tret = atomic.fetch_sub(0, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.fetch_sub(0, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.add_fetch(0);\n\n\t\tret = atomic.add_fetch(0, eastl::memory_order_relaxed);\n\n\t\tret = atomic.add_fetch(0, eastl::memory_order_acquire);\n\n\t\tret = atomic.add_fetch(0, eastl::memory_order_release);\n\n\t\tret = atomic.add_fetch(0, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.add_fetch(0, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.sub_fetch(0);\n\n\t\tret = atomic.sub_fetch(0, eastl::memory_order_relaxed);\n\n\t\tret = atomic.sub_fetch(0, eastl::memory_order_acquire);\n\n\t\tret = atomic.sub_fetch(0, eastl::memory_order_release);\n\n\t\tret = atomic.sub_fetch(0, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.sub_fetch(0, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic.exchange((PtrType)0x4);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_acquire);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_release);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.exchange((PtrType)0x4, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\n\t\tbool ret = atomic.compare_exchange_weak(observed, (PtrType)0x4);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\n\t\tbool ret = atomic.compare_exchange_strong(observed, (PtrType)0x4);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType observed = (PtrType)0x0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, (PtrType)0x4, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestFetchAdd()\n{\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x8);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.fetch_add(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestAddFetch()\n{\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.add_fetch(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x8);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x8);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.add_fetch(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestFetchSub()\n{\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.fetch_sub(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.fetch_sub(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestSubFetch()\n{\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.sub_fetch(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n\n\t{\n\t\tPtrType val = (PtrType)0x4;\n\t\tAtomicType atomic{ val };\n\n\t\tPtrType ret = atomic.sub_fetch(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n}\n\nvoid AtomicPointerBasicTest::TestAtomicPointerStandalone()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic_is_lock_free(&atomic) == true);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType val = (PtrType)0x4;\n\n\t\tatomic_store(&atomic, val);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == val);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tPtrType val = (PtrType)0x4;\n\n\t\tatomic_store_explicit(&atomic, val, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == val);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_load(&atomic);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_load_explicit(&atomic, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_load_cond(&atomic, [](PtrType) { return true; });\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_load_cond_explicit(&atomic, [](PtrType) { return true; }, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_exchange(&atomic, (PtrType)0x4);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_exchange_explicit(&atomic, (PtrType)0x4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_add_fetch(&atomic, 1);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_add_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_fetch_add(&atomic, 1);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType ret = atomic_fetch_add_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic{ (PtrType)0x4 };\n\n\t\tPtrType ret = atomic_fetch_sub(&atomic, 1);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ (PtrType)0x4 };\n\n\t\tPtrType ret = atomic_fetch_sub_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x4);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ (PtrType)0x4 };\n\n\t\tPtrType ret = atomic_sub_fetch(&atomic, 1);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ (PtrType)0x4 };\n\n\t\tPtrType ret = atomic_sub_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == (PtrType)0x0);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType expected = (PtrType)0x0;\n\t\tbool ret = atomic_compare_exchange_strong(&atomic, &expected, (PtrType)0x4);\n\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(expected == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType expected = (PtrType)0x0;\n\t\tbool ret = atomic_compare_exchange_strong_explicit(&atomic, &expected, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(expected == (PtrType)0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType expected = (PtrType)0x0;\n\t\tbool ret = atomic_compare_exchange_weak(&atomic, &expected, (PtrType)0x4);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\n\t\t\tVERIFY(expected == (PtrType)0x0);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tPtrType expected = (PtrType)0x0;\n\t\tbool ret = atomic_compare_exchange_weak_explicit(&atomic, &expected, (PtrType)0x4, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\n\t\t\tVERIFY(expected == (PtrType)0x0);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == (PtrType)0x4);\n\t\t}\n\t}\n}\n\nstruct AtomicNonTriviallyConstructible\n{\n\tAtomicNonTriviallyConstructible()\n\t\t: a(0)\n\t\t, b(0)\n\t{\n\t}\n\n\tAtomicNonTriviallyConstructible(uint16_t a, uint16_t b)\n\t\t: a(a)\n\t\t, b(b)\n\t{\n\t}\n\n\tfriend bool operator==(const AtomicNonTriviallyConstructible& a, const AtomicNonTriviallyConstructible& b)\n\t{\n\t\treturn a.a == b.a && a.b == b.b;\n\t}\n\n\tuint16_t a;\n\tuint16_t b;\n};\n\nstruct AtomicNonTriviallyConstructibleNoExcept\n{\n\tAtomicNonTriviallyConstructibleNoExcept() noexcept\n\t\t: a(0)\n\t\t, b(0)\n\t{\n\t}\n\n\tAtomicNonTriviallyConstructibleNoExcept(uint16_t a, uint16_t b) noexcept\n\t\t: a(a)\n\t\t, b(b)\n\t{\n\t}\n\n\tfriend bool operator==(const AtomicNonTriviallyConstructibleNoExcept& a, const AtomicNonTriviallyConstructibleNoExcept& b)\n\t{\n\t\treturn a.a == b.a && a.b == b.b;\n\t}\n\n\tuint16_t a;\n\tuint16_t b;\n};\n\nstruct AtomicUserType16\n{\n\tuint8_t a;\n\tuint8_t b;\n\n\tfriend bool operator==(const AtomicUserType16& a, const AtomicUserType16& b)\n\t{\n\t\treturn (a.a == b.a) && (a.b == b.b);\n\t}\n};\n\nstruct AtomicUserType128\n{\n\tuint32_t a;\n\tuint32_t b;\n\tuint32_t c;\n\tuint32_t d;\n\n\tAtomicUserType128() = default;\n\n\tAtomicUserType128(const AtomicUserType128&) = default;\n\n\tAtomicUserType128(uint32_t a, uint32_t b)\n\t\t: a(a)\n\t\t, b(b)\n\t\t, c(0)\n\t\t, d(0)\n\t{\n\t}\n\n\tAtomicUserType128& operator=(const AtomicUserType128&) = default;\n\n\tfriend bool operator==(const AtomicUserType128& a, const AtomicUserType128& b)\n\t{\n\t\treturn (a.a == b.a) && (a.b == b.b) && (a.c == b.c) && (a.d == b.d);\n\t}\n};\n\ntemplate <typename T>\nclass AtomicUserTypeBasicTest\n{\npublic:\n\n\tusing AtomicType = eastl::atomic<T>;\n\tusing UserType = T;\n\n\tint RunTest()\n\t{\n\t\tTestAtomicCtor();\n\n\t\tTestAssignmentOperators();\n\n\t\tTestIsLockFree();\n\n\t\tTestStore();\n\n\t\tTestLoad();\n\n\t\tTestExchange();\n\n\t\tTestCompareExchangeWeak();\n\n\t\tTestCompareExchangeStrong();\n\n\t\tTestAllMemoryOrders();\n\n\t\treturn nErrorCount;\n\t}\n\nprivate:\n\n\tvoid TestAtomicCtor();\n\n\tvoid TestAssignmentOperators();\n\n\tvoid TestIsLockFree();\n\n\tvoid TestStore();\n\n\tvoid TestLoad();\n\n\tvoid TestExchange();\n\n\tvoid TestCompareExchangeWeak();\n\n\tvoid TestCompareExchangeStrong();\n\n\tvoid TestAllMemoryOrders();\n\nprivate:\n\n\tint nErrorCount = 0;\n};\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestAtomicCtor()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{0, 0};\n\n\t\tUserType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == expected);\n\t}\n\n\t{\n\t\tAtomicType atomic{ {5, 8} };\n\t\tUserType expected{5, 8};\n\n\t\tUserType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == expected);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestAssignmentOperators()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{5, 6};\n\n\t\tatomic = {5, 6};\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{0, 0};\n\n\t\tatomic = {0, 0};\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestIsLockFree()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic.is_lock_free() == true);\n\n\t\tVERIFY(AtomicType::is_always_lock_free == true);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestStore()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{5, 6};\n\n\t\tatomic.store(expected, eastl::memory_order_relaxed);\n\n\t\tUserType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == expected);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{5, 6};\n\n\t\tatomic.store({5, 6}, eastl::memory_order_relaxed);\n\n\t\tUserType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == expected);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestLoad()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{0, 0};\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\n\t\tVERIFY(atomic == expected);\n\t}\n\n\t{\n\t\tAtomicType atomic{ {5, 6} };\n\t\tUserType expected{5, 6};\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\n\t\tVERIFY(atomic == expected);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestExchange()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{0, 0};\n\n\t\tUserType ret = atomic.exchange({0, 0}, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == expected);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\t\tUserType expected{0, 0};\n\t\tUserType expected2{0, 1};\n\n\t\tUserType ret = atomic.exchange({0, 1}, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == expected);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected2);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestCompareExchangeWeak()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\t\tbool ret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_relaxed);\n\n\t\tUserType expected{0, 0};\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\t\t\tVERIFY(observed == expected);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\t\tbool ret = atomic.compare_exchange_weak(observed, {0, 1}, eastl::memory_order_relaxed);\n\n\t\tUserType expected{0, 1};\n\t\tUserType expected2{0, 0};\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\t\t\tVERIFY(observed == expected2);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 1};\n\t\tbool ret = atomic.compare_exchange_weak(observed, {0, 1}, eastl::memory_order_relaxed);\n\n\t\tUserType expected{0, 0};\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == expected);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestCompareExchangeStrong()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\t\tbool ret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_relaxed);\n\n\t\tUserType expected{0, 0};\n\n\t\tVERIFY(ret == true);\n\t\tVERIFY(observed == expected);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\t\tbool ret = atomic.compare_exchange_strong(observed, {0, 1}, eastl::memory_order_relaxed);\n\n\t\tUserType expected{0, 1};\n\t\tUserType expected2{0, 0};\n\n\t\tVERIFY(ret == true);\n\t\tVERIFY(observed == expected2);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == expected);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 1};\n\t\tbool ret = atomic.compare_exchange_strong(observed, {0, 1}, eastl::memory_order_relaxed);\n\n\t\tUserType expected{0, 0};\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == expected);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicUserTypeBasicTest<T>::TestAllMemoryOrders()\n{\n\t{\n\t\tAtomicType atomic;\n\t\tUserType val{0, 1};\n\n\t\tatomic.store(val);\n\n\t\tatomic.store(val, eastl::memory_order_relaxed);\n\n\t\tatomic.store(val, eastl::memory_order_release);\n\n\t\tatomic.store(val, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType ret = atomic.load();\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tret = atomic.load(eastl::memory_order_acquire);\n\n\t\tret = atomic.load(eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType ret = atomic.exchange({0, 1});\n\n\t\tret = atomic.exchange({0, 0}, eastl::memory_order_relaxed);\n\n\t\tret = atomic.exchange({0, 0}, eastl::memory_order_acquire);\n\n\t\tret = atomic.exchange({0, 0}, eastl::memory_order_release);\n\n\t\tret = atomic.exchange({0, 0}, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.exchange({0, 0}, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\n\t\tbool ret = atomic.compare_exchange_weak(observed, {0, 0});\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\n\t\tbool ret = atomic.compare_exchange_strong(observed, {0, 0});\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tUserType observed{0, 0};\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, {0, 0}, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n}\n\n\nclass AtomicBoolBasicTest\n{\npublic:\n\n\tusing AtomicType = eastl::atomic<bool>;\n\tusing BoolType = bool;\n\n\tint RunTest()\n\t{\n\t\tTestAtomicCtor();\n\n\t\tTestAssignmentOperators();\n\n\t\tTestIsLockFree();\n\n\t\tTestStore();\n\n\t\tTestLoad();\n\n\t\tTestExchange();\n\n\t\tTestCompareExchangeWeak();\n\n\t\tTestCompareExchangeStrong();\n\n\t\tTestAllMemoryOrders();\n\n\t\treturn nErrorCount;\n\t}\n\nprivate:\n\n\tvoid TestAtomicCtor();\n\n\tvoid TestAssignmentOperators();\n\n\tvoid TestIsLockFree();\n\n\tvoid TestStore();\n\n\tvoid TestLoad();\n\n\tvoid TestExchange();\n\n\tvoid TestCompareExchangeWeak();\n\n\tvoid TestCompareExchangeStrong();\n\n\tvoid TestAllMemoryOrders();\n\nprivate:\n\n\tint nErrorCount = 0;\n};\n\nvoid AtomicBoolBasicTest::TestAtomicCtor()\n{\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tBoolType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{ true };\n\n\t\tBoolType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tBoolType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestAssignmentOperators()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic = true;\n\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == true);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestIsLockFree()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tbool ret = atomic.is_lock_free();\n\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(AtomicType::is_always_lock_free == true);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestStore()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic.store(true, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == true);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestLoad()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == false);\n\n\t\tVERIFY(atomic == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{ true };\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == true);\n\n\t\tVERIFY(atomic == true);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestExchange()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic.exchange(false, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == false);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic.exchange(true, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == true);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestCompareExchangeWeak()\n{\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_weak(observed, false, eastl::memory_order_relaxed);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\t\t\tVERIFY(observed == false);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == false);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\t\t\tVERIFY(observed == false);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == true);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tBoolType observed = true;\n\t\tbool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == false);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestCompareExchangeStrong()\n{\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_weak(observed, false, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\t\tVERIFY(observed == false);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == false);\n\t}\n\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\t\tVERIFY(observed == false);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == true);\n\t}\n\n\t{\n\t\tAtomicType atomic{ false };\n\n\t\tBoolType observed = true;\n\t\tbool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == false);\n\t}\n}\n\nvoid AtomicBoolBasicTest::TestAllMemoryOrders()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic.store(true);\n\n\t\tatomic.store(true, eastl::memory_order_relaxed);\n\n\t\tatomic.store(true, eastl::memory_order_release);\n\n\t\tatomic.store(true, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic.load();\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tret = atomic.load(eastl::memory_order_acquire);\n\n\t\tret = atomic.load(eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType ret = atomic.exchange(true);\n\n\t\tret = atomic.exchange(true, eastl::memory_order_relaxed);\n\n\t\tret = atomic.exchange(true, eastl::memory_order_acquire);\n\n\t\tret = atomic.exchange(true, eastl::memory_order_release);\n\n\t\tret = atomic.exchange(true, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.exchange(true, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_weak(observed, true);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_strong(observed, true);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tBoolType observed = false;\n\t\tbool ret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acquire, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acquire, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_release, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_acq_rel, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, true, eastl::memory_order_seq_cst, eastl::memory_order_seq_cst);\n\t}\n}\n\n\ntemplate <typename T>\nclass AtomicIntegralBasicTest\n{\npublic:\n\n\tusing AtomicType = eastl::atomic<T>;\n\tusing IntegralType = T;\n\n\tint RunTest()\n\t{\n\t\tTestAtomicCtor();\n\n\t\tTestAtomicFetchAdd();\n\t\tTestAtomicAddFetch();\n\n\t\tTestAtomicFetchSub();\n\t\tTestAtomicSubFetch();\n\n\t\tTestAtomicFetchAnd();\n\t\tTestAtomicAndFetch();\n\n\t\tTestAtomicFetchOr();\n\t\tTestAtomicOrFetch();\n\n\t\tTestAtomicFetchXor();\n\t\tTestAtomicXorFetch();\n\n\t\tTestAssignmentOperators();\n\n\t\tTestIsLockFree();\n\n\t\tTestStore();\n\n\t\tTestLoad();\n\n\t\tTestExchange();\n\n\t\tTestCompareExchangeWeak();\n\n\t\tTestCompareExchangeStrong();\n\n\t\tTestAllMemoryOrders();\n\n\t\tTestAtomicStandalone();\n\n\t\treturn nErrorCount;\n\t}\n\nprivate:\n\n\tvoid TestAtomicCtor();\n\n\tvoid TestAtomicFetchAdd();\n\tvoid TestAtomicAddFetch();\n\n\tvoid TestAtomicFetchSub();\n\tvoid TestAtomicSubFetch();\n\n\tvoid TestAtomicFetchAnd();\n\tvoid TestAtomicAndFetch();\n\n\tvoid TestAtomicFetchOr();\n\tvoid TestAtomicOrFetch();\n\n\tvoid TestAtomicFetchXor();\n\tvoid TestAtomicXorFetch();\n\n\tvoid TestAssignmentOperators();\n\n\tvoid TestIsLockFree();\n\n\tvoid TestStore();\n\n\tvoid TestLoad();\n\n\tvoid TestExchange();\n\n\tvoid TestCompareExchangeWeak();\n\n\tvoid TestCompareExchangeStrong();\n\n\tvoid TestAllMemoryOrders();\n\n\tvoid TestAtomicStandalone();\n\nprivate:\n\n\tint nErrorCount = 0;\n};\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicCtor()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 20 };\n\n\t\tIntegralType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 20);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicFetchAdd()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic.fetch_add(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 5 };\n\n\t\tIntegralType ret = atomic.fetch_add(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 5);\n\n\t\tret = atomic.fetch_add(4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 5);\n\n\t\tret = atomic.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 9);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 10);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicAddFetch()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic.add_fetch(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic.add_fetch(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 5 };\n\n\t\tIntegralType ret = atomic.add_fetch(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 5);\n\n\t\tret = atomic.add_fetch(4, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 9);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 9);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicFetchSub()\n{\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic.fetch_sub(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic.fetch_sub(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 5 };\n\n\t\tIntegralType ret = atomic.fetch_sub(2, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 5);\n\n\t\tret = atomic.fetch_sub(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 3);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 2);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicSubFetch()\n{\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic.sub_fetch(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic.sub_fetch(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 5 };\n\n\t\tIntegralType ret = atomic.sub_fetch(2, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 3);\n\n\t\tret = atomic.sub_fetch(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 2);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 2);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicFetchAnd()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.fetch_and(0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.fetch_and(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0xF };\n\n\t\tIntegralType ret = atomic.fetch_and(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0xF);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0X1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0xF };\n\n\t\tIntegralType ret = atomic.fetch_and(0xF0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0xF);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicAndFetch()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.and_fetch(0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.and_fetch(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0xF };\n\n\t\tIntegralType ret = atomic.and_fetch(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0xF };\n\n\t\tIntegralType ret = atomic.and_fetch(0xF0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicFetchOr()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.fetch_or(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic.fetch_or(0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic.fetch_or(0x2, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x3);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicOrFetch()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.or_fetch(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic.or_fetch(0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic.or_fetch(0x2, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x3);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x3);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicFetchXor()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.fetch_xor(0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic.fetch_xor(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x0 };\n\n\t\tIntegralType ret = atomic.fetch_xor(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicXorFetch()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.xor_fetch(0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic.xor_fetch(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x0 };\n\n\t\tIntegralType ret = atomic.xor_fetch(0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAssignmentOperators()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = (atomic = 5);\n\n\t\tVERIFY(ret == 5);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 5);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = ++atomic;\n\n\t\tVERIFY(ret == 1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic++;\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = --atomic;\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic--;\n\n\t\tVERIFY(ret == 1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic += 5;\n\n\t\tVERIFY(ret == 5);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 5);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 5 };\n\n\t\tIntegralType ret = atomic -= 3;\n\n\t\tVERIFY(ret == 2);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 2);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x0 };\n\n\t\tIntegralType ret = atomic |= 0x1;\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic &= 0x1;\n\n\t\tVERIFY(ret == 0x1);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic ^= 0x1;\n\n\t\tVERIFY(ret == 0x0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestIsLockFree()\n{\n\t{\n\t\tconst AtomicType atomic{ 5 };\n\n\t\tVERIFY(atomic.is_lock_free() == true);\n\n\t\tVERIFY(AtomicType::is_always_lock_free == true);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestStore()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tatomic.store(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tatomic.store(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestLoad()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\n\t\tbool ret = atomic == 0;\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(atomic == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 5 };\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 5);\n\n\t\tbool ret = atomic == 5;\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(atomic == 5);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestExchange()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.exchange(0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType ret = atomic.exchange(1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestCompareExchangeWeak()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType observed = 0;\n\t\tbool ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_relaxed);\n\n\t\tif (ret == true)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\t\t\tVERIFY(observed == 0);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType observed = 1;\n\t\tbool ret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestCompareExchangeStrong()\n{\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType observed = 0;\n\t\tbool ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\t\tVERIFY(observed == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0 };\n\n\t\tIntegralType observed = 1;\n\t\tbool ret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == false);\n\t\tVERIFY(observed == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\t}\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAllMemoryOrders()\n{\n\t{\n\t\tAtomicType atomic{};\n\n\t\tatomic.store(1);\n\n\t\tatomic.store(1, eastl::memory_order_relaxed);\n\n\t\tatomic.store(1, eastl::memory_order_release);\n\n\t\tatomic.store(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.load();\n\n\t\tret = atomic.load(eastl::memory_order_relaxed);\n\n\t\tret = atomic.load(eastl::memory_order_acquire);\n\n\t\tret = atomic.load(eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.exchange(1);\n\n\t\tret = atomic.exchange(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.exchange(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.exchange(1, eastl::memory_order_release);\n\n\t\tret = atomic.exchange(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.exchange(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.fetch_add(1);\n\n\t\tret = atomic.fetch_add(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.fetch_add(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.fetch_add(1, eastl::memory_order_release);\n\n\t\tret = atomic.fetch_add(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.fetch_add(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.add_fetch(1);\n\n\t\tret = atomic.add_fetch(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.add_fetch(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.add_fetch(1, eastl::memory_order_release);\n\n\t\tret = atomic.add_fetch(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.add_fetch(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.fetch_sub(1);\n\n\t\tret = atomic.fetch_sub(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.fetch_sub(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.fetch_sub(1, eastl::memory_order_release);\n\n\t\tret = atomic.fetch_sub(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.fetch_sub(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.sub_fetch(1);\n\n\t\tret = atomic.sub_fetch(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.sub_fetch(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.sub_fetch(1, eastl::memory_order_release);\n\n\t\tret = atomic.sub_fetch(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.sub_fetch(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.fetch_and(1);\n\n\t\tret = atomic.fetch_and(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.fetch_and(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.fetch_and(1, eastl::memory_order_release);\n\n\t\tret = atomic.fetch_and(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.fetch_and(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.and_fetch(1);\n\n\t\tret = atomic.and_fetch(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.and_fetch(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.and_fetch(1, eastl::memory_order_release);\n\n\t\tret = atomic.and_fetch(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.and_fetch(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.fetch_or(1);\n\n\t\tret = atomic.fetch_or(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.fetch_or(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.fetch_or(1, eastl::memory_order_release);\n\n\t\tret = atomic.fetch_or(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.fetch_or(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.or_fetch(1);\n\n\t\tret = atomic.or_fetch(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.or_fetch(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.or_fetch(1, eastl::memory_order_release);\n\n\t\tret = atomic.or_fetch(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.or_fetch(1, eastl::memory_order_seq_cst);\n\t }\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.fetch_xor(1);\n\n\t\tret = atomic.fetch_xor(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.fetch_xor(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.fetch_xor(1, eastl::memory_order_release);\n\n\t\tret = atomic.fetch_xor(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.fetch_xor(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType ret = atomic.xor_fetch(1);\n\n\t\tret = atomic.xor_fetch(1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.xor_fetch(1, eastl::memory_order_acquire);\n\n\t\tret = atomic.xor_fetch(1, eastl::memory_order_release);\n\n\t\tret = atomic.xor_fetch(1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.xor_fetch(1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType observed = 0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_weak(observed, 1);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType observed = 0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_strong(observed, 1);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_release);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_acq_rel);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1, eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType observed = 0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_relaxed,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_acquire,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_acquire,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_release,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_acq_rel,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_acq_rel,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_seq_cst,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_seq_cst,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_weak(observed, 1,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_seq_cst,\n\t\t\t\t\t\t\t\t\t\t   eastl::memory_order_seq_cst);\n\t}\n\n\t{\n\t\tAtomicType atomic{};\n\n\t\tIntegralType observed = 0;\n\t\tbool ret;\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_relaxed,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_acquire,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_acquire,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_release,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_acq_rel,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_acq_rel,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_seq_cst,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_relaxed);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_seq_cst,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_acquire);\n\n\t\tret = atomic.compare_exchange_strong(observed, 1,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_seq_cst,\n\t\t\t\t\t\t\t\t\t\t\t eastl::memory_order_seq_cst);\n\t}\n\n}\n\ntemplate <typename T>\nvoid AtomicIntegralBasicTest<T>::TestAtomicStandalone()\n{\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType expected = 0;\n\t\tbool ret = atomic_compare_exchange_weak(&atomic, &expected, 1);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\n\t\t\tVERIFY(expected == 0);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType expected = 0;\n\t\tbool ret = atomic_compare_exchange_weak_explicit(&atomic, &expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tif (ret)\n\t\t{\n\t\t\tVERIFY(ret == true);\n\n\t\t\tVERIFY(expected == 0);\n\t\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t\t}\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType expected = 0;\n\t\tbool ret = atomic_compare_exchange_strong(&atomic, &expected, 1);\n\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(expected == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType expected = 0;\n\t\tbool ret = atomic_compare_exchange_strong_explicit(&atomic, &expected, 1, eastl::memory_order_relaxed, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == true);\n\n\t\tVERIFY(expected == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_fetch_xor(&atomic, 0x1);\n\n\t\tVERIFY(ret == 0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_fetch_xor_explicit(&atomic, 0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_xor_fetch(&atomic, 0x1);\n\n\t\tVERIFY(ret == 0x1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_xor_fetch_explicit(&atomic, 0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_fetch_or(&atomic, 0x1);\n\n\t\tVERIFY(ret == 0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_fetch_or_explicit(&atomic, 0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_or_fetch(&atomic, 0x1);\n\n\t\tVERIFY(ret == 0x1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_or_fetch_explicit(&atomic, 0x1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x1);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic_fetch_and(&atomic, 0x0);\n\n\t\tVERIFY(ret == 0x1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic_fetch_and_explicit(&atomic, 0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic_and_fetch(&atomic, 0x0);\n\n\t\tVERIFY(ret == 0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 0x1 };\n\n\t\tIntegralType ret = atomic_and_fetch_explicit(&atomic, 0x0, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0x0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0x0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic_fetch_sub(&atomic, 1);\n\n\t\tVERIFY(ret == 1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic_fetch_sub_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic_sub_fetch(&atomic, 1);\n\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic{ 1 };\n\n\t\tIntegralType ret = atomic_sub_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_fetch_add(&atomic, 1);\n\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_fetch_add_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_add_fetch(&atomic, 1);\n\n\t\tVERIFY(ret == 1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_add_fetch_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 1);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_exchange(&atomic, 1);\n\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_exchange_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_load(&atomic);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_load_explicit(&atomic, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_load_cond(&atomic, [](IntegralType) { return true; });\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tIntegralType ret = atomic_load_cond_explicit(&atomic, [](IntegralType) { return true; }, eastl::memory_order_relaxed);\n\n\t\tVERIFY(ret == 0);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic_store(&atomic, 1);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tatomic_store_explicit(&atomic, 1, eastl::memory_order_relaxed);\n\n\t\tVERIFY(atomic.load(eastl::memory_order_relaxed) == 1);\n\t}\n\n\t{\n\t\tAtomicType atomic;\n\n\t\tVERIFY(atomic_is_lock_free(&atomic) == true);\n\t}\n}\n\nstruct AtomicNonDefaultConstructible\n{\n\tAtomicNonDefaultConstructible(uint8_t a)\n\t\t: a(a)\n\t{\n\t}\n\n\tfriend bool operator==(const AtomicNonDefaultConstructible& a, const AtomicNonDefaultConstructible& b)\n\t{\n\t\treturn a.a == b.a;\n\t}\n\n\tuint8_t a;\n};\n\n#if defined(EASTL_ATOMIC_HAS_8BIT)\n\nint TestAtomicNonDefaultConstructible()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\teastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};\n\n\t\tVERIFY(atomic.load() == AtomicNonDefaultConstructible{(uint8_t)3});\n\t}\n\n\t{\n\t\teastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};\n\n\t\tatomic.store(AtomicNonDefaultConstructible{(uint8_t)4});\n\n\t\tVERIFY(atomic.load() == AtomicNonDefaultConstructible{(uint8_t)4});\n\t}\n\n\t{\n\t\teastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};\n\n\t\tVERIFY(atomic_load_cond(&atomic, [] (AtomicNonDefaultConstructible) { return true; }) == AtomicNonDefaultConstructible{(uint8_t)3});\n\t}\n\n\t{\n\t\teastl::atomic<AtomicNonDefaultConstructible> atomic{AtomicNonDefaultConstructible{(uint8_t)3}};\n\n\t\tVERIFY(atomic_load_cond_explicit(&atomic, [] (AtomicNonDefaultConstructible) { return true; }, eastl::memory_order_seq_cst) == AtomicNonDefaultConstructible{(uint8_t)3});\n\t}\n\n\treturn nErrorCount;\n}\n\n#endif\n\nstruct Atomic128LoadType\n{\n\tfriend bool operator==(const Atomic128LoadType& a, const Atomic128LoadType& b)\n\t{\n\t\treturn a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d;\n\t}\n\n\tuint32_t a, b, c, d;\n};\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\nint TestAtomic128Loads()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 1, 0, 0}};\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{1, 1, 0, 0}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 1, 1}};\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{0, 0, 1, 1}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 1, 0, 1}};\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{0, 1, 0, 1}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 0, 1, 0}};\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{1, 0, 1, 0}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 1, 0, 0}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{1, 1, 0, 0});\n\n\t\tVERIFY((expected == Atomic128LoadType{1, 1, 0, 0}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 1, 1}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{0, 0, 1, 1});\n\n\t\tVERIFY((expected == Atomic128LoadType{0, 0, 1, 1}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 1, 0, 1}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{0, 1, 0, 1});\n\n\t\tVERIFY((expected == Atomic128LoadType{0, 1, 0, 1}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{1, 0, 1, 0}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{1, 0, 1, 0});\n\n\t\tVERIFY((expected == Atomic128LoadType{1, 0, 1, 0}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{1, 1, 0, 0});\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{1, 1, 0, 0}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{0, 0, 1, 1});\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{0, 0, 1, 1}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{0, 1, 0, 1});\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{0, 1, 0, 1}));\n\t}\n\n\t{\n\t\teastl::atomic<Atomic128LoadType> atomic{Atomic128LoadType{0, 0, 0, 0}};\n\n\t\tAtomic128LoadType expected{0, 0, 0, 0};\n\t\tatomic.compare_exchange_strong(expected, Atomic128LoadType{1, 0, 1, 0});\n\n\t\tVERIFY((atomic.load() == Atomic128LoadType{1, 0, 1, 0}));\n\t}\n\n\treturn nErrorCount;\n}\n\n#endif\n\nint TestAtomicBasic()\n{\n\tint nErrorCount = 0;\n\n\t#if defined(EASTL_ATOMIC_HAS_8BIT)\n\t\t{\n\t\t\tAtomicIntegralBasicTest<uint8_t> u8AtomicTest;\n\n\t\t\tnErrorCount += u8AtomicTest.RunTest();\n\t\t}\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_16BIT)\n\t\t{\n\t\t\tAtomicIntegralBasicTest<uint16_t> u16AtomicTest;\n\n\t\t\tnErrorCount += u16AtomicTest.RunTest();\n\t\t}\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\t{\n\t\t\tAtomicIntegralBasicTest<uint32_t> u32AtomicTest;\n\n\t\t\tnErrorCount += u32AtomicTest.RunTest();\n\t\t}\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_64BIT)\n\t\t{\n\t\t\tAtomicIntegralBasicTest<uint64_t> u64AtomicTest;\n\n\t\t\tnErrorCount += u64AtomicTest.RunTest();\n\t\t}\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT) && (defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_GNUC))\n\t\t{\n\t\t\tAtomicIntegralBasicTest<__uint128_t> u128AtomicTest;\n\n\t\t\tnErrorCount += u128AtomicTest.RunTest();\n\t\t}\n\n\t\t{\n\t\t\tAtomicIntegralBasicTest<eastl_uint128_t> u128AtomicTest;\n\n\t\t\tnErrorCount += u128AtomicTest.RunTest();\n\t\t}\n\t#endif\n\n\t{\n\t\tAtomicBoolBasicTest boolAtomicTest;\n\n\t\tnErrorCount += boolAtomicTest.RunTest();\n\t}\n\n\t#if defined(EASTL_ATOMIC_HAS_16BIT)\n\t\t{\n\t\t\tAtomicUserTypeBasicTest<AtomicUserType16> userTypeAtomicTest;\n\n\t\t\tnErrorCount += userTypeAtomicTest.RunTest();\n\t\t}\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_32BIT)\n\t\t\t{\n\t\t\t\tAtomicUserTypeBasicTest<AtomicNonTriviallyConstructible> userTypeAtomicTest;\n\n\t\t\t\tnErrorCount += userTypeAtomicTest.RunTest();\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tAtomicUserTypeBasicTest<AtomicNonTriviallyConstructibleNoExcept> userTypeAtomicTest;\n\n\t\t\t\tnErrorCount += userTypeAtomicTest.RunTest();\n\t\t\t}\n\t#endif\n\n\t#if defined(EASTL_ATOMIC_HAS_128BIT)\n\t\t{\n\t\t\tAtomicUserTypeBasicTest<AtomicUserType128> userTypeAtomicTest;\n\n\t\t\tnErrorCount += userTypeAtomicTest.RunTest();\n\t\t}\n\t#endif\n\n\t{\n\t\tAtomicPointerBasicTest ptrAtomicTest;\n\n\t\tnErrorCount += ptrAtomicTest.RunTest();\n\t}\n\n\t{\n\t\tAtomicVoidPointerBasicTest voidPtrAtomicTest;\n\n\t\tnErrorCount += voidPtrAtomicTest.RunTest();\n\t}\n\n\t{\n\t\tAtomicFlagBasicTest atomicFlagBasicTest;\n\n\t\tnErrorCount += atomicFlagBasicTest.RunTest();\n\t}\n\n\t{\n\t\tAtomicStandaloneBasicTest atomicStandaloneBasicTest;\n\n\t\tnErrorCount += atomicStandaloneBasicTest.RunTest();\n\t}\n\n#if defined(EASTL_ATOMIC_HAS_128BIT)\n\n\tnErrorCount += TestAtomic128Loads();\n\n#endif\n\n#if defined(EASTL_ATOMIC_HAS_8BIT)\n\n\tnErrorCount += TestAtomicNonDefaultConstructible();\n\n#endif\n\n\tnErrorCount += TestAtomicConstantInitialization();\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestAtomicMultiThreaded.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n// This one first because it defines EASTL_THREAD_SUPPORT_AVAILABLE\n#include <EASTL/internal/thread_support.h>\n\n#if EASTL_THREAD_SUPPORT_AVAILABLE\n\n#include <EASTL/atomic.h>\n#include <eathread/eathread_thread.h>\n\n#include \"EASTLTest.h\"\n\n/**\n * These are some basic tests to test \"atomicity\" of operations.\n */\n\nnamespace\n{\n\n\tstruct Test128BitType\n\t{\n\t\tTest128BitType() = default;\n\t\tTest128BitType(uint32_t x) : a{x}, b{x}, c{x}, d{x} {};\n\t\tTest128BitType(uint32_t x, uint32_t y, uint32_t z, uint32_t w) : a{x}, b{y}, c{z}, d{w} {};\n\n\t\tbool operator==(const Test128BitType& rhs) const\n\t\t{\n\t\t\treturn a == rhs.a && b == rhs.b && c == rhs.c && d == rhs.d;\n\t\t}\n\n\t\tuint32_t a{};\n\t\tuint32_t b{};\n\t\tuint32_t c{};\n\t\tuint32_t d{};\n\t};\n\n\tbool AreAllMembersEqual(const Test128BitType& x) { return x.a == x.b && x.b == x.c && x.c == x.d; }\n\n// We don't support 128bit atomics on 32-bit x86.\n#if !defined(EA_PROCESSOR_X86)\n\tstruct Test128BitLoadStoreData\n\t{\n\t\teastl::atomic<Test128BitType> mX;\n\t\tEA::Thread::Semaphore mStartSem{0};\n\t\teastl::atomic<bool> mShouldStop{};\n\t\teastl::atomic<bool> mFoundTornRead{};\n\t};\n\n\tstatic intptr_t RelaxedLoadAndCheck(void* v)\n\t{\n\t\tTest128BitLoadStoreData* data = static_cast<Test128BitLoadStoreData*>(v);\n\n\t\t// Wait to be signaled that we can start.\n\t\tdata->mStartSem.Wait();\n\n\t\tbool foundTornRead = false;\n\t\t// Until we're signaled we should stop.\n\t\twhile (!data->mShouldStop.load(eastl::memory_order_relaxed))\n\t\t{\n\t\t\t// Do a relaxed load and make sure we don't ever tear. The\n\t\t\t// writing thread will do atomic stores with values satisfying\n\t\t\t// this condition.\n\t\t\tauto loaded = data->mX.load(eastl::memory_order_relaxed);\n\n\t\t\tfoundTornRead |= !AreAllMembersEqual(loaded);\n\t\t}\n\n\t\tdata->mFoundTornRead = foundTornRead;\n\n\t\treturn 0;\n\t}\n\n\tstatic intptr_t RelaxedStore(void* v)\n\t{\n\t\tTest128BitLoadStoreData* data = static_cast<Test128BitLoadStoreData*>(v);\n\n\t\t// Wait to be signaled that we can start.\n\t\tdata->mStartSem.Wait();\n\n\t\tuint32_t counter{};\n\n\t\t// Until we're signaled we should stop.\n\t\twhile (!data->mShouldStop.load(eastl::memory_order_relaxed))\n\t\t{\n\t\t\t// This thread just stores incremental values which have identical entries.\n\t\t\tTest128BitType x{counter};\n\t\t\tdata->mX.store(x, eastl::memory_order_relaxed);\n\n\t\t\t// This could wrap, but that's OK, it's not UB on unsigned types.\n\t\t\t++counter;\n\t\t}\n\n\t\treturn 0;\n\t}\n#endif\n\n\ttemplate <class T>\n\tstruct TestSequentialConsistencyData\n\t{\n\t\teastl::atomic<T> mA1;\n\t\teastl::atomic<T> mA2;\n\t\teastl::atomic<T> mB1;\n\t\teastl::atomic<T> mB2;\n\t\tEA::Thread::Semaphore mStartSem1{0};\n\t\tEA::Thread::Semaphore mStartSem2{0};\n\t\tEA::Thread::Semaphore mEndSem{0};\n\t\teastl::atomic<uint32_t> mLoopCount{10000};\n\t\teastl::atomic<uint32_t> mThreadCounter{};\n\t};\n\n\ttemplate <class T>\n\tstatic intptr_t TestSequentialConsistencyThreadFn(void* v)\n\t{\n\t\tTestSequentialConsistencyData<T>& data = *static_cast<TestSequentialConsistencyData<T>*>(v);\n\n\t\t// We're doing x = 1, r = y in order, but we want different\n\t\t// order on different threads, and different r's for the\n\t\t// different orders.\n\t\t//\n\t\t// See the following link for details:\n\t\t// https://preshing.com/20120515/memory-reordering-caught-in-the-act/\n\n\t\tconst uint32_t threadNumber = ++data.mThreadCounter;\n\t\tconst bool chooseFirst = threadNumber % 2;\n\n\t\tauto& x = chooseFirst ? data.mA1 : data.mA2;\n\t\tauto& y = chooseFirst ? data.mA2 : data.mA1;\n\t\tauto& r = chooseFirst ? data.mB1 : data.mB2;\n\n\t\tauto& startSem = chooseFirst ? data.mStartSem1 : data.mStartSem2;\n\n\t\tuint32_t loops = data.mLoopCount;\n\t\twhile (loops--)\n\t\t{\n\t\t\tstartSem.Wait();\n\n\t\t\t// x = 1;\n\t\t\tx.store(T(1), eastl::memory_order_seq_cst);\n\n\t\t\t// r = y;\n\t\t\tr.store(y.load(eastl::memory_order_seq_cst), eastl::memory_order_seq_cst);\n\n\t\t\tdata.mEndSem.Post();\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\ttemplate <class T>\n\tstatic int TestSequentialConsistencyImpl()\n\t{\n\t\tTestSequentialConsistencyData<T> data;\n\n\t\tint nErrorCount = 0;\n\t\tEA::Thread::Thread threads[2];\n\n\t\tthreads[0].Begin(TestSequentialConsistencyThreadFn<T>, static_cast<void*>(&data));\n\t\tthreads[1].Begin(TestSequentialConsistencyThreadFn<T>, static_cast<void*>(&data));\n\n\t\tuint32_t loops = data.mLoopCount;\n\n\t\twhile (loops--)\n\t\t{\n\t\t\t// Reset the input.\n\t\t\tdata.mA1.store(T(0), eastl::memory_order_seq_cst);\n\t\t\tdata.mA2.store(T(0), eastl::memory_order_seq_cst);\n\n\t\t\t// Signal the threads\n\t\t\tdata.mStartSem1.Post();\n\t\t\tdata.mStartSem2.Post();\n\n\t\t\t// Wait for both threads;\n\t\t\tdata.mEndSem.Wait();\n\t\t\tdata.mEndSem.Wait();\n\n\t\t\t// Check if there was a CPU reorder.\n\t\t\tconst auto b1 = data.mB1.load(eastl::memory_order_seq_cst);\n\t\t\tconst auto b2 = data.mB2.load(eastl::memory_order_seq_cst);\n\n\t\t\tconst bool reorderHappened = (b1 == T{0} && b2 == T{0});\n\t\t\tEATEST_VERIFY(!reorderHappened);\n\t\t}\n\n\t\treturn nErrorCount;\n\t}\n\n\n} // namespace\n\nint Test128BitLoadStoreMultiThreaded()\n{\n\tint nErrorCount = 0;\n\n// We don't support 128bit atomics on 32-bit x86.\n#if !defined(EA_PROCESSOR_X86)\n\tconstexpr int kNumThreads = 4; // 2 readers and 2 writers.\n\tEA::Thread::Thread threads[kNumThreads];\n\tTest128BitLoadStoreData data;\n\n\tfor (int i = 0; (i + 1) < kNumThreads; i += 2)\n\t{\n\t\tthreads[i].Begin(RelaxedLoadAndCheck, static_cast<void*>(&data));\n\t\tthreads[i + 1].Begin(RelaxedStore, static_cast<void*>(&data));\n\t}\n\n\tdata.mStartSem.Post(kNumThreads);\n\n\tEA::Thread::ThreadSleep(3000);\n\n\tdata.mShouldStop = true;\n\n\tfor (auto& t : threads)\n\t{\n\t\tt.WaitForEnd();\n\t}\n\n\tnErrorCount += data.mFoundTornRead;\n#endif\n\n\treturn nErrorCount;\n}\n\nint TestSequentialConsistency()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestSequentialConsistencyImpl<uint16_t>();\n\tnErrorCount += TestSequentialConsistencyImpl<uint32_t>();\n\tnErrorCount += TestSequentialConsistencyImpl<uint64_t>();\n\n// We don't support 128bit atomics on 32-bit x86.\n#if !defined(EA_PROCESSOR_X86)\n\tnErrorCount += TestSequentialConsistencyImpl<Test128BitType>();\n#endif\n\n\treturn nErrorCount;\n}\n\nstruct ReadDependsTestData\n{\n\teastl::atomic<int*> ptr{};\n\tint a{10};\n\tint errorCount{};\n};\n\nintptr_t Post(void* p)\n{\n\tauto& data = *static_cast<ReadDependsTestData*>(p);\n\tdata.a = 5;\n\tdata.ptr.store(&data.a, eastl::memory_order_release);\n\treturn 0;\n}\n\nintptr_t Wait(void* p)\n{\n\tauto& data = *static_cast<ReadDependsTestData*>(p);\n\tint* ptr{};\n\n\t// wait for the message to be posted\n\tfor (; ptr == nullptr; ptr = data.ptr.load(eastl::memory_order_read_depends)) {}\n\n\t// ptr should point to a, which should have a value of 5 since it's a dependent load.\n\tint x = *ptr;\n\tif (x != 5)\n\t{\n\t\t++data.errorCount;\n\t}\n\n\treturn 0;\n}\n\nint TestReadDepends()\n{\n\tint nErrorCount{};\n\n\t// Do this 100 times, why not, this test is \"timing dependent\".\n\tfor (auto i = 0; i < 100; ++i)\n\t{\n\t\tconstexpr eastl_size_t kThreadCount = 4;\n\t\teastl::vector<EA::Thread::Thread> threads{kThreadCount};\n\n\t\tReadDependsTestData data;\n\n\t\t// one \"post\" thread.\n\t\tthreads[0].Begin(Post, &data);\n\n\t\t// N-1 \"wait\" threads\n\t\tfor (int k = 1; k < kThreadCount; ++k)\n\t\t\tthreads[k].Begin(Wait, &data);\n\n\t\t// Wait for all threads to finish\n\t\tfor (int k = 0; k < kThreadCount; ++k)\n\t\t\tthreads[k].WaitForEnd();\n\n\t\tnErrorCount += data.errorCount;\n\t}\n\treturn nErrorCount;\n}\n\nstruct RefCountingTestData\n{\n\tinline static constexpr int kThreadCount = 4;\n\talignas(64) eastl::atomic<int> mThreadIndex;\n\talignas(64) eastl::atomic<int> mDecrementCount;\n\talignas(64) eastl::atomic<int> mRefCount;\n\talignas(64) eastl::atomic<int> mErrorCount;\n\n\tvoid incrementRefCount()\n\t{\n\t\tmRefCount.fetch_add(1, eastl::memory_order_relaxed);\n\t}\n\n\t// returns true if the count is still >0\n\tbool decrementRefCount()\n\t{\n\t\t// increment this so we can test the synchronization.\n\t\tmDecrementCount.fetch_add(1, eastl::memory_order_relaxed);\n\t\tif (mRefCount.fetch_sub(1, eastl::memory_order_release) == 1)\n\t\t{\n\t\t\tmRefCount.acquire_fence();\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n};\n\nintptr_t IncrementDecrement(void* p)\n{\n\tauto& data = *static_cast<RefCountingTestData*>(p);\n\n\t// Do one here which we'll clear at the end so only the last thread exiting reaches zero.\n\tdata.incrementRefCount();\n\n\tdata.mThreadIndex.fetch_add(1, eastl::memory_order_relaxed);\n\n\t// wait until all threads have started:\n\twhile(data.mThreadIndex.load(eastl::memory_order_relaxed) != data.kThreadCount) {}\n\n\tconst auto kLoopCount = 1024;\n\t// increment and decrement the ref counts concurrently with the other threads a bit...\n\tfor (int i = 0; i < kLoopCount; ++i)\n\t{\n\t\tdata.incrementRefCount();\n\t\tdata.decrementRefCount();\n\t}\n\n\t// check if we're the last thread to exit.\n\tif (!data.decrementRefCount())\n\t{\n\t\t// check this won't be reordered.\n\t\tconst auto decrementCount = data.mDecrementCount.load(eastl::memory_order_relaxed);\n\t\tdata.mErrorCount += (decrementCount != data.kThreadCount * (kLoopCount + 1));\n\t}\n\n\treturn 0;\n}\n\n\nint TestRefCounting()\n{\n\tint nErrorCount{};\n\n\t// Do this 10 times, why not, this test is \"timing dependent\".\n\tfor (auto i = 0; i < 10; ++i)\n\t{\n\t\tRefCountingTestData data;\n\t\teastl::vector<EA::Thread::Thread> threads{data.kThreadCount};\n\n\t\tfor (int k = 0; k < data.kThreadCount; ++k)\n\t\t\tthreads[k].Begin(IncrementDecrement, &data);\n\n\t\t// Wait for all threads to finish\n\t\tfor (int k = 0; k < data.kThreadCount; ++k)\n\t\t\tthreads[k].WaitForEnd();\n\n\t\tnErrorCount += data.mErrorCount;\n\t}\n\treturn nErrorCount;\n}\n\nint TestAtomicMultiThreaded()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += Test128BitLoadStoreMultiThreaded();\n\tnErrorCount += TestSequentialConsistency();\n\tnErrorCount += TestReadDepends();\n\tnErrorCount += TestRefCounting();\n\n\treturn nErrorCount;\n}\n\n#endif\n"
  },
  {
    "path": "test/source/TestAtomicRaw.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include <EASTL/atomic.h>\n#include <EASTL/atomic_raw.h>\n#include <EASTL/meta.h>\n\n#include \"EASTLTest.h\"\n\n// Minimal tests to make sure that all eastl::atomic_X functions compile with the memory\n// orders we expect them to and do what we expect them to (single threaded tests only, for now)\n\ntemplate <class Fn, class... MemOrd>\nint TestMemoryOrders(Fn fn, MemOrd... mem_ord)\n{\n\treturn (fn(mem_ord) + ...);\n}\n\ntemplate <class Fn, class MemOrdSuccess, class MemOrdFailure>\nint TestMemoryOrderPair(Fn fn, eastl::meta::type_list<MemOrdSuccess, MemOrdFailure>)\n{\n\treturn fn(MemOrdSuccess{}, MemOrdFailure{});\n}\n\ntemplate <class... Pairs>\nstruct TestMemoryOrderPairs\n{\n\ttemplate <class Fn>\n\tstatic int Run(Fn fn)\n\t{\n\t\treturn (TestMemoryOrderPair(fn, Pairs{}) + ...);\n\t}\n};\n\ntemplate <class... MemOrd>\nstruct TestAtomicLoadAPIImpl\n{\n\ttemplate <typename T>\n\tstatic int Run(T initVal, T otherVal)\n\t{\n\t\tauto test = [=](auto mem_ord)\n\t\t{\n\t\t\tint nErrorCount{};\n\t\t\tT a{initVal};\n\t\t\tT x = eastl::atomic_raw_load(&a, mem_ord);\n\t\t\tVERIFY(x == initVal);\n\t\t\tVERIFY(a == initVal);\n\t\t\ta = otherVal;\n\t\t\tT y = eastl::atomic_raw_load(&a, mem_ord);\n\t\t\tVERIFY(otherVal == y);\n\t\t\tVERIFY(otherVal == a);\n\t\t\treturn nErrorCount;\n\t\t};\n\n\t\treturn TestMemoryOrders(test, MemOrd{}...);\n\t}\n};\n\ntemplate <class T>\nint TestAtomicLoadAPI(T initVal, T otherVal)\n{\n\n\tusing namespace eastl::internal;\n\treturn TestAtomicLoadAPIImpl<memory_order_relaxed_s, memory_order_acquire_s, memory_order_seq_cst_s>::Run(initVal,\n\t                                                                                                          otherVal);\n}\n\ntemplate <class T>\nint TestAtomicStoreAPI(T initVal, T otherVal)\n{\n\tauto test = [=](auto mem_ord)\n\t{\n\t\tint nErrorCount{};\n\t\tT a{initVal};\n\t\tT b = otherVal;\n\t\teastl::atomic_raw_store(&a, b, mem_ord);\n\t\tVERIFY(a == otherVal);\n\t\tVERIFY(b == otherVal);\n\t\treturn nErrorCount;\n\t};\n\n\treturn TestMemoryOrders(test, eastl::memory_order_relaxed, eastl::memory_order_release,\n\t                        eastl::memory_order_seq_cst);\n}\n\ntemplate <class T>\nint TestAtomicExchangeAPI(T initVal, T exchangeVal)\n{\n\tauto test = [=](auto mem_ord)\n\t{\n\t\tint nErrorCount{};\n\t\tT a{initVal};\n\t\tT x = eastl::atomic_raw_exchange(&a, exchangeVal, mem_ord);\n\t\tVERIFY(initVal == x);\n\t\tVERIFY(a == exchangeVal);\n\t\tT y = eastl::atomic_raw_exchange(&a, initVal, mem_ord);\n\t\tVERIFY(initVal == a);\n\t\tVERIFY(y == exchangeVal);\n\t\treturn nErrorCount;\n\t};\n\n\treturn TestMemoryOrders(test, eastl::memory_order_relaxed, eastl::memory_order_acquire, eastl::memory_order_release,\n\t                        eastl::memory_order_acq_rel, eastl::memory_order_seq_cst);\n}\n\ntemplate <class T>\nint TestAtomicCmpxchgAPI(T initVal, T newVal)\n{\n\tusing namespace eastl::internal;\n\tusing namespace eastl::meta;\n\n\t// this can be used to test with one or two memory orders.\n\tauto test = [=](auto... mem_orders)\n\t{\n\t\tauto testInternal = [=](auto cmpxchg_fn)\n\t\t{\n\t\t\tint nErrorCount{};\n\t\t\tT a{initVal};\n\t\t\tT x = newVal;\n\t\t\tT y = initVal;\n\t\t\tVERIFY(cmpxchg_fn(&a, y, x, mem_orders...));\n\t\t\tVERIFY(y == initVal);\n\t\t\tVERIFY(a == newVal);\n\t\t\tVERIFY(!cmpxchg_fn(&a, y, x, mem_orders...));\n\t\t\tVERIFY(y == newVal);\n\t\t\tVERIFY(a == newVal);\n\t\t\tVERIFY(cmpxchg_fn(&a, y, initVal, mem_orders...));\n\t\t\tVERIFY(y == newVal);\n\t\t\tVERIFY(a == initVal);\n\t\t\treturn nErrorCount;\n\t\t};\n\n\t\tauto cmpxchg_weak = [](auto&&... args)\n\t\t{ return eastl::atomic_raw_compare_exchange_weak(eastl::forward<decltype(args)>(args)...); };\n\n\t\tauto cmpxchg_strong = [](auto&&... args)\n\t\t{ return eastl::atomic_raw_compare_exchange_strong(eastl::forward<decltype(args)>(args)...); };\n\n\t\treturn testInternal(cmpxchg_weak) + testInternal(cmpxchg_strong);\n\t};\n\n\t// Note: the supported pairs are specified by the standard like this:\n\t// - the failure ordering cannot be stronger than the success.\n\t// - the failure ordering cannot be one of release or acq_rel\n\treturn TestMemoryOrderPairs<type_list<memory_order_relaxed_s, memory_order_relaxed_s>,\n\t                            type_list<memory_order_acquire_s, memory_order_relaxed_s>,\n\t                            type_list<memory_order_acquire_s, memory_order_acquire_s>,\n\t                            type_list<memory_order_release_s, memory_order_relaxed_s>,\n\t                            type_list<memory_order_acq_rel_s, memory_order_relaxed_s>,\n\t                            type_list<memory_order_acq_rel_s, memory_order_acquire_s>,\n\t                            type_list<memory_order_seq_cst_s, memory_order_relaxed_s>,\n\t                            type_list<memory_order_seq_cst_s, memory_order_acquire_s>,\n\t                            type_list<memory_order_seq_cst_s, memory_order_seq_cst_s>>::Run(test) +\n\t       // There are also versions which only take the order for the RMW operation order \"deduce\" the order for the\n\t       // load operation under the following rules:\n\t       // - if the order for RMW is acq_rel then the order for the load is acquire.\n\t       // - if the order for RMW is release then the order for the load is relaxed.\n\t       // - otherwise, if the order for RMW is X then the order for the load is X.\n\t       TestMemoryOrders(test, eastl::memory_order_relaxed, eastl::memory_order_acquire, eastl::memory_order_release,\n\t                        eastl::memory_order_acq_rel, eastl::memory_order_seq_cst);\n}\n\ntemplate <class T, class U, class FetchFn, class VerificationFn>\nint TestFetchFunction(T initVal, U increment, FetchFn fetchFn, VerificationFn verificationFn)\n{\n\tauto test = [=](auto mem_ord)\n\t{\n\t\tint nErrorCount{};\n\n\t\tT x1{initVal};\n\t\tT x2{initVal};\n\t\tT y1 = fetchFn(&x1, increment, mem_ord);\n\t\tT y2 = verificationFn(x2, increment);\n\t\tVERIFY(x1 == x2);\n\t\tVERIFY(y1 == y2);\n\n\t\treturn nErrorCount;\n\t};\n\n\treturn TestMemoryOrders(test, eastl::memory_order_relaxed, eastl::memory_order_acquire, eastl::memory_order_release,\n\t                        eastl::memory_order_acq_rel, eastl::memory_order_seq_cst);\n}\n\ntemplate <class T, class U>\nint TestAtomicFetchCommonAPI(T initVal, U increment)\n{\n\tauto fetchAddAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_fetch_add(x, y, mem_ord); };\n\tauto fetchAddVerifyFn = [=](T& x, U y)\n\t{\n\t\tT ret = x;\n\t\tx += y;\n\t\treturn ret;\n\t};\n\n\tauto addFetchAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_add_fetch(x, y, mem_ord); };\n\tauto addFetchVerifyFn = [=](T& x, U y)\n\t{\n\t\tx += y;\n\t\treturn x;\n\t};\n\n\tauto fetchSubAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_fetch_sub(x, y, mem_ord); };\n\tauto fetchSubVerifyFn = [=](T& x, U y)\n\t{\n\t\tT ret = x;\n\t\tx -= y;\n\t\treturn ret;\n\t};\n\n\tauto subFetchAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_sub_fetch(x, y, mem_ord); };\n\tauto subFetchVerifyFn = [=](T& x, U y)\n\t{\n\t\tx -= y;\n\t\treturn x;\n\t};\n\n\treturn TestFetchFunction(initVal, increment, fetchAddAtomicFn, fetchAddVerifyFn) +\n\t       TestFetchFunction(initVal, increment, addFetchAtomicFn, addFetchVerifyFn) +\n\t       TestFetchFunction(initVal, increment, fetchSubAtomicFn, fetchSubVerifyFn) +\n\t       TestFetchFunction(initVal, increment, subFetchAtomicFn, subFetchVerifyFn);\n}\n\ntemplate <class T, class U>\nint TestAtomicFetchIntegralAPI(T initVal, U increment)\n{\n\tauto fetchAndAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_fetch_and(x, y, mem_ord); };\n\tauto fetchAndVerifyFn = [=](T& x, U y)\n\t{\n\t\tT ret = x;\n\t\tx &= y;\n\t\treturn ret;\n\t};\n\n\tauto andFetchAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_and_fetch(x, y, mem_ord); };\n\tauto andFetchVerifyFn = [=](T& x, U y)\n\t{\n\t\tx &= y;\n\t\treturn x;\n\t};\n\n\tauto fetchOrAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_fetch_or(x, y, mem_ord); };\n\tauto fetchOrVerifyFn = [=](T& x, U y)\n\t{\n\t\tT ret = x;\n\t\tx |= y;\n\t\treturn ret;\n\t};\n\n\tauto orFetchAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_or_fetch(x, y, mem_ord); };\n\tauto orFetchVerifyFn = [=](T& x, U y)\n\t{\n\t\tx |= y;\n\t\treturn x;\n\t};\n\n\tauto fetchXorAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_fetch_xor(x, y, mem_ord); };\n\tauto fetchXorVerifyFn = [=](T& x, U y)\n\t{\n\t\tT ret = x;\n\t\tx ^= y;\n\t\treturn ret;\n\t};\n\n\tauto xorFetchAtomicFn = [=](T* x, U y, auto mem_ord) { return eastl::atomic_raw_xor_fetch(x, y, mem_ord); };\n\tauto xorFetchVerifyFn = [=](T& x, U y)\n\t{\n\t\tx ^= y;\n\t\treturn x;\n\t};\n\n\n\treturn TestFetchFunction(initVal, increment, fetchAndAtomicFn, fetchAndVerifyFn) +\n\t       TestFetchFunction(initVal, increment, andFetchAtomicFn, andFetchVerifyFn) +\n\t       TestFetchFunction(initVal, increment, fetchOrAtomicFn, fetchOrVerifyFn) +\n\t       TestFetchFunction(initVal, increment, orFetchAtomicFn, orFetchVerifyFn) +\n\t       TestFetchFunction(initVal, increment, fetchXorAtomicFn, fetchXorVerifyFn) +\n\t       TestFetchFunction(initVal, increment, xorFetchAtomicFn, xorFetchVerifyFn);\n}\n\ntemplate <class T>\nint TestAtomicIntAPI()\n{\n\tint nError{};\n\n\tnError += TestAtomicLoadAPI(static_cast<T>(10), static_cast<T>(5));\n\tnError += TestAtomicStoreAPI(static_cast<T>(10), static_cast<T>(5));\n\tnError += TestAtomicExchangeAPI(static_cast<T>(10), static_cast<T>(5));\n\tnError += TestAtomicCmpxchgAPI(static_cast<T>(10), static_cast<T>(5));\n\tnError += TestAtomicFetchCommonAPI(static_cast<T>(10), static_cast<T>(3));\n\tnError += TestAtomicFetchIntegralAPI(static_cast<T>(10), static_cast<T>(7));\n\n\treturn nError;\n}\n\n\nint TestAtomicAPIForBool()\n{\n\tint nError{};\n\n\tnError += TestAtomicLoadAPI(true, false);\n\tnError += TestAtomicStoreAPI(true, false);\n\tnError += TestAtomicExchangeAPI(true, false);\n\tnError += TestAtomicCmpxchgAPI(true, false);\n\n\treturn nError;\n}\n\nint TestAtomicAPIForInts()\n{\n\tint nError{};\n\n\tnError += TestAtomicIntAPI<uint8_t>();\n\tnError += TestAtomicIntAPI<uint16_t>();\n\tnError += TestAtomicIntAPI<uint32_t>();\n\tnError += TestAtomicIntAPI<uint64_t>();\n\n\tnError += TestAtomicIntAPI<int8_t>();\n\tnError += TestAtomicIntAPI<int16_t>();\n\tnError += TestAtomicIntAPI<int32_t>();\n\tnError += TestAtomicIntAPI<int64_t>();\n\n\tnError += TestAtomicIntAPI<unsigned char>();\n\tnError += TestAtomicIntAPI<signed char>();\n\tnError += TestAtomicIntAPI<char>();\n\n\tnError += TestAtomicIntAPI<unsigned int>();\n\tnError += TestAtomicIntAPI<int>();\n\n\tnError += TestAtomicIntAPI<unsigned long>();\n\tnError += TestAtomicIntAPI<long>();\n\n\tnError += TestAtomicIntAPI<unsigned long long>();\n\tnError += TestAtomicIntAPI<long long>();\n\n\tnError += TestAtomicIntAPI<size_t>();\n\tnError += TestAtomicIntAPI<eastl_size_t>();\n\n\tnError += TestAtomicIntAPI<ssize_t>();\n\tnError += TestAtomicIntAPI<eastl_ssize_t>();\n\n\tnError += TestAtomicIntAPI<uintptr_t>();\n\n\treturn nError;\n}\n\ntemplate <class T>\nint TestAtomicPtrAPI()\n{\n\tT array[15]{};\n\n\tint nError{};\n\n\tnError += TestAtomicLoadAPI(array + 5, array + 3);\n\tnError += TestAtomicStoreAPI(array + 5, array + 3);\n\tnError += TestAtomicExchangeAPI(array + 5, array + 3);\n\tnError += TestAtomicCmpxchgAPI(array + 5, array + 3);\n\tnError += TestAtomicFetchCommonAPI(array + 5, 3);\n\n\tnError += TestAtomicLoadAPIImpl<eastl::internal::memory_order_read_depends_s>::Run(array + 5, array + 3);\n\n\treturn nError;\n}\n\nint TestAtomicAPIForPtrs()\n{\n\n\tint nError{};\n\n\tstruct S\n\t{\n\t\tuint64_t x;\n\t\tuint64_t y;\n\t};\n\n\tnError += TestAtomicPtrAPI<int32_t>();\n\tnError += TestAtomicPtrAPI<int64_t>();\n\tnError += TestAtomicPtrAPI<S>();\n\n\t// Also test pointer to pointer:\n\tnError += TestAtomicPtrAPI<S*>();\n\n\treturn nError;\n}\n\n\nint TestAtomicRaw()\n{\n\tint nError{};\n\n\tnError += TestAtomicAPIForBool();\n\tnError += TestAtomicAPIForInts();\n\tnError += TestAtomicAPIForPtrs();\n\n\treturn nError;\n}\n"
  },
  {
    "path": "test/source/TestBit.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/bit.h>\n\ntemplate <typename T>\nint TestHasSingleBit()\n{\n\tint nErrorCount = 0;\n\n\tVERIFY(eastl::has_single_bit(T(0)) == false);\n\tVERIFY(eastl::has_single_bit(T(1)) == true);\n\tVERIFY(eastl::has_single_bit(T(2)) == true);\n\tVERIFY(eastl::has_single_bit(T(3)) == false);\n\n\tVERIFY(eastl::has_single_bit(eastl::numeric_limits<T>::min()) == false);\n\tVERIFY(eastl::has_single_bit(eastl::numeric_limits<T>::max()) == false);\n\n\tfor (int i = 4; i < eastl::numeric_limits<T>::digits; i++)\n\t{\n\t\tT power_of_two = static_cast<T>(T(1U) << i);\n\t\tVERIFY(eastl::has_single_bit(power_of_two));\n\t\tVERIFY(eastl::has_single_bit(static_cast<T>(power_of_two - 1)) == false);\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nstatic int TestBitCeil()\n{\n\tint nErrorCount = 0;\n\n\tVERIFY(eastl::bit_ceil(T(0)) == T(1));\n\tVERIFY(eastl::bit_ceil(T(1)) == T(1));\n\tVERIFY(eastl::bit_ceil(T(2)) == T(2));\n\tVERIFY(eastl::bit_ceil(T(3)) == T(4));\n\n\tEA_CONSTEXPR auto DIGITS = eastl::numeric_limits<T>::digits;\n\tEA_CONSTEXPR auto MIN = eastl::numeric_limits<T>::min();\n\tEA_CONSTEXPR auto MAX = static_cast<T>(T(1) << (DIGITS - 1));\n\n\tVERIFY(eastl::bit_ceil(MAX) == MAX);\n\tVERIFY(eastl::bit_ceil(static_cast<T>(MAX - 1)) == MAX);\n\tVERIFY(eastl::bit_ceil(MIN) == T(1));\n\n\tfor (int i = 4; i < eastl::numeric_limits<T>::digits; i++)\n\t{\n\t\tT power_of_two = static_cast<T>(T(1U) << i);\n\t\tVERIFY(eastl::bit_ceil(power_of_two) == power_of_two);\n\t\tVERIFY(eastl::bit_ceil(static_cast<T>(power_of_two - 1)) == power_of_two);\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nstatic int TestBitFloor()\n{\n\tint nErrorCount = 0;\n\tVERIFY(eastl::bit_floor(T(0)) == T(0));\n\tVERIFY(eastl::bit_floor(T(1)) == T(1));\n\tVERIFY(eastl::bit_floor(T(2)) == T(2));\n\tVERIFY(eastl::bit_floor(T(3)) == T(2));\n\n\tEA_CONSTEXPR auto DIGITS = eastl::numeric_limits<T>::digits;\n\tEA_CONSTEXPR auto MIN = eastl::numeric_limits<T>::min();\n\tEA_CONSTEXPR auto MAX = eastl::numeric_limits<T>::max();\n\n\tVERIFY(eastl::bit_floor(MAX) == T(1) << (DIGITS - 1));\n\tVERIFY(eastl::bit_floor(MIN) == T(0));\n\n\tfor (int i = 4; i < eastl::numeric_limits<T>::digits; i++)\n\t{\n\t\tT power_of_two = static_cast<T>(T(1U) << i);\n\t\tVERIFY(eastl::bit_floor(power_of_two) == power_of_two);\n\t\tVERIFY(eastl::bit_floor(static_cast<T>(power_of_two + 1)) == power_of_two);\n\t}\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nstatic int TestBitWidth()\n{\n\tint nErrorCount = 0;\n\n\tVERIFY(eastl::bit_width(T(0)) == T(0));\n\tVERIFY(eastl::bit_width(T(1)) == T(1));\n\tVERIFY(eastl::bit_width(T(2)) == T(2));\n\tVERIFY(eastl::bit_width(T(3)) == T(2));\n\n\tEA_CONSTEXPR auto DIGITS = eastl::numeric_limits<T>::digits;\n\tEA_CONSTEXPR auto MIN = eastl::numeric_limits<T>::min();\n\tEA_CONSTEXPR auto MAX = eastl::numeric_limits<T>::max();\n\n\tVERIFY(eastl::bit_width(MIN) == 0);\n\tVERIFY(eastl::bit_width(MAX) == DIGITS);\n\n\tfor (int i = 4; i < eastl::numeric_limits<T>::digits; i++)\n\t{\n\t\tT power_of_two = static_cast<T>(T(1U) << i);\n\t\tVERIFY(eastl::bit_width(power_of_two) == i + 1);\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nint TestCountlZero()\n{\n\tint nErrorCount = 0;\n\n\tVERIFY(eastl::countl_zero(T(0)) == (sizeof(T) * CHAR_BIT));\n\tVERIFY(eastl::countl_zero(T(0b1)) == (sizeof(T) * CHAR_BIT - 1));\n\tVERIFY(eastl::countl_zero(T(0b11)) == (sizeof(T) * CHAR_BIT - 2));\n\tVERIFY(eastl::countl_zero(T(0b111)) == (sizeof(T) * CHAR_BIT - 3));\n\tVERIFY(eastl::countl_zero(T(0b1111)) == (sizeof(T) * CHAR_BIT - 4));\n\tVERIFY(eastl::countl_zero(T(0b1010)) == (sizeof(T) * CHAR_BIT - 4));\n\tVERIFY(eastl::countl_zero(T(0b1100)) == (sizeof(T) * CHAR_BIT - 4));\n\n\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\tfor (int r = 0; r < 100; ++r)\n\t{\n\t\tT num = 0;\n\t\tint min_index = sizeof(T) * CHAR_BIT;\n\t\tfor (unsigned int i = 0; i < 4; ++i)\n\t\t{\n\t\t\tint index = rng.RandRange(0, eastl::numeric_limits<T>::digits);\n\t\t\tnum = num | (T(1) << (sizeof(T) * CHAR_BIT - 1 - index));\n\t\t\tmin_index = eastl::min(min_index, index);\n\t\t}\n\n\t\tVERIFY(eastl::countl_zero(num) == min_index);\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nint TestPopCount()\n{\n\tint nErrorCount = 0;\n\n\tVERIFY(eastl::popcount(T(0)) == 0);\n\tVERIFY(eastl::popcount(T(0b1)) == 1);\n\tVERIFY(eastl::popcount(T(0b11)) == 2);\n\tVERIFY(eastl::popcount(T(0b111)) == 3);\n\tVERIFY(eastl::popcount(T(0b1111)) == 4);\n\tVERIFY(eastl::popcount(T(0b1010)) == 2);\n\tVERIFY(eastl::popcount(T(0b1100)) == 2);\n\n\tEA_CONSTEXPR auto digits = eastl::numeric_limits<T>::digits;\n\n\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\tfor (int r = 0; r < 100; ++r)\n\t{\n\t\tT num = 0;\n\t\tint count = 0;\n\t\tfor (unsigned int i = 0; i < digits; ++i)\n\t\t{\n\t\t\tif (rng.RandRange(0, 4) == 0)\n\t\t\t{\n\t\t\t\t++count;\n\t\t\t\tnum = num | (T(1) << i);\n\t\t\t}\n\t\t}\n\n\t\tVERIFY(eastl::popcount(num) == count);\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestBit\n//\nint TestBit()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestHasSingleBit<unsigned int>();\n\tnErrorCount += TestHasSingleBit<unsigned char>();\n\tnErrorCount += TestHasSingleBit<unsigned short>();\n\tnErrorCount += TestHasSingleBit<unsigned long>();\n\tnErrorCount += TestHasSingleBit<unsigned long long>();\n#if EASTL_INT128_SUPPORTED\n\tnErrorCount += TestHasSingleBit<eastl_uint128_t>();\n#endif\n\n\tnErrorCount += TestCountlZero<unsigned int>();\n\tnErrorCount += TestCountlZero<unsigned char>();\n\tnErrorCount += TestCountlZero<unsigned short>();\n\tnErrorCount += TestCountlZero<unsigned long>();\n\tnErrorCount += TestCountlZero<unsigned long long>();\n#if EASTL_INT128_SUPPORTED\n\tnErrorCount += TestCountlZero<eastl_uint128_t>();\n#endif\n\n\tnErrorCount += TestBitWidth<unsigned int>();\n\tnErrorCount += TestBitWidth<unsigned char>();\n\tnErrorCount += TestBitWidth<unsigned short>();\n\tnErrorCount += TestBitWidth<unsigned long>();\n\tnErrorCount += TestBitWidth<unsigned long long>();\n#if EASTL_INT128_SUPPORTED\n\tnErrorCount += TestBitWidth<eastl_uint128_t>();\n#endif\n\n\tnErrorCount += TestBitCeil<unsigned int>();\n\tnErrorCount += TestBitCeil<unsigned char>();\n\tnErrorCount += TestBitCeil<unsigned short>();\n\tnErrorCount += TestBitCeil<unsigned long>();\n\tnErrorCount += TestBitCeil<unsigned long long>();\n#if EASTL_INT128_SUPPORTED\n\tnErrorCount += TestBitCeil<eastl_uint128_t>();\n#endif\n\n\tnErrorCount += TestBitFloor<unsigned int>();\n\tnErrorCount += TestBitFloor<unsigned char>();\n\tnErrorCount += TestBitFloor<unsigned short>();\n\tnErrorCount += TestBitFloor<unsigned long>();\n\tnErrorCount += TestBitFloor<unsigned long long>();\n#if EASTL_INT128_SUPPORTED\n\tnErrorCount += TestBitFloor<eastl_uint128_t>();\n#endif\n\n\tnErrorCount += TestPopCount<unsigned int>();\n\tnErrorCount += TestPopCount<unsigned char>();\n\tnErrorCount += TestPopCount<unsigned short>();\n\tnErrorCount += TestPopCount<unsigned long>();\n\tnErrorCount += TestPopCount<unsigned long long>();\n#if EASTL_INT128_SUPPORTED\n\tnErrorCount += TestPopCount<eastl_uint128_t>();\n#endif\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestBitVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EABase/eabase.h>\n#include <EASTL/bitvector.h>\n#include <EASTL/vector.h>\n#include <EASTL/deque.h>\n#include <EASTL/string.h>\n\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::bitvector<>;\ntemplate class eastl::bitvector<MallocAllocator>;\ntemplate class eastl::bitvector<EASTLAllocatorType, uint8_t>;\ntemplate class eastl::bitvector<EASTLAllocatorType, int16_t>;\ntemplate class eastl::bitvector<EASTLAllocatorType, int32_t>;\ntemplate class eastl::bitvector<EASTLAllocatorType, int64_t, eastl::vector<int64_t, EASTLAllocatorType> >;\n\n// No way to use type aliases in template instantiations?\ntemplate class eastl::bitvector<EASTLAllocatorType, eastl::BitvectorWordType, eastl::fixed_vector<eastl::BitvectorWordType, 65, true, EASTLAllocatorType>>;\ntemplate class eastl::bitvector<MallocAllocator,    eastl::BitvectorWordType, eastl::fixed_vector<eastl::BitvectorWordType, 65, true, MallocAllocator>>;\ntemplate class eastl::bitvector<EASTLAllocatorType, uint8_t, eastl::fixed_vector<uint8_t, 65, true, EASTLAllocatorType>>;\ntemplate class eastl::bitvector<EASTLAllocatorType, int16_t, eastl::fixed_vector<int16_t, 65, true, EASTLAllocatorType>>;\ntemplate class eastl::bitvector<EASTLAllocatorType, int32_t, eastl::fixed_vector<int32_t, 65, true, EASTLAllocatorType>>;\ntemplate class eastl::bitvector<EASTLAllocatorType, int64_t, eastl::fixed_vector<int64_t, 65, true, EASTLAllocatorType>>;\n\n// bitvector doesn't yet support deque.\n//template class eastl::bitvector<EASTLAllocatorType, uint8_t, eastl::deque<uint64_t, EASTLAllocatorType> >;\n//template class eastl::bitvector<EASTLAllocatorType, uint8_t, eastl::deque<int32_t, EASTLAllocatorType, 64> >;\n\n\ntemplate<typename BV_TYPE, typename BV_TYPE_MALLOC>\nstatic int TestBitVectorHelper(eastl_size_t startCapacity = 0)\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\t{\n\t\t// typedef bitvector<Allocator, Element>           this_type;\n\t\t// typedef bool                                    value_type;\n\t\t// typedef bitvector_reference<Element>            reference;\n\t\t// typedef bool                                    const_reference;\n\t\t// typedef bitvector_iterator<Element>             iterator;\n\t\t// typedef bitvector_const_iterator<Element>       const_iterator;\n\t\t// typedef eastl::reverse_iterator<iterator>       reverse_iterator;\n\t\t// typedef eastl::reverse_iterator<const_iterator> const_reverse_iterator;\n\t\t// typedef Allocator                               allocator_type;\n\t\t// typedef Element                                 element_type;\n\t\t// typedef Container                               container_type;\n\t\t// typedef eastl_size_t                            size_type;\n\n\t\ttypename BV_TYPE::this_type              this_typeVariable;\n\t\ttypename BV_TYPE::value_type             value_typeVariable = 0;\n\t\ttypename BV_TYPE::const_reference        const_referenceVariable(false);\n\t\ttypename BV_TYPE::iterator               iteratorVariable(NULL, 0);\n\t\ttypename BV_TYPE::const_iterator         const_iteratorVariable(NULL, 0);\n\t\ttypename BV_TYPE::reverse_iterator       reverse_iteratorVariable(iteratorVariable);\n\t\ttypename BV_TYPE::const_reverse_iterator const_reverse_iteratorVariable(const_iteratorVariable);\n\t\ttypename BV_TYPE::allocator_type         allocator_typeVariable;\n\t\ttypename BV_TYPE::element_type           element_typeVariable = 0;\n\t\ttypename BV_TYPE::container_type         container_typeVariable;\n\t\ttypename BV_TYPE::size_type              size_typeVariable = 0;\n\n\t\tstring sAddresses(string::CtorSprintf(), \"%p %p %p %p %p %p %p %p %p %p %p\", \n\t\t\t\t\t\t   &this_typeVariable, &value_typeVariable, &const_referenceVariable, &iteratorVariable,\n\t\t\t\t\t\t   &const_iteratorVariable, &reverse_iteratorVariable,&const_reverse_iteratorVariable,\n\t\t\t\t\t\t   &allocator_typeVariable, &element_typeVariable, &container_typeVariable, &size_typeVariable);\n\t\tEATEST_VERIFY(sAddresses.size() > 0); \n\t}\n\n\t{\n\t\t// bitvector();\n\t\t// explicit bitvector(const allocator_type& allocator);\n\t\t// explicit bitvector(size_type n, const allocator_type& allocator = EASTL_BITVECTOR_DEFAULT_ALLOCATOR);\n\t\t// bitvector(size_type n, value_type value, const allocator_type& allocator = EASTL_BITVECTOR_DEFAULT_ALLOCATOR);\n\t\t// bitvector(const bitvector& copy);\n\t\t// template <typename InputIterator> bitvector(InputIterator first, InputIterator last);\n\t\t// bitvector& operator=(const bitvector& x);\n\t\t// reference       operator[](size_type n);            // behavior is undefined if n is invalid.\n\t\t// const_reference operator[](size_type n) const;\n\t\tMallocAllocator          mallocAllocator;\n\t\tBV_TYPE                  bv0;\n\t\tBV_TYPE_MALLOC           bv1(mallocAllocator);\n\t\tBV_TYPE                  bv2(200);\n\t\tBV_TYPE                  bv3(300, true);\n\t\tBV_TYPE_MALLOC           bv4(400, false, mallocAllocator);\n\t\tconst BV_TYPE            bv5(bv2);\n\t\tbool                     boolArray[] = { true, false, true };\n\t\tBV_TYPE                  bv6(boolArray, boolArray + EAArrayCount(boolArray));\n\t\tBV_TYPE                  bv7(bv3.begin(), bv3.end());\n  \n\t\t{\n\t\t\t// Validate the above constructions\n\t\t\tEATEST_VERIFY(bv0.validate());\n\t\t\tEATEST_VERIFY(bv0.empty());\n\n\t\t\tEATEST_VERIFY(bv1.validate());\n\t\t\tEATEST_VERIFY(bv1.empty());\n\n\t\t\tEATEST_VERIFY(bv2.validate());\n\t\t\tEATEST_VERIFY(bv2.size() == 200);\n\t\t\tfor(eastl_size_t i = 0; i < bv2.size(); i++)\n\t\t\t\tEATEST_VERIFY(bv2[i] == false);\n\n\t\t\tEATEST_VERIFY(bv3.validate());\n\t\t\tEATEST_VERIFY(bv3.size() == 300);\n\t\t\tfor(eastl_size_t i = 0; i < bv3.size(); i++)\n\t\t\t\tEATEST_VERIFY(bv3[i] == true);\n\n\t\t\tEATEST_VERIFY(bv4.validate());\n\t\t\tEATEST_VERIFY(bv4.size() == 400);\n\t\t\tfor(eastl_size_t i = 0; i < bv4.size(); i++)\n\t\t\t\tEATEST_VERIFY(bv4[i] == false);\n\n\t\t\tEATEST_VERIFY(bv5.validate());\n\t\t\tEATEST_VERIFY(bv5 == bv2);\n\t\t\tfor(eastl_size_t i = 0; i < bv5.size(); i++)\n\t\t\t\tEATEST_VERIFY(bv5[i] == false);\n\n\t\t\tEATEST_VERIFY(bv6.validate());\n\t\t\tEATEST_VERIFY(bv6.size() == EAArrayCount(boolArray));\n\t\t\tfor(eastl_size_t i = 0; i < bv6.size(); i++)\n\t\t\t\tEATEST_VERIFY(bv6[i] == boolArray[i]);\n\n\t\t\tEATEST_VERIFY(bv7.validate());\n\t\t\tEATEST_VERIFY(bv7.size() == bv3.size()); // The == test theoretically includes this test, be we check anyway.\n\t\t\tfor(eastl_size_t j = 0; j < bv7.size(); j++)\n\t\t\t\tEATEST_VERIFY(bv7[j] == bv3[j]);\n\t\t\tEATEST_VERIFY(bv7 == bv3);\n\t\t\tfor(eastl_size_t i = 0; (i < bv3.size()) && (i < bv7.size()); i++)\n\t\t\t\tEATEST_VERIFY(bv3[i] == bv7[i]);\n\t\t}\n\n\t\t{\n\t\t\t// void swap(this_type& x);\n\n\t\t\tbv7.swap(bv7); // Test swapping against self.\n\t\t\tEATEST_VERIFY(bv7.validate());\n\t\t\tEATEST_VERIFY(bv7 == bv3);\n\t\t\tEATEST_VERIFY(bv7.size() == bv3.size()); // The == test theoretically includes this test, be we check anyway.\n\t\t\tfor(eastl_size_t i = 0; (i < bv3.size()) && (i < bv7.size()); i++)\n\t\t\t\tEATEST_VERIFY(bv3[i] == bv7[i]);\n\n\t\t\tbv3.swap(bv2);  // Note that bv3 and bv4 use different allocators, so we are exercizing that.\n\t\t\tEATEST_VERIFY(bv3.validate());\n\t\t\tEATEST_VERIFY(bv3.size() == 200);\n\t\t\tfor(eastl_size_t i = 0; i < bv3.size(); i++)\n\t\t\t\tEATEST_VERIFY(bv3[i] == false);\n\n\t\t\tEATEST_VERIFY(bv2.validate());\n\t\t\tEATEST_VERIFY(bv2.size() == 300);\n\t\t\tfor(eastl_size_t i = 0; i < bv2.size(); i++)\n\t\t\t\tEATEST_VERIFY(bv2[i] == true);\n\n\n\t\t\t// bitvector& operator=(const bitvector& x);\n\n\t\t\tbv6 = bv7;\n\t\t\tEATEST_VERIFY(bv6.validate());\n\t\t\tEATEST_VERIFY(bv6 == bv7);\n\n\n\t\t\t// template <typename InputIterator> void assign(InputIterator first, InputIterator last);\n\t\t\tbv0.assign(bv3.begin(), bv3.end());\n\t\t\tEATEST_VERIFY(bv0 == bv3);\n\n\t\t\tbv0.assign(boolArray, boolArray + EAArrayCount(boolArray));\n\t\t\tEATEST_VERIFY(bv0 == BV_TYPE(boolArray, boolArray + EAArrayCount(boolArray)));\n\n\t\t\tbv0.resize(0);\n\t\t\tEATEST_VERIFY(bv0.begin()==bv0.end());//should not crash\n\t\t\tbv3.resize(0);\n\t\t\tEATEST_VERIFY(bv0 == bv3);\n\t\t}\n\n\t\t{\n\t\t\t// any/all\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(!bv0.any());\n\t\t\t\tEATEST_VERIFY(bv0.all());\n\t\t\t\tbool all[] = {true, true, true};\n\t\t\t\tbv0.assign(all, all + EAArrayCount(all));\n\t\t\t\tEATEST_VERIFY(bv0.any());\n\t\t\t\tEATEST_VERIFY(bv0.all());\n\t\t\t\tbool any[] = {false, true, true};\n\t\t\t\tbv0.assign(any, any + EAArrayCount(any));\n\t\t\t\tEATEST_VERIFY(bv0.any());\n\t\t\t\tEATEST_VERIFY(!bv0.all());\n\t\t\t\tbool none[] = {false, false, false};\n\t\t\t\tbv0.assign(none, none + EAArrayCount(none));\n\t\t\t\tbv0.resize(0);\n\n\t\t\t\tbv0.resize(64);\n\t\t\t\tbv0.set(63, true);\n\t\t\t\tbv0.resize(1);\n\t\t\t\tEATEST_VERIFY(!bv0.any()); \n\t\t\t\tbv0.resize(0);\n\n\t\t\t\tbv0.resize(decltype(bv0)::kBitCount * 2);\n\t\t\t\tfor (eastl_size_t i = 0; i < bv0.size(); ++i)\n\t\t\t\t\tbv0[i] = true;\n\t\t\t\tbv0.resize(decltype(bv0)::kBitCount + 1);\n\t\t\t\tEATEST_VERIFY(bv0.all()); \n\t\t\t\tbv0.resize(0);\n\n\t\t\t\tEATEST_VERIFY(!bv0.any()); \n\t\t\t\tEATEST_VERIFY(bv0.all()); \n\t\t\t}\n\n\n\t\t\tusing ElementType = typename decltype(bv0)::element_type;\n\n\t\t\ttypename decltype(bv0)::element_type boundsTest[] = {0, 1, 2, 3, 4, 5, 6, ~ElementType(0), ~ElementType(0) & ~ElementType(1), ~ElementType(0) & ~ElementType(2), ~ElementType(0) & ~ElementType(3)};\n\n\t\t\tfor (int resize = 0; resize < 2; ++resize)\n\t\t\t{\n\t\t\t\tbv0.resize(decltype(bv0)::kBitCount * 2);\n\t\t\t\tfor (int i = 0; i < EAArrayCount(boundsTest); ++i)\n\t\t\t\t{\n\t\t\t\t\tfor (int j = 0; j < EAArrayCount(boundsTest); ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tElementType comp0 = boundsTest[i];\n\t\t\t\t\t\tElementType comp1 = boundsTest[j];\n\t\t\t\t\t\tif (comp0 == 0 && comp1 == 0) comp0 = 1;\n\t\t\t\t\t\tElementType maxComp0 = ~ElementType(0);\n\t\t\t\t\t\tElementType maxComp1 = ~ElementType(0);\n\n\t\t\t\t\t\tif (resize)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (comp0 || comp1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (comp1 == 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbv0.resize(eastl::GetLastBit(comp0) + 1);\n\t\t\t\t\t\t\t\t\tif (bv0.size() == decltype(bv0)::kBitCount)\n\t\t\t\t\t\t\t\t\t\tmaxComp0 = ~ElementType(0);\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tmaxComp0 = (1 << bv0.size()) - 1;\n\t\t\t\t\t\t\t\t\tmaxComp1 = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbv0.resize(sizeof(ElementType) * CHAR_BIT + eastl::GetLastBit(comp1) + 1);\n\t\t\t\t\t\t\t\t\tElementType shift = bv0.size() - sizeof(ElementType) * CHAR_BIT; \n\t\t\t\t\t\t\t\t\tif (shift == decltype(bv0)::kBitCount)\n\t\t\t\t\t\t\t\t\t\tmaxComp1 = ~ElementType(0);\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tmaxComp1 = (1 << (shift)) - 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbv0.resize(decltype(bv0)::kBitCount * 2);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\tbv0.get_container().data()[0] = comp0;\n\t\t\t\t\t\tbv0.get_container().data()[1] = comp1;\n\n\t\t\t\t\t\tEATEST_VERIFY(bv0.any() || (comp0 == 0 && comp1 == 0));\n\t\t\t\t\t\tEATEST_VERIFY(bv0.all() && comp0 == maxComp0 && comp1 == maxComp1 || !bv0.all());\n\n\t\t\t\t\t\tbool any = false;\n\t\t\t\t\t\tbool all = true;\n\t\t\t\t\t\tfor (bool x : bv0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tany = any || x;\n\t\t\t\t\t\t\tall = all && x;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tEATEST_VERIFY(all && bv0.all() || !all && !bv0.all());\n\t\t\t\t\t\tEATEST_VERIFY(any && bv0.any() || !any && !bv0.any());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t{\n\t\t// move constructor/assignment\n\t\tconst eastl_size_t kTestSize = 100;\n\t\tconst eastl_size_t kTestIncrement = 5;\n\t\tBV_TYPE bv1(kTestSize, false);\n\t\tBV_TYPE bv2(kTestSize, false);\n\t\tfor (eastl_size_t i = 0; i < kTestSize; i += kTestIncrement)\n\t\t{\n\t\t\tbv1[i] = true;\n\t\t\tbv2[i] = true;\n\t\t}\n\n\t\tBV_TYPE bv3(std::move(bv1));\n\t\tBV_TYPE bv4(kTestSize / 2, true);\n\t\tbv4 = std::move(bv2);\n\n\t\tfor (eastl_size_t i = 0; i < kTestSize; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(bv3[i] == (i % kTestIncrement == 0));\n\t\t\tEATEST_VERIFY(bv4[i] == (i % kTestIncrement == 0));\n\t\t}\n\t}\n\n\t{\n\t\t// iterator       begin();\n\t\t// const_iterator begin() const;\n\t\t// iterator       end();\n\t\t// const_iterator end() const;\n\n\t\tbool                        boolArray[] = { true, false, true, true, false, true };\n\t\tconst BV_TYPE           bv0(boolArray, boolArray + EAArrayCount(boolArray));\n\t\ttypename BV_TYPE::const_iterator it;\n\t\teastl_size_t                i;\n\n\t\tfor(it = bv0.begin(), i = 0; it != bv0.end(); ++it, ++i)        // Iterate forward by 1.\n\t\t{\n\t\t\tconst bool value = *it;\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\t\tfor(--it, --i; (eastl_ssize_t)i >= 0; --it, --i)                // Iterate backward by 1. Problem: this test code does --it for it == begin(), which isn't strictly allowed.\n\t\t{\n\t\t\tconst bool value = *it;\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\t\t// The following code asssumes an even number of elements.\n\t\tEASTL_CT_ASSERT((EAArrayCount(boolArray) % 2) == 0);  \n\t\tfor(it = bv0.begin(), ++i; it != bv0.end(); it += 2, i += 2)  // Iterate forward by 2.\n\t\t{\n\t\t\tconst bool value = *it;\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\t\tfor(it -= 2, i -= 2; (eastl_ssize_t)i >= 0; it -= 2, i -= 2)    // Iterate backward by 1. Problem: this test code does it -= 2 for it == begin(), which isn't strictly allowed.\n\t\t{\n\t\t\tconst bool value = *it;\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\n\t\t// reverse_iterator       rbegin();\n\t\t// const_reverse_iterator rbegin() const;\n\t\t// reverse_iterator       rend();\n\t\t// const_reverse_iterator rend() const;\n\n\t\ttypename BV_TYPE::const_reverse_iterator rit;\n\t\ti = (bv0.size() - 1);\n\n\t\tfor(rit = bv0.rbegin(); rit != bv0.rend(); ++rit, --i)              // Reverse-iterate forward by 1.\n\t\t{\n\t\t\t//const bool value = *rit; // This is currently broken and will require a bit of work to fix.\n\t\t\tconst bool value = *--rit.base();\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\t\tfor(--rit, ++i; i < bv0.size(); --rit, ++i)                  // Reverse-iterate backward by 1.\n\t\t{\n\t\t\t//const bool value = *rit; // This is currently broken and will require a bit of work to fix.\n\t\t\tconst bool value = *--rit.base();\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\t\t// The following code asssumes an even number of elements.\n\t\tEASTL_CT_ASSERT((EAArrayCount(boolArray) % 2) == 0);  \n\t\tfor(rit = bv0.rbegin(), --i; rit != bv0.rend(); rit += 2, i -= 2) // Reverse-iterate forward by 2.\n\t\t{\n\t\t\t//const bool value = *rit; // This is currently broken and will require a bit of work to fix.\n\t\t\tconst bool value = *--rit.base();\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\t\tfor(rit -= 2, i += 2; i < bv0.size(); rit -= 2, i += 2)            // Reverse-iterate backward by 2.\n\t\t{\n\t\t\t//const bool value = *rit; // This is currently broken and will require a bit of work to fix.\n\t\t\tconst bool value = *--rit.base();\n\t\t\tEATEST_VERIFY(value == boolArray[i]);\n\t\t}\n\n\n\t\t// find_first, etc.\n\t\t/* This work is not complete.\n\t\t{\n\t\t\tBV_TYPE bv(30, false);\n\n\t\t\tBV_TYPE::iterator it = bv.find_first();\n\t\t\tEATEST_VERIFY(it == bv.begin());\n\t\t}\n\t\t*/\n\t}\n\n\t{\n\t\tMallocAllocator            mallocAllocator;\n\t\tBV_TYPE_MALLOC             bv0(mallocAllocator);\n\n\t\t// bool      empty() const;\n\t\t// size_type size() const;\n\t\t// size_type capacity() const;\n\n\t\tEATEST_VERIFY(bv0.empty());\n\t\tEATEST_VERIFY(bv0.size() == 0);\n\t\t// EASTL requires that newly constructed containers have 0 capacity.\n\t\t// (but fixed_ variants have the fixed portion always alive!)\n\t\tEATEST_VERIFY(bv0.capacity() == startCapacity);  \n\n\t\tbool boolArray[] = { false, true, true };\n\t\tbv0.assign(boolArray, boolArray + EAArrayCount(boolArray));\n\n\t\tEATEST_VERIFY(!bv0.empty());\n\t\tEATEST_VERIFY(bv0.size() == EAArrayCount(boolArray));\n\t\tif (!startCapacity)\n\t\t\tEATEST_VERIFY((bv0.capacity() > 0) && (bv0.capacity() <= (8 * sizeof(typename BV_TYPE::element_type))));\n\n\n\t\t// reference       front();\n\t\t// const_reference front() const;\n\t\t// reference       back();\n\t\t// const_reference back() const;\n\n\t\tEATEST_VERIFY(bv0.front() == false);\n\t\tEATEST_VERIFY(bv0.back() == true);\n\t\tbv0.erase(bv0.begin());\n\t\tEATEST_VERIFY(bv0.front() == true);\n\t\tbv0.erase(bv0.rbegin());\n\t\tEATEST_VERIFY(bv0.back() == true);\n\n\t\t//  void set_capacity(size_type n = npos);\n\n\t\tbv0.reserve(startCapacity + 17);\n\t\tEATEST_VERIFY((bv0.capacity() >= startCapacity+ 17) && (bv0.capacity() <= startCapacity + 100)); // It's hard to make a unit test to portably test an upper limit.\n\n\t\tint allocCountBefore = MallocAllocator::mAllocCountAll;\n\t\twhile(bv0.size() < 17)\n\t\t\tbv0.push_back(false);\n\t\tEATEST_VERIFY(allocCountBefore == MallocAllocator::mAllocCountAll); // Verify no new memory was allocated.\n\n\t\tbv0.set_capacity();\n\t\tEATEST_VERIFY(bv0.capacity() >= bv0.size());\n\n\t\tbv0.set_capacity(0);\n\t\tEATEST_VERIFY(bv0.capacity() == startCapacity);\n\t\tEATEST_VERIFY(bv0.empty());\n\n\n\t\t// void resize(size_type n, value_type value);\n\t\t// void resize(size_type n);\n\t\t// void reserve(size_type n);\n\n\t\tbv0.reserve(800);\n\t\tEATEST_VERIFY(bv0.capacity() >= 800);\n\t\tallocCountBefore = MallocAllocator::mAllocCountAll;\n\t\tbv0.resize(800, true);\n\t\tEATEST_VERIFY(allocCountBefore == MallocAllocator::mAllocCountAll); // Verify no new memory was allocated.\n\n\n\t\t// void push_back();\n\t\t// void push_back(value_type value);\n\t\t// void pop_back();\n\t\t// reference       operator[](size_type n);\n\t\t// const_reference operator[](size_type n) const;\n\n\t\tbv0.push_back();\n\t\tbv0.back() = true;\n\t\tbv0.push_back(false);\n\t\tbv0.push_back(true);\n\n\t\tEATEST_VERIFY(bv0[bv0.size()-1] == true);\n\t\tEATEST_VERIFY(bv0[bv0.size()-2] == false);\n\t\tEATEST_VERIFY(bv0[bv0.size()-3] == true);\n\n\n\t\t// reference       at(size_type n);\n\t\t// const_reference at(size_type n) const;\n\n\t\tEATEST_VERIFY(bv0.at(bv0.size()-1) == true);\n\t\tEATEST_VERIFY(bv0.at(bv0.size()-2) == false);\n\t\tEATEST_VERIFY(bv0.at(bv0.size()-3) == true);\n\n\n\t\t// void clear();\n\t\t// bool test(size_type n, bool defaultValue) const;\n\t\t// void set(bool value, size_type n);\n\n\t\tbv0.clear();\n\t\tbv0.resize(17, true);\n\t\tEATEST_VERIFY(bv0.test(0, false) == true);\n\t\tEATEST_VERIFY(bv0.test(17, false) == false); // Test past the end.\n\t\tEATEST_VERIFY(bv0.test(17, true) == true);\n\n\t\tbv0.set(3, false);\n\t\tEATEST_VERIFY(bv0.test(3, true) == false);\n\n\t\tbv0.set(100, true);\n\t\tEATEST_VERIFY(bv0.test(100, false) == true);\n\n\n\t\t// container_type&       get_container();\n\t\t// const container_type& get_container() const;\n\n\t\tEATEST_VERIFY(!bv0.get_container().empty());\n\n\n\t\t// bool validate() const;\n\t\t// int  validate_iterator(const_iterator i) const;\n\n\t\tEATEST_VERIFY(bv0.validate());\n\t\ttypename BV_TYPE::iterator it;\n\t\tEATEST_VERIFY(bv0.validate_iterator(it) == isf_none);\n\t\tfor(it = bv0.begin(); it != bv0.end(); ++it)\n\t\t\tEATEST_VERIFY(bv0.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\tEATEST_VERIFY(bv0.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\n\n\n\t\t// iterator insert(iterator position, value_type value);\n\t\t// void     insert(iterator position, size_type n, value_type value);\n\n\t\tbv0.clear();\n\t\tbv0.resize(17, true);\n\t\tbv0.insert(bv0.begin() + 5, false);\n\t\tEATEST_VERIFY(bv0[5] == false);\n\t\tbv0[5] = true;\n\t\tEATEST_VERIFY(bv0[5] == true);\n\n\t\tbv0.insert(bv0.begin() + 5, 7, false);\n\t\tEATEST_VERIFY((bv0[5] == false) && (bv0[11] == false));\n\n\t\tEATEST_VERIFY(bv0.back() == true);\n\t\tbv0.insert(bv0.end(), false);\n\t\tEATEST_VERIFY(bv0.back() == false);\n\n\n\t\t// iterator erase(iterator position);\n\t\t// iterator erase(iterator first, iterator last);\n\n\t\tEATEST_VERIFY((bv0[10] == false) && (bv0[11] == false));\n\t\tbv0.erase(bv0.begin() + 11);\n\t\tEATEST_VERIFY((bv0[10] == false) && (bv0[11] == true));\n\n\t\tEATEST_VERIFY(bv0[5] == false);\n\t\tbool bv06 = bv0[6];\n\t\tbv0.erase(bv0.begin() + 5, bv0.begin() + 6);\n\t\tEATEST_VERIFY(bv0[5] == bv06);\n\n\n\t\t// reverse_iterator erase(reverse_iterator position);\n\t\t// reverse_iterator erase(reverse_iterator first, reverse_iterator last);\n\n\t\tbv0.clear();\n\t\tbv0.resize(10, true);\n\t\tbv0.back() = false;\n\t\tbv0.erase(bv0.rbegin());\n\t\tEATEST_VERIFY((bv0.size() == 9) && (bv0.back() == true));\n\n\t\tbv0.erase(bv0.rbegin(), bv0.rend());\n\t\tEATEST_VERIFY(bv0.empty());\n\n\n\t\t// template <typename InputIterator> Not yet implemented. See below for disabled definition.\n\t\t// void      insert(iterator position, InputIterator first, InputIterator last);\n\t\t//\n\t\t// Disabled because insert isn't implemented yet.\n\t\t// const bool boolArray2[4] = { false, true, false, true };        \n\t\t// bv0.insert(bv0.end(), boolArray2, boolArray2 + EAArrayCount(boolArray));\n\t\t// EATEST_VERIFY(bv0.size() == EAArrayCount(boolArray2));\n\n\n\t\t// element_type*         data();\n\t\t// const element_type*   data() const;\n\n\t\tEATEST_VERIFY(bv0.data() != NULL);\n\t\tbv0.set_capacity(0);\n\t\tEATEST_VERIFY(bv0.data() == NULL || startCapacity > 0);\n\n\n\t\t// void reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.\n\n\t\tMallocAllocator::mpLastAllocation = nullptr;\n\t\tbv0.resize(startCapacity + BV_TYPE_MALLOC::kBitCount, true);\n\t\tEATEST_VERIFY(MallocAllocator::mpLastAllocation != NULL);\n\t\tvoid* pSaved = MallocAllocator::mpLastAllocation;\n\t\tbv0.reset_lose_memory();\n\t\tEATEST_VERIFY(bv0.validate());\n\t\tfree(pSaved); // Call the C free function.\n\t\tMallocAllocator::mpLastAllocation = NULL;\n\t}\n\treturn 0;\n}\n\n\nint TestBitVector()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t#define FIXED_TEST(n) \\\n\t\tnErrorCount += TestBitVectorHelper<eastl::fixed_bitvector<(n)>, eastl::fixed_bitvector<(n), MallocAllocator>>( \\\n\t\t((n) + eastl::fixed_bitvector<(n)>::kBitCount - 1) / eastl::fixed_bitvector<(n)>::kBitCount * eastl::fixed_bitvector<(n)>::kBitCount);\n\n\tnErrorCount += TestBitVectorHelper<eastl::bitvector<>, eastl::bitvector<MallocAllocator>>();\n\tnErrorCount += FIXED_TEST(24);\n\tnErrorCount += FIXED_TEST(1);\n\tnErrorCount += FIXED_TEST(65);\n\tnErrorCount += FIXED_TEST(64);\n\tnErrorCount += FIXED_TEST(231231);\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestBitcast.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/bit.h>\n\nusing namespace eastl;\n\n\nint TestBitcast()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tuint32_t int32Value = 0x12345678;\n\t\tfloat floatValue = eastl::bit_cast<float>(int32Value);\n\t\tVERIFY(memcmp(&int32Value, &floatValue, sizeof(float)) == 0);\n\t}\n\n\t{\n\t\tstruct IntFloatStruct\n\t\t{\n\t\t\tuint32_t i = 0x87654321;\n\t\t\tfloat f = 10.f;\n\t\t};\n\t\tstruct CharIntStruct\n\t\t{\n\t\t\tchar c1;\n\t\t\tchar c2;\n\t\t\tchar c3;\n\t\t\tchar c4;\n\t\t\tuint32_t i;\n\t\t};\n\n\t\tIntFloatStruct ifStruct;\n\t\tCharIntStruct ciStruct = eastl::bit_cast<CharIntStruct>(ifStruct);\n\t\tVERIFY(memcmp(&ifStruct, &ciStruct, sizeof(IntFloatStruct)) == 0);\n\t}\n\n#if EASTL_CONSTEXPR_BIT_CAST_SUPPORTED\n\t{\n\t\tconstexpr uint32_t int32Value = 40;\n\t\tconstexpr float floatValue = eastl::bit_cast<float>(int32Value);\n\t\tVERIFY(memcmp(&int32Value, &floatValue, sizeof(float)) == 0);\n\t}\n#endif\n\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestBitset.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/bitset.h>\n#include <EABase/eabase.h>\n#include <EASTL/bit.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#if defined(_MSC_VER)\n\t#pragma warning(pop)\n\t#pragma warning(disable: 4310) // Cast truncates constant value\n#endif\n\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\n\n#if (EASTL_BITSET_WORD_SIZE_DEFAULT != 1)\n\ttemplate class eastl::bitset<1,   uint8_t>;\n\ttemplate class eastl::bitset<33,  uint8_t>;\n\ttemplate class eastl::bitset<65,  uint8_t>;\n\ttemplate class eastl::bitset<129, uint8_t>;\n#endif\n\n#if (EASTL_BITSET_WORD_SIZE_DEFAULT != 2)\n\ttemplate class eastl::bitset<1,   uint16_t>;\n\ttemplate class eastl::bitset<33,  uint16_t>;\n\ttemplate class eastl::bitset<65,  uint16_t>;\n\ttemplate class eastl::bitset<129, uint16_t>;\n#endif\n\n#if (EASTL_BITSET_WORD_SIZE_DEFAULT != 4) // If not already represented \n\ttemplate class eastl::bitset<1,   uint32_t>;\n\ttemplate class eastl::bitset<33,  uint32_t>;\n\ttemplate class eastl::bitset<65,  uint32_t>;\n\ttemplate class eastl::bitset<129, uint32_t>;\n#endif\n\n#if (EASTL_BITSET_WORD_SIZE_DEFAULT != 8)\n\ttemplate class eastl::bitset<1,   uint64_t>;\n\ttemplate class eastl::bitset<33,  uint64_t>;\n\ttemplate class eastl::bitset<65,  uint64_t>;\n\ttemplate class eastl::bitset<129, uint64_t>;\n#endif\n\n#if (EASTL_BITSET_WORD_SIZE_DEFAULT != 16)\n\t#if EASTL_INT128_SUPPORTED\n\t\ttemplate class eastl::bitset<1,   eastl_uint128_t>;\n\t\ttemplate class eastl::bitset<33,  eastl_uint128_t>;\n\t\ttemplate class eastl::bitset<65,  eastl_uint128_t>;\n\t\ttemplate class eastl::bitset<129, eastl_uint128_t>;\n\t#endif\n#endif\n\ntemplate<typename UInt>\nint TestGetFirstBit()\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(GetFirstBit((UInt) 0) == sizeof(UInt) * CHAR_BIT);\n\t// EATEST_VERIFY(countr_zero((UInt) 0) == sizeof(UInt) * CHAR_BIT);\n\n\tfor (uint32_t i = 0; i < sizeof(UInt) * CHAR_BIT; ++i)\n\t{\n\t\tUInt x = ((UInt) 1 << i) | (UInt(1) << (sizeof(UInt) * CHAR_BIT - 1));\n\t\tEATEST_VERIFY(GetFirstBit(x) == i);\n\t\t//EATEST_VERIFY(GetFirstBit(x) == countr_zero(x));\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate<typename UInt>\nint TestGetLastBit()\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(GetLastBit((UInt) 0) == sizeof(UInt) * CHAR_BIT);\n\tEATEST_VERIFY(bit_width((UInt) 0) == 0);\n\n\tfor (uint32_t i = 0; i < sizeof(UInt) * CHAR_BIT; ++i)\n\t{\n\t\tUInt x = ((UInt)1 << i) | UInt(1);\n\t\tEATEST_VERIFY(GetLastBit(x) == i);\n\t\tEATEST_VERIFY(GetLastBit(x) == ((uint32_t) bit_width(x) - 1));\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate<size_t N, typename WordType, typename UInt>\nint VerifyBitsetConversionThrows(const bitset<N, WordType>& bs, UInt(*convert)(const bitset<N, WordType>&), UInt truncatedValue) {\n\tint nErrorCount = 0;\n\n#if EASTL_EXCEPTIONS_ENABLED\n\ttry {\n\t\tconvert(bs);\n\t\tEATEST_VERIFY(false);\n\t}\n\tcatch (std::overflow_error&)\n\t{\n\t\tEATEST_VERIFY(true);  // This pathway should be taken.\n\t}\n\tcatch (...)\n\t{\n\t\tEATEST_VERIFY(false);\n\t}\n#else\n\tEATEST_VERIFY(convert(bs) == truncatedValue);\n#endif\n\n\treturn nErrorCount;\n}\n\ntemplate<typename WordType>\nint TestBitsetWithWord()\n{\n\tint nErrorCount = 0;\n\n\tauto verifyToUint32Throws = [&nErrorCount](const auto& bs, uint32_t truncatedValue) {\n\t\tuint32_t(*convert)(const decltype(bs)&) = [](const auto& bs) { return bs.to_uint32_no_assert_convertible(); };\n\t\tnErrorCount += VerifyBitsetConversionThrows(bs, convert, truncatedValue);\n\t};\n\n\tauto verifyToUint64Throws = [&nErrorCount](const auto& bs, uint64_t truncatedValue) {\n\t\tuint64_t(*convert)(const decltype(bs)&) = [](const auto& bs) { return bs.to_uint64_no_assert_convertible(); };\n\t\tnErrorCount += VerifyBitsetConversionThrows(bs, convert, truncatedValue);\n\t};\n\n\tauto verifyToUlongThrowsIf32bit = [&nErrorCount](const auto& bs, unsigned long truncatedValue) {\n\t\tif constexpr (sizeof(unsigned long) < 8)\n\t\t{\n\t\t\tunsigned long(*convert)(const decltype(bs)&) = [](const auto& bs) { return bs.to_ulong_no_assert_convertible(); };\n\t\t\tnErrorCount += VerifyBitsetConversionThrows(bs, convert, truncatedValue);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tEATEST_VERIFY(bs.to_ulong_no_assert_convertible() == truncatedValue);\n\t\t}\n\t};\n\n\t{\n\t\t// bitset<0, WordType> tests\n#if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC before v3.0 can't handle our bitset<0, WordType>.\n\t\tbitset<0, WordType> b0(0x10101010);\n\t\tEATEST_VERIFY(b0.count() == 0);\n\t\tEATEST_VERIFY(b0.to_ulong_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint32_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint64_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint64_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.as_uint64() == 0x00000000);\n\t\tEATEST_VERIFY(b0.template as_uint<uint64_t>() == 0x00000000);\n\n\t\tb0.flip();\n\t\tEATEST_VERIFY(b0.count() == 0);\n\t\tEATEST_VERIFY(b0.to_ulong_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint32_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint64_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint64_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.as_uint64() == 0x00000000);\n\t\tEATEST_VERIFY(b0.template as_uint<uint64_t>() == 0x00000000);\n\n\t\tb0 <<= 1;\n\t\tEATEST_VERIFY(b0.count() == 0);\n\t\tEATEST_VERIFY(b0.to_ulong_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint32_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint64_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.to_uint64_assert_convertible() == 0x00000000);\n\t\tEATEST_VERIFY(b0.as_uint64() == 0x00000000);\n\t\tEATEST_VERIFY(b0.template as_uint<uint64_t>() == 0x00000000);\n\n\t\tb0 = 0x10101010;\n\t\tEATEST_VERIFY(b0.to_uint32_assert_convertible() == 0x00000000);\n#if EA_IS_ENABLED(EASTL_DEPRECATIONS_FOR_2024_SEPT)\n\t\tb0 = UINT64_C(0x1010101010101010);\n#else\n\t\tb0.from_uint64(UINT64_C(0x1010101010101010));\n#endif\n\t\tEATEST_VERIFY(b0.to_uint64_assert_convertible() == UINT64_C(0x0000000000000000));\n#endif\n\n// bitset<8, WordType> tests\n\t\tbitset<8, WordType> b8(0x10101010);\n\t\tEATEST_VERIFY(b8.count() == 1);\n\t\tEATEST_VERIFY(b8.to_ulong_assert_convertible()  == 0x00000010);\n\t\tEATEST_VERIFY(b8.to_uint32_assert_convertible() == 0x00000010);\n\t\tEATEST_VERIFY(b8.to_uint64_assert_convertible() == 0x00000010);\n\t\tEATEST_VERIFY(b8.to_uint64_assert_convertible() == 0x00000010);\n\t\tEATEST_VERIFY(b8.as_uint64() == 0x00000010);\n\t\tEATEST_VERIFY(b8.template as_uint<uint64_t>() == 0x00000010);\n\n\t\tb8.flip();\n\t\tEATEST_VERIFY(b8.count() == 7);\n\t\tEATEST_VERIFY(b8.to_ulong_assert_convertible()  == 0x000000ef);\n\t\tEATEST_VERIFY(b8.to_uint32_assert_convertible() == 0x000000ef);\n\t\tEATEST_VERIFY(b8.to_uint64_assert_convertible() == 0x000000ef);\n\t\tEATEST_VERIFY(b8.to_uint64_assert_convertible() == 0x000000ef);\n\t\tEATEST_VERIFY(b8.as_uint64() == 0x000000ef);\n\t\tEATEST_VERIFY(b8.template as_uint<uint64_t>() == 0x000000ef);\n\n\t\tb8 <<= 1;\n\t\tEATEST_VERIFY(b8.count() == 6);\n\t\tEATEST_VERIFY(b8.to_ulong_assert_convertible()  == 0x000000de);\n\t\tEATEST_VERIFY(b8.to_uint32_assert_convertible() == 0x000000de);\n\t\tEATEST_VERIFY(b8.to_uint64_assert_convertible() == 0x000000de);\n\t\tEATEST_VERIFY(b8.to_uint64_assert_convertible() == 0x000000de);\n\t\tEATEST_VERIFY(b8.as_uint64() == 0x000000de);\n\t\tEATEST_VERIFY(b8.template as_uint<uint64_t>() == 0x000000de);\n\n\t\tb8.reset();\n\t\tb8.flip();\n\t\tb8 >>= 33;\n\t\tEATEST_VERIFY(b8.count() == 0);\n\n\t\tb8.reset();\n\t\tb8.flip();\n\t\tb8 >>= 65;\n\t\tEATEST_VERIFY(b8.count() == 0);\n\n\t\tb8 = 0x10101010;\n\t\tEATEST_VERIFY(b8.to_uint32_assert_convertible() == 0x00000010);\n\t\tb8 = UINT64_C(0x0000000000000010);\n\t\tEATEST_VERIFY(b8.to_uint64_assert_convertible() == UINT64_C(0x0000000000000010));\n\n\n\n\t\t// bitset<16, WordType> tests\n\t\tbitset<16, WordType> b16(0x10101010);\n\t\tEATEST_VERIFY(b16.count() == 2);\n\t\tEATEST_VERIFY(b16.to_ulong_assert_convertible()  == 0x00001010);\n\t\tEATEST_VERIFY(b16.to_uint32_assert_convertible() == 0x00001010);\n\t\tEATEST_VERIFY(b16.to_uint64_assert_convertible() == 0x00001010);\n\t\tEATEST_VERIFY(b16.to_uint64_assert_convertible() == 0x00001010);\n\t\tEATEST_VERIFY(b16.as_uint64() == 0x00001010);\n\t\tEATEST_VERIFY(b16.template as_uint<uint64_t>() == 0x00001010);\n\n\t\tb16.flip();\n\t\tEATEST_VERIFY(b16.count() == 14);\n\t\tEATEST_VERIFY(b16.to_ulong_assert_convertible()  == 0x0000efef);\n\t\tEATEST_VERIFY(b16.to_uint32_assert_convertible() == 0x0000efef);\n\t\tEATEST_VERIFY(b16.to_uint64_assert_convertible() == 0x0000efef);\n\t\tEATEST_VERIFY(b16.to_uint64_assert_convertible() == 0x0000efef);\n\t\tEATEST_VERIFY(b16.as_uint64() == 0x0000efef);\n\t\tEATEST_VERIFY(b16.template as_uint<uint64_t>() == 0x0000efef);\n\n\t\tb16 <<= 1;\n\t\tEATEST_VERIFY(b16.count() == 13);\n\t\tEATEST_VERIFY(b16.to_ulong_assert_convertible()  == 0x0000dfde);\n\t\tEATEST_VERIFY(b16.to_uint32_assert_convertible() == 0x0000dfde);\n\t\tEATEST_VERIFY(b16.to_uint64_assert_convertible() == 0x0000dfde);\n\t\tEATEST_VERIFY(b16.to_uint64_assert_convertible() == 0x0000dfde);\n\t\tEATEST_VERIFY(b16.as_uint64() == 0x0000dfde);\n\t\tEATEST_VERIFY(b16.template as_uint<uint64_t>() == 0x0000dfde);\n\n\t\tb16.reset();\n\t\tb16.flip();\n\t\tb16 >>= 33;\n\t\tEATEST_VERIFY(b16.count() == 0);\n\n\t\tb16.reset();\n\t\tb16.flip();\n\t\tb16 >>= 65;\n\t\tEATEST_VERIFY(b16.count() == 0);\n\n\t\tb16 = 0x10101010;\n\t\tEATEST_VERIFY(b16.to_uint32_assert_convertible() == 0x00001010);\n\t\tb16 = UINT64_C(0x0000000000001010);\n\t\tEATEST_VERIFY(b16.to_uint64_assert_convertible() == UINT64_C(0x0000000000001010));\n\n\n\n\t\t// bitset<32, WordType> tests\n\t\tbitset<32, WordType> b32(0x10101010);\n\t\tEATEST_VERIFY(b32.count() == 4);\n\t\tEATEST_VERIFY(b32.to_ulong_assert_convertible()  == 0x10101010);\n\t\tEATEST_VERIFY(b32.to_uint32_assert_convertible() == 0x10101010);\n\t\tEATEST_VERIFY(b32.to_uint64_assert_convertible() == 0x10101010);\n\t\tEATEST_VERIFY(b32.to_uint64_assert_convertible() == 0x10101010);\n\t\tEATEST_VERIFY(b32.as_uint64() == 0x10101010);\n\t\tEATEST_VERIFY(b32.template as_uint<uint64_t>() == 0x10101010);\n\n\t\tb32.flip();\n\t\tEATEST_VERIFY(b32.count() == 28);\n\t\tEATEST_VERIFY(b32.to_ulong_assert_convertible()  == 0xefefefef);\n\t\tEATEST_VERIFY(b32.to_uint32_assert_convertible() == 0xefefefef);\n\t\tEATEST_VERIFY(b32.to_uint64_assert_convertible() == 0xefefefef);\n\t\tEATEST_VERIFY(b32.to_uint64_assert_convertible() == 0xefefefef);\n\t\tEATEST_VERIFY(b32.as_uint64() == 0xefefefef);\n\t\tEATEST_VERIFY(b32.template as_uint<uint64_t>() == 0xefefefef);\n\n\t\tb32 <<= 1;\n\t\tEATEST_VERIFY(b32.count() == 27);\n\t\tEATEST_VERIFY(b32.to_ulong_assert_convertible()  == 0xdfdfdfde);\n\t\tEATEST_VERIFY(b32.to_uint32_assert_convertible() == 0xdfdfdfde);\n\t\tEATEST_VERIFY(b32.to_uint64_assert_convertible() == 0xdfdfdfde);\n\t\tEATEST_VERIFY(b32.to_uint64_assert_convertible() == 0xdfdfdfde);\n\t\tEATEST_VERIFY(b32.as_uint64() == 0xdfdfdfde);\n\t\tEATEST_VERIFY(b32.template as_uint<uint64_t>() == 0xdfdfdfde);\n\n\t\tb32.reset();\n\t\tb32.flip();\n\t\tb32 >>= 33;\n\t\tEATEST_VERIFY(b32.count() == 0);\n\n\t\tb32.reset();\n\t\tb32.flip();\n\t\tb32 >>= 65;\n\t\tEATEST_VERIFY(b32.count() == 0);\n\n\t\tb32 = 0x10101010;\n\t\tEATEST_VERIFY(b32.to_uint32_assert_convertible() == 0x10101010);\n\t\tb32 = UINT64_C(0x0000000010101010);\n\t\tEATEST_VERIFY(b32.to_uint64_assert_convertible() == UINT64_C(0x0000000010101010));\n\n\t\t// bitset<64, WordType> tests\n\t\tbitset<64, WordType> b64(0x10101010);                                 // b64 => 00000000 00000000 00000000 00000000 00010000 00010000 00010000 00010000\n\t\tEATEST_VERIFY(b64.count() == 4);\n\t\tEATEST_VERIFY(b64.to_ulong_assert_convertible()  == 0x10101010);\n\t\tEATEST_VERIFY(b64.to_uint32_assert_convertible() == 0x10101010);\n\t\tEATEST_VERIFY(b64.to_uint64_assert_convertible() == 0x10101010);\n\t\tEATEST_VERIFY(b64.to_uint64_assert_convertible() == 0x10101010);\n\t\t// EATEST_VERIFY(b64.as_uint32() == 0x10101010); // compile error: cannot represent the entire bitset as a uint32_t.\n\t\tEATEST_VERIFY(b64.as_uint64() == 0x10101010);\n\t\tEATEST_VERIFY(b64.template as_uint<uint64_t>() == 0x10101010);\n\n\t\tb64.flip();                                                 // b64 => 11111111 11111111 11111111 11111111 11101111 11101111 11101111 11101111\n\t\tEATEST_VERIFY(b64.count() == 60);\n\t\tverifyToUlongThrowsIf32bit(b64, static_cast<unsigned long>(0xffffffffefefefeful));\n\t\tverifyToUint32Throws(b64, 0xefefefef);\n\t\tEATEST_VERIFY(b64.to_uint64_assert_convertible() == 0xffffffffefefefefull);\n\t\tEATEST_VERIFY(b64.as_uint64() == 0xffffffffefefefefull);\n\t\tEATEST_VERIFY(b64.template as_uint<uint64_t>() == 0xffffffffefefefefull);\n\n\t\tb64 <<= 1;                                                  // b64 => 11111111 11111111 11111111 11111111 11011111 11011111 11011111 11011110\n\t\tEATEST_VERIFY(b64.count() == 59);\n\t\tverifyToUlongThrowsIf32bit(b64, static_cast<unsigned long>(0xffffffffdfdfdfdeul));\n\t\tverifyToUint32Throws(b64, 0xdfdfdfde);\n\t\tEATEST_VERIFY(b64.to_uint64_assert_convertible() == 0xffffffffdfdfdfdeull);\n\t\tEATEST_VERIFY(b64.as_uint64() == 0xffffffffdfdfdfdeull);\n\t\tEATEST_VERIFY(b64.template as_uint<uint64_t>() == 0xffffffffdfdfdfdeull);\n\n\t\tb64.reset();                                                // b64 => 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000\n\t\tEATEST_VERIFY(b64.count() == 0);\n\t\tEATEST_VERIFY(b64.to_ulong_assert_convertible() == 0);\n\n\t\tb64 <<= 1;                                                  // b64 => 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000\n\t\tEATEST_VERIFY(b64.count() == 0);\n\t\tEATEST_VERIFY(b64.to_ulong_assert_convertible() == 0);\n\n\t\tb64.flip();                                                 // b64 => 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111\n\t\tEATEST_VERIFY(b64.count() == 64);\n\t\tverifyToUlongThrowsIf32bit(b64, static_cast<unsigned long>(0xfffffffffffffffful));\n\n\t\tb64 <<= 1;                                                  // b64 => 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111110\n\t\tEATEST_VERIFY(b64.count() == 63);\n\t\tverifyToUlongThrowsIf32bit(b64, static_cast<unsigned long>(0xfffffffffffffffeul));\n\n\t\tb64.reset();\n\t\tb64.flip();\n\t\tb64 >>= 33;\n\t\tEATEST_VERIFY(b64.count() == 31);\n\n\t\tb64.reset();\n\t\tb64.flip();\n\t\tb64 >>= 65;\n\t\tEATEST_VERIFY(b64.count() == 0);\n\n\t\tb64 = 0x10101010;\n\t\tEATEST_VERIFY(b64.to_uint32_assert_convertible() == 0x10101010);\n#if EA_IS_ENABLED(EASTL_DEPRECATIONS_FOR_2024_SEPT)\n\t\tb64 = UINT64_C(0x1010101010101010);\n#else\n\t\tb64.from_uint64(UINT64_C(0x1010101010101010));\n#endif\n\t\tEATEST_VERIFY(b64.to_uint64_assert_convertible() == UINT64_C(0x1010101010101010));\n\t}\n\n\n\t{\n\t\tbitset<1, WordType> b1;\n\t\tbitset<1, WordType> b1A(1);\n\n\t\tEATEST_VERIFY(b1.size()       == 1);\n\t\tEATEST_VERIFY(b1.any()        == false);\n\t\tEATEST_VERIFY(b1.all()        == false);\n\t\tEATEST_VERIFY(b1.none()       == true);\n\t\tEATEST_VERIFY(b1.to_ulong_assert_convertible()   == 0);\n\t\tEATEST_VERIFY(b1A.any()       == true);\n\t\tEATEST_VERIFY(b1A.all()       == true);\n\t\tEATEST_VERIFY(b1A.none()      == false);\n\t\tEATEST_VERIFY(b1A.to_ulong_assert_convertible()  == 1);\n\t\tEATEST_VERIFY(b1A.to_uint32_assert_convertible() == 1);\n\t\tEATEST_VERIFY(b1A.to_uint64_assert_convertible() == 1);\n\n\n\t\tbitset<33, WordType> b33;\n\t\tbitset<33, WordType> b33A(1);\n\n\t\tEATEST_VERIFY(b33.size()      == 33);\n\t\tEATEST_VERIFY(b33.any()       == false);\n\t\tEATEST_VERIFY(b33.all()       == false);\n\t\tEATEST_VERIFY(b33.none()      == true);\n\t\tEATEST_VERIFY(b33.to_ulong_assert_convertible()  == 0);\n\t\tEATEST_VERIFY(b33A.any()      == true);\n\t\tEATEST_VERIFY(b33A.all()      == false);\n\t\tEATEST_VERIFY(b33A.none()     == false);\n\t\tEATEST_VERIFY(b33A.to_ulong_assert_convertible() == 1);\n\n\n\t\tbitset<65, WordType> b65;\n\t\tbitset<65, WordType> b65A(1);\n\n\t\tEATEST_VERIFY(b65.size()      == 65);\n\t\tEATEST_VERIFY(b65.any()       == false);\n\t\tEATEST_VERIFY(b65.all()       == false);\n\t\tEATEST_VERIFY(b65.none()      == true);\n\t\tEATEST_VERIFY(b65.to_ulong_assert_convertible()  == 0);\n\t\tEATEST_VERIFY(b65A.any()      == true);\n\t\tEATEST_VERIFY(b65A.all()      == false);\n\t\tEATEST_VERIFY(b65A.none()     == false);\n\t\tEATEST_VERIFY(b65A.to_ulong_assert_convertible() == 1);\n\n\n\t\tbitset<129, WordType> b129;\n\t\tbitset<129, WordType> b129A(1);\n\n\t\tEATEST_VERIFY(b129.size()      == 129);\n\t\tEATEST_VERIFY(b129.any()       == false);\n\t\tEATEST_VERIFY(b129.all()       == false);\n\t\tEATEST_VERIFY(b129.none()      == true);\n\t\tEATEST_VERIFY(b129.to_ulong_assert_convertible()  == 0);\n\t\tEATEST_VERIFY(b129A.any()      == true);\n\t\tEATEST_VERIFY(b129A.all()      == false);\n\t\tEATEST_VERIFY(b129A.none()     == false);\n\t\tEATEST_VERIFY(b129A.to_ulong_assert_convertible() == 1);\n\n\n\t\t// operator[], data, test, to_ulong, count\n\t\tb1[0]   = true;\n\t\tEATEST_VERIFY(b1.test(0)   == true);\n\t\tEATEST_VERIFY(b1.count()   == 1);\n\n\t\tb33[0]  = true;\n\t\tb33[32] = true;\n\t\tEATEST_VERIFY(b33.test(0)  == true);\n\t\tEATEST_VERIFY(b33.test(15) == false);\n\t\tEATEST_VERIFY(b33.test(32) == true);\n\t\tEATEST_VERIFY(b33.count()  == 2);\n\n\t\tb65[0]  = true;\n\t\tb65[32] = true;\n\t\tb65[64] = true;\n\t\tEATEST_VERIFY(b65.test(0)  == true);\n\t\tEATEST_VERIFY(b65.test(15) == false);\n\t\tEATEST_VERIFY(b65.test(32) == true);\n\t\tEATEST_VERIFY(b65.test(47) == false);\n\t\tEATEST_VERIFY(b65.test(64) == true);\n\t\tEATEST_VERIFY(b65.count()  == 3);\n\n\t\tb129[0]   = true;\n\t\tb129[32]  = true;\n\t\tb129[64]  = true;\n\t\tb129[128] = true;\n\t\tEATEST_VERIFY(b129.test(0)   == true);\n\t\tEATEST_VERIFY(b129.test(15)  == false);\n\t\tEATEST_VERIFY(b129.test(32)  == true);\n\t\tEATEST_VERIFY(b129.test(47)  == false);\n\t\tEATEST_VERIFY(b129.test(64)  == true);\n\t\tEATEST_VERIFY(b129.test(91)  == false);\n\t\tEATEST_VERIFY(b129.test(128) == true);\n\t\tEATEST_VERIFY(b129.count()   == 4);\n\n\t\ttypename bitset<1, WordType>::word_type* pWordArray;\n\n\t\tpWordArray = b1.data();\n\t\tEATEST_VERIFY(pWordArray != NULL);\n\t\tpWordArray = b33.data();\n\t\tEATEST_VERIFY(pWordArray != NULL);\n\t\tpWordArray = b65.data();\n\t\tEATEST_VERIFY(pWordArray != NULL);\n\t\tpWordArray = b129.data();\n\t\tEATEST_VERIFY(pWordArray != NULL);\n\n\n\t\t// bitset<1, WordType> set, reset, flip, ~\n\t\tb1.reset();\n\t\tEATEST_VERIFY(b1.count() == 0);\n\n\t\tb1.set();\n\t\tEATEST_VERIFY(b1.count() == b1.size());\n\t\tEATEST_VERIFY(b1.all());\n\n\t\tb1.flip();\n\t\tEATEST_VERIFY(b1.count() == 0);\n\t\tEATEST_VERIFY(!b1.all());\n\t\tEATEST_VERIFY(b1.none());\n\n\t\tb1.set(0, true);\n\t\tEATEST_VERIFY(b1[0] == true);\n\n\t\tb1.reset(0);\n\t\tEATEST_VERIFY(b1[0] == false);\n\n\t\tb1.flip(0);\n\t\tEATEST_VERIFY(b1[0] == true);\n\n\t\tbitset<1, WordType> b1Not = ~b1;\n\t\tEATEST_VERIFY(b1[0]    == true);\n\t\tEATEST_VERIFY(b1Not[0] == false);\n\n\n\t\t// bitset<33, WordType> set, reset, flip, ~\n\t\tb33.reset();\n\t\tEATEST_VERIFY(b33.count() == 0);\n\n\t\tb33.set();\n\t\tEATEST_VERIFY(b33.count() == b33.size());\n\t\tEATEST_VERIFY(b33.all());\n\n\n\t\tb33.flip();\n\t\tEATEST_VERIFY(b33.count() == 0);\n\t\tEATEST_VERIFY(!b33.all());\n\n\t\tb33.set(0, true);\n\t\tb33.set(32, true);\n\t\tEATEST_VERIFY(b33[0]  == true);\n\t\tEATEST_VERIFY(b33[15] == false);\n\t\tEATEST_VERIFY(b33[32] == true);\n\n\t\tb33.reset(0);\n\t\tb33.reset(32);\n\t\tEATEST_VERIFY(b33[0]  == false);\n\t\tEATEST_VERIFY(b33[32] == false);\n\n\t\tb33.flip(0);\n\t\tb33.flip(32);\n\t\tEATEST_VERIFY(b33[0]  == true);\n\t\tEATEST_VERIFY(b33[32] == true);\n\n\t\tbitset<33, WordType> b33Not(~b33);\n\t\tEATEST_VERIFY(b33[0]     == true);\n\t\tEATEST_VERIFY(b33[32]    == true);\n\t\tEATEST_VERIFY(b33Not[0]  == false);\n\t\tEATEST_VERIFY(b33Not[32] == false);\n\n\n\t\t// bitset<65, WordType> set, reset, flip, ~\n\t\tb65.reset();\n\t\tEATEST_VERIFY(b65.count() == 0);\n\t\tEATEST_VERIFY(!b65.all());\n\t\tEATEST_VERIFY(b65.none());\n\n\t\tb65.set();\n\t\tEATEST_VERIFY(b65.count() == b65.size());\n\t\tEATEST_VERIFY(b65.all());\n\t\tEATEST_VERIFY(!b65.none());\n\n\t\tb65.flip();\n\t\tEATEST_VERIFY(b65.count() == 0);\n\t\tEATEST_VERIFY(!b65.all());\n\t\tEATEST_VERIFY(b65.none());\n\n\n\t\tb65.set(0, true);\n\t\tb65.set(32, true);\n\t\tb65.set(64, true);\n\t\tEATEST_VERIFY(b65[0]  == true);\n\t\tEATEST_VERIFY(b65[15] == false);\n\t\tEATEST_VERIFY(b65[32] == true);\n\t\tEATEST_VERIFY(b65[50] == false);\n\t\tEATEST_VERIFY(b65[64] == true);\n\n\t\tb65.reset(0);\n\t\tb65.reset(32);\n\t\tb65.reset(64);\n\t\tEATEST_VERIFY(b65[0]  == false);\n\t\tEATEST_VERIFY(b65[32] == false);\n\t\tEATEST_VERIFY(b65[64] == false);\n\n\t\tb65.flip(0);\n\t\tb65.flip(32);\n\t\tb65.flip(64);\n\t\tEATEST_VERIFY(b65[0]  == true);\n\t\tEATEST_VERIFY(b65[32] == true);\n\t\tEATEST_VERIFY(b65[64] == true);\n\n\t\tbitset<65, WordType> b65Not(~b65);\n\t\tEATEST_VERIFY(b65[0]     == true);\n\t\tEATEST_VERIFY(b65[32]    == true);\n\t\tEATEST_VERIFY(b65[64]    == true);\n\t\tEATEST_VERIFY(b65Not[0]  == false);\n\t\tEATEST_VERIFY(b65Not[32] == false);\n\t\tEATEST_VERIFY(b65Not[64] == false);\n\n\n\t\t// bitset<65, WordType> set, reset, flip, ~\n\t\tb129.reset();\n\t\tEATEST_VERIFY(b129.count() == 0);\n\n\t\tb129.set();\n\t\tEATEST_VERIFY(b129.count() == b129.size());\n\t\tEATEST_VERIFY(b129.all());\n\n\t\tb129.flip();\n\t\tEATEST_VERIFY(b129.count() == 0);\n\t\tEATEST_VERIFY(!b129.all());\n\t\tEATEST_VERIFY(b129.none());\n\n\t\tb129.set(0, true);\n\t\tb129.set(32, true);\n\t\tb129.set(64, true);\n\t\tb129.set(128, true);\n\t\tEATEST_VERIFY(b129[0]   == true);\n\t\tEATEST_VERIFY(b129[15]  == false);\n\t\tEATEST_VERIFY(b129[32]  == true);\n\t\tEATEST_VERIFY(b129[50]  == false);\n\t\tEATEST_VERIFY(b129[64]  == true);\n\t\tEATEST_VERIFY(b129[90]  == false);\n\t\tEATEST_VERIFY(b129[128] == true);\n\n\t\tb129.reset(0);\n\t\tb129.reset(32);\n\t\tb129.reset(64);\n\t\tb129.reset(128);\n\t\tEATEST_VERIFY(b129[0]   == false);\n\t\tEATEST_VERIFY(b129[32]  == false);\n\t\tEATEST_VERIFY(b129[64]  == false);\n\t\tEATEST_VERIFY(b129[128] == false);\n\n\t\tb129.flip(0);\n\t\tb129.flip(32);\n\t\tb129.flip(64);\n\t\tb129.flip(128);\n\t\tEATEST_VERIFY(b129[0]   == true);\n\t\tEATEST_VERIFY(b129[32]  == true);\n\t\tEATEST_VERIFY(b129[64]  == true);\n\t\tEATEST_VERIFY(b129[128] == true);\n\n\t\tbitset<129, WordType> b129Not(~b129);\n\t\tEATEST_VERIFY(b129[0]      == true);\n\t\tEATEST_VERIFY(b129[32]     == true);\n\t\tEATEST_VERIFY(b129[64]     == true);\n\t\tEATEST_VERIFY(b129[128]    == true);\n\t\tEATEST_VERIFY(b129Not[0]   == false);\n\t\tEATEST_VERIFY(b129Not[32]  == false);\n\t\tEATEST_VERIFY(b129Not[64]  == false);\n\t\tEATEST_VERIFY(b129Not[128] == false);\n\n\n\t\t// operator ==, !=\n\t\tbitset<1, WordType> b1Equal(b1);\n\t\tEATEST_VERIFY(b1Equal == b1);\n\t\tEATEST_VERIFY(b1Equal != b1Not);\n\n\t\tbitset<33, WordType> b33Equal(b33);\n\t\tEATEST_VERIFY(b33Equal == b33);\n\t\tEATEST_VERIFY(b33Equal != b33Not);\n\n\t\tbitset<65, WordType> b65Equal(b65);\n\t\tEATEST_VERIFY(b65Equal == b65);\n\t\tEATEST_VERIFY(b65Equal != b65Not);\n\n\t\tbitset<129, WordType> b129Equal(b129);\n\t\tEATEST_VERIFY(b129Equal == b129);\n\t\tEATEST_VERIFY(b129Equal != b129Not);\n\n\n\t\t// bitset<1, WordType> operator<<=, operator>>=, operator<<, operator>>\n\t\tb1.reset();\n\n\t\tb1[0] = true;\n\t\tb1 >>= 0;\n\t\tEATEST_VERIFY(b1[0] == true);\n\t\tb1 >>= 1;\n\t\tEATEST_VERIFY(b1[0] == false);\n\n\t\tb1[0] = true;\n\t\tb1 <<= 0;\n\t\tEATEST_VERIFY(b1[0] == true);\n\t\tb1 <<= 1;\n\t\tEATEST_VERIFY(b1[0] == false);\n\n\t\tb1[0] = true;\n\t\tb1Equal = b1 >> 0;\n\t\tEATEST_VERIFY(b1Equal == b1);\n\t\tb1Equal = b1 >> 1;\n\t\tEATEST_VERIFY(b1Equal[0] == false);\n\n\t\tb1[0] = true;\n\t\tb1Equal = b1 << 0;\n\t\tEATEST_VERIFY(b1Equal[0] == true);\n\t\tb1Equal = b1 << 1;\n\t\tEATEST_VERIFY(b1Equal[0] == false);\n\n\t\tb1.reset();\n\t\tb1.flip();\n\t\tb1 >>= 33;\n\t\tEATEST_VERIFY(b1.count() == 0);\n\t\tEATEST_VERIFY(!b1.all());\n\t\tEATEST_VERIFY(b1.none());\n\n\t\tb1.reset();\n\t\tb1.flip();\n\t\tb1 <<= 33;\n\t\tEATEST_VERIFY(b1.count() == 0);\n\t\tEATEST_VERIFY(!b1.all());\n\t\tEATEST_VERIFY(b1.none());\n\n\t\tb1.reset();\n\t\tb1.flip();\n\t\tb1 >>= 65;\n\t\tEATEST_VERIFY(b1.count() == 0);\n\t\tEATEST_VERIFY(!b1.all());\n\t\tEATEST_VERIFY(b1.none());\n\n\t\tb1.reset();\n\t\tb1.flip();\n\t\tb1 <<= 65;\n\t\tEATEST_VERIFY(b1.count() == 0);\n\t\tEATEST_VERIFY(!b1.all());\n\t\tEATEST_VERIFY(b1.none());\n\n\n\t\t// bitset<33, WordType> operator<<=, operator>>=, operator<<, operator>>\n\t\tb33.reset();\n\n\t\tb33[0]  = true;\n\t\tb33[32] = true;\n\t\tb33 >>= 0;\n\t\tEATEST_VERIFY(b33[0]  == true);\n\t\tEATEST_VERIFY(b33[32] == true);\n\t\tb33 >>= 10;\n\t\tEATEST_VERIFY(b33[22] == true);\n\n\t\tb33.reset();\n\t\tb33[0]  = true;\n\t\tb33[32] = true;\n\t\tb33 <<= 0;\n\t\tEATEST_VERIFY(b33[0] == true);\n\t\tEATEST_VERIFY(b33[32] == true);\n\t\tb33 <<= 10;\n\t\tEATEST_VERIFY(b33[10] == true);\n\n\t\tb33.reset();\n\t\tb33[0]  = true;\n\t\tb33[32] = true;\n\t\tb33Equal = b33 >> 0;\n\t\tEATEST_VERIFY(b33Equal == b33);\n\t\tb33Equal = b33 >> 10;\n\t\tEATEST_VERIFY(b33Equal[22] == true);\n\n\t\tb33.reset();\n\t\tb33[0]  = true;\n\t\tb33[32] = true;\n\t\tb33Equal = b33 << 10;\n\t\tEATEST_VERIFY(b33Equal[10] == true);\n\n\t\tb33.reset();\n\t\tb33.flip();\n\t\tb33 >>= 33;\n\t\tEATEST_VERIFY(b33.count() == 0);\n\t\tEATEST_VERIFY(!b33.all());\n\t\tEATEST_VERIFY(b33.none());\n\n\t\tb33.reset();\n\t\tb33.flip();\n\t\tb33 <<= 33;\n\t\tEATEST_VERIFY(b33.count() == 0);\n\t\tEATEST_VERIFY(!b33.all());\n\t\tEATEST_VERIFY(b33.none());\n\n\t\tb33.reset();\n\t\tb33.flip();\n\t\tb33 >>= 65;\n\t\tEATEST_VERIFY(b33.count() == 0);\n\t\tEATEST_VERIFY(!b33.all());\n\t\tEATEST_VERIFY(b33.none());\n\n\t\tb33.reset();\n\t\tb33.flip();\n\t\tb33 <<= 65;\n\t\tEATEST_VERIFY(b33.count() == 0);\n\t\tEATEST_VERIFY(!b33.all());\n\t\tEATEST_VERIFY(b33.none());\n\n\n\t\t// bitset<65, WordType> operator<<=, operator>>=, operator<<, operator>>\n\t\tb65.reset();\n\n\t\tb65[0]  = true;\n\t\tb65[32] = true;\n\t\tb65[64] = true;\n\t\tb65 >>= 0;\n\t\tEATEST_VERIFY(b65[0]  == true);\n\t\tEATEST_VERIFY(b65[32] == true);\n\t\tEATEST_VERIFY(b65[64] == true);\n\t\tb65 >>= 10;\n\t\tEATEST_VERIFY(b65[22] == true);\n\t\tEATEST_VERIFY(b65[54] == true);\n\n\t\tb65.reset();\n\t\tb65[0]  = true;\n\t\tb65[32] = true;\n\t\tb65[64] = true;\n\t\tb65 <<= 0;\n\t\tEATEST_VERIFY(b65[0] == true);\n\t\tEATEST_VERIFY(b65[32] == true);\n\t\tEATEST_VERIFY(b65[64] == true);\n\t\tb65 <<= 10;\n\t\tEATEST_VERIFY(b65[10] == true);\n\t\tEATEST_VERIFY(b65[42] == true);\n\n\t\tb65.reset();\n\t\tb65[0]  = true;\n\t\tb65[32] = true;\n\t\tb65[64] = true;\n\t\tb65Equal = b65 >> 0;\n\t\tEATEST_VERIFY(b65Equal == b65);\n\t\tb65Equal = b65 >> 10;\n\t\tEATEST_VERIFY(b65Equal[22] == true);\n\t\tEATEST_VERIFY(b65Equal[54] == true);\n\n\t\tb65.reset();\n\t\tb65[0]  = true;\n\t\tb65[32] = true;\n\t\tb65[64] = true;\n\t\tb65Equal = b65 << 10;\n\t\tEATEST_VERIFY(b65Equal[10] == true);\n\t\tEATEST_VERIFY(b65Equal[42] == true);\n\n\t\tb65.reset();\n\t\tb65.flip();\n\t\tb65 >>= 33;\n\t\tEATEST_VERIFY(b65.count() == 32);\n\n\t\tb65.reset();\n\t\tb65.flip();\n\t\tb65 <<= 33;\n\t\tEATEST_VERIFY(b65.count() == 32);\n\n\t\tb65.reset();\n\t\tb65.flip();\n\t\tb65 >>= 65;\n\t\tEATEST_VERIFY(b65.count() == 0);\n\n\t\tb65.reset();\n\t\tb65.flip();\n\t\tb65 <<= 65;\n\t\tEATEST_VERIFY(b65.count() == 0);\n\n\n\t\t// bitset<129, WordType> operator<<=, operator>>=, operator<<, operator>>\n\t\tb129.reset();\n\n\t\tb129[0]  = true;\n\t\tb129[32] = true;\n\t\tb129[64] = true;\n\t\tb129[128] = true;\n\t\tb129 >>= 0;\n\t\tEATEST_VERIFY(b129[0]  == true);\n\t\tEATEST_VERIFY(b129[32] == true);\n\t\tEATEST_VERIFY(b129[64] == true);\n\t\tEATEST_VERIFY(b129[128] == true);\n\t\tb129 >>= 10;\n\t\tEATEST_VERIFY(b129[22] == true);\n\t\tEATEST_VERIFY(b129[54] == true);\n\t\tEATEST_VERIFY(b129[118] == true);\n\n\t\tb129.reset();\n\t\tb129[0]  = true;\n\t\tb129[32] = true;\n\t\tb129[64] = true;\n\t\tb129[128] = true;\n\t\tb129 <<= 0;\n\t\tEATEST_VERIFY(b129[0] == true);\n\t\tEATEST_VERIFY(b129[32] == true);\n\t\tEATEST_VERIFY(b129[64] == true);\n\t\tEATEST_VERIFY(b129[128] == true);\n\t\tb129 <<= 10;\n\t\tEATEST_VERIFY(b129[10] == true);\n\t\tEATEST_VERIFY(b129[42] == true);\n\t\tEATEST_VERIFY(b129[74] == true);\n\n\t\tb129.reset();\n\t\tb129[0]  = true;\n\t\tb129[32] = true;\n\t\tb129[64] = true;\n\t\tb129[128] = true;\n\t\tb129Equal = b129 >> 0;\n\t\tEATEST_VERIFY(b129Equal == b129);\n\t\tb129Equal = b129 >> 10;\n\t\tEATEST_VERIFY(b129Equal[22] == true);\n\t\tEATEST_VERIFY(b129Equal[54] == true);\n\t\tEATEST_VERIFY(b129Equal[118] == true);\n\n\t\tb129.reset();\n\t\tb129[0]  = true;\n\t\tb129[32] = true;\n\t\tb129[64] = true;\n\t\tb129[128] = true;\n\t\tb129Equal = b129 << 10;\n\t\tEATEST_VERIFY(b129Equal[10] == true);\n\t\tEATEST_VERIFY(b129Equal[42] == true);\n\t\tEATEST_VERIFY(b129Equal[74] == true);\n\n\t\tb129.reset();\n\t\tb129.flip();\n\t\tb129 >>= 33;\n\t\tEATEST_VERIFY(b129.count() == 96);\n\n\t\tb129.reset();\n\t\tb129.flip();\n\t\tb129 <<= 33;\n\t\tEATEST_VERIFY(b129.count() == 96);\n\n\t\tb129.reset();\n\t\tb129.flip();\n\t\tb129 >>= 65;\n\t\tEATEST_VERIFY(b129.count() == 64);\n\n\t\tb129.reset();\n\t\tb129.flip();\n\t\tb129 <<= 65;\n\t\tEATEST_VERIFY(b129.count() == 64);\n\n\n\t\t// operator&=(const this_type& x), operator|=(const this_type& x), operator^=(const this_type& x)\n\t\tb1.set();\n\t\tb1[0]  = false;\n\t\tb1A[0] = true;\n\t\tb1 &= b1A;\n\t\tEATEST_VERIFY(b1[0] == false);\n\t\tb1 |= b1A;\n\t\tEATEST_VERIFY(b1[0] == true);\n\t\tb1 ^= b1A;\n\t\tEATEST_VERIFY(b1[0] == false);\n\t\tb1 |= b1A;\n\t\tEATEST_VERIFY(b1[0] == true);\n\n\t\tb33.set();\n\t\tb33[0]   = false;\n\t\tb33[32]  = false;\n\t\tb33A[0]  = true;\n\t\tb33A[32] = true;\n\t\tb33 &= b33A;\n\t\tEATEST_VERIFY((b33[0] == false) && (b33[32] == false));\n\t\tb33 |= b33A;\n\t\tEATEST_VERIFY((b33[0] == true) && (b33[32] == true));\n\t\tb33 ^= b33A;\n\t\tEATEST_VERIFY((b33[0] == false) && (b33[32] == false));\n\t\tb33 |= b33A;\n\t\tEATEST_VERIFY((b33[0] == true) && (b33[32] == true));\n\n\t\tb65.set();\n\t\tb65[0]   = false;\n\t\tb65[32]  = false;\n\t\tb65[64]  = false;\n\t\tb65A[0]  = true;\n\t\tb65A[32] = true;\n\t\tb65A[64] = true;\n\t\tb65 &= b65A;\n\t\tEATEST_VERIFY((b65[0] == false) && (b65[32] == false) && (b65[64] == false));\n\t\tb65 |= b65A;\n\t\tEATEST_VERIFY((b65[0] == true) && (b65[32] == true) && (b65[64] == true));\n\t\tb65 ^= b65A;\n\t\tEATEST_VERIFY((b65[0] == false) && (b65[32] == false) && (b65[64] == false));\n\t\tb65 |= b65A;\n\t\tEATEST_VERIFY((b65[0] == true) && (b65[32] == true) && (b65[64] == true));\n\n\t\tb129.set();\n\t\tb129[0]    = false;\n\t\tb129[32]   = false;\n\t\tb129[64]   = false;\n\t\tb129[128]  = false;\n\t\tb129A[0]   = true;\n\t\tb129A[32]  = true;\n\t\tb129A[64]  = true;\n\t\tb129A[128] = true;\n\t\tb129 &= b129A;\n\t\tEATEST_VERIFY((b129[0] == false) && (b129[32] == false) && (b129[64] == false) && (b129[128] == false));\n\t\tb129 |= b129A;\n\t\tEATEST_VERIFY((b129[0] == true) && (b129[32] == true) && (b129[64] == true) && (b129[128] == true));\n\t\tb129 ^= b129A;\n\t\tEATEST_VERIFY((b129[0] == false) && (b129[32] == false) && (b129[64] == false) && (b129[128] == false));\n\t\tb129 |= b129A;\n\t\tEATEST_VERIFY((b129[0] == true) && (b129[32] == true) && (b129[64] == true) && (b129[128] == true));\n\t}\n\n\t{ // Test bitset::reference\n\t\tbitset<65, WordType> b65;\n\t\ttypename bitset<65, WordType>::reference r = b65[33];\n\n\t\tr = true;\n\t\tEATEST_VERIFY(r == true);\n\t}\n\n\t{ // Test find_first, find_next\n\t\tsize_t i, j;\n\n\t\t// bitset<1, WordType>\n\t\tbitset<1, WordType>   b1;\n\n\t\ti = b1.find_first();\n\t\tEATEST_VERIFY(i == b1.kSize);  \n\t\tb1.set(0, true);\n\t\ti = b1.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b1.find_next(i);\n\t\tEATEST_VERIFY(i ==  b1.kSize);  \n\n\t\tb1.set();\n\t\tfor(i = 0, j = b1.find_first(); j != b1.kSize; j = b1.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 1);\n\n\t\t// bitset<7, WordType>\n\t\tbitset<7, WordType>   b7;\n\n\t\ti = b7.find_first();\n\t\tEATEST_VERIFY(i == b7.kSize);  \n\t\tb7.set(0, true);\n\t\tb7.set(5, true);\n\t\ti = b7.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b7.find_next(i);\n\t\tEATEST_VERIFY(i == 5);\n\t\ti = b7.find_next(i);\n\t\tEATEST_VERIFY(i ==  b7.kSize);  \n\n\t\tb7.set();\n\t\tfor(i = 0, j = b7.find_first(); j != b7.kSize; j = b7.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 7);\n\n\t\t// bitset<32, WordType>\n\t\tbitset<32, WordType>  b32;\n\n\t\ti = b32.find_first();\n\t\tEATEST_VERIFY(i == b32.kSize);  \n\t\tb32.set(0, true);\n\t\tb32.set(27, true);\n\t\ti = b32.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b32.find_next(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b32.find_next(i);\n\t\tEATEST_VERIFY(i == b32.kSize);  \n\n\t\tb32.set();\n\t\tfor(i = 0, j = b32.find_first(); j != b32.kSize; j = b32.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 32);\n\n\t\t// bitset<41, WordType>\n\t\tbitset<41, WordType>  b41;\n\n\t\ti = b41.find_first();\n\t\tEATEST_VERIFY(i == b41.kSize);  \n\t\tb41.set(0, true);\n\t\tb41.set(27, true);\n\t\tb41.set(37, true);\n\t\ti = b41.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b41.find_next(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b41.find_next(i);\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b41.find_next(i);\n\t\tEATEST_VERIFY(i == b41.kSize);  \n\n\t\tb41.set();\n\t\tfor(i = 0, j = b41.find_first(); j != b41.kSize; j = b41.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 41);\n\n\t\t// bitset<64, WordType>\n\t\tbitset<64, WordType>  b64;\n\n\t\ti = b64.find_first();\n\t\tEATEST_VERIFY(i == b64.kSize);  \n\t\tb64.set(0, true);\n\t\tb64.set(27, true);\n\t\tb64.set(37, true);\n\t\ti = b64.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b64.find_next(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b64.find_next(i);\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b64.find_next(i);\n\t\tEATEST_VERIFY(i == b64.kSize);  \n\n\t\tb64.set();\n\t\tfor(i = 0, j = b64.find_first(); j != b64.kSize; j = b64.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 64);\n\n\t\t// bitset<79, WordType>\n\t\tbitset<79, WordType>  b79;\n\n\t\ti = b79.find_first();\n\t\tEATEST_VERIFY(i == b79.kSize);  \n\t\tb79.set(0, true);\n\t\tb79.set(27, true);\n\t\tb79.set(37, true);\n\t\ti = b79.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b79.find_next(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b79.find_next(i);\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b79.find_next(i);\n\t\tEATEST_VERIFY(i == b79.kSize);  \n\n\t\tb79.set();\n\t\tfor(i = 0, j = b79.find_first(); j != b79.kSize; j = b79.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 79);\n\n\t\t// bitset<128, WordType>\n\t\tbitset<128, WordType> b128;\n\n\t\ti = b128.find_first();\n\t\tEATEST_VERIFY(i == b128.kSize);  \n\t\tb128.set(0, true);\n\t\tb128.set(27, true);\n\t\tb128.set(37, true);\n\t\tb128.set(77, true);\n\t\ti = b128.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b128.find_next(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b128.find_next(i);\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b128.find_next(i);\n\t\tEATEST_VERIFY(i == 77);\n\t\ti = b128.find_next(i);\n\t\tEATEST_VERIFY(i == b128.kSize);  \n\n\t\tb128.set();\n\t\tfor(i = 0, j = b128.find_first(); j != b128.kSize; j = b128.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 128);\n\n\t\t// bitset<137, WordType>\n\t\tbitset<137, WordType> b137;\n\n\t\ti = b137.find_first();\n\t\tEATEST_VERIFY(i == b137.kSize);  \n\t\tb137.set(0, true);\n\t\tb137.set(27, true);\n\t\tb137.set(37, true);\n\t\tb137.set(77, true);\n\t\tb137.set(99, true);\n\t\tb137.set(136, true);\n\t\ti = b137.find_first();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b137.find_next(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b137.find_next(i);\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b137.find_next(i);\n\t\tEATEST_VERIFY(i == 77);\n\t\ti = b137.find_next(i);\n\t\tEATEST_VERIFY(i == 99);\n\t\ti = b137.find_next(i);\n\t\tEATEST_VERIFY(i == 136);\n\t\ti = b137.find_next(i);\n\t\tEATEST_VERIFY(i == b137.kSize);\n\n\t\tb137.set();\n\t\tfor(i = 0, j = b137.find_first(); j != b137.kSize; j = b137.find_next(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 137);\n\t}\n\n\t{ // Test find_last, find_prev\n\t\tsize_t i, j;\n\n\t\t// bitset<1, WordType>\n\t\tbitset<1, WordType>   b1;\n\n\t\ti = b1.find_last();\n\t\tEATEST_VERIFY(i == b1.kSize);  \n\t\tb1.set(0, true);\n\t\ti = b1.find_last();\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b1.find_prev(i);\n\t\tEATEST_VERIFY(i ==  b1.kSize);  \n\n\t\tb1.set();\n\t\tfor(i = 0, j = b1.find_last(); j != b1.kSize; j = b1.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 1);\n\n\t\t// bitset<7, WordType>\n\t\tbitset<7, WordType>   b7;\n\n\t\ti = b7.find_last();\n\t\tEATEST_VERIFY(i == b7.kSize);  \n\t\tb7.set(0, true);\n\t\tb7.set(5, true);\n\t\ti = b7.find_last();\n\t\tEATEST_VERIFY(i == 5);\n\t\ti = b7.find_prev(i);\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b7.find_prev(i);\n\t\tEATEST_VERIFY(i ==  b7.kSize);  \n\n\t\tb7.set();\n\t\tfor(i = 0, j = b7.find_last(); j != b7.kSize; j = b7.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 7);\n\n\t\t// bitset<32, WordType>\n\t\tbitset<32, WordType>  b32;\n\n\t\ti = b32.find_last();\n\t\tEATEST_VERIFY(i == b32.kSize);  \n\t\tb32.set(0, true);\n\t\tb32.set(27, true);\n\t\ti = b32.find_last();\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b32.find_prev(i);\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b32.find_prev(i);\n\t\tEATEST_VERIFY(i == b32.kSize);  \n\n\t\tb32.set();\n\t\tfor(i = 0, j = b32.find_last(); j != b32.kSize; j = b32.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 32);\n\n\t\t// bitset<41, WordType>\n\t\tbitset<41, WordType>  b41;\n\n\t\ti = b41.find_last();\n\t\tEATEST_VERIFY(i == b41.kSize);  \n\t\tb41.set(0, true);\n\t\tb41.set(27, true);\n\t\tb41.set(37, true);\n\t\ti = b41.find_last();\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b41.find_prev(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b41.find_prev(i);\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b41.find_prev(i);\n\t\tEATEST_VERIFY(i == b41.kSize);  \n\n\t\tb41.set();\n\t\tfor(i = 0, j = b41.find_last(); j != b41.kSize; j = b41.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 41);\n\n\t\t// bitset<64, WordType>\n\t\tbitset<64, WordType>  b64;\n\n\t\ti = b64.find_last();\n\t\tEATEST_VERIFY(i == b64.kSize);  \n\t\tb64.set(0, true);\n\t\tb64.set(27, true);\n\t\tb64.set(37, true);\n\t\ti = b64.find_last();\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b64.find_prev(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b64.find_prev(i);\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b64.find_prev(i);\n\t\tEATEST_VERIFY(i == b64.kSize);  \n\n\t\tverifyToUint32Throws(b64, 0x08000001);\n\n\t\tb64.set();\n\t\tfor(i = 0, j = b64.find_last(); j != b64.kSize; j = b64.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 64);\n\n\t\t// bitset<79, WordType>\n\t\tbitset<79, WordType>  b79;\n\n\t\ti = b79.find_last();\n\t\tEATEST_VERIFY(i == b79.kSize);  \n\t\tb79.set(0, true);\n\t\tb79.set(27, true);\n\t\tb79.set(37, true);\n\t\ti = b79.find_last();\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b79.find_prev(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b79.find_prev(i);\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b79.find_prev(i);\n\t\tEATEST_VERIFY(i == b79.kSize);  \n\n\t\tEATEST_VERIFY(b79.to_uint64_assert_convertible() == 0x0000002008000001);\n\n\t\tb79.set();\n\t\tfor(i = 0, j = b79.find_last(); j != b79.kSize; j = b79.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 79);\n\n\t\tverifyToUint64Throws(b79, 0xffffffffffffffff);\n\n\t\t// bitset<128, WordType>\n\t\tbitset<128, WordType> b128;\n\n\t\ti = b128.find_last();\n\t\tEATEST_VERIFY(i == b128.kSize);  \n\t\tb128.set(0, true);\n\t\tb128.set(27, true);\n\t\tb128.set(37, true);\n\t\tb128.set(77, true);\n\t\ti = b128.find_last();\n\t\tEATEST_VERIFY(i == 77);\n\t\ti = b128.find_prev(i);\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b128.find_prev(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b128.find_prev(i);\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b128.find_prev(i);\n\t\tEATEST_VERIFY(i == b128.kSize);  \n\n\t\tverifyToUint64Throws(b128, 0x0000002008000001);\n\n\t\tb128.set();\n\t\tfor(i = 0, j = b128.find_last(); j != b128.kSize; j = b128.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 128);\n\n\t\t// bitset<137, WordType>\n\t\tbitset<137, WordType> b137;\n\n\t\ti = b137.find_last();\n\t\tEATEST_VERIFY(i == b137.kSize);  \n\t\tb137.set(0, true);\n\t\tb137.set(27, true);\n\t\tb137.set(37, true);\n\t\tb137.set(77, true);\n\t\tb137.set(99, true);\n\t\tb137.set(136, true);\n\t\ti = b137.find_last();\n\t\tEATEST_VERIFY(i == 136);\n\t\ti = b137.find_prev(i);\n\t\tEATEST_VERIFY(i == 99);\n\t\ti = b137.find_prev(i);\n\t\tEATEST_VERIFY(i == 77);\n\t\ti = b137.find_prev(i);\n\t\tEATEST_VERIFY(i == 37);\n\t\ti = b137.find_prev(i);\n\t\tEATEST_VERIFY(i == 27);\n\t\ti = b137.find_prev(i);\n\t\tEATEST_VERIFY(i == 0);\n\t\ti = b137.find_prev(i);\n\t\tEATEST_VERIFY(i == b137.kSize);\n\n\t\tb137.set();\n\t\tfor(i = 0, j = b137.find_last(); j != b137.kSize; j = b137.find_prev(j))\n\t\t\t++i;\n\t\tEATEST_VERIFY(i == 137);\n\n\t\t// bitset<99, WordType>\n\t\tbitset<99, WordType> b99;\n\t\tb99.set(63);\n\t\tverifyToUint32Throws(b99, 0x0);\n\t\tEATEST_VERIFY(b99.to_uint64_assert_convertible() == 0x8000000000000000);\n\t\tverifyToUlongThrowsIf32bit(b99, static_cast<unsigned long>(0x8000000000000000ul));\n\t}\n\n\tnErrorCount += TestGetFirstBit<WordType>();\n\tnErrorCount += TestGetLastBit<WordType>();\n\n\treturn nErrorCount;\n}\n\nint TestBitset()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestBitsetWithWord<EASTL_BITSET_WORD_TYPE_DEFAULT>();\n\n\tnErrorCount += TestBitsetWithWord<uint8_t>();\n\tnErrorCount += TestBitsetWithWord<uint16_t>();\n\tnErrorCount += TestBitsetWithWord<uint32_t>();\n\tnErrorCount += TestBitsetWithWord<uint64_t>();\n#if EASTL_INT128_SUPPORTED\n\tnErrorCount += TestBitsetWithWord<eastl_uint128_t>();\n#endif\n\n\tnErrorCount += TestBitsetWithWord<unsigned char>();\n\tnErrorCount += TestBitsetWithWord<unsigned short>();\n\tnErrorCount += TestBitsetWithWord<unsigned int>();\n\tnErrorCount += TestBitsetWithWord<unsigned long>();\n\tnErrorCount += TestBitsetWithWord<unsigned long long>();\n\n\t// test BITSET_WORD_COUNT macro\n\t{\n\t\t{\n\t\t\ttypedef eastl::bitset<32, unsigned char> bitset_t;\n\t\t\tstatic_assert(bitset_t::kWordCount == BITSET_WORD_COUNT(bitset_t::kSize, bitset_t::word_type), \"bitset failure\");\n\t\t}\n\t\t{\n\t\t\ttypedef eastl::bitset<32, unsigned int> bitset_t;\n\t\t\tstatic_assert(bitset_t::kWordCount == BITSET_WORD_COUNT(bitset_t::kSize, bitset_t::word_type), \"bitset failure\");\n\t\t}\n\t\t{\n\t\t\ttypedef eastl::bitset<32, uint16_t> bitset_t;\n\t\t\tstatic_assert(bitset_t::kWordCount == BITSET_WORD_COUNT(bitset_t::kSize, bitset_t::word_type), \"bitset failure\");\n\t\t}\n\t\t{\n\t\t\ttypedef eastl::bitset<32, uint32_t> bitset_t;\n\t\t\tstatic_assert(bitset_t::kWordCount == BITSET_WORD_COUNT(bitset_t::kSize, bitset_t::word_type), \"bitset failure\");\n\t\t}\n\t\t{\n\t\t\ttypedef eastl::bitset<128, uint64_t> bitset_t;\n\t\t\tstatic_assert(bitset_t::kWordCount == BITSET_WORD_COUNT(bitset_t::kSize, bitset_t::word_type), \"bitset failure\");\n\t\t}\n\t\t{\n\t\t\ttypedef eastl::bitset<256, uint64_t> bitset_t;\n\t\t\tstatic_assert(bitset_t::kWordCount == BITSET_WORD_COUNT(bitset_t::kSize, bitset_t::word_type), \"bitset failure\");\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestCharTraits.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EABase/eabase.h>\n#include <EASTL/internal/char_traits.h>\n#include <EASTL/string.h>\n\n\ntemplate<typename CharT>\nint TestCharTraits()\n{\n\tint nErrorCount = 0;\n\n\t// Compare(const T* p1, const T* p2, size_t n)\n\t// Compare(const char* p1, const char* p2, size_t n)\n\t{\n\t\tauto create = [](const char* cstr, eastl_size_t sz)\n\t\t{\n\t\t\teastl::basic_string<CharT> result;\n\t\t\tresult.assign_convert(cstr, sz - 1);\n\t\t\treturn result;\n\t\t};\n\n\t\teastl::basic_string<CharT> empty;\n\t\teastl::basic_string<CharT> abc = create(\"abc\", 4);\n\t\teastl::basic_string<CharT> abd = create(\"abd\", 4);\n\t\teastl::basic_string<CharT> ABC = create(\"ABC\", 4);\n\t\tEATEST_VERIFY(eastl::Compare(empty.data(), empty.data(), 0) == 0);\n\t\tEATEST_VERIFY(eastl::Compare(abc.data(), abc.data(), 3) == 0);\n\t\tEATEST_VERIFY(eastl::Compare(abc.data(), abd.data(), 3) < 0);\n\t\tEATEST_VERIFY(eastl::Compare(abd.data(), abc.data(), 3) > 0);\n\t\tEATEST_VERIFY(eastl::Compare(ABC.data(), abc.data(), 3) < 0);\n\t\tEATEST_VERIFY(eastl::Compare(empty.data(), abc.data(), 0) == 0);\n\t}\n\n\treturn nErrorCount;\n}\n\n\nint TestCharTraits()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestCharTraits<char>();\n\t// eastl::DecodePart() is not implemented for (un)signed char.\n\t//nErrorCount += TestCharTraits<unsigned char>();\n\t//nErrorCount += TestCharTraits<signed char>();\n\tnErrorCount += TestCharTraits<wchar_t>();\n\tnErrorCount += TestCharTraits<char8_t>();\n\tnErrorCount += TestCharTraits<char16_t>();\n\tnErrorCount += TestCharTraits<char32_t>();\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestChrono.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EABase/eabase.h>\n#include <EASTL/chrono.h>\n#include <EASTL/numeric.h>\n#include <EASTL/string.h>\n\n\nusing namespace eastl;\nusing namespace eastl::chrono;\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////////\n// TestDuration\n//\nint TestDuration()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\thours h{1}; // 1 hour\n\t\tmilliseconds ms{3}; // 3 milliseconds\n\t\tduration<int, kilo> ks{3}; // 3000 seconds\n\n\t\tduration<double, ratio<1, 30>> hz30{3.5};\n\t\tmicroseconds us = ms; \n\t\tduration<double, milli> ms2 = us; // 3.0 milliseconds\n\n\t\tEA_UNUSED(h);\n\t\tEA_UNUSED(ms2);\n\t\tEA_UNUSED(ks);\n\t\tEA_UNUSED(hz30);\n\t\tEA_UNUSED(us);\n\t}\n\n\t{\n\t\ttypedef duration<double, ratio<1, 30>> dur_t;\n\t\tVERIFY(dur_t::min()  < dur_t::zero());\n\t\tVERIFY(dur_t::zero() < dur_t::max());\n\t\tVERIFY(dur_t::min()  < dur_t::max());\n\t}\n\n\t{\n\t\tseconds s1(10);\n\t\tseconds s2 = -s1;\n\t\tVERIFY(s1.count() ==  10);\n\t\tVERIFY(s2.count() == -10);\n\t}\n\n\t{\n\t\t{\n\t\t\thours h(1);\n\t\t\tminutes m = ++h;\n\t\t\tm--;\n\t\t\tVERIFY(m.count() == 119);\n\t\t}\n\n\t\t{\n\t\t\thours h(24);\n\t\t\tminutes m = h;\n\t\t\tseconds s = m; \n\t\t\tmilliseconds ms = s; \n\n\t\t\tVERIFY(h.count()  == 24);\n\t\t\tVERIFY(m.count()  == 1440);\n\t\t\tVERIFY(s.count()  == 86400);\n\t\t\tVERIFY(ms.count() == 86400000);\n\t\t}\n\n\t\t{    \n\t\t\tminutes m(11);\n\t\t\tm *= 2;\n\t\t\tVERIFY(m.count() == 22);\n\t\t\tm += hours(10); \n\t\t\tVERIFY(m.count() == 622);\n\t\t\tVERIFY(duration_cast<hours>(m).count() == 10);\n\t\t\tm %= hours(1);\n\t\t\tVERIFY(duration_cast<hours>(m).count() == 0);\n\t\t\tVERIFY(m.count() == 22);\n\t\t}\n\n\t\t{\n\t\t\tmilliseconds ms(3);       // 3 milliseconds\n\t\t\tVERIFY(ms.count() == 3);\n\n\t\t\tmicroseconds us = 2 * ms; // 6000 microseconds constructed from 3 milliseconds\n\t\t\tVERIFY(us.count() == 6000);\n\t\t\t\n\t\t\tmicroseconds us2 = ms * 2; // 6000 microseconds constructed from 3 milliseconds\n\t\t\tVERIFY(us2.count() == 6000);\n\n\t\t\tmicroseconds us3 = us / 2;\n\t\t\tVERIFY(us3.count() == 3000);\n\n\t\t\tmicroseconds us4 = us % 2;\n\t\t\tVERIFY(us4.count() == 0);\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////////\n// TestTimePoint\n//\nint TestTimePoint()\n{\n\tint nErrorCount = 0;\n\t{\n\t\t{\n\t\t\tsystem_clock::time_point t0 = system_clock::now();\n\t\t\tauto tomorrow = t0 + hours(24);\n\t\t\tauto today = tomorrow - system_clock::now();\n\t\t\tauto hours_count = duration_cast<hours>(today).count();\n\n\t\t\tVERIFY(hours_count == 24 || hours_count == 23);  // account for time flux\n\t\t}\n\n\t\t{\n\t\t\ttime_point<system_clock, hours> hour1(hours(1));\n\n\t\t\tauto hour_to_min \t  = time_point_cast<minutes>(hour1);\n\t\t\tauto hour_to_sec      = time_point_cast<seconds>(hour1);\n\t\t\tauto hour_to_millisec = time_point_cast<milliseconds>(hour1);\n\t\t\tauto hour_to_microsec = time_point_cast<microseconds>(hour1);\n\t\t\tauto hour_to_nanosec  = time_point_cast<nanoseconds>(hour1);\n\t\t\n\t\t\tVERIFY(hour_to_min.time_since_epoch().count()      == 60);\n\t\t\tVERIFY(hour_to_sec.time_since_epoch().count()      == 3600);\n\t\t\tVERIFY(hour_to_millisec.time_since_epoch().count() == 3600000ll);\n\t\t\tVERIFY(hour_to_microsec.time_since_epoch().count() == 3600000000ll);\n\t\t\tVERIFY(hour_to_nanosec.time_since_epoch().count()  == 3600000000000ll);\n\t\t}\n\t}\n\treturn nErrorCount;\n}\n\n\n//////////////////////////////////////////////////////////////////////////////////////////////////\n// TestClocks\n//\nint TestClocks()\n{\n\tint nErrorCount = 0;\n\t{\n\t\t{\n\t\t\tauto sys = system_clock::now();\n\t\t\tVERIFY(sys.time_since_epoch().count() > 0);\n\n\t\t\tauto stdy = steady_clock::now();\n\t\t\tVERIFY(stdy.time_since_epoch().count() > 0);\n\n\t\t\tauto hrc = high_resolution_clock::now();\n\t\t\tVERIFY(hrc.time_since_epoch().count() > 0);\n\t\t}\n\n\t\t{\n\t\t\tauto start = system_clock::now();\n\t\t\tauto end   = system_clock::now();\n\t\t\tauto d = end - start;\n\t\t\tEA_UNUSED(d);\n\t\t\tVERIFY(d.count() >= 0);\n\t\t}\n\n\t\t{\n\t\t\tauto start = steady_clock::now();\n\t\t\tauto end   = steady_clock::now();\n\t\t\tauto d = end - start;\n\t\t\tEA_UNUSED(d);\n\t\t\tVERIFY(d.count() >= 0);\n\t\t}\n\n\t\t{\n\t\t\tauto start = high_resolution_clock::now();\n\t\t\tauto end   = high_resolution_clock::now();\n\t\t\tauto d = end - start;\n\t\t\tEA_UNUSED(d);\n\t\t\tVERIFY(d.count() >= 0);\n\t\t}\n\n\t\t{\n\t\t\ttypedef duration<int, ratio<1, 100000000>> shakes;\n\t\t\ttypedef duration<int, centi> jiffies;\n\t\t\ttypedef duration<float, ratio<12096, 10000>> microfortnights;\n\t\t\ttypedef duration<float, ratio<3155, 1000>> nanocenturies;\n\n\t\t\tseconds sec(1);\n\n\t\t\tVERIFY(duration_cast<shakes>(sec).count() == 100000000);\n\t\t\tVERIFY(duration_cast<jiffies>(sec).count() == 100);\n\t\t\tVERIFY(microfortnights(sec).count() > 0.82f);\n\t\t\tVERIFY(nanocenturies(sec).count() > 0.31f);\n\t\t}\n\t}\n\treturn nErrorCount;\n}\n\n\nint TestChrono()\n{\n\tint nErrorCount = 0;\n\tnErrorCount += TestDuration();\n\tnErrorCount += TestTimePoint();\n\tnErrorCount += TestClocks();\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestConcepts.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include <EASTL/internal/concepts.h>\n#include <EASTL/memory.h>\n\n#include \"EASTL/unique_ptr.h\"\n#include \"EASTLTest.h\"\n\nstruct NoExceptFalseDestructor\n{\n\t~NoExceptFalseDestructor() noexcept(false) = default;\n};\n\n// In GCC prior to version 14, the following static_assert fails:\n//\n//    static_assert(!noexcept(std::declval<NoExceptFalseDestructor&>().~NoExceptFalseDestructor()), \"bad noexcept!\");\n//\n// our implementation of some of these concepts depends on that working correctly so we don't\n// do these tests in older versions of GCC. Clang handles this properly and on MSVC we use\n// __is_nothrow_destructible instead of rolling our own.\n#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION <= 14000)\n\t#define EA_TEST_NoExceptFalseDestructor 0\n#else\n\t#define EA_TEST_NoExceptFalseDestructor 1\n#endif\n\nstruct From;\n\nstruct To\n{\n\tTo(const From&)\n\t{}\n\n\tTo(const int&) // To can be implicitly constructed from int, but int cannot be explicitly converted to To.\n\t{}\n};\n\nstruct From\n{\n\texplicit operator To() const\n\t{\n\t\treturn To{*this};\n\t}\n};\n\nstruct NotMoveable\n{\n\tNotMoveable() = default;\n\n\tNotMoveable(const NotMoveable&) = delete;\n\tNotMoveable& operator=(const NotMoveable&) = delete;\n\tNotMoveable(NotMoveable&&) = delete;\n\tNotMoveable& operator=(NotMoveable&&) = delete;\n\n\t~NotMoveable() = default;\n};\n\nint TestConcepts()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t// destructible\n\t{\n\t\tstatic_assert(internal::concepts::destructible<int>, \"destructible concept failure.\");\n\t\tstatic_assert(!internal::concepts::destructible<void>, \"destructible concept failure.\");\n#if EA_TEST_NoExceptFalseDestructor\n\t\tstatic_assert(!internal::concepts::destructible<NoExceptFalseDestructor>, \"destructible concept failure.\");\n#endif\n\t}\n\n\t// constructible_from\n\t{\n\t\tstatic_assert(internal::concepts::constructible_from<int>, \"constructible_from concept failure.\");\n\t\tstatic_assert(internal::concepts::constructible_from<int, int>, \"constructible_from concept failure.\");\n\t\tstatic_assert(internal::concepts::constructible_from<int, bool>, \"constructible_from concept failure.\");\n\t\tstatic_assert(internal::concepts::constructible_from<To, From>, \"constructible_from concept failure.\");\n\n\t\tstatic_assert(!internal::concepts::constructible_from<int, int*>, \"constructible_from concept failure.\");\n\t\tstatic_assert(!internal::concepts::constructible_from<int, bool, bool>, \"constructible_from concept failure.\");\n\t\tstatic_assert(!internal::concepts::constructible_from<int, void>, \"constructible_from concept failure.\");\n#if EA_TEST_NoExceptFalseDestructor\n\t\tstatic_assert(!internal::concepts::constructible_from<NoExceptFalseDestructor>, \"constructible_from concept failure.\");\n\t\tstatic_assert(!internal::concepts::constructible_from<NoExceptFalseDestructor, NoExceptFalseDestructor>, \"constructible_from concept failure.\");\n#endif\n\t}\n\n\t// constructible_to\n\t{\n\t\tstatic_assert(internal::concepts::convertible_to<bool, int>, \"convertible_to concept failure.\");\n\t\tstatic_assert(internal::concepts::convertible_to<int, int>, \"convertible_to concept failure.\");\n\t\tstatic_assert(internal::concepts::convertible_to<NoExceptFalseDestructor, NoExceptFalseDestructor>, \"convertible_to concept failure.\");\n\t\tstatic_assert(internal::concepts::convertible_to<From, To>, \"convertible_to concept failure.\");\n\n\t\tstatic_assert(!internal::concepts::convertible_to<From, int>, \"convertible_to concept failure.\"); // No implicit conversion for int.\n\t\tstatic_assert(!internal::concepts::convertible_to<int*, int>, \"convertible_to concept failure.\");\n\t\tstatic_assert(!internal::concepts::convertible_to<void, int>, \"convertible_to concept failure.\");\n\t}\n\n\t// move_constructible\n\t{\n\t\tstatic_assert(internal::concepts::move_constructible<int>, \"move_constructible concept failure.\");\n\t\tstatic_assert(internal::concepts::move_constructible<unique_ptr<int>>, \"move_constructible concept failure.\");\n\n#if EA_TEST_NoExceptFalseDestructor\n\t\tstatic_assert(!internal::concepts::move_constructible<NoExceptFalseDestructor>, \"move_constructible concept failure.\");\n#endif\n\t\tstatic_assert(!internal::concepts::move_constructible<NotMoveable>, \"move_constructible concept failure.\");\n\t}\n\n\t// copy_constructible\n\t{\n\t\tstatic_assert(internal::concepts::copy_constructible<int>, \"copy_constructible concept failure.\");\n\t\t\n\t\tstatic_assert(!internal::concepts::copy_constructible<unique_ptr<int>>, \"copy_constructible concept failure.\");\n#if EA_TEST_NoExceptFalseDestructor\n\t\tstatic_assert(!internal::concepts::move_constructible<NoExceptFalseDestructor>, \"copy_constructible concept failure.\");\n#endif\n\t\tstatic_assert(!internal::concepts::move_constructible<NotMoveable>, \"copy_constructible concept failure.\");\n\t}\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestContainerBehaviour.cpp",
    "content": "// (c) 2025 Electronic Arts Inc.\n\n#include \"EASTLTest.h\"\n#include <EASTL/list.h>\n#include <EASTL/bonus/list_map.h>\n#include <EASTL/slist.h>\n#include <EASTL/vector.h>\n#include <EASTL/deque.h>\n#include <EASTL/map.h>\n#include <EASTL/set.h>\n#include <EASTL/string.h>\n#include <EASTL/hash_map.h>\n#include <EASTL/hash_set.h>\n#include <EASTL/segmented_vector.h>\n#include <EASTL/fixed_list.h>\n#include <EASTL/fixed_slist.h>\n#include <EASTL/fixed_vector.h>\n#include <EASTL/fixed_map.h>\n#include <EASTL/fixed_set.h>\n#include <EASTL/fixed_hash_map.h>\n#include <EASTL/fixed_hash_set.h>\n#include <EASTL/fixed_string.h>\n\ntemplate <typename Container, typename T>\nint TestContainerCtorMoveWithAllocator(bool useSameAllocator,\n                                       std::initializer_list<T> ilist,\n                                       const char* containerName,\n                                       bool expectElementsMoved,\n                                       bool expectElementsCopied)\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tconst InstanceAllocator moveAllocator = InstanceAllocator(useSameAllocator ? 1 : 2);\n\t\tconst Container expected(ilist, InstanceAllocator(1));\n\t\tContainer src(ilist, InstanceAllocator(1));\n\n\t\tint64_t toCopyCtorCount = TestObject::sTOCopyCtorCount, toMoveCtorCount = TestObject::sTOMoveCtorCount,\n\t\t        toCtorCount = TestObject::sTOCtorCount, toAssignCount = TestObject::sTOAssignCount;\n\n\t\tContainer dest(eastl::move(src), moveAllocator);\n\n\t\t// required by the standard:\n\t\tEATEST_VERIFY(get_allocator(dest) == moveAllocator);\n\t\tEATEST_VERIFY(dest.size() == expected.size());\n\t\tEATEST_VERIFY(eastl::equal(dest.begin(), dest.end(), expected.begin()));\n\n\t\t// strengthened compared to the standard:\n\t\tif (expectElementsMoved)\n\t\t\tEATEST_VERIFY(TestObject::sTOMoveCtorCount - toMoveCtorCount == static_cast<int64_t>(ilist.size()));\n\t\tif (expectElementsCopied)\n\t\t\tEATEST_VERIFY(TestObject::sTOCopyCtorCount - toCopyCtorCount == static_cast<int64_t>(ilist.size()));\n\t\tEATEST_VERIFY(TestObject::sTOCtorCount - toCtorCount ==\n\t\t              ((expectElementsMoved || expectElementsCopied) ? static_cast<int64_t>(ilist.size()) : 0));\n\t\tEATEST_VERIFY(TestObject::sTOAssignCount == toAssignCount);\n\t}\n\n\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t                  \"Container elements should be deallocated by the allocator that allocated it.\");\n\n\tif (nErrorCount > 0)\n\t\tEASTLTest_Printf(\"%s move constructor with allocator: failure\\n\", containerName);\n\n\treturn nErrorCount;\n}\n\nint TestContainerBehaviour()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(TestObject::Reset());\n\n\t{ // move constructor with allocator\n\t\t// only correct because it has incorrect propagate on swap behaviour, see TestAllocatorPropagate\n\t\tnErrorCount += TestContainerCtorMoveWithAllocator<list<TestObject, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"list\", false, true);\n\t\tEATEST_VERIFY(TestObject::Reset());\n\t\t// only correct because it has incorrect propagate on swap behaviour, see TestAllocatorPropagate\n\t\tnErrorCount += TestContainerCtorMoveWithAllocator<slist<TestObject, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"slist\", false, true);\n\t\tEATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<vector<TestObject, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"vector\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<deque<TestObject, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"deque\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<map<TestObject, int, less<TestObject>, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"map\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<multimap<TestObject, int, less<TestObject>, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"multimap\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<set<TestObject, less<TestObject>, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"set\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<multiset<TestObject, less<TestObject>, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"multiset\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<hash_map<TestObject, int, hash<TestObject>, equal_to<TestObject>, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"hash_map\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<hash_multimap<TestObject, int, hash<TestObject>, equal_to<TestObject>, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"hash_multimap\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<hash_set<TestObject, hash<TestObject>, equal_to<TestObject>, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"hash_set\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<hash_multiset<TestObject, hash<TestObject>, equal_to<TestObject>, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"hash_multiset\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<basic_string<char, InstanceAllocator>>(false, { 'a', 'b', 'c' }, \"basic_string\", false, false);\n\n\t\t// fixed types with overflow, but all elements fit in the fixed portion of the container:\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_list<TestObject, 8, true, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_list (no overflow)\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_slist<TestObject, 8, true, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_slist (no overflow)\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_vector<TestObject, 8, true, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_vector (no overflow)\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_map<TestObject, int, 8, true, less<TestObject>, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"fixed_map (no overflow)\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_multimap<TestObject, int, 8, true, less<TestObject>, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"fixed_multimap (no overflow)\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_set<TestObject, 8, true, less<TestObject>, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_set (no overflow)\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_multiset<TestObject, 8, true, less<TestObject>, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_multiset (no overflow)\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_map<TestObject, int, 8, 9, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"fixed_hash_map (no overflow)\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_multimap<TestObject, int, 8, 9, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(false, { pair<const TestObject, int>(1, 1) }, \"fixed_hash_multimap (no overflow)\", false, true);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_set<TestObject, 8, 9, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_hash_set (no overflow)\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_multiset<TestObject, 8, 9, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(false, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_hash_multiset (no overflow)\", true, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_string<char, 8, true, InstanceAllocator>>(false, { 'a', 'b', 'c' }, \"fixed_string (no overflow)\", false, true);\n\t\t\n\t\t// fixed types that will use the overflow allocator and therefore the constructor can elide copying or moving elements, ie. equivalent to a regular move constructor:\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_list<TestObject, 2, true, InstanceAllocator>>(true, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_list (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_slist<TestObject, 2, true, InstanceAllocator>>(true, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_slist (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_vector<TestObject, 2, true, InstanceAllocator>>(true, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_vector (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_map<TestObject, int, 2, true, less<TestObject>, InstanceAllocator>>(true, { pair<const TestObject, int>(1, 1) }, \"fixed_map (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_multimap<TestObject, int, 2, true, less<TestObject>, InstanceAllocator>>(true, { pair<const TestObject, int>(1, 1) }, \"fixed_multimap (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_set<TestObject, 2, true, less<TestObject>, InstanceAllocator>>(true, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_set (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_multiset<TestObject, 2, true, less<TestObject>, InstanceAllocator>>(true, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_multiset (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_map<TestObject, int, 2, 3, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(true, { pair<const TestObject, int>(1, 1) }, \"fixed_hash_map (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_multimap<TestObject, int, 2, 3, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(true, { pair<const TestObject, int>(1, 1) }, \"fixed_hash_multimap (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_set<TestObject, 2, 3, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(true, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_hash_set (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_hash_multiset<TestObject, 2, 3, true, hash<TestObject>, equal_to<TestObject>, true, InstanceAllocator>>(true, { TestObject{1}, TestObject{2}, TestObject{3} }, \"fixed_hash_multiset (use overflow)\", false, false);\n\t\t//EATEST_VERIFY(TestObject::Reset());\n\t\t//nErrorCount += TestContainerCtorMoveWithAllocator<fixed_string<char, 2, true, InstanceAllocator>>(true, { 'a', 'b', 'c' }, \"fixed_string (use overflow)\", false, false);\n\n\t\t// following types haven't implemented the appropriate constructor:\n\t\t// segmented_vector\n\t\t// list_map\n\t\t// string_map\n\t\t// string_hash_map\n\n\t\t// other containers not tested:\n\t\t// container adaptors are not tested because their behaviour should be the same as their underlying container.\n\t\t// tuple_vector_alloc - what is this type?\n\t}\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestCppCXTypeTraits.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/type_traits.h>\n\nusing namespace eastl;\n\n#if defined(__cplusplus_winrt)\n\tref class Foo\n\t{\n\n\t};\n#endif\n\nint TestCppCXTypeTraits()\n{\n\tint nErrorCount = 0;\n\n\t// We can only build this code if C++/CX is enabled\n#if defined(__cplusplus_winrt)\n\t{\n\t\tFoo^ foo = ref new Foo();\n\t\tstatic_assert(eastl::is_pod<Foo^>::value == false, \"Ref types are not POD\");\n\t\tstatic_assert(eastl::is_trivially_destructible<Foo^>::value == false, \"Ref types cannot be trivially destructible\");\n\t\tstatic_assert(eastl::is_trivially_constructible<Foo^>::value == false, \"Ref types cannot be trivially constructible\");\n\t\tstatic_assert(eastl::is_trivially_copy_constructible<Foo^>::value == false, \"Ref types cannot be trivially copyable\");\n\t\tstatic_assert(eastl::is_trivially_copy_assignable<Foo^>::value == false, \"Ref types cannot be trivially copyable\");\n\t}\n#endif\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestDeque.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include \"EASTLTestIterators.h\"\n#include <EABase/eabase.h>\n#include <EASTL/deque.h>\n#include <EASTL/list.h>\n#include <EASTL/vector.h>\n#include <EASTL/string.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/unique_ptr.h>\n#include \"ConceptImpls.h\"\n\n\nusing namespace eastl;\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::deque<int>;\ntemplate class eastl::deque<TestObject>;\n\n\n// Test compiler issue that appeared in VS2012 relating to deque::kAlignment.\nstruct StructWithContainerOfStructs\n{\n\teastl::deque<StructWithContainerOfStructs, EASTLAllocatorType, 16> children;\n};\n\n// The following will not compile because the default value of kDequeSubarraySize\n// relies on sizeof(T). Thus, a non-default value must be provided, or the full type\n// will be required at the time of instantiation, but it is not available.\n// struct StructWithContainerOfStructsDefault\n// {\n//     eastl::deque<StructWithContainerOfStructsDefault> children;\n// };\n\n\n///////////////////////////////////////////////////////////////////////////////\ntypedef eastl::deque<int>                            IntDeque;\ntypedef eastl::deque<int, EASTLAllocatorType, 1>     IntDeque1;\ntypedef eastl::deque<int, EASTLAllocatorType, 32768> IntDeque32768;\n\n\ntypedef eastl::deque<TestObject>                            TestObjectDeque;\ntypedef eastl::deque<TestObject, EASTLAllocatorType, 1>     TestObjectDeque1;\ntypedef eastl::deque<TestObject, EASTLAllocatorType, 32768> TestObjectDeque32768;\n\n///////////////////////////////////////////////////////////////////////////////\n// TestDequeConstruction\n//\ntemplate <typename Deque>\nint TestDequeConstruction()\n{\n\ttypedef typename Deque::value_type value_type;\n\ttypedef typename Deque::size_type size_type;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\t// constructors\n\t\tDeque dA;\n\t\tEATEST_VERIFY(dA.size() == 0);\n\n\t\tDeque dB((size_type)0);\n\t\tEATEST_VERIFY(dB.size() == 0);\n\n\t\tDeque dC(1000);\n\t\tEATEST_VERIFY(dC.size() == 1000);\n\t\tfor (const auto& elem : dC)\n\t\t\tEATEST_VERIFY(elem == value_type());\n\n\t\tDeque dD(2000, value_type(1));\n\t\tEATEST_VERIFY(dD.size() == 2000);\n\t\tfor (const auto& elem : dD)\n\t\t\tEATEST_VERIFY(elem == value_type(1));\n\n\t\tDeque dE(dC);\n\t\tEATEST_VERIFY(dE.size() == 1000);\n\t\tfor (const auto& elem : dE)\n\t\t\tEATEST_VERIFY(elem == value_type());\n\n\t\tDeque dF(dC.begin(), dC.end());\n\t\tEATEST_VERIFY(dF.size() == 1000);\n\t\tfor (const auto& elem : dF)\n\t\t\tEATEST_VERIFY(elem == value_type());\n\n\t\t// operator=\n\t\tdE = dD;\n\t\tEATEST_VERIFY(dE.size() == 2000);\n\t\tfor (const auto& elem : dE)\n\t\t\tEATEST_VERIFY(elem == value_type(1));\n\n\t\t// swap\n\t\tdE.swap(dC);\n\t\tEATEST_VERIFY(dE.size() == 1000);\n\t\tfor (const auto& elem : dE)\n\t\t\tEATEST_VERIFY(elem == value_type());\n\t\tEATEST_VERIFY(dC.size() == 2000);\n\t\tfor (const auto& elem : dC)\n\t\t\tEATEST_VERIFY(elem == value_type(1));\n\n\t\t// clear\n\t\tdA.clear();\n\t\tEATEST_VERIFY(dA.size() == 0);\n\t\tEATEST_VERIFY(dA.empty());\n\n\t\tdB.clear();\n\t\tEATEST_VERIFY(dB.size() == 0);\n\t\tEATEST_VERIFY(dB.empty());\n\t}\n\n\tEATEST_VERIFY(TestObject::sTOCount == 0);\n\tEATEST_VERIFY(TestObject::sMagicErrorCount == 0);\n\n\treturn nErrorCount;\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestDequeSimpleMutation\n//\ntemplate <typename Deque>\nint TestDequeSimpleMutation()\n{\n\ttypedef typename Deque::value_type value_type;\n\ttypedef typename Deque::size_type size_type;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\tDeque d;\n\n\t\t// push_back(value_type&)\n\t\t// front\n\t\t// back\n\t\tfor (int i = 0; i < 1000; i++)\n\t\t{\n\t\t\td.push_back(value_type(i));\n\t\t\tEATEST_VERIFY(d.back() == value_type(i));\n\t\t}\n\t\tEATEST_VERIFY(d.front() == value_type(0));\n\n\t\t// operator[]\n\t\t// at()\n\t\tfor (unsigned int i = 0; i < d.size(); ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(d[i] == value_type(i));\n\t\t\tEATEST_VERIFY(d.at(i) == value_type(i));\n\t\t}\n\t}\n\n\t{\n\t\tDeque d;\n\n\t\t// push_back()\n\t\t// this overloads is an EASTL extension.\n\t\tfor (int i = 0; i < 1000; i++)\n\t\t{\n\t\t\tvalue_type& ref = d.push_back();\n\t\t\tEATEST_VERIFY(&ref == &d.back());\n\t\t\tEATEST_VERIFY(d.back() == value_type());\n\t\t}\n\t\tEATEST_VERIFY(d.front() == value_type());\n\n\t\t// operator[]\n\t\t// at()\n\t\tfor (size_type i = 0, iEnd = d.size(); i < iEnd; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(d[i] == value_type());\n\t\t\tEATEST_VERIFY(d.at(i) == value_type());\n\t\t}\n\t}\n\n\t{\n\t\tDeque d;\n\n\t\t// push_front(value_type&)\n\t\tfor (int i = 0; i < 1000; i++)\n\t\t{\n\t\t\td.push_front(value_type(i));\n\t\t\tEATEST_VERIFY(d.front() == value_type(i));\n\t\t}\n\n\t\t// operator[]\n\t\t// at()\n\t\tEATEST_VERIFY(d.size() == 1000);\n\t\tfor (int i = 0; i < 1000; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(d[1000 - 1 - i] == value_type(i));\n\t\t\tEATEST_VERIFY(d.at(1000 - 1 - i) == value_type(i));\n\t\t}\n\t}\n\n\t{\n\t\tDeque d;\n\n\t\t// push_front()\n\t\t// this overloads is an EASTL extension.\n\t\tfor (int i = 0; i < 1000; i++)\n\t\t{\n\t\t\tvalue_type& ref = d.push_front();\n\t\t\tEATEST_VERIFY(&ref == &d.front());\n\t\t\tEATEST_VERIFY(d.front() == value_type());\n\t\t}\n\t\tEATEST_VERIFY(d.back() == value_type());\n\n\t\t// operator[]\n\t\t// at()\n\t\tfor (size_type i = 0, iEnd = d.size(); i < iEnd; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(d[i] == value_type());\n\t\t\tEATEST_VERIFY(d.at(i) == value_type());\n\t\t}\n\n\t\t// pop_back()\n\t\tfor (int i = 0; i < 500; i++)\n\t\t{\n\t\t\td.pop_back();\n\t\t}\n\t\tEATEST_VERIFY(d.size() == 500);\n\t\tfor (const auto& elem : d)\n\t\t\tEATEST_VERIFY(elem == value_type());\n\n\t\t// pop_front()\n\t\tfor (int i = 0; i < 500; i++)\n\t\t{\n\t\t\td.pop_front();\n\t\t}\n\t\tEATEST_VERIFY(d.size() == 0);\n\t}\n\n\t{\n\t\tDeque d;\n\n\t\t// resize(value_type&)\n\t\tfor(int i = 0; i < 500; i++)\n\t\t{\n\t\t\td.resize(d.size() + 3, value_type(i));\n\t\t\tEATEST_VERIFY(d.size() == size_type((i + 1) * 3));\n\t\t}\n\t\t\n\t\tEATEST_VERIFY(d.size() == 1500);\n\n\t\tfor (int i = 0; i < 500; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(d[i * 3 + 0] == value_type(i));\n\t\t\tEATEST_VERIFY(d[i * 3 + 1] == value_type(i));\n\t\t\tEATEST_VERIFY(d[i * 3 + 2] == value_type(i));\n\t\t}\n\n\t\t// resize()\n\t\tfor(int i = 0; i < 500; i++)\n\t\t{\n\t\t\td.resize(d.size() - 2);\n\t\t\tEATEST_VERIFY(d.size() == size_type(1500 - ((i + 1) * 2)));\n\t\t}\n\t\tEATEST_VERIFY(d.size() == 500);\n\t}\n\n\tEATEST_VERIFY(TestObject::sTOCount == 0);\n\tEATEST_VERIFY(TestObject::sMagicErrorCount == 0);\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestDequeComplexMutation\n//\ntemplate <typename Deque>\nint TestDequeComplexMutation()\n{\n\ttypedef typename Deque::value_type value_type;\n\ttypedef typename Deque::size_type size_type;\n\ttypedef typename Deque::iterator iterator;\n\ttypedef typename Deque::reverse_iterator reverse_iterator;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\tDeque d;\n\n\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// void assign(size_type n, const value_type& value);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\td.assign(100, 1);\n\t\tEATEST_VERIFY(d.size() == 100);\n\t\tfor (const auto& elem : d)\n\t\t\tEATEST_VERIFY(elem == value_type(1));\n\n\t\td.assign(50, 2);\n\t\tEATEST_VERIFY(d.size() == 50);\n\t\tfor (const auto& elem : d)\n\t\t\tEATEST_VERIFY(elem == value_type(2));\n\n\t\td.assign(150, 3);\n\t\tEATEST_VERIFY(d.size() == 150);\n\t\tfor (const auto& elem : d)\n\t\t\tEATEST_VERIFY(elem == value_type(3));\n\n\n\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// template <typename InputIterator>\n\t\t// void assign(InputIterator first, InputIterator last);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\tlist<value_type> valueList;\n\t\tfor(int i = 0; i < 100; i++)\n\t\t\tvalueList.push_back(value_type(i));\n\n\t\td.assign(valueList.begin(), valueList.end());\n\t\tEATEST_VERIFY(d.size() == 100);\n\t\tfor (int i = 0; i < 100; i++)\n\t\t\tEATEST_VERIFY(d[i] == value_type(i));\n\n\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// iterator insert(iterator position, const value_type& value);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\titerator itFirstInserted = d.insert(d.begin(), d[1]);\n\t\tEATEST_VERIFY(itFirstInserted == d.begin());\n\t\tEATEST_VERIFY(d[0] == value_type(1));\n\n\t\tvalue_type value = d[d.size() - 2];\n\t\titFirstInserted = d.insert(d.end(), value);\n\t\tEATEST_VERIFY(itFirstInserted == d.end() - 1);\n\t\tEATEST_VERIFY(*(d.end() - 1) == value);\n\n\t\titerator itNearBegin = d.begin();\n\t\tadvance(itNearBegin, 1);\n\n\t\tvalue = d[3];\n\t\titFirstInserted = d.insert(itNearBegin, value);\n\t\tEATEST_VERIFY(itFirstInserted == d.begin() + 1);\n\t\tEATEST_VERIFY(d[1] == value);\n\n\t\titerator itNearEnd = d.begin();\n\t\tadvance(itNearEnd, d.size() - 1);\n\n\t\tvalue = d[d.size() - 2];\n\t\titFirstInserted = d.insert(itNearEnd, value);\n\t\tEATEST_VERIFY(itFirstInserted == d.end() - 2);\n\t\tEATEST_VERIFY(d[d.size() - 2] == value);\n\n\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// iterator insert(iterator position, size_type n, const value_type& value);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\titFirstInserted = d.insert(d.begin(), d.size() * 2, value_type(3)); // Insert a large number of items at the front.\n\t\tEATEST_VERIFY(itFirstInserted == d.begin());\n\t\tfor (size_type i = 0; i < d.size() / 2; i++)\n\t\t\tEATEST_VERIFY(d[i] == value_type(3));\n\n\t\titFirstInserted = d.insert(d.end(), d.size() * 2, value_type(3)); // Insert a large number of items at the end.\n\t\tEATEST_VERIFY(itFirstInserted == d.begin() + (d.size() / 3));\n\t\tfor (size_type i = 0; i < d.size() / 2; i++)\n\t\t\tEATEST_VERIFY(d[d.size() - 1 - i] == value_type(3));\n\n\t\titNearBegin = d.begin();\n\t\tadvance(itNearBegin, 3);\n\n\t\titFirstInserted = d.insert(itNearBegin, 3, value_type(4));\n\t\tEATEST_VERIFY(itFirstInserted == d.begin() + 3);\n\t\tEATEST_VERIFY(VerifySequence(d.begin() + 3, d.begin() + 6, { value_type(4), value_type(4), value_type(4) }, \"insert()\"));\n\n\t\titNearEnd = d.begin();\n\t\tadvance(itNearEnd, d.size() - 1);\n\n\t\titFirstInserted = d.insert(d.end(), 5, value_type(6));\n\t\tEATEST_VERIFY(itFirstInserted == d.end() - 5);\n\t\tEATEST_VERIFY(VerifySequence(d.end() - 5, d.end(), { value_type(6), value_type(6), value_type(6), value_type(6), value_type(6) }, \"insert()\"));\n\n\n\t\tEATEST_VERIFY(d.begin() == d.insert(d.begin(), 0, value_type(9)));\n\n\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// template <typename InputIterator>\n\t\t// iterator insert(iterator position, InputIterator first, InputIterator last);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\titNearBegin = d.begin();\n\t\tadvance(itNearBegin, 3);\n\n\t\titFirstInserted = d.insert(itNearBegin, valueList.begin(), valueList.end());\n\t\tfor (int i = 0; i < 100; ++i, ++itFirstInserted)\n\t\t\tEATEST_VERIFY(*itFirstInserted == value_type(i));\n\n\t\tvalue_type x(0);\n\t\titFirstInserted = d.insert(d.begin(), InputIterator<value_type>(&x), InputIterator<value_type>(EndSentinel(), value_type(5)));\n\t\tEATEST_VERIFY(itFirstInserted == d.begin());\n\t\tEATEST_VERIFY(VerifySequence(d.begin(), d.begin() + 5, { value_type(0), value_type(1), value_type(2), value_type(3), value_type(4) }, \"deque::insert() with input iterators\"));\n\n\t\tauto inputEnd = InputIterator<value_type>(EndSentinel(), value_type(5));\n\t\tEATEST_VERIFY(d.begin() == d.insert(d.begin(), inputEnd, inputEnd));\n\n\t\tvalue_type* itContiguous = nullptr;\n\t\tEATEST_VERIFY(d.begin() == d.insert(d.begin(), itContiguous, itContiguous));\n\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// iterator erase(iterator position);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\titNearBegin = d.begin();\n\n\t\tsize_type sizeBeforeErase = d.size();\n\t\twhile(itNearBegin != d.end()) // Run a loop whereby we erase every fourth element.\n\t\t{\n\t\t\tfor(int i = 0; (i < 3) && (itNearBegin != d.end()); ++i)\n\t\t\t{\n\t\t\t\t++itNearBegin;\n\t\t\t}\n\n\t\t\tif(itNearBegin != d.end())\n\t\t\t{\n\t\t\t\titNearBegin = d.erase(itNearBegin);\n\t\t\t}\n\t\t}\n\t\tEATEST_VERIFY(sizeBeforeErase - (sizeBeforeErase / 4) == d.size());\n\n\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// iterator erase(iterator first, iterator last);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\titNearBegin = d.begin();\n\n\t\twhile(itNearBegin != d.end()) // Run a loop whereby we erase spans of elements.\n\t\t{\n\t\t\titerator itSaved = itNearBegin;\n\n\t\t\tsize_type numElementsToErase = 0;\n\t\t\tfor(; (numElementsToErase < 22) && (itNearBegin != d.end()); ++numElementsToErase)\n\t\t\t{\n\t\t\t\t++itNearBegin;\n\t\t\t}\n\n\t\t\tif(itNearBegin != d.end())\n\t\t\t{\n\t\t\t\tsize_type numElementsPrior = d.size();\n\t\t\t\titNearBegin = d.erase(itSaved, itNearBegin);\n\t\t\t\tEATEST_VERIFY(d.size() == numElementsPrior - numElementsToErase);\n\t\t\t}\n\n\t\t\tfor(int i = 0; (i < 17) && (itNearBegin != d.end()); ++i)\n\t\t\t{\n\t\t\t\t++itNearBegin;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t{\n\t\t//////////////////////////////////////////////////////////////////\n\t\t// reverse_iterator erase(reverse_iterator position);\n\t\t// reverse_iterator erase(reverse_iterator first, reverse_iterator last);\n\t\t//////////////////////////////////////////////////////////////////\n\n\t\tDeque dErase;\n\n\t\tfor(int i = 0; i < 20; i++)\n\t\t{\n\t\t\tvalue_type val(i);\n\t\t\tdErase.push_back(val);\n\t\t}\n\t\tEATEST_VERIFY((dErase.size() == 20) && (dErase[0] == value_type(0)) && (dErase[19] == value_type(19)));\n\n\n\t\treverse_iterator rA = dErase.rbegin();\n\t\treverse_iterator rB = rA + 3;\n\t\tdErase.erase(rA, rB);\n\t\tEATEST_VERIFY((dErase.size() == 17));\n\t\tEATEST_VERIFY((dErase[0] == value_type(0)));\n\t\tEATEST_VERIFY((dErase[16] == value_type(16)));\n\n\n\t\trB = dErase.rend();\n\t\trA = rB - 3;\n\t\tdErase.erase(rA, rB);\n\t\tEATEST_VERIFY((dErase.size() == 14));\n\t\tEATEST_VERIFY((dErase[0] == value_type(3)));\n\t\tEATEST_VERIFY((dErase[13] == value_type(16)));\n\n\n\t\trB = dErase.rend() - 1;\n\t\tdErase.erase(rB);\n\t\tEATEST_VERIFY((dErase.size() == 13));\n\t\tEATEST_VERIFY((dErase[0] == value_type(4)));\n\t\tEATEST_VERIFY((dErase[12] == value_type(16)));\n\n\n\t\trB = dErase.rbegin();\n\t\tdErase.erase(rB);\n\t\tEATEST_VERIFY((dErase.size() == 12));\n\t\tEATEST_VERIFY((dErase[0] == value_type(4)));\n\t\tEATEST_VERIFY((dErase[11] == value_type(15)));\n\n\n\t\trA = dErase.rbegin();\n\t\trB = dErase.rend();\n\t\tdErase.erase(rA, rB);\n\t\tEATEST_VERIFY(dErase.size() == 0);\n\t}\n\n\n\tEATEST_VERIFY(TestObject::sTOCount == 0);\n\tEATEST_VERIFY(TestObject::sMagicErrorCount == 0);\n\n\treturn nErrorCount;\n}\n\n\nint TestDeque()\n{\n\tint nErrorCount = 0;\n\n\t{   // Test construction\n\t\tnErrorCount += TestDequeConstruction<IntDeque>();\n\t\tnErrorCount += TestDequeConstruction<IntDeque1>();\n\t\tnErrorCount += TestDequeConstruction<IntDeque32768>();\n\n\t\tnErrorCount += TestDequeConstruction<TestObjectDeque>();\n\t\tnErrorCount += TestDequeConstruction<TestObjectDeque1>();\n\t\tnErrorCount += TestDequeConstruction<TestObjectDeque32768>();\n\t}\n\n\t{   // Test simple mutating functionality.\n\t\tnErrorCount += TestDequeSimpleMutation<IntDeque>();\n\t\tnErrorCount += TestDequeSimpleMutation<IntDeque1>();\n\t\tnErrorCount += TestDequeSimpleMutation<IntDeque32768>();\n\n\t\tnErrorCount += TestDequeSimpleMutation<TestObjectDeque>();\n\t\tnErrorCount += TestDequeSimpleMutation<TestObjectDeque1>();\n\t\tnErrorCount += TestDequeSimpleMutation<TestObjectDeque32768>();\n\t}\n\n\t{   // Test complex mutating functionality.\n\t\tnErrorCount += TestDequeComplexMutation<IntDeque>();\n\t\tnErrorCount += TestDequeComplexMutation<IntDeque1>();\n\t\tnErrorCount += TestDequeComplexMutation<IntDeque32768>();\n\n\t\tnErrorCount += TestDequeComplexMutation<TestObjectDeque>();\n\t\tnErrorCount += TestDequeComplexMutation<TestObjectDeque1>();\n\t\tnErrorCount += TestDequeComplexMutation<TestObjectDeque32768>();\n\t}\n\n\t// test deque support of move-only types\n\t{\n\t\t{\n\t\t\teastl::deque<MoveAssignable> d;\n\t\t\tEATEST_VERIFY(d.emplace_back(MoveAssignable::Create()).value == 42);\n\t\t\tEATEST_VERIFY(d.emplace_front(MoveAssignable::Create()).value == 42);\n\n\t\t\tauto cd = eastl::move(d);\n\t\t\tEATEST_VERIFY( d.size() == 0);\n\t\t\tEATEST_VERIFY(cd.size() == 2);\n\t\t}\n\n\t\t{\n\t\t\teastl::deque<MoveAssignable> from;\n\t\t\tfrom.emplace_back(MoveAssignable::Create());\n\t\t\t\n\t\t\teastl::deque<MoveAssignable> to;\n\t\t\tto = eastl::move(from);\n\n\t\t\tEATEST_VERIFY(from.empty());\n\t\t\tEATEST_VERIFY(!to.empty());\n\t\t}\n\n\t\t{\n\t\t\t// User regression but passing end() to deque::erase is not valid.  \n\t\t\t// Iterator passed to deque::erase but must valid and dereferencable.\n\t\t\t//\n\t\t\t// eastl::deque<MoveAssignable> d;  // empty deque\n\t\t\t// d.erase(d.begin());\n\t\t\t// EATEST_VERIFY(d.size() == 0);\n\t\t}\n\n\t\t// simply test the basic api of deque with a move-only type\n\t\t{\n\t\t\teastl::deque<MoveAssignable> d;\n\n\t\t\t// emplace_back\n\t\t\tEATEST_VERIFY(d.emplace_back(MoveAssignable::Create()).value == 42);\n\t\t\tEATEST_VERIFY(d.emplace_back(MoveAssignable::Create()).value == 42);\n\t\t\tEATEST_VERIFY(d.emplace_back(MoveAssignable::Create()).value == 42);\n\n\t\t\t// erase\n\t\t\td.erase(d.begin());\n\t\t\tEATEST_VERIFY(d.size() == 2);\n\n\t\t\t// at / front / back / operator[]\n\t\t\tEATEST_VERIFY(d[0].value == 42);\n\t\t\tEATEST_VERIFY(d.at(0).value == 42);\n\t\t\tEATEST_VERIFY(d.front().value == 42);\n\t\t\tEATEST_VERIFY(d.back().value == 42);\n\n\t\t\t// clear\n\t\t\td.clear();\n\t\t\tEATEST_VERIFY(d.size() == 0);\n\n\t\t\t// emplace\n\t\t\td.emplace(d.begin(), MoveAssignable::Create());\n\t\t\td.emplace(d.begin(), MoveAssignable::Create());\n\t\t\tEATEST_VERIFY(d.size() == 2);\n\n\t\t\t// pop_back\n\t\t\td.pop_back();\n\t\t\tEATEST_VERIFY(d.size() == 1);\n\n\t\t\t// push_back / push_front / resize requires T be 'CopyConstructible' \n\n\t\t\t{\n\t\t\t\teastl::deque<MoveAssignable> swapped_d;\n\n\t\t\t\t// emplace_front\n\t\t\t\tEATEST_VERIFY(swapped_d.emplace_front(MoveAssignable::Create()).value == 42);\n\t\t\t\tEATEST_VERIFY(swapped_d.emplace_front(MoveAssignable::Create()).value == 42);\n\t\t\t\tEATEST_VERIFY(swapped_d.emplace_front(MoveAssignable::Create()).value == 42);\n\n\t\t\t\t// swap\n\t\t\t\tswapped_d.swap(d);\n\t\t\t\tEATEST_VERIFY(swapped_d.size() == 1);\n\t\t\t\tEATEST_VERIFY(d.size() == 3);\n\t\t\t}\n\n\t\t\t// pop_front\n\t\t\td.pop_front();\n\t\t\tEATEST_VERIFY(d.size() == 2);\n\n\t\t\t// insert\n\t\t\td.insert(d.end(), MoveAssignable::Create());\n\t\t\tEATEST_VERIFY(d.size() == 3);\n\t\t}\n\t}\n\n\t{\n\t\t// deque(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_DEQUE_DEFAULT_ALLOCATOR);\n\t\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t\t// void assign(std::initializer_list<value_type> ilist);\n\t\t// iterator insert(iterator position, std::initializer_list<value_type> ilist);\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\teastl::deque<int> intDeque = { 0, 1, 2 };\n\t\t\tEATEST_VERIFY(VerifySequence(intDeque, { 0, 1, 2 }, \"deque std::initializer_list\"));\n\n\t\t\tintDeque = { 13, 14, 15 };\n\t\t\tEATEST_VERIFY(VerifySequence(intDeque, { 13, 14, 15 }, \"deque std::initializer_list\"));\n\n\t\t\tintDeque.assign({ 16, 17, 18 });\n\t\t\tEATEST_VERIFY(VerifySequence(intDeque, { 16, 17, 18 }, \"deque std::initializer_list\"));\n\n\t\t\teastl::deque<int>::iterator it = intDeque.insert(intDeque.begin(), { 14, 15 });\n\t\t\tEATEST_VERIFY(VerifySequence(intDeque, { 14, 15, 16, 17, 18 }, \"deque std::initializer_list\"));\n\t\t\tEATEST_VERIFY(*it == 14);\n\t\t#endif\n\t}\n\n\n\t{   // C++11 functionality\n\t\t// deque(this_type&& x);\n\t\t// deque(this_type&& x, const allocator_type& allocator);\n\t\t// this_type& operator=(this_type&& x);\n\t\t// void push_front(value_type&& value);\n\t\t// void push_back(value_type&& value);\n\t\t// iterator insert(const_iterator position, value_type&& value);\n\n\t\tusing namespace eastl;\n\n\t\tdeque<TestObject> deque3TO33(3, TestObject(33));\n\t\tdeque<TestObject> toDequeA(eastl::move(deque3TO33));\n\t\tEATEST_VERIFY((toDequeA.size() == 3) && (toDequeA.front().mX == 33) && (deque3TO33.size() == 0));\n\n\t\t// The following is not as strong a test of this ctor as it could be. A stronger test would be to use IntanceAllocator with different instances.\n\t\tdeque<TestObject, MallocAllocator> deque4TO44(4, TestObject(44));\n\t\tdeque<TestObject, MallocAllocator> toDequeB(eastl::move(deque4TO44), MallocAllocator());\n\t\tEATEST_VERIFY((toDequeB.size() == 4) && (toDequeB.front().mX == 44) && (deque4TO44.size() == 0));\n\n\t\tdeque<TestObject, MallocAllocator> deque5TO55(5, TestObject(55));\n\t\ttoDequeB = eastl::move(deque5TO55);\n\t\tEATEST_VERIFY((toDequeB.size() == 5) && (toDequeB.front().mX == 55) && (deque5TO55.size() == 0));\n\t}\n\n\n\t{   // C++11 functionality\n\t\t// template<class... Args>\n\t\t// iterator emplace(const_iterator position, Args&&... args);\n\n\t\t// template<class... Args>\n\t\t// void emplace_front(Args&&... args);\n\n\t\t// template<class... Args>\n\t\t// void emplace_back(Args&&... args);\n\t\tTestObject::Reset();\n\n\t\tdeque<TestObject, eastl::allocator, 16> toDequeA;\n\n\t\tEATEST_VERIFY(toDequeA.emplace_back(2, 3, 4).mX == (2 + 3 + 4));\n\t\tEATEST_VERIFY_F((toDequeA.size() == 1) && (toDequeA.back().mX == (2+3+4)) && (TestObject::sTOCtorCount == 1), \"size: %u, mX: %u, count: %d\", (unsigned)toDequeA.size(), (unsigned)toDequeA.back().mX, (int)TestObject::sTOCtorCount);\n\n\t\ttoDequeA.emplace(toDequeA.begin(), 3, 4, 5);                                                              // This is 3 because of how subarray allocation works.\n\t\tEATEST_VERIFY_F((toDequeA.size() == 2) && (toDequeA.front().mX == (3+4+5)) && (TestObject::sTOCtorCount == 3), \"size: %u, mX: %u, count: %d\", (unsigned)toDequeA.size(), (unsigned)toDequeA.front().mX, (int)TestObject::sTOCtorCount);\n\n\t\tEATEST_VERIFY(toDequeA.emplace_front(6, 7, 8).mX == (6 + 7 + 8));\n\t\tEATEST_VERIFY_F((toDequeA.size() == 3) && (toDequeA.front().mX == (6+7+8)) && (TestObject::sTOCtorCount == 4), \"size: %u, mX: %u, count: %d\", (unsigned)toDequeA.size(), (unsigned)toDequeA.front().mX, (int)TestObject::sTOCtorCount);\n\n\n\t\t// This test is similar to the emplace pathway above. \n\t\tTestObject::Reset();\n\n\t\t//void push_front(T&& x);\n\t\t//void push_back(T&& x);\n\t\t//iterator insert(const_iterator position, T&& x);\n\n\t\tdeque<TestObject, eastl::allocator, 16> toDequeC; // Specify a non-small kSubarrayCount of 16 because the move count tests below assume there is no reallocation.\n\n\t\ttoDequeC.push_back(TestObject(2, 3, 4));\n\t\tEATEST_VERIFY((toDequeC.size() == 1) && (toDequeC.back().mX == (2+3+4)) && (TestObject::sTOMoveCtorCount == 1));\n\n\t\ttoDequeC.insert(toDequeC.begin(), TestObject(3, 4, 5));\n\t\tEATEST_VERIFY((toDequeC.size() == 2) && (toDequeC.front().mX == (3+4+5)) && (TestObject::sTOMoveCtorCount == 3));\n\n\t\ttoDequeC.push_front(TestObject(6, 7, 8));\n\t\tEATEST_VERIFY((toDequeC.size() == 3) && (toDequeC.front().mX == (6+7+8)) && (TestObject::sTOMoveCtorCount == 4));\n\t}\n\n\n\t{\n\t\t// Regression of deque::operator= for the case of EASTL_ALLOCATOR_COPY_ENABLED=1\n\t\t// For this test we need to use InstanceAllocator to create two containers of the same\n\t\t// type but with different and unequal allocator instances. The bug was that when \n\t\t// EASTL_ALLOCATOR_COPY_ENABLED was enabled operator=(this_type& x) assigned x.mAllocator\n\t\t// to this and then proceeded to assign member elements from x to this. That's invalid \n\t\t// because the existing elements of this were allocated by a different allocator and \n\t\t// will be freed in the future with the allocator copied from x. \n\t\t// The test below should work for the case of EASTL_ALLOCATOR_COPY_ENABLED == 0 or 1.\n\t\t{\n\t\t\tInstanceAllocator ia0((uint8_t)0);\n\t\t\tInstanceAllocator ia1((uint8_t)1);\n\n\t\t\teastl::deque<int, InstanceAllocator> v0((eastl_size_t)1, (int)0, ia0);\n\t\t\teastl::deque<int, InstanceAllocator> v1((eastl_size_t)1, (int)1, ia1);\n\n\t\t\tEATEST_VERIFY((v0.front() == 0) && (v1.front() == 1));\n\t\t\tEATEST_VERIFY(v0.get_allocator() != v1.get_allocator());\n\t\t\tv0 = v1;\n\t\t\tEATEST_VERIFY((v0.front() == 1) && (v1.front() == 1));\n\t\t\tEATEST_VERIFY(v0.validate());\n\t\t\tEATEST_VERIFY(v1.validate());\n\t\t\tbool allocatorsEqual = v0.get_allocator() == v1.get_allocator();\n\t\t\tEATEST_VERIFY(allocatorsEqual == (bool)EASTL_ALLOCATOR_COPY_ENABLED);\n\n\t\t\t// destroying containers to invoke InstanceAllocator::deallocate() checks\n\t\t}\n\n\t\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t\t                  \"Container elements should be deallocated by the allocator that allocated it.\");\n\t}\n\n\n\t{   // Regression of kDequeSubarraySize calculations\n\t\tEATEST_VERIFY(IntDeque::kSubarraySize      >= 4);\n\t\tEATEST_VERIFY(IntDeque1::kSubarraySize     == 1);\n\t\tEATEST_VERIFY(IntDeque32768::kSubarraySize == 32768);\n\n\t\tEATEST_VERIFY(TestObjectDeque::kSubarraySize       >= 2);\n\t\tEATEST_VERIFY(TestObjectDeque1::kSubarraySize      == 1);\n\t\tEATEST_VERIFY(TestObjectDeque32768::kSubarraySize  == 32768);\n\t}\n\n\n\t{   // Regression of user-reported bug\n\n\t\t// The following was reported by Nicolas Mercier on April 9, 2008 as causing a crash:\n\t\t//     This code breaks on our machines because it overwrites the \n\t\t//     first 4 bytes before the beginning of the memory that was \n\t\t//     allocated for mpPtrArray. So when temp goes out of scope, \n\t\t//     it will free this pointer and the debug allocator will detect \n\t\t//     that these bytes have been changed.\n\n\t\teastl::deque<eastl::string> testArray;\n\t\teastl::string s(\"a\");\n\n\t\tfor(int j = 0; j < 65; j++)\n\t\t\ttestArray.push_back(s);\n\n\t\teastl::deque<eastl::string> temp;\n\t\ttemp = testArray;                     // This is where the corruption occurred.\n\t}\n\n\n\t{   // Regression of user-reported bug\n\n\t\t// The problem is that the pointer arrays on the deques are growing without bound. \n\t\t// This is causing our game to crash on a soak test due to its frame event queues \n\t\t// consuming inordinate amounts of memory. It looks like the current version of \n\t\t// eastl::deque is missing logic to recenter the pointer array, so it keeps growing \n\t\t// slowly as blocks are allocated on the tail and removed from the head. \n\t\t// Note: This bug was introduced by the (mistaken) fix for April 9 bug above.\n\n\t\teastl::deque<int, MallocAllocator> x;\n\t\teastl::deque<int, MallocAllocator> y;\n\n\t\tconst MallocAllocator& maX = x.get_allocator();\n\t\tconst MallocAllocator& maY = y.get_allocator();\n\n\t\tsize_t allocVolumeX1 = 0;\n\t\tsize_t allocVolumeY1 = 0;\n\t\tsize_t allocVolumeX2 = 0;\n\t\tsize_t allocVolumeY2 = 0;\n\n\t\tfor(int i = 0; i < 1001; ++i)  // With the bug, each time through this loop the containers mistakenly allocate more memory.\n\t\t{\n\t\t\tif(i == 100) // Save the allocated volume after 50 iterations.\n\t\t\t{\n\t\t\t\tallocVolumeX1 = maX.mAllocVolume;\n\t\t\t\tallocVolumeY1 = maY.mAllocVolume;\n\t\t\t}\n\n\t\t\tfor(int j = 0; j < 5; ++j)\n\t\t\t\tx.push_back(0);\n\n\t\t\tx.swap(y);\n\n\t\t\twhile(!x.empty())\n\t\t\t\tx.pop_front();\n\t\t}\n\n\t\tallocVolumeX2 = maX.mAllocVolume; // Save the allocated volume after 1001 iterations.\n\t\tallocVolumeY2 = maY.mAllocVolume;\n\n\t\tEATEST_VERIFY((allocVolumeX1 == allocVolumeX2) && (allocVolumeX2 < 350));  // Test that the volume has not changed and is below some nominal value.\n\t\tEATEST_VERIFY((allocVolumeY1 == allocVolumeY2) && (allocVolumeY2 < 350));  // This value is somewhat arbitrary and slightly hardware dependent (e.g. 32 vs. 64 bit). I bumped it up from 300 to 350 when Linux64 showed it to be 320, which was ~still OK.\n\t}\n\n\n\t{ // Regression to verify that const deque works.\n\t\tconst eastl::deque<int> constIntDeque1;\n\t\tEATEST_VERIFY(constIntDeque1.empty());\n\n\t\tint intArray[3] = { 37, 38, 39 };\n\t\tconst eastl::deque<int> constIntDeque2(intArray, intArray + 3);\n\t\tEATEST_VERIFY(constIntDeque2.size() == 3);\n\n\t\tconst eastl::deque<int> constIntDeque3(4, 37);\n\t\tEATEST_VERIFY(constIntDeque3.size() == 4);\n\n\t\tconst eastl::deque<int> constIntDeque4;\n\t\tconst eastl::deque<int> constIntDeque5 = constIntDeque4;\n\t}\n\n\t{\n\t\t// test shrink_to_fit \n\t\teastl::deque<int, CountingAllocator> d(4096);\n\t\td.erase(d.begin(), d.end());\n\n\t\tauto prev = d.get_allocator().getActiveAllocationSize();\n\t\td.shrink_to_fit();\n\t\tEATEST_VERIFY(d.get_allocator().getActiveAllocationSize() < prev);\n\t}\n\n\t{\n\t#ifndef EASTL_OPENSOURCE\n\t\tauto prevAllocCount = gEASTLTest_AllocationCount.load(eastl::memory_order_relaxed);\n\t#endif\n\t\t{\n\t\t\tEA_DISABLE_VC_WARNING(4625 4626)\n\t\t\tstruct a\n\t\t\t{\n\t\t\t\ta(int* p)\n\t\t\t\t\t: ptr(p) { }\n\n\t\t\t\teastl::unique_ptr<int> ptr;\n\t\t\t};\n\t\t\tEA_RESTORE_VC_WARNING()\n\n\t\t\tstatic_assert(eastl::is_trivial<a>::value == false, \"failure\");\n\t\t\tstatic_assert(eastl::is_trivially_constructible<a>::value == false, \"failure\");\n\t\t\tstatic_assert(eastl::is_trivially_copyable<a>::value == false, \"failure\");\n\n\t\t\teastl::deque<a> d;\n\n\t\t\tEATEST_VERIFY(*d.emplace_back(new int(1)).ptr == 1);\n\t\t\tEATEST_VERIFY(*d.emplace_back(new int(2)).ptr == 2);\n\t\t\tEATEST_VERIFY(*d.emplace_back(new int(3)).ptr == 3);\n\n\t\t\td.erase(d.begin() + 1);\n\t\t}\n\t#ifndef EASTL_OPENSOURCE\n\t\tEATEST_VERIFY(gEASTLTest_AllocationCount.load(eastl::memory_order_relaxed) == prevAllocCount);\n\t#endif\n\t}\n\n\n\t{ // Test erase / erase_if\n\t\t{\n\t\t\teastl::deque<int> d = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t\tauto numErased = eastl::erase(d, 2);\n\t\t\tEATEST_VERIFY((d == eastl::deque<int>{1, 3, 4, 5, 6, 7, 8, 9}));\n\t\t    EATEST_VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(d, 7);\n\t\t\tEATEST_VERIFY((d == eastl::deque<int>{1, 3, 4, 5, 6, 8, 9}));\n\t\t    EATEST_VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(d, 9);\n\t\t\tEATEST_VERIFY((d == eastl::deque<int>{1, 3, 4, 5, 6, 8}));\n\t\t    EATEST_VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(d, 5);\n\t\t\tEATEST_VERIFY((d == eastl::deque<int>{1, 3, 4, 6, 8}));\n\t\t    EATEST_VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(d, 3);\n\t\t\tEATEST_VERIFY((d == eastl::deque<int>{1, 4, 6, 8}));\n\t\t    EATEST_VERIFY(numErased == 1);\n\t\t}\n\n\t\t{\n\t\t\teastl::deque<int> d = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tauto numErased = eastl::erase_if(d, [](auto i) { return i % 2 == 0; });\n\t\t\tEATEST_VERIFY((d == eastl::deque<int>{1, 3, 5, 7, 9}));\n\t\t    EATEST_VERIFY(numErased == 4);\n\t\t}\n\t}\n\n\t// Tests for erase_unordered\n\t{\n\t\t{\n\t\t\teastl::deque<int> vec = {0, 1, 2, 3};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 1);\n\t\t\tEATEST_VERIFY(numErased == 1);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 3, 2}, \"erase_unordered\") );\n\t\t}\n\t\t{\n\t\t\teastl::deque<int> vec = {};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 42);\n\t\t\tEATEST_VERIFY(numErased == 0);\n\t\t\tEATEST_VERIFY(vec.size() == 0);\n\t\t}\n\t\t// The following test checks that the correct implementation is called for deque by checking the order\n\t\t// of the remaining values. It is not a strict requirement that they have this order but it\n\t\t// is expected to be the result based on that it minimizes the amount of work.\n\t\t{\n\t\t\teastl::deque<int> vec = {0, 1, 2, 3, 1, 5, 6, 1, 8, 9};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 1);\n\t\t\tEATEST_VERIFY(numErased == 3);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 9, 2, 3, 8, 5, 6}, \"erase_unordered\") );\n\t\t}\n\t}\n\n\t// Tests for erase_unordered_if\n\t{\n\t\t{\n\t\t\teastl::deque<int> vec = {0, 1, 2, 3};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 2);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 2}, \"erase_unordered_if\") );\n\t\t}\n\t\t{\n\t\t\teastl::deque<int> vec = {};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 0);\n\t\t\tEATEST_VERIFY(vec.size() == 0);\n\t\t}\n\t\t// The following test checks that the correct implementation is called for deque by checking the order\n\t\t// of the remaining values. It is not a strict requirement that they have this order but it\n\t\t// is expected to be the result based on that it minimizes the amount of work.\n\t\t{\n\t\t\teastl::deque<int> vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 5);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 8, 2, 6, 4}, \"erase_unordered_if\") );\n\t\t}\n\t}\n\n\t{\n\t\teastl::deque<TriviallyCopyableWithCopy> d1;\n\t\teastl::deque<TriviallyCopyableWithCopy> d2{d1};\n\t}\n\n\t{\n\t\teastl::deque<TriviallyCopyableWithMove> d1;\n\t\teastl::deque<TriviallyCopyableWithMove> d2{ eastl::move(d1) };\n\t}\n\n\t{\n\t\t// unusual type - not well supported: eastl containers implicitly assume that ctor and operator= are both defined.\n\t\teastl::deque<TriviallyCopyableWithCopyCtor> d1;\n\t\teastl::deque<TriviallyCopyableWithCopyCtor> d2{ d1 };\n\t}\n\n\t{\n\t\t// unusual type - not well supported: eastl containers implicitly assume that ctor and operator= are both defined.\n\t\teastl::deque<TriviallyCopyableWithMoveCtor> d1;\n\t\teastl::deque<TriviallyCopyableWithMoveCtor> d2{ eastl::move(d1) };\n\t}\n\n\t{\n\t\t// our deque implementation always has allocations. this set_allocator() is unlike other container's set_allocator() member function in that it\n\t\t// actually frees allocations when assigning the allocator. this lack of consistency is unfortunate.\n\t\teastl::deque<TestObject, InstanceAllocator, 16> d(0, TestObject(), InstanceAllocator(1));\n\t\td.set_allocator(InstanceAllocator(2));\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\n\t{ // Test <=>\n\t    eastl::deque<int> d1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t    eastl::deque<int> d2 = {9, 8, 7, 6, 5, 4, 3, 2, 1};\n\t    eastl::deque<int> d3 = {1, 2, 3, 4, 5};\n\t    eastl::deque<int> d4 = {10};\n\n\t\tEATEST_VERIFY(d1 != d2);\n\t\tEATEST_VERIFY(d1 < d2);\n\t\tEATEST_VERIFY(d1 != d3);\n\t\tEATEST_VERIFY(d1 > d3);\n\t\tEATEST_VERIFY(d4 > d1);\n\t\tEATEST_VERIFY(d4 > d2);\n\t\tEATEST_VERIFY(d4 > d3);\n\n\t\tEATEST_VERIFY((d1 <=> d2) != 0);\n\t\tEATEST_VERIFY((d1 <=> d2) < 0);\n\t\tEATEST_VERIFY((d1 <=> d3) != 0);\n\t\tEATEST_VERIFY((d1 <=> d3) > 0);\n\t\tEATEST_VERIFY((d4 <=> d1) > 0);\n\t\tEATEST_VERIFY((d4 <=> d2) > 0);\n\t\tEATEST_VERIFY((d4 <=> d3) > 0);\n\t}\n#endif\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestExpected.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n#include <EABase/eabase.h>\n\n// We use a few c++17 features in the implementation of eastl::expceted, so we only provide\n// it from c++17 onwards.\n#if EA_COMPILER_CPP17_ENABLED\n\n#include <EASTL/expected.h>\n#include <EASTL/unique_ptr.h>\n#include <EASTL/vector.h>\n\n#include \"EASTLTest.h\"\n\n\nusing namespace eastl;\n\nnamespace\n{\n\tenum class TestError\n\t{\n\t\tError1,\n\t\tError2,\n\t\tError3,\n\t};\n\n\t// TODO: Move some of these \"testing types\" to a common header, perhaps EASTLTest.h?\n\tstruct AggregateTest\n\t{\n\t\tint mX;\n\t\tint mY;\n\t};\n\n\tstruct Point\n\t{\n\t\tPoint(int x, int y) noexcept : mX{x}, mY{y} {};\n\t\tint mX{};\n\t\tint mY{};\n\t};\n\n\tstruct SomeClass\n\t{\n\t\tint mI{};\n\t};\n\n\tstruct ConversionTest\n\t{\n\t\tConversionTest(const SomeClass& s) : mI{s.mI} {}\n\t\tint mI{};\n\t};\n\n\tstruct DefaultConstructible\n\t{\n\t\tstatic constexpr int DefaultID = 10;\n\t\tDefaultConstructible() : mId(DefaultID){};\n\t\tint mId;\n\t};\n\n\tstruct NoDefaultConstructible\n\t{\n\t\tNoDefaultConstructible(int i) : mId(i){};\n\t\tint mId;\n\t};\n\n\tstruct NoCopyConstructible\n\t{\n\t\tNoCopyConstructible() = default;\n\t\tNoCopyConstructible(const NoCopyConstructible&) = delete;\n\t\tNoCopyConstructible(NoCopyConstructible&&) = default;\n\t};\n\n\tstruct CopyNoMove\n\t{\n\t\tCopyNoMove() = default;\n\t\tCopyNoMove(const CopyNoMove&) = default;\n\t\tCopyNoMove(CopyNoMove&&) = delete;\n\t};\n\n\tstruct MoveNoCopy\n\t{\n\t\tMoveNoCopy() = default;\n\t\tMoveNoCopy(const MoveNoCopy&) = delete;\n\t\tMoveNoCopy(MoveNoCopy&&) = default;\n\t};\n\n\tstruct NoTriviallyCopyable\n\t{\n\t\tNoTriviallyCopyable() = default;\n\t\tNoTriviallyCopyable(int i) : mId{i} {}\n\t\tNoTriviallyCopyable(const NoTriviallyCopyable& other) { mId = other.mId; }\n\t\tint mId{};\n\t};\n\n\tstruct NoTriviallyDestructible\n\t{\n\t\t~NoTriviallyDestructible() { ++mId; }\n\n\tpublic:\n\t\tint mId{};\n\t};\n\n\tstruct NoTriviallyCopyableNoDefaultConstructible\n\t{\n\t\tNoTriviallyCopyableNoDefaultConstructible() = delete;\n\t\tNoTriviallyCopyableNoDefaultConstructible(int i) : mId(i) {}\n\t\tNoTriviallyCopyableNoDefaultConstructible(const NoTriviallyCopyableNoDefaultConstructible& other)\n\t\t{\n\t\t\tmId = other.mId;\n\t\t}\n\t\tint mId{};\n\t};\n\n\tstruct NoImplilcitIntConversion\n\t{\n\t\texplicit NoImplilcitIntConversion(int i) : mId(i) {}\n\t\tint mId;\n\t};\n\n\tstruct ImplilcitIntConversion\n\t{\n\t\tImplilcitIntConversion(int i) : mId(i) {}\n\t\tint mId;\n\t};\n\n\tstruct CopyAssignableNoMoveAssignable\n\t{\n\t\tCopyAssignableNoMoveAssignable() = default;\n\t\tCopyAssignableNoMoveAssignable(const CopyAssignableNoMoveAssignable&) = default;\n\t\tCopyAssignableNoMoveAssignable(CopyAssignableNoMoveAssignable&&) = delete;\n\t\tCopyAssignableNoMoveAssignable& operator=(const CopyAssignableNoMoveAssignable&) = default;\n\t\tCopyAssignableNoMoveAssignable& operator=(CopyAssignableNoMoveAssignable&&) = delete;\n\t};\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tstruct ThrowOnMoveOrCopy\n\t{\n\t\tThrowOnMoveOrCopy() = default;\n\t\tThrowOnMoveOrCopy(const ThrowOnMoveOrCopy& x)\n\t\t{\n\t\t\tif (x.mShouldThrow)\n\t\t\t\tthrow 0;\n\t\t}\n\t\tThrowOnMoveOrCopy(ThrowOnMoveOrCopy&& x)\n\t\t{\n\t\t\tif (x.mShouldThrow)\n\t\t\t\tthrow 1;\n\t\t}\n\t\tThrowOnMoveOrCopy& operator=(const ThrowOnMoveOrCopy& x)\n\t\t{\n\t\t\tif (x.mShouldThrow)\n\t\t\t\tthrow 2;\n\t\t\treturn *this;\n\t\t}\n\t\tThrowOnMoveOrCopy& operator=(ThrowOnMoveOrCopy&& x)\n\t\t{\n\t\t\tif (x.mShouldThrow)\n\t\t\t\tthrow 3;\n\t\t\treturn *this;\n\t\t}\n\t\tbool mShouldThrow{};\n\t};\n#endif\n\n\tstruct ClearOnMove\n\t{\n\t\tClearOnMove() = default;\n\t\tClearOnMove(int i) : mId{i} {}\n\t\tClearOnMove(const ClearOnMove&) = default;\n\t\tClearOnMove(ClearOnMove&& other) noexcept : mId{other.mId} { other.mId = 0; }\n\t\tClearOnMove& operator=(const ClearOnMove&) = default;\n\t\tClearOnMove& operator=(ClearOnMove&& other) noexcept\n\t\t{\n\t\t\tmId = other.mId;\n\t\t\tother.mId = 0;\n\t\t\treturn *this;\n\t\t};\n\t\tint mId;\n\t};\n\n\ttemplate <class T>\n\tstruct InitListTest\n\t{\n\t\tInitListTest(std::initializer_list<T> il) noexcept : mVec(il){};\n\t\teastl::vector<T> mVec;\n\t};\n\n\ttemplate <class T, class Value, class Error, template <class> class... Rest>\n\tstruct ExpectedTypeTraitsChecker : eastl::true_type\n\t{\n\t};\n\n\ttemplate <class T, class Value, class Error, template <class> class Trait, template <class> class... Rest>\n\tstruct ExpectedTypeTraitsChecker<T, Value, Error, Trait, Rest...>\n\t{\n\t\tstatic_assert(Trait<T>::value == Trait<eastl::expected<Value, Error>>::value);\n\t\tstatic constexpr bool value = (Trait<T>::value == Trait<eastl::expected<Value, Error>>::value) &&\n\t\t                              ExpectedTypeTraitsChecker<T, Value, Error, Rest...>::value;\n\t};\n\n\n\ttemplate <class T>\n\tconstexpr bool CheckExpectedValueTypeTraits = ExpectedTypeTraitsChecker<\n\t    T,   // This is the type to test against.\n\t    T,   // This is the value type\n\t    int, // This is the error type\n\t    eastl::is_default_constructible,\n\t    eastl::is_copy_constructible,\n\t    eastl::is_move_constructible,\n\t    eastl::is_trivially_copy_constructible,\n\t    eastl::is_trivially_move_constructible,\n\t    // clang-format off\n\t    // in the standard, this one is more strict for expected than for the template type parameters\n\t    // eastl::is_copy_assignable,\n\t    // in the standard, this one is more strict for expected than for the template type parameters\n\t    // eastl::is_move_assignable,\n\t    // no specification about when assignment is trivial\n\t    // eastl::is_trivially_copy_assignable,\n\t    // no specification about when assignment is trivial\n\t    // eastl::is_trivially_move_assignable,\n\t    // clang-format on\n\t    eastl::is_trivially_destructible>::value;\n\n\ttemplate <class T>\n\tconstexpr bool CheckExpectedErrorTypeTraits =\n\t    ExpectedTypeTraitsChecker<\n\t        T,   // This is the type to test against.\n\t        int, // This is the value type\n\t        T,   // This is the error type\n\t        // clang-format off\n\t\t\t// if the value is default constructible, expected should be as well, this check is below.\n\t    \t// eastl::is_default_constructible,\n\t        // clang-format on\n\t        eastl::is_copy_constructible,\n\t        eastl::is_move_constructible,\n\t        eastl::is_trivially_copy_constructible,\n\t        eastl::is_trivially_move_constructible,\n\t        // clang-format off\n\t    \t// in the standard, this one is more strict for expected than for the template type parameters\n\t    \t// eastl::is_copy_assignable,\n\t    \t// in the standard, this one is more strict for expected than for the template type parameters\n\t    \t// eastl::is_move_assignable,\n\t    \t// no specification about when assignment is trivial\n\t    \t// eastl::is_trivially_copy_assignable,\n\t    \t// no specification about when assignment is trivial\n\t    \t// eastl::is_trivially_move_assignable,\n\t        // clang-format on\n\t        eastl::is_trivially_destructible>::value &&\n\t    // This just checks expected<int, T> is default constructible.\n\t    ExpectedTypeTraitsChecker<int, int, T, eastl::is_default_constructible>::value;\n\n\n\ttemplate <class T>\n\tconstexpr bool CheckExpectedTypeTraits = CheckExpectedValueTypeTraits<T> && CheckExpectedErrorTypeTraits<T>;\n\n\ttemplate <class T>\n\tconstexpr bool CheckExpectedVoidTypeTraits =\n\t    ExpectedTypeTraitsChecker<T,    // This is the type to test against.\n\t                              void, // This is the value type\n\t                              T,    // This is the error type\n\t                              eastl::is_copy_constructible,\n\t                              eastl::is_move_constructible,\n\t                              eastl::is_trivially_copy_constructible,\n\t                              eastl::is_trivially_move_constructible,\n\t                              eastl::is_trivially_destructible>::value &&\n\t    // This just checks expected<void, T> is default constructible.\n\t    ExpectedTypeTraitsChecker<int, void, T, eastl::is_default_constructible>::value;\n\n} // namespace\n\nint TestUnexpected()\n{\n\tint nErrorCount = 0;\n\t{\n\t\t// simple construction and getter.\n\t\teastl::unexpected<int> u(1);\n\t\tEATEST_VERIFY(u.error() == 1);\n\t\teastl::unexpected<float> v(2.0f);\n\t\tEATEST_VERIFY(v.error() == 2.0f);\n\t\teastl::unexpected<TestError> w(TestError::Error1);\n\t\tEATEST_VERIFY(w.error() == TestError::Error1);\n\t\tw.error() = TestError::Error2;\n\t\tEATEST_VERIFY(w.error() == TestError::Error2);\n\t\teastl::unexpected<Point> x(Point{1, 2});\n\t\tEATEST_VERIFY(x.error().mX == 1 && x.error().mY == 2);\n\t}\n\n\t{\n\t\t// in place construction.\n\t\teastl::unexpected<Point> u(eastl::in_place, 1, 2);\n\t\tEATEST_VERIFY(u.error().mX == 1 && u.error().mY == 2);\n\t}\n\n#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t{\n\t\t// initializer_list construction (how is this different than the normal in place construction?)\n\t\teastl::unexpected<InitListTest<int>> u(eastl::in_place, {1, 2, 3, 4});\n\t\teastl::vector<int> v = {1, 2, 3, 4};\n\t\tEATEST_VERIFY(u.error().mVec == v);\n\t}\n#endif\n\n\t{\n\t\t// swap\n\t\teastl::unexpected<int> u(1);\n\t\teastl::unexpected<int> v(2);\n\t\tswap(u, v);\n\t\tEATEST_VERIFY(u.error() == 2);\n\t\tEATEST_VERIFY(v.error() == 1);\n\t}\n\n\t{\n\t\t// operator ==\n\t\teastl::unexpected<int> u(1);\n\t\teastl::unexpected<int> v(2);\n\t\teastl::unexpected<int> w(2);\n\t\tEATEST_VERIFY(!(u == v));\n\t\tEATEST_VERIFY(w == v);\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestBadExpectedAccess()\n{\n\tint nErrorCount = 0;\n\n#if EASTL_EXCEPTIONS_ENABLED\n\t{\n\t\texpected<int, int> e{unexpect, 1};\n\t\tbool exceptionFired = false;\n\t\ttry\n\t\t{\n\t\t\te.value();\n\t\t}\n\t\tcatch (const bad_expected_access<int>& b)\n\t\t{\n\t\t\texceptionFired = true;\n\t\t\tEATEST_VERIFY(b.error() == 1);\n\t\t}\n\t\tEATEST_VERIFY(exceptionFired);\n\t}\n\n\t{\n\t\texpected<void, int> e{unexpect, 2};\n\t\tbool exceptionFired = false;\n\t\ttry\n\t\t{\n\t\t\te.value();\n\t\t}\n\t\tcatch (const bad_expected_access<int>& b)\n\t\t{\n\t\t\texceptionFired = true;\n\t\t\tEATEST_VERIFY(b.error() == 2);\n\t\t}\n\t\tEATEST_VERIFY(exceptionFired);\n\t}\n#endif\n\n\treturn nErrorCount;\n}\n\nint TestExpectedGeneric()\n{\n\tstatic_assert(CheckExpectedTypeTraits<int>);\n\tstatic_assert(CheckExpectedTypeTraits<DefaultConstructible>);\n\tstatic_assert(CheckExpectedTypeTraits<NoDefaultConstructible>);\n\tstatic_assert(CheckExpectedTypeTraits<NoCopyConstructible>);\n\tstatic_assert(CheckExpectedTypeTraits<NoTriviallyCopyable>);\n\tstatic_assert(CheckExpectedTypeTraits<NoTriviallyDestructible>);\n\tstatic_assert(CheckExpectedTypeTraits<NoTriviallyCopyableNoDefaultConstructible>);\n\tstatic_assert(CheckExpectedTypeTraits<MoveNoCopy>);\n\tstatic_assert(CheckExpectedTypeTraits<eastl::vector<int>>);\n\tstatic_assert(CheckExpectedTypeTraits<eastl::unique_ptr<int>>);\n\n\t// Note: even if a type has a deleted move constructor, it's\n\t// corresponding expected type should be both copy and move\n\t// constructible.\n\tstatic_assert(is_copy_constructible_v<expected<CopyNoMove, int>>);\n\tstatic_assert(is_move_constructible_v<expected<CopyNoMove, int>>);\n\tstatic_assert(is_copy_constructible_v<expected<int, CopyNoMove>>);\n\tstatic_assert(is_move_constructible_v<expected<int, CopyNoMove>>);\n\n\t// Note: even if a type has a deleted move assignment, it's\n\t// corresponding expected type should still be both copy and move\n\t// assignable.\n\tstatic_assert(is_copy_assignable_v<expected<CopyAssignableNoMoveAssignable, int>>);\n\tstatic_assert(is_move_assignable_v<expected<CopyAssignableNoMoveAssignable, int>>);\n\tstatic_assert(is_copy_assignable_v<expected<int, CopyAssignableNoMoveAssignable>>);\n\tstatic_assert(is_move_assignable_v<expected<int, CopyAssignableNoMoveAssignable>>);\n\n\tint nErrorCount = 0;\n\t{\n\t\t// default construction for default constructible type\n\t\texpected<int, TestError> e;\n\t\tEATEST_VERIFY(e.has_value());\n\n\t\t// check for value initialization of contained type.\n\t\tEATEST_VERIFY(e.value() == 0);\n\n\t\te.value() = 42;\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value() == 42);\n\n\t\t// copy constructor\n\t\texpected<int, TestError> e1{e};\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value() == 42);\n\n\t\t// copy assignement\n\t\texpected<int, TestError> e2{unexpect, TestError::Error2};\n\n\t\t// value->no_value\n\t\te1 = e2;\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY((e1.error() == TestError::Error2));\n\n\t\t// no_value->value;\n\t\te2 = e;\n\t\tEATEST_VERIFY(e2.has_value());\n\t\tEATEST_VERIFY(e2.value() == 42);\n\t}\n\n\t{\n\t\texpected<DefaultConstructible, TestError> e;\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e->mId == 10);\n\t}\n\n\t{\n\t\texpected<NoTriviallyCopyable, TestError> e{5};\n\t\texpected<NoTriviallyCopyable, TestError> e1 = e;\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value().mId == 5);\n\t}\n\n\t{\n\t\texpected<NoTriviallyCopyable, TestError> e{unexpect, TestError::Error3};\n\t\texpected<NoTriviallyCopyable, TestError> e1 = e;\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == TestError::Error3);\n\t}\n\n\n\t{\n\t\texpected<NoDefaultConstructible, TestError> e{2};\n\t\texpected<NoDefaultConstructible, TestError> e1 = e;\n\t\tEATEST_VERIFY(e1.value().mId == 2);\n\t}\n\n\t{\n\t\texpected<NoDefaultConstructible, NoDefaultConstructible> e{2};\n\t\tEATEST_VERIFY(e.has_value());\n\t\texpected<NoDefaultConstructible, NoDefaultConstructible> e1 = e;\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value().mId == 2);\n\t}\n\n\t{\n\t\texpected<NoTriviallyCopyableNoDefaultConstructible, NoTriviallyCopyableNoDefaultConstructible> e{2};\n\t\tEATEST_VERIFY(e.has_value());\n\t\texpected<NoTriviallyCopyableNoDefaultConstructible, NoTriviallyCopyableNoDefaultConstructible> e1 = e;\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value().mId == 2);\n\t}\n\n\t{\n\t\texpected<NoTriviallyCopyableNoDefaultConstructible, TestError> e{2};\n\t\tEATEST_VERIFY(e.has_value());\n\t\texpected<NoTriviallyCopyableNoDefaultConstructible, TestError> e1 = e;\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value().mId == 2);\n\t}\n\n\t{\n\t\texpected<NoCopyConstructible, TestError> e;\n\t\tEATEST_VERIFY(e.has_value());\n\t}\n\n\t{\n\t\teastl::vector<int> v = {1, 2, 3, 4};\n\t\texpected<eastl::vector<int>, TestError> e(v);\n\t\tEATEST_VERIFY(e.value() == v);\n\t\texpected<eastl::vector<int>, TestError> e1 = e;\n\t\tEATEST_VERIFY(e1.value() == v);\n\n\t\texpected<eastl::vector<int>, TestError> e2 = std::move(e);\n\t\tEATEST_VERIFY(e2.value() == v);\n\n\t\teastl::vector<int> v1 = {1, 2, 3, 4, 5, 6};\n\t\texpected<eastl::vector<int>, TestError> e3(v1);\n\t\te2 = e3;\n\t\tEATEST_VERIFY(e2.value() == v1);\n\n\t\te2 = std::move(e1);\n\t\tEATEST_VERIFY(e2.value() == v);\n\n\t\t// just check that we did in fact move from e1.\n\t\tEATEST_VERIFY(e1.value().size() == 0);\n\t}\n\n\t{\n\t\texpected<NoTriviallyCopyableNoDefaultConstructible, TestError> e(2);\n\t\tEATEST_VERIFY(e.value().mId == 2);\n\t\texpected<NoTriviallyCopyableNoDefaultConstructible, TestError> e1 = e;\n\t\tEATEST_VERIFY(e1.value().mId == 2);\n\t}\n\n\t{\n\t\t// implicit conversion\n\t\texpected<ImplilcitIntConversion, int> e = 1;\n\t\tEATEST_VERIFY(e.has_value());\n\t\t// explicit conversion\n\t\texpected<NoImplilcitIntConversion, int> e1(1);\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value().mId == e.value().mId);\n\t}\n\n\t{\n\t\t// check things work with move only types.\n\t\texpected<unique_ptr<int>, TestError> e(new int(2));\n\t\texpected<unique_ptr<int>, TestError> e1 = eastl::move(e);\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(*e1.value() == 2);\n\t\te1 = eastl::unexpected<TestError>(TestError::Error2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == TestError::Error2);\n\t\texpected<unique_ptr<int>, TestError> e3(new int(5));\n\t\tEATEST_VERIFY(e3.has_value());\n\t\tEATEST_VERIFY(*e3.value() == 5);\n\t\te3 = eastl::move(e1);\n\t\tEATEST_VERIFY(!e3.has_value());\n\t\tEATEST_VERIFY(e3.error() == TestError::Error2);\n\t}\n\n\t{\n\t\t// conversion between expected\n\t\texpected<unsigned int, unsigned int> e(1u);\n\t\texpected<int, int> e1(e);\n\t\tEATEST_VERIFY(e1.value() == 1);\n\t}\n\n\t{\n\t\t// conversion between expected\n\t\teastl::vector<int> v = {1, 2, 3, 4};\n\t\texpected<eastl::vector<int>, unsigned int> e(v);\n\t\texpected<eastl::vector<int>, int> e1(eastl::move(e));\n\t\tEATEST_VERIFY(e1.value() == v);\n\t}\n\n\t{\n\t\teastl::unexpected<TestError> unex(TestError::Error2);\n\t\texpected<int, TestError> e{unex};\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == TestError::Error2);\n\t}\n\n\t{\n\t\tvector<int> v = {1, 2, 3, 4};\n\t\texpected<int, vector<int>> e{eastl::unexpected<vector<int>>(v)};\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == v);\n\n\t\texpected<int, vector<int>> e1{eastl::move(e)};\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == v);\n\t}\n\n\t{\n\t\texpected<Point, int> e(in_place, 1, 2);\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value().mX == 1 && e.value().mY == 2);\n\t}\n\n\t{\n\t\texpected<int, Point> e(unexpect, 1, 2);\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error().mX == 1 && e.error().mY == 2);\n\t}\n\n\t{\n\t\texpected<vector<int>, int> e(in_place, {1, 2, 3, 4});\n\t\tEATEST_VERIFY(e.has_value());\n\t\tvector<int> v = {1, 2, 3, 4};\n\t\tEATEST_VERIFY(e.value() == v);\n\t}\n\n\t{\n\t\texpected<int, vector<int>> e(unexpect, {1, 2, 3, 4});\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tvector<int> v = {1, 2, 3, 4};\n\t\tEATEST_VERIFY(e.error() == v);\n\t}\n\n\t{\n\t\t// assignment from has_value -> has_value\n\t\texpected<vector<int>, int> e(in_place, {1, 2, 3, 4});\n\t\tvector<int> v = {1, 2, 3, 5};\n\t\te = v;\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value() == v);\n\t}\n\n\t{\n\t\t// assignment from !has_value -> has_value\n\t\texpected<vector<int>, int> e(unexpect, 1);\n\t\tvector<int> v = {1, 2, 3, 5};\n\t\te = v;\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value() == v);\n\t}\n\n\t{\n\t\t// assignment from has_value -> !has_value\n\t\texpected<vector<int>, int> e(in_place, {1, 2, 3, 4});\n\t\teastl::unexpected<int> u{2};\n\t\te = u;\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == u.error());\n\t}\n\n\t{\n\t\t// assignment from !has_value -> !has_value\n\t\texpected<vector<int>, int> e(unexpect, 1);\n\t\teastl::unexpected<int> u{2};\n\t\te = u;\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == u.error());\n\t}\n\n\t{\n\t\texpected<int, TestError> e(1);\n\t\te = 3;\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value() == 3);\n\t}\n\n\t{\n\t\texpected<unsigned int, TestError> e(1u);\n\t\te = 3; // test with conversion.\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value() == static_cast<float>(3));\n\n\t\te = eastl::unexpected<TestError>(TestError::Error3);\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == TestError::Error3);\n\n\t\tauto unex = eastl::unexpected<TestError>(TestError::Error2);\n\t\te = unex;\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == TestError::Error2);\n\t}\n\n\t{\n\t\texpected<Point, TestError> e(in_place, 1, 2);\n\t\te.emplace(3, 4);\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value().mX == 3 && e.value().mY == 4);\n\t}\n\n\t{\n#if defined EA_COMPILER_CPP20_ENABLED\n\t\t// NOTE: This should work in C++20 but not before since\n\t\t// C++20 changed how aggregates can be constructed.  See\n\t\t// https://godbolt.org/z/TnqWbebac\n\t\texpected<AggregateTest, TestError> e(in_place, 1, 2);\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value().mX == 1 && e.value().mY == 2);\n\t\te.emplace(3, 4);\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value().mX == 3 && e.value().mY == 4);\n#endif\n\t}\n\n\t{\n\t\texpected<InitListTest<int>, TestError> e(in_place, {1, 2});\n\t\tEATEST_VERIFY(e.has_value());\n\t\tEATEST_VERIFY(e.value().mVec == vector<int>({1, 2}));\n\t\te.emplace({4, 5, 6});\n\t}\n\n\t{\n\t\texpected<int, TestError> e1(1);\n\t\texpected<int, TestError> e2(2);\n\t\te1.swap(e2);\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value() == 2);\n\t\tEATEST_VERIFY(e2.has_value());\n\t\tEATEST_VERIFY(e2.value() == 1);\n\t}\n#if EASTL_EXCEPTIONS_ENABLED\n\t{\n\t\texpected<ClearOnMove, ThrowOnMoveOrCopy> e1(1);\n\t\texpected<ClearOnMove, ThrowOnMoveOrCopy> e2(eastl::unexpected<ThrowOnMoveOrCopy>{ThrowOnMoveOrCopy{}});\n\n\t\t// Make it so we throw when we move or copy, so the swap throws.\n\t\te2.error().mShouldThrow = true;\n\t\tbool exceptionThrown = false;\n\t\ttry\n\t\t{\n\t\t\te1.swap(e2);\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\texceptionThrown = true;\n\t\t}\n\t\tEATEST_VERIFY(exceptionThrown);\n\t\t// Verify that e1 is in a good state:\n\t\tEATEST_VERIFY(e1.has_value());\n\t\t// Verify that e1 has its old value:\n\t\tEATEST_VERIFY(e1.value().mId == 1);\n\n\t\t// Verify that moving from e1.vlaue() would've cleared the value.\n\t\tClearOnMove x = eastl::move(e1.value());\n\t\tEATEST_VERIFY(e1.value().mId == 0);\n\t}\n\n\t{\n\t\t// Same as above, but now T throws on move construct.\n\t\texpected<ThrowOnMoveOrCopy, ClearOnMove> e1;\n\t\texpected<ThrowOnMoveOrCopy, ClearOnMove> e2(eastl::unexpected<ClearOnMove>{1});\n\n\t\t// Make it so we throw when we move or copy, so the swap throws.\n\t\te1.value().mShouldThrow = true;\n\t\tbool exceptionThrown = false;\n\t\ttry\n\t\t{\n\t\t\te1.swap(e2);\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\texceptionThrown = true;\n\t\t}\n\t\tEATEST_VERIFY(exceptionThrown);\n\t\t// Verify that e1 is in a good state:\n\t\tEATEST_VERIFY(!e2.has_value());\n\t\t// Verify that e1 has its old value:\n\t\tEATEST_VERIFY(e2.error().mId == 1);\n\n\t\t// Verify that moving from e1.vlaue() would've cleared the value.\n\t\tClearOnMove x = eastl::move(e2.error());\n\t\tEATEST_VERIFY(e2.error().mId == 0);\n\t}\n#endif\n\n\t{\n\t\texpected<int, TestError> e1(1);\n\t\texpected<int, TestError> e2{eastl::unexpected<TestError>(TestError::Error1)};\n\t\te1.swap(e2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == TestError::Error1);\n\t\tEATEST_VERIFY(e2.has_value());\n\t\tEATEST_VERIFY(e2.value() == 1);\n\t}\n\n\t{\n\t\texpected<int, TestError> e1(1);\n\t\texpected<int, TestError> e2(2);\n\n\t\tusing eastl::swap;\n\t\tswap(e1, e2);\n\t\tstatic_assert(noexcept(swap(e1, e2)));\n\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e1.value() == 2);\n\t\tEATEST_VERIFY(e2.has_value());\n\t\tEATEST_VERIFY(e2.value() == 1);\n\t}\n\n\t{\n\t\texpected<int, TestError> e1(1);\n\t\texpected<int, TestError> e2{eastl::unexpected<TestError>(TestError::Error1)};\n\t\tusing eastl::swap;\n\t\tswap(e1, e2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == TestError::Error1);\n\t\tEATEST_VERIFY(e2.has_value());\n\t\tEATEST_VERIFY(e2.value() == 1);\n\t}\n\n\t{\n\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\texpected<int, eastl::vector<int>> e1{3};\n\t\texpected<int, eastl::vector<int>> e2{unexpect, v};\n\t\tusing eastl::swap;\n\t\tswap(e1, e2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == v);\n\t\tEATEST_VERIFY(e2.has_value());\n\t\tEATEST_VERIFY(e2.value() == 3);\n\t}\n\n\t{\n\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\texpected<eastl::vector<int>, int> e1{v};\n\t\texpected<eastl::vector<int>, int> e2{unexpect, 5};\n\t\tusing eastl::swap;\n\t\tswap(e1, e2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == 5);\n\t\tEATEST_VERIFY(e2.has_value());\n\t\tEATEST_VERIFY(e2.value() == v);\n\t}\n\n\t{\n\t\texpected<float, TestError> e(2.0f);\n\t\tEATEST_VERIFY(e.value_or(10.f) == 2.0f);\n\t\tEATEST_VERIFY(e.error_or(TestError::Error2) == TestError::Error2);\n\t\te = eastl::unexpected{TestError::Error3};\n\t\tEATEST_VERIFY(e.value_or(10.f) == 10.0f);\n\t\tEATEST_VERIFY(e.value_or(1) == static_cast<float>(1));\n\t\tEATEST_VERIFY(e.error_or(TestError::Error2) == TestError::Error3);\n\t}\n\n\t{\n\t\texpected<int, int> e1(1);\n\t\texpected<int, int> e2(1);\n\t\tEATEST_VERIFY(e1 == e2);\n\t\te2 = 5;\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te1 = eastl::unexpected{5};\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te2 = eastl::unexpected{5};\n\t\tEATEST_VERIFY(e1 == e2);\n\t}\n\n\t{\n\t\texpected<int, int> e1(1);\n\t\texpected<float, float> e2(1.0f);\n\t\tEATEST_VERIFY(e1 == e2);\n\t\te2 = 5.0f;\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te1 = eastl::unexpected{1};\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te2 = eastl::unexpected{1.0f};\n\t\tEATEST_VERIFY(e1 == e2);\n\t}\n\n\t{\n\t\tconst auto addHalf = [](int val) -> expected<float, TestError> { return static_cast<float>(val) + 0.5f; };\n\t\tconst auto getVector = [](float val) -> expected<vector<int>, TestError>\n\t\t{\n\t\t\tif (val > 10.f)\n\t\t\t{\n\t\t\t\treturn vector<int>{1, 2, 3, 4};\n\t\t\t}\n\t\t\tif (val > 0.0f)\n\t\t\t{\n\t\t\t\treturn vector<int>{1};\n\t\t\t}\n\t\t\treturn eastl::unexpected{TestError::Error2};\n\t\t};\n\n\t\tconst auto isBigVector = [](vector<int> val) -> expected<bool, TestError> { return val.size() > 2; };\n\n\t\t// test and_then...\n\t\t{\n\t\t\texpected<int, TestError> e(1); // 1->1.5->{1}->false\n\t\t\tauto r1 = e.and_then(addHalf).and_then(getVector).and_then(isBigVector);\n\t\t\tEATEST_VERIFY(!*r1);\n\t\t}\n\n\t\t{\n\t\t\texpected<int, TestError> e(10); // 10->10.5->{1, 2, 3, 4}->true\n\t\t\tauto r1 = e.and_then(addHalf).and_then(getVector).and_then(isBigVector);\n\t\t\tEATEST_VERIFY(*r1);\n\t\t}\n\n\t\t{\n\t\t\texpected<int, TestError> e(-5); // -5->-4.5->Error2->Error2\n\t\t\tauto r1 = e.and_then(addHalf).and_then(getVector).and_then(isBigVector);\n\t\t\tEATEST_VERIFY(r1.error() == TestError::Error2);\n\t\t}\n\n\t\t// test or_else\n\t\tconst auto getVectorForError = [](TestError err) -> expected<vector<int>, TestError>\n\t\t{\n\t\t\tswitch (err)\n\t\t\t{\n\t\t\t\tcase TestError::Error1:\n\t\t\t\t\treturn vector<int>{1, 1, 1, 1};\n\t\t\t\tcase TestError::Error2:\n\t\t\t\t\treturn vector<int>{4, 3, 2, 1};\n\t\t\t\tcase TestError::Error3:\n\t\t\t\t\treturn vector<int>{0, 1, 2};\n\t\t\t}\n\t\t\treturn vector<int>{};\n\t\t};\n\n\t\t{\n\t\t\texpected<float, TestError> e(1.0f); // 1.0->{1}->{1}\n\t\t\tauto r1 = e.and_then(getVector).or_else(getVectorForError);\n\t\t\tvector v = {1};\n\t\t\tEATEST_VERIFY(*r1 == v);\n\t\t}\n\n\t\t{\n\t\t\texpected<float, TestError> e(-5.0f); // -5.0f->TestError2->{4, 3, 2, 1}\n\t\t\tauto r1 = e.and_then(getVector).or_else(getVectorForError);\n\t\t\tvector v = {4, 3, 2, 1};\n\t\t\tEATEST_VERIFY(*r1 == v);\n\t\t}\n\n\t\tconst auto pushBackTen = [](auto val)\n\t\t{\n\t\t\tval.push_back(10);\n\t\t\treturn val;\n\t\t};\n\n\t\tconst auto getSize = [](const vector<int>& val) { return val.size(); };\n\n\t\t{\n\t\t\texpected<float, TestError> e(1.0f); // 1.0f->{1}->{1, 10}->2\n\t\t\tauto r1 = e.and_then(getVector).transform(pushBackTen).transform(getSize);\n\t\t\tEATEST_VERIFY(*r1 == 2);\n\t\t}\n\n\t\t{\n\t\t\texpected<float, TestError> e(-5.0f); // -5.0f->TestError2->TesError2->TestError2\n\t\t\tauto r1 = e.and_then(getVector).transform(pushBackTen).transform(getSize);\n\t\t\tEATEST_VERIFY(r1.error() == TestError::Error2);\n\t\t}\n\n\t\t{\n\t\t\texpected<float, TestError> e(-5.0f); // -5.0f->TestError2->{4, 3, 2, 1}->4\n\t\t\tauto r1 = e.and_then(getVector).or_else(getVectorForError).transform(getSize);\n\t\t\tEATEST_VERIFY(*r1 == 4);\n\t\t}\n\n\t\t{\n\t\t\texpected<float, TestError> e(1.0f); // 1.0f->{1}->{1}->1\n\t\t\tauto r1 = e.and_then(getVector).or_else(getVectorForError).transform(getSize);\n\t\t\tEATEST_VERIFY(*r1 == 1);\n\t\t}\n\n\t\tauto cycleError = [](TestError err)\n\t\t{\n\t\t\tswitch (err)\n\t\t\t{\n\t\t\t\tcase TestError::Error1:\n\t\t\t\t\treturn TestError::Error2;\n\t\t\t\tcase TestError::Error2:\n\t\t\t\t\treturn TestError::Error3;\n\t\t\t\tcase TestError::Error3:\n\t\t\t\t\treturn TestError::Error1;\n\t\t\t}\n\t\t\treturn TestError::Error1;\n\t\t};\n\n\t\t{\n\t\t\texpected<float, TestError> e(-5.0f); // -5->TestError2->TestError3->{0, 1, 2}->3\n\t\t\tauto r1 = e.and_then(getVector).transform_error(cycleError).or_else(getVectorForError).transform(getSize);\n\t\t\tEATEST_VERIFY(*r1 == 3);\n\t\t}\n\n\t\t{\n\t\t\texpected<float, TestError> e(1.0f); // 1->{1}->{1}->{1}->1\n\t\t\tauto r1 = e.and_then(getVector).transform_error(cycleError).or_else(getVectorForError).transform(getSize);\n\t\t\tEATEST_VERIFY(*r1 == 1);\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestExpectedVoid()\n{\n\n\tstatic_assert(CheckExpectedVoidTypeTraits<int>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<NoDefaultConstructible>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<NoCopyConstructible>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<NoTriviallyCopyable>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<NoTriviallyDestructible>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<NoTriviallyCopyableNoDefaultConstructible>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<MoveNoCopy>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<eastl::vector<int>>);\n\tstatic_assert(CheckExpectedVoidTypeTraits<eastl::unique_ptr<int>>);\n\n\t// Note: even if a type has a deleted move constructor,\n\t// expected should be both copy and move constructible.\n\tstatic_assert(is_copy_constructible_v<expected<void, CopyNoMove>>);\n\tstatic_assert(is_move_constructible_v<expected<void, CopyNoMove>>);\n\n\tint nErrorCount = 0;\n\t{\n\t\t// default construction\n\t\texpected<void, TestError> e;\n\t\tEATEST_VERIFY(e.has_value());\n\n\t\t// even if the error is not default constructible.\n\t\texpected<void, NoDefaultConstructible> e1;\n\t\tEATEST_VERIFY(e1.has_value());\n\n\t\t// copy constructor.\n\t\texpected<void, TestError> e2{e};\n\t\tEATEST_VERIFY(e2.has_value());\n\t}\n\n\t{\n\t\t// unexpected constructor test.\n\t\teastl::unexpected<SomeClass> unex(SomeClass{3});\n\t\texpected<void, SomeClass> e{unex};\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error().mI == 3);\n\n\t\t// Test constructor with different types.\n\t\texpected<void, ConversionTest> e1{e};\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error().mI == 3);\n\n\t\t// Test constructor with different types rvalues.\n\t\texpected<void, ConversionTest> e2{eastl::move(e)};\n\t\tEATEST_VERIFY(!e2.has_value());\n\t\tEATEST_VERIFY(e2.error().mI == 3);\n\t}\n\n\t{\n\t\t// Test constructor converting from an unexpected.\n\t\teastl::unexpected<SomeClass> unex{SomeClass{4}};\n\t\texpected<void, ConversionTest> e{unex};\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error().mI == 4);\n\n\t\t// With r-values\n\t\texpected<void, ConversionTest> e1{eastl::move(unex)};\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error().mI == 4);\n\t}\n\n\t{\n\t\t// Non trivial copies work.\n\t\texpected<void, NoTriviallyCopyable> e{unexpect, 4};\n\t\texpected<void, NoTriviallyCopyable> e1 = e;\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error().mId == 4);\n\t}\n\n\t{\n\t\teastl::vector<int> v = {1, 2, 3, 4};\n\t\texpected<void, eastl::vector<int>> e(unexpect, v);\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == v);\n\n\t\texpected<void, eastl::vector<int>> e1 = e;\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == v);\n\n\t\texpected<void, eastl::vector<int>> e2 = std::move(e);\n\t\tEATEST_VERIFY(!e2.has_value());\n\t\tEATEST_VERIFY(e2.error() == v);\n\n\t\teastl::vector<int> v1 = {1, 2, 3, 4, 5, 6};\n\t\texpected<void, eastl::vector<int>> e3(unexpect, v1);\n\t\te2 = e3;\n\t\tEATEST_VERIFY(e2.error() == v1);\n\n\t\te2 = std::move(e1);\n\t\tEATEST_VERIFY(e2.error() == v);\n\n\t\t// just check that we did in fact move from e1.\n\t\tEATEST_VERIFY(e1.error().size() == 0);\n\t}\n\n\t{\n\t\texpected<void, NoTriviallyCopyableNoDefaultConstructible> e(unexpect, 2);\n\t\tEATEST_VERIFY(e.error().mId == 2);\n\t\texpected<void, NoTriviallyCopyableNoDefaultConstructible> e1 = e;\n\t\tEATEST_VERIFY(e1.error().mId == 2);\n\t}\n\n\t{\n\t\t// implicit conversion\n\t\texpected<void, ImplilcitIntConversion> e{unexpect, 1};\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error().mId == 1);\n\t}\n\n\t{\n\t\t// check things work with move only types.\n\t\texpected<void, unique_ptr<int>> e(unexpect, new int(2));\n\t\texpected<void, unique_ptr<int>> e1 = eastl::move(e);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(*e1.error() == 2);\n\n\t\te = eastl::move(e1);\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(*e.error() == 2);\n\n\t\texpected<void, unique_ptr<int>> e2;\n\t\tEATEST_VERIFY(e2.has_value());\n\n\t\t// assignment changes from value -> error\n\t\te2 = eastl::move(e);\n\t\tEATEST_VERIFY(!e2.has_value());\n\t\tEATEST_VERIFY(*e2.error() == 2);\n\n\t\texpected<void, unique_ptr<int>> e3;\n\t\tEATEST_VERIFY(e3.has_value());\n\n\t\t// assignment changes from error -> value\n\t\te2 = eastl::move(e3);\n\t\tEATEST_VERIFY(e2.has_value());\n\t}\n\n\t{\n\t\t// conversion between expected\n\t\texpected<void, unsigned int> e(unexpect, 1u);\n\t\texpected<void, int> e1(e);\n\t\tEATEST_VERIFY(e1.error() == 1);\n\t}\n\n\t{\n\t\tvector<int> v = {1, 2, 3, 4};\n\t\texpected<void, vector<int>> e{eastl::unexpected<vector<int>>(v)};\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == v);\n\n\t\texpected<void, vector<int>> e1{eastl::move(e)};\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == v);\n\n\t\tEATEST_VERIFY(e.error().size() == 0);\n\t}\n\n\t{\n\t\texpected<void, Point> e(unexpect, 1, 2);\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error().mX == 1 && e.error().mY == 2);\n\t}\n\n\t{\n\t\texpected<void, vector<int>> e(unexpect, {1, 2, 3, 4});\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tvector<int> v = {1, 2, 3, 4};\n\t\tEATEST_VERIFY(e.error() == v);\n\t}\n\n\t{\n\t\texpected<void, TestError> e;\n\t\tEATEST_VERIFY(e.has_value());\n\n\t\te = eastl::unexpected<TestError>(TestError::Error3);\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == TestError::Error3);\n\n\t\tauto unex = eastl::unexpected<TestError>(TestError::Error2);\n\t\te = unex;\n\t\tEATEST_VERIFY(!e.has_value());\n\t\tEATEST_VERIFY(e.error() == TestError::Error2);\n\t}\n\n\t{\n\t\texpected<void, TestError> e1;\n\t\texpected<void, TestError> e2;\n\t\te1.swap(e2);\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e2.has_value());\n\t}\n\n\t{\n\t\texpected<void, TestError> e1;\n\t\texpected<void, TestError> e2{eastl::unexpected<TestError>(TestError::Error1)};\n\t\te1.swap(e2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == TestError::Error1);\n\t\tEATEST_VERIFY(e2.has_value());\n\t}\n\n\t{\n\t\texpected<void, TestError> e1;\n\t\texpected<void, TestError> e2;\n\t\tusing eastl::swap;\n\t\tswap(e1, e2);\n\t\tEATEST_VERIFY(e1.has_value());\n\t\tEATEST_VERIFY(e2.has_value());\n\t}\n\n\t{\n\t\texpected<void, TestError> e1;\n\t\texpected<void, TestError> e2{unexpect, TestError::Error1};\n\t\tusing eastl::swap;\n\t\tswap(e1, e2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == TestError::Error1);\n\t\tEATEST_VERIFY(e2.has_value());\n\t}\n\n\t{\n\t\teastl::vector<int> v = {1, 2, 3, 4, 5};\n\t\texpected<void, eastl::vector<int>> e1;\n\t\texpected<void, eastl::vector<int>> e2{unexpect, v};\n\t\tusing eastl::swap;\n\t\tswap(e1, e2);\n\t\tEATEST_VERIFY(!e1.has_value());\n\t\tEATEST_VERIFY(e1.error() == v);\n\t\tEATEST_VERIFY(e2.has_value());\n\t}\n\n\t{\n\t\texpected<void, TestError> e;\n\t\tEATEST_VERIFY(e.error_or(TestError::Error2) == TestError::Error2);\n\t\te = eastl::unexpected<TestError>{TestError::Error3};\n\t\tEATEST_VERIFY(e.error_or(TestError::Error2) == TestError::Error3);\n\t}\n\n\t{\n\t\texpected<void, int> e1;\n\t\texpected<void, int> e2;\n\t\tEATEST_VERIFY(e1 == e2);\n\t\te2 = eastl::unexpected<int>{5};\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te1 = eastl::unexpected<int>{4};\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te2 = eastl::unexpected<int>{4};\n\t\tEATEST_VERIFY(e1 == e2);\n\t}\n\n\t{\n\t\texpected<void, int> e1;\n\t\texpected<void, float> e2;\n\t\tEATEST_VERIFY(e1 == e2);\n\t\te2 = eastl::unexpected<float>{5.0f};\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te1 = eastl::unexpected<int>{1};\n\t\tEATEST_VERIFY(!(e1 == e2));\n\t\te2 = eastl::unexpected<float>{1.0f};\n\t\tEATEST_VERIFY(e1 == e2);\n\t}\n\n\t{\n\t\tint counter{};\n\t\tconst auto foo = [&counter]() -> expected<void, TestError>\n\t\t{\n\t\t\t++counter;\n\t\t\treturn {};\n\t\t};\n\t\t{\n\t\t\texpected<void, TestError> e;\n\t\t\tauto e1 = e.and_then(foo);\n\t\t\tEATEST_VERIFY(counter == 1);\n\t\t\tEATEST_VERIFY(e1.has_value());\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t{\n\t\t\texpected<void, TestError> e{unexpect, TestError::Error2};\n\t\t\texpected<void, TestError> e1 = e.and_then(foo);\n\t\t\tEATEST_VERIFY(counter == 0);\n\t\t\tEATEST_VERIFY(!e1.has_value());\n\t\t\tEATEST_VERIFY(e1.error() == TestError::Error2);\n\t\t\tcounter = 0;\n\t\t}\n\n\t\tconst auto fooError = [&counter](TestError t) -> expected<void, TestError>\n\t\t{\n\t\t\t++counter;\n\t\t\tswitch (t)\n\t\t\t{\n\t\t\t\tcase TestError::Error1:\n\t\t\t\t\treturn eastl::unexpected<TestError>(TestError::Error1);\n\t\t\t\tcase TestError::Error2:\n\t\t\t\t\treturn {};\n\t\t\t\tcase TestError::Error3:\n\t\t\t\t\treturn eastl::unexpected<TestError>(TestError::Error1);\n\t\t\t}\n\t\t\treturn {};\n\t\t};\n\n\t\t{\n\t\t\texpected<void, TestError> e;\n\t\t\t// valid -> valid (pass-through without function call)\n\t\t\texpected<void, TestError> e1 = e.or_else(fooError);\n\t\t\tEATEST_VERIFY(counter == 0);\n\t\t\tEATEST_VERIFY(e1.has_value());\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t{\n\t\t\texpected<void, TestError> e{unexpect, TestError::Error3};\n\t\t\t// Error3 -> fooError(Error3) = Error1\n\t\t\texpected<void, TestError> e1 = e.or_else(fooError);\n\t\t\tEATEST_VERIFY(counter == 1);\n\t\t\tEATEST_VERIFY(!e1.has_value());\n\t\t\tEATEST_VERIFY(e1.error() == TestError::Error1);\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t{\n\t\t\texpected<void, TestError> e{unexpect, TestError::Error2};\n\t\t\t// Error2 -> fooError(Error2) = valid\n\t\t\texpected<void, TestError> e1 = e.or_else(fooError);\n\t\t\tEATEST_VERIFY(counter == 1);\n\t\t\tEATEST_VERIFY(e1.has_value());\n\t\t\tcounter = 0;\n\t\t}\n\n\n\t\t// transform from void -> vector<int>\n\t\tconst auto getVector = [&counter]() -> vector<int>\n\t\t{\n\t\t\tif (counter > 3)\n\t\t\t{\n\t\t\t\treturn {1, 2, 3, 4};\n\t\t\t}\n\t\t\treturn {1, 2};\n\t\t};\n\n\t\t{\n\t\t\texpected<void, TestError> e;\n\t\t\texpected<vector<int>, TestError> e1 = e.transform(getVector);\n\t\t\tEATEST_VERIFY(e1.has_value());\n\t\t\tEATEST_VERIFY(e1.value().size() == 2);\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t{\n\t\t\tcounter = 5;\n\t\t\texpected<void, TestError> e;\n\t\t\texpected<vector<int>, TestError> e1 = e.transform(getVector);\n\t\t\tEATEST_VERIFY(e1.has_value());\n\t\t\tEATEST_VERIFY(e1.value().size() == 4);\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t{\n\t\t\texpected<void, TestError> e{unexpect, TestError::Error3};\n\t\t\texpected<vector<int>, TestError> e1 = e.transform(getVector);\n\t\t\tEATEST_VERIFY(counter == 0);\n\t\t\tEATEST_VERIFY(!e1.has_value());\n\t\t\tEATEST_VERIFY(e1.error() == TestError::Error3);\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t// transform from int -> void\n\t\tconst auto setCount = [&counter](int i) -> void { counter = i; };\n\n\t\t{\n\t\t\texpected<int, TestError> e{unexpect, TestError::Error3};\n\t\t\t// Error3 -> Error3\n\t\t\texpected<void, TestError> e1 = e.transform(setCount);\n\t\t\tEATEST_VERIFY(counter == 0);\n\t\t\tEATEST_VERIFY(!e1.has_value());\n\t\t\tEATEST_VERIFY(e1.error() == TestError::Error3);\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t{\n\t\t\texpected<int, TestError> e{5};\n\t\t\t// 5 -> valid\n\t\t\texpected<void, TestError> e1 = e.transform(setCount);\n\t\t\tEATEST_VERIFY(counter == 5);\n\t\t\tEATEST_VERIFY(e1.has_value());\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t// transform from int -> void\n\t\tconst auto numberToError = [&counter](int i) -> TestError\n\t\t{\n\t\t\tcounter = i;\n\t\t\tif (i <= 1)\n\t\t\t{\n\t\t\t\treturn TestError::Error1;\n\t\t\t}\n\t\t\tif (i == 2)\n\t\t\t{\n\t\t\t\treturn TestError::Error2;\n\t\t\t}\n\t\t\treturn TestError::Error3;\n\t\t};\n\n\t\t{\n\t\t\texpected<void, int> e{unexpect, 5};\n\t\t\texpected<void, TestError> e1 = e.transform_error(numberToError);\n\t\t\tEATEST_VERIFY(counter == 5);\n\t\t\tEATEST_VERIFY(!e1.has_value());\n\t\t\tEATEST_VERIFY(e1.error() == TestError::Error3);\n\t\t\tcounter = 0;\n\t\t}\n\n\t\t{\n\t\t\texpected<void, int> e{unexpect, 2};\n\t\t\texpected<void, TestError> e1 = e.transform_error(numberToError);\n\t\t\tEATEST_VERIFY(counter == 2);\n\t\t\tEATEST_VERIFY(!e1.has_value());\n\t\t\tEATEST_VERIFY(e1.error() == TestError::Error2);\n\t\t\tcounter = 0;\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestExpected() { return TestExpectedGeneric() + TestExpectedVoid(); }\n\n#endif\n"
  },
  {
    "path": "test/source/TestExtra.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////\n// Test forward delcarations\n/////////////////////////////////////////////////////////////////////////////\n\nnamespace eastl\n{\n\tclass allocator;\n\n\ttemplate <typename T, typename Allocator> class basic_string;\n\ttypedef basic_string<char, allocator> local_string8;  // collides with eastl::string8 in bulkbuilds\n\n\ttemplate <typename T> struct local_less {};\n\n\tstatic void UseForwardDeclaredString(local_string8*)\n\t{\n\t}\n\n\n\ttemplate <typename T, typename Allocator> class vector;\n\ttypedef vector<char, allocator> vector8;\n\n\tstatic void UseForwardDeclaredVector(vector8*)\n\t{\n\t}\n\n\n\ttemplate <typename Value, typename Hash, typename Predicate, typename Allocator, bool bCacheHashCode> class hash_set;\n\ttypedef hash_set<char, char, local_less<char>, allocator, false> hash_set8;\n\n\tstatic void UseForwardDeclaredHashSet(hash_set8*)\n\t{\n\t}\n\n\n\ttemplate <typename Key, typename T, typename Compare, typename Allocator> class map;\n\ttypedef map<char, char, local_less<char>, allocator> map8;\n\n\tstatic void UseForwardDeclaredMap(map8*)\n\t{\n\t}\n}\n\n\n#include \"EASTLTest.h\"\n#include <EAStdC/EASprintf.h>\n#include <EASTL/functional.h>\n#include <EASTL/utility.h>\n#include <EASTL/memory.h>\n#include <EASTL/allocator.h>\n#include <EASTL/allocator_malloc.h>\n#include <EASTL/fixed_allocator.h>\n#include <EASTL/intrusive_list.h>\n#include <EASTL/numeric.h>\n#include <EASTL/queue.h>\n#include <EASTL/priority_queue.h>\n#include <EASTL/stack.h>\n#include <EASTL/heap.h>\n#include <EASTL/vector.h>\n#include <EASTL/deque.h>\n#include <EASTL/list.h>\n#include <EASTL/map.h>\n#include <EASTL/string.h>\n#include <EASTL/hash_set.h>\n#include <EASTL/random.h>\n#include <EASTL/bit.h>\n#include <EASTL/core_allocator_adapter.h>\n#include <EASTL/bonus/call_traits.h>\n#include <EASTL/bonus/compressed_pair.h>\n#include <EASTL/bonus/adaptors.h>\n#include <EAStdC/EAAlignment.h>\n#include <EAStdC/EAMemory.h>\n#include <EAStdC/EAString.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n\n#include <stdio.h>\n#include <string.h>\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <algorithm>\n\t#include <utility>\n\t#include <stack>\n\t#include <queue>\n\t#include <vector>\n\t#include <deque>\n\t#include <math.h>\n#endif\n\n#if defined(_MSC_VER)\n\t#pragma warning(pop)\n#endif\n\n\n\nusing namespace eastl;\n\n\n\nnamespace\n{\n\t/// IntNode\n\t///\n\t/// Test intrusive_list node.\n\t///\n\tstruct IntNode : public eastl::intrusive_list_node\n\t{\n\t\tint mX;\n\n\t\tIntNode(int x = 0)\n\t\t\t: mX(x) { }\n\n\t\toperator int() const\n\t\t\t{ return mX; }\n\t};\n\n\tbool operator<(const IntNode& a, const IntNode& b)\n\t\t{ return a.mX < b.mX; }\n}\n\n\n\n\n\n\nstruct TestClass\n{\n\tmutable int mX;\n\n\tTestClass() : mX(37) { }\n\n\tvoid Increment()\n\t{\n\t\tmX++;\n\t}\n\n\tvoid IncrementConst() const\n\t{\n\t\tmX++;\n\t}\n\n\tint MultiplyBy(int x)\n\t{\n\t\treturn mX * x;\n\t}\n\n\tint MultiplyByConst(int x) const\n\t{\n\t\treturn mX * x;\n\t}\n};\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestForwardDeclarations\n//\nstatic int TestForwardDeclarations()\n{\n\tint nErrorCount = 0;\n\n\teastl::local_string8 s8;\n\tUseForwardDeclaredString(&s8);   \n\n\teastl::vector8 v8;\n\tUseForwardDeclaredVector(&v8);\n\n\teastl::hash_set8 h8;\n\tUseForwardDeclaredHashSet(&h8);\n\n\teastl::map8 m8;\n\tUseForwardDeclaredMap(&m8);\n\n\treturn nErrorCount;\n}\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// fixed_pool_reference\n//\nstruct fixed_pool_reference\n{\npublic:\n\tfixed_pool_reference(const char* = NULL)\n\t{\n\t\tmpFixedPool = NULL;\n\t}\n\n\tfixed_pool_reference(eastl::fixed_pool& fixedPool)\n\t{\n\t\tmpFixedPool = &fixedPool;\n\t}\n\n\tfixed_pool_reference(const fixed_pool_reference& x)\n\t{\n\t\tmpFixedPool = x.mpFixedPool;\n\t}\n\n\tfixed_pool_reference& operator=(const fixed_pool_reference& x)\n\t{\n\t\tmpFixedPool = x.mpFixedPool;\n\t\treturn *this;\n\t}\n\n\tvoid* allocate(size_t /*n*/, int /*flags*/ = 0)\n\t{\n\t\treturn mpFixedPool->allocate();\n\t}\n\n\tvoid* allocate(size_t /*n*/, size_t /*alignment*/, size_t /*offset*/, int /*flags*/ = 0)\n\t{\n\t\treturn mpFixedPool->allocate();\n\t}\n\n\tvoid deallocate(void* p, size_t /*n*/)\n\t{\n\t\treturn mpFixedPool->deallocate(p);\n\t}\n\n\tconst char* get_name() const\n\t{\n\t\treturn \"fixed_pool_reference\";\n\t}\n\n\tvoid set_name(const char* /*pName*/)\n\t{\n\t}\n\nprotected:\n\tfriend bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b);\n\tfriend bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b);\n\n\teastl::fixed_pool* mpFixedPool;\n};\n\n\ninline bool operator==(const fixed_pool_reference& a, const fixed_pool_reference& b)\n{\n\treturn (a.mpFixedPool == b.mpFixedPool);\n}\n\ninline bool operator!=(const fixed_pool_reference& a, const fixed_pool_reference& b)\n{\n\treturn (a.mpFixedPool != b.mpFixedPool);\n}\n\n\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::queue<int, deque<int> >;\ntemplate class eastl::queue<Align64, deque<Align64> >;\ntemplate class eastl::queue<TestObject, list<TestObject> >;\n//template class eastl::queue<IntNode, intrusive_list<IntNode> >;// This test has been disabled as of the addition of initializer_list support to eastl::queue. initializer_lists have const nodes, which is incompatible with intrusive_list. You can use eastl::queue<IntNode, intrusive_list<IntNode> > as long as you don't use initializer_list with it. The problem with this line of code is that it forces compilation of the entire class.\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestQueue\n//\nstatic int TestQueue()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\t// Exercise IntNode.\n\t\tIntNode x, y;\n\t\tEATEST_VERIFY((x < y) || !(x < y) || ((int)x < (int)y));\n\t}\n\n\tTestObject::Reset();\n\n\t{\n\t\t// queue(const Sequence& x = Sequence());\n\t\tqueue<TestObject, list<TestObject>> toListQueue;\n\t\tqueue<TestObject, list<TestObject>> toListQueue2;\n\n\n\t\t// global operators\n\t\tEATEST_VERIFY( (toListQueue == toListQueue2));\n\t\tEATEST_VERIFY(!(toListQueue != toListQueue2));\n\t\tEATEST_VERIFY( (toListQueue <= toListQueue2));\n\t\tEATEST_VERIFY( (toListQueue >= toListQueue2));\n\t\tEATEST_VERIFY(!(toListQueue <  toListQueue2));\n\t\tEATEST_VERIFY(!(toListQueue >  toListQueue2));\n\n\t\t// bool      empty() const;\n\t\t// size_type size() const;\n\t\tEATEST_VERIFY(toListQueue.empty());\n\t\tEATEST_VERIFY(toListQueue.size() == 0);\n\n\n\t\t// void            push(const value_type& value);\n\t\t// reference       front();\n\t\t// const_reference front() const;\n\t\t// reference       back();\n\t\t// const_reference back() const;\n\t\ttoListQueue.push(TestObject(0));\n\t\tEATEST_VERIFY(toListQueue.front() == TestObject(0));\n\t\tEATEST_VERIFY(toListQueue.back()  == TestObject(0));\n\n\t\ttoListQueue.push(TestObject(1));\n\t\tEATEST_VERIFY(toListQueue.front() == TestObject(0));\n\t\tEATEST_VERIFY(toListQueue.back()  == TestObject(1));\n\n\t\ttoListQueue.push(TestObject(2));\n\t\tEATEST_VERIFY(toListQueue.front() == TestObject(0));\n\t\tEATEST_VERIFY(toListQueue.back()  == TestObject(2));\n\t\tEATEST_VERIFY(!toListQueue.empty());\n\t\tEATEST_VERIFY(toListQueue.size() == 3);\n\n\n\t\t// void pop();\n\t\ttoListQueue.pop();\n\t\tEATEST_VERIFY(toListQueue.front() == TestObject(1));\n\t\tEATEST_VERIFY(toListQueue.back()  == TestObject(2));\n\n\t\ttoListQueue.pop();\n\t\tEATEST_VERIFY(toListQueue.front() == TestObject(2));\n\t\tEATEST_VERIFY(toListQueue.back()  == TestObject(2));\n\n\t\ttoListQueue.pop();\n\t\tEATEST_VERIFY(toListQueue.empty());\n\t\tEATEST_VERIFY(toListQueue.size() == 0);\n\n\n\t\t// decltype(auto) emplace(Args&&... args);\n\t\ttoListQueue.emplace(1);\n\t\tEATEST_VERIFY(!toListQueue.empty());\n\t\tEATEST_VERIFY(toListQueue.front() == TestObject(1));\n\t\tEATEST_VERIFY(toListQueue.size() == 1);\n\n\n\t\t// container_type&       get_container();\n\t\t// const container_type& get_container() const;\n\t\tlist<TestObject>& ref = toListQueue.get_container();\n\t\tEATEST_VERIFY(ref.size() == toListQueue.size());\n\n\n\t\t// queue(std::initializer_list<value_type> ilist);\n\t\tqueue<int> intQueue = { 3, 4, 5 };\n\t\tEATEST_VERIFY(intQueue.size() == 3);\n\t\tEATEST_VERIFY(intQueue.front() == 3);\n\t\tintQueue.pop();\n\t\tEATEST_VERIFY(intQueue.front() == 4);\n\t\tintQueue.pop();\n\t\tEATEST_VERIFY(intQueue.front() == 5);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{\n\t\t// queue(const Sequence& x = Sequence());\n\t\tqueue<TestObject, list<TestObject>> toListQueue;\n\t\tqueue<TestObject, list<TestObject>> toListQueue2;\n\n\n\t\t// global operators\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) == 0));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) != 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) <= 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) >= 0));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) < 0));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) > 0));\n\n\t\t// bool      empty() const;\n\t\t// size_type size() const;\n\t\tEATEST_VERIFY(toListQueue.empty());\n\t\tEATEST_VERIFY(toListQueue.size() == 0);\n\n\t\t// Verify toListQueue > toListQueue2\n\t\ttoListQueue.push(TestObject(0));\n\t\ttoListQueue.push(TestObject(1));\n\t\ttoListQueue2.push(TestObject(0));\n\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) == 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) != 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) >= 0));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) <= 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) > 0));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) < 0));\n\n\t\t// Verify toListQueue2 > toListQueue by element size\n\t\ttoListQueue2.push(TestObject(3));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) == 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) != 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) <= 0));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) >= 0));\n\t\tEATEST_VERIFY( ((toListQueue <=> toListQueue2) < 0));\n\t\tEATEST_VERIFY(!((toListQueue <=> toListQueue2) > 0));\n\n\t\tqueue<TestObject, list<TestObject>> toListQueue3;\n\t\tqueue<TestObject, list<TestObject>> toListQueue4;\n\n\t\tfor (int i = 0; i < 10; i++)\n\t\t{\n\t\t\ttoListQueue3.push(TestObject(i));\n\t\t\tif (i < 5)\n\t\t\t\ttoListQueue4.push(TestObject(i));\n\t\t}\n\n\t\t// Verify toListQueue4 is a strict subset of toListQueue3\n\t\tEATEST_VERIFY(!((toListQueue3 <=> toListQueue4) == 0));\n\t\tEATEST_VERIFY( ((toListQueue3 <=> toListQueue4) != 0));\n\t\tEATEST_VERIFY( ((toListQueue3 <=> toListQueue4) >= 0));\n\t\tEATEST_VERIFY(!((toListQueue3 <=> toListQueue4) <= 0));\n\t\tEATEST_VERIFY( ((toListQueue3 <=> toListQueue4) > 0));\n\t\tEATEST_VERIFY(!((toListQueue3 <=> toListQueue4) < 0));\n\n\t\t// Verify that even thoughn toListQueue4 has a smaller size, it's lexicographically larger\n\t\ttoListQueue4.push(TestObject(11));\n\t\tEATEST_VERIFY(!((toListQueue3 <=> toListQueue4) == 0));\n\t\tEATEST_VERIFY( ((toListQueue3 <=> toListQueue4) != 0));\n\t\tEATEST_VERIFY( ((toListQueue3 <=> toListQueue4) <= 0));\n\t\tEATEST_VERIFY(!((toListQueue3 <=> toListQueue4) >= 0));\n\t\tEATEST_VERIFY( ((toListQueue3 <=> toListQueue4) < 0));\n\t\tEATEST_VERIFY(!((toListQueue3 <=> toListQueue4) > 0));\n\t\t\n\t}\n\n\t{\n\t\tqueue<TestObject, list<TestObject>> toListQueue1;\n\t\tqueue<TestObject, list<TestObject>> toListQueue2;\n\t\tqueue<TestObject, list<TestObject>> toListQueue3;\n\n\t\tfor (int i = 0; i < 10; i++)\n\t\t{\n\t\t\ttoListQueue1.push(TestObject(i));\n\t\t\ttoListQueue2.push(TestObject(9-i));\n\t\t\tif (i < 5)\n\t\t\t\ttoListQueue3.push(TestObject(i));\n\t\t}\n\n\t\tstruct weak_ordering_queue\n\t\t{\n\t\t\tqueue<TestObject, list<TestObject>> queue;\n\t\t    inline std::weak_ordering operator<=>(const weak_ordering_queue& b) const { return queue <=> b.queue; }\n\t\t};\n\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue1}, weak_ordering_queue{toListQueue2}) == std::weak_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue3}, weak_ordering_queue{toListQueue1}) == std::weak_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue2}, weak_ordering_queue{toListQueue1}) == std::weak_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue2}, weak_ordering_queue{toListQueue3}) == std::weak_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue1}, weak_ordering_queue{toListQueue1}) == std::weak_ordering::equivalent);\n\t}\n\t#endif\n\n\t{\n\t\tvector<TestObject> toVector;\n\t\tfor(int i = 0; i < 100; i++)\n\t\t\ttoVector.push_back(TestObject(i));\n\n\t\t// template <class Allocator>\n\t\t// queue(this_type&& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL);\n\t\t//\n\t\t// explicit queue(container_type&& x);\n\t\t//\n\t\t// void push(value_type&& x);\n\n\t\tqueue<TestObject, vector<TestObject> > toQ_0;\n\t\tqueue<TestObject, vector<TestObject> > toQ_A(eastl::move(toQ_0), toQ_0.get_container().get_allocator()); // It would be better if we also tested an alternative allocator.\n\t\tEATEST_VERIFY(toQ_A.size() == 0);\n\t\ttoQ_A.push(TestObject(1000));\n\t\tEATEST_VERIFY(toQ_A.size() == 1);\n\n\t\tqueue<TestObject, vector<TestObject> > toQ_B(eastl::move(toQ_A), toQ_A.get_container().get_allocator()); // It would be better if we also tested an alternative allocator.\n\t\tEATEST_VERIFY((toQ_B.size() == 1) && toQ_A.empty());\n\n\t\teastl::vector<TestObject> toVectorM(toVector);\n\t\tqueue<TestObject, vector<TestObject> > toQ_C(eastl::move(toVectorM));\n\t\tEATEST_VERIFY((toQ_C.size() == toVector.size()) && toVectorM.empty());\n\n\t\t// template <class... Args>\n\t\t// void emplace_back(Args&&... args);\n\n\t\tqueue<TestObject, vector<TestObject> > toQ_D;\n\t\ttoQ_D.emplace(0, 1, 2);\n\t\tEATEST_VERIFY(toQ_D.size() == 1) && (toQ_D.back() == TestObject(0, 1, 2));\n\t}\n\n\n\t{ // Test std namespace elements contained in queue\n\t\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t\teastl::queue< std::pair<int, int> > stlQueue;\n\t\t\tstlQueue.push(std::make_pair(1, 1));\n\t\t\tEATEST_VERIFY(stlQueue.size() == 1);\n\t\t#endif\n\t}\n\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::priority_queue<int, vector<int> >;\ntemplate class eastl::priority_queue<Align64, deque<Align64> >;\ntemplate class eastl::priority_queue<TestObject, vector<TestObject> >;\ntemplate class eastl::priority_queue<float, vector<float>, less<float> >;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestPriorityQueue\n//\nstatic int TestPriorityQueue()\n{\n\tint nErrorCount = 0;\n\n\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\n\tTestObject::Reset();\n\n\t{\n\t\tless<TestObject> toLess;\n\n\t\tvector<TestObject> toVector;\n\t\tfor(int i = 0; i < 100; i++)\n\t\t\ttoVector.push_back(TestObject(i));\n\t\trandom_shuffle(toVector.begin(), toVector.end(), rng);\n\n\t\tlist<TestObject> toList;\n\t\tfor(eastl_size_t j = 0; j < 100; j++)\n\t\t\ttoList.push_back(toVector[j]);\n\n\n\t\t// priority_queue(const Compare& compare = Compare(), const Sequence& x = Sequence());\n\t\t// template <typename InputIterator>\n\t\t// priority_queue(InputIterator first, InputIterator last, const Compare& compare = Compare(), const Sequence& x = Sequence());\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQ;\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQV(toLess, toVector);\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQL(toList.begin(), toList.end());\n\n\t\tEATEST_VERIFY(toPQ.empty());\n\t\tEATEST_VERIFY(toPQ.size() == 0);\n\n\t\tEATEST_VERIFY(!toPQV.empty());\n\t\tEATEST_VERIFY( toPQV.size() == toVector.size());\n\n\t\tEATEST_VERIFY(!toPQL.empty());\n\t\tEATEST_VERIFY( toPQL.size() == toList.size());\n\n\n\t\t// global operators\n\t\tEATEST_VERIFY( (toPQ  != toPQL));\n\t\tEATEST_VERIFY( (toPQV == toPQL));\n\t\tEATEST_VERIFY(!(toPQV != toPQL));\n\t\tEATEST_VERIFY( (toPQV <= toPQL));\n\t\tEATEST_VERIFY( (toPQV >= toPQL));\n\t\tEATEST_VERIFY(!(toPQV <  toPQL));\n\t\tEATEST_VERIFY(!(toPQV >  toPQL));\n\n\n\t\t// container_type&       get_container();\n\t\t// const container_type& get_container() const;\n\t\tvector<TestObject>& ref = toPQL.get_container();\n\t\tEATEST_VERIFY(ref.size() == toPQL.size());\n\t\tEATEST_VERIFY(is_heap(ref.begin(), ref.end()));\n\n\t\t// bool validate() const;\n\t\tEATEST_VERIFY(toPQL.validate());\n\t\t// To consider: Verify that validate detects an invalid heap. \n\t\t// Testing this might be an issue if the validation function actively complains in some way.\n\n\n\t\t// const_reference top() const;\n\t\t// void pop();\n\t\tconst TestObject& to1 = toPQL.top();\n\t\tEATEST_VERIFY(to1 == TestObject(99));\n\n\t\ttoPQL.pop();\n\t\tEATEST_VERIFY(!toPQL.empty());\n\t\tEATEST_VERIFY( toPQL.size() == toList.size() - 1);\n\t\tEATEST_VERIFY(to1 == TestObject(98));\n\t\tEATEST_VERIFY(is_heap(ref.begin(), ref.end()));\n\n\n\t\t// void push(const value_type& value);\n\t\ttoPQL.push(TestObject(1000));\n\t\tEATEST_VERIFY(toPQL.size() == toList.size());\n\t\tconst TestObject& to2 = toPQL.top();\n\t\tEATEST_VERIFY(to2 == TestObject(1000));\n\t\ttoPQL.pop();\n\t\tconst TestObject& to3 = toPQL.top();\n\t\tEATEST_VERIFY(to3 == TestObject(98));\n\t\tEATEST_VERIFY(is_heap(ref.begin(), ref.end()));\n\n\n\t\t// void change(size_type n);\n\t\tTestObject& to4 = ref[50];\n\t\tto4 = TestObject(2000);\n\t\ttoPQL.change(50);\n\t\tconst TestObject& to5 = toPQL.top();\n\t\tEATEST_VERIFY(to5 == TestObject(2000));\n\t\tEATEST_VERIFY(is_heap(ref.begin(), ref.end()));\n\n\n\t\t// void remove(size_type n);\n\t\tTestObject to6 = ref[20];\n\t\ttoPQL.remove(20);\n\t\tEATEST_VERIFY( toPQL.size() == toList.size() - 2);\n\t\tTestObject& to7 = ref[20];\n\t\tEATEST_VERIFY(!(to6 == to7));\n\t\tEATEST_VERIFY(is_heap(ref.begin(), ref.end()));\n\n\n\t\t// priority_queue(std::initializer_list<value_type> ilist, const compare_type& compare = compare_type());\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\tpriority_queue<int, vector<int> > intPQ = { 3, 4, 5 };\n\t\t\tEATEST_VERIFY(intPQ.size() == 3);\n\t\t\tEATEST_VERIFY(intPQ.top() == 5);\n\t\t\tintPQ.pop();\n\t\t\tEATEST_VERIFY(intPQ.top() == 4);\n\t\t\tintPQ.pop();\n\t\t\tEATEST_VERIFY(intPQ.top() == 3);\n\t\t#endif\n\t}\n\n\t{\n\t\tvector<TestObject> toVector;\n\t\tfor(int i = 0; i < 100; i++)\n\t\t\ttoVector.push_back(TestObject(i));\n\n\t\t// template <class Allocator>\n\t\t// priority_queue(this_type&& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL);\n\t\t//\n\t\t// explicit priority_queue(const compare_type& compare, container_type&& x);\n\t\t//\n\t\t// template <class InputIterator>\n\t\t// priority_queue(InputIterator first, InputIterator last, const compare_type& compare, container_type&& x);\n\t\t//\n\t\t// void push(value_type&& x);\n\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQ_0;\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQ_A(toPQ_0.get_container().begin(), toPQ_0.get_container().begin(), eastl::less<TestObject>(), toPQ_0.get_container());\n\t\tEATEST_VERIFY(toPQ_A.size() == 0);\n\t\ttoPQ_A.push(TestObject(1000));\n\t\tEATEST_VERIFY(toPQ_A.size() == 1);\n\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQ_B(eastl::move(toPQ_A), toPQ_A.get_container().get_allocator()); // It would be better if we also tested an alternative allocator.\n\t\tEATEST_VERIFY((toPQ_B.size() == 1) && toPQ_A.empty());\n\n\t\teastl::vector<TestObject> toVectorM(toVector);\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQ_C(eastl::less<TestObject>(), eastl::move(toVectorM));\n\t\tEATEST_VERIFY((toPQ_C.size() == toVector.size()) && toVectorM.empty());\n\n\t\t// template <class... Args>\n\t\t// void emplace(Args&&... args);\n\t\tpriority_queue<TestObject, vector<TestObject> > toPQ_D;\n\t\ttoPQ_D.emplace(0, 1, 2);\n\t\tEATEST_VERIFY(toPQ_D.size() == 1) && (toPQ_D.top() == TestObject(0, 1, 2));\n\t}\n\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::stack<int, vector<int> >;\ntemplate class eastl::stack<Align64, list<Align64> >;\ntemplate class eastl::stack<TestObject, vector<TestObject> >;\n//template class eastl::stack<IntNode, intrusive_list<IntNode> >; // This test has been disabled as of the addition of initializer_list support to eastl::stack. initializer_lists have const nodes, which is incompatible with intrusive_list. You can use eastl::stack<IntNode, intrusive_list<IntNode> > as long as you don't use initializer_list with it. The problem with this line of code is that it forces compilation of the entire class.\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestStack\n//\nstatic int TestStack()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{\n\t\t// stack(const Sequence& x = Sequence());\n\t\tstack<TestObject, list<TestObject> > toListStack;\n\t\tstack<TestObject, list<TestObject> > toListStack2;\n\n\n\t\t// bool      empty() const;\n\t\t// size_type size() const;\n\t\tEATEST_VERIFY(toListStack.empty());\n\t\tEATEST_VERIFY(toListStack.size() == 0);\n\n\n\t\t// global operators\n\t\tEATEST_VERIFY( (toListStack == toListStack2));\n\t\tEATEST_VERIFY(!(toListStack != toListStack2));\n\t\tEATEST_VERIFY( (toListStack <= toListStack2));\n\t\tEATEST_VERIFY( (toListStack >= toListStack2));\n\t\tEATEST_VERIFY(!(toListStack <  toListStack2));\n\t\tEATEST_VERIFY(!(toListStack >  toListStack2));\n\n\t\t// void push(const value_type& value);\n\t\t// reference       top();\n\t\t// const_reference top() const;\n\t\ttoListStack.push(TestObject(0));\n\t\tEATEST_VERIFY(toListStack.top() == TestObject(0));\n\n\t\ttoListStack.push(TestObject(1));\n\t\tEATEST_VERIFY(toListStack.top() == TestObject(1));\n\n\t\ttoListStack.push(TestObject(2));\n\t\tEATEST_VERIFY( toListStack.top() == TestObject(2));\n\t\tEATEST_VERIFY(!toListStack.empty());\n\t\tEATEST_VERIFY( toListStack.size() == 3);\n\n\t\t// void pop();\n\t\ttoListStack.pop();\n\t\tEATEST_VERIFY(toListStack.top() == TestObject(1));\n\n\t\ttoListStack.pop();\n\t\tEATEST_VERIFY(toListStack.top() == TestObject(0));\n\n\t\ttoListStack.pop();\n\t\tEATEST_VERIFY(toListStack.empty());\n\t\tEATEST_VERIFY(toListStack.size() == 0);\n\n\n\t\t// container_type&       get_container();\n\t\t// const container_type& get_container() const;\n\t\tlist<TestObject>& ref = toListStack.get_container();\n\t\tEATEST_VERIFY(ref.size() == toListStack.size());\n\n\n\t\t// stack(std::initializer_list<value_type> ilist);\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\tstack<int> intStack = { 3, 4, 5 };\n\t\t\tEATEST_VERIFY(intStack.size() == 3);\n\t\t\tEATEST_VERIFY(intStack.top() == 5);\n\t\t\tintStack.pop();\n\t\t\tEATEST_VERIFY(intStack.top() == 4);\n\t\t\tintStack.pop();\n\t\t\tEATEST_VERIFY(intStack.top() == 3);\n\t\t#endif\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{\n\t\t// stack(const Sequence& x = Sequence());\n\t\tstack<TestObject, list<TestObject> > toListStack;\n\t\tstack<TestObject, list<TestObject> > toListStack2;\n\n\t\t// bool      empty() const;\n\t\t// size_type size() const;\n\t\tEATEST_VERIFY(toListStack.empty());\n\t\tEATEST_VERIFY(toListStack.size() == 0);\n\n\n\t\t// global operators\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) == 0));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) != 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) <= 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) >= 0));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) < 0));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) > 0));\n\n\t\ttoListStack.push(TestObject(0));\n\t\ttoListStack.push(TestObject(1));\n\t\ttoListStack2.push(TestObject(0));\n\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) == 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) != 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) >= 0));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) <= 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) > 0));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) < 0));\n\n\t\t// Verify toListStack2 > toListStack by element size\n\t\ttoListStack2.push(TestObject(3));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) == 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) != 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) <= 0));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) >= 0));\n\t\tEATEST_VERIFY( ((toListStack <=> toListStack2) < 0));\n\t\tEATEST_VERIFY(!((toListStack <=> toListStack2) > 0));\n\n\t\tstack<TestObject, list<TestObject> > toListStack3;\n\t\tstack<TestObject, list<TestObject> > toListStack4;\n\n\t\tfor (int i = 0; i < 10; i++)\n\t\t{\n\t\t\ttoListStack3.push(TestObject(i));\n\t\t\tif (i < 5)\n\t\t\t\ttoListStack4.push(TestObject(i));\n\t\t}\n\n\t\t// Verify toListStack4 is a strict subset of toListStack3\n\t\tEATEST_VERIFY(!((toListStack3 <=> toListStack4) == 0));\n\t\tEATEST_VERIFY( ((toListStack3 <=> toListStack4) != 0));\n\t\tEATEST_VERIFY( ((toListStack3 <=> toListStack4) >= 0));\n\t\tEATEST_VERIFY(!((toListStack3 <=> toListStack4) <= 0));\n\t\tEATEST_VERIFY( ((toListStack3 <=> toListStack4) > 0));\n\t\tEATEST_VERIFY(!((toListStack3 <=> toListStack4) < 0));\n\n\t\t// Verify that even thoughn toListQueue4 has a smaller size, it's lexicographically larger\n\t\ttoListStack4.push(TestObject(11));\n\t\tEATEST_VERIFY(!((toListStack3 <=> toListStack4) == 0));\n\t\tEATEST_VERIFY( ((toListStack3 <=> toListStack4) != 0));\n\t\tEATEST_VERIFY( ((toListStack3 <=> toListStack4) <= 0));\n\t\tEATEST_VERIFY(!((toListStack3 <=> toListStack4) >= 0));\n\t\tEATEST_VERIFY( ((toListStack3 <=> toListStack4) < 0));\n\t\tEATEST_VERIFY(!((toListStack3 <=> toListStack4) > 0));\n\t}\n\n\t{\n\t\tstack<TestObject, list<TestObject> > toListStack1;\n\t\tstack<TestObject, list<TestObject> > toListStack2;\n\t\tstack<TestObject, list<TestObject> > toListStack3;\n\n\t\tfor (int i = 0; i < 10; i++)\n\t\t{\n\t\t\ttoListStack1.push(TestObject(i));\n\t\t\ttoListStack2.push(TestObject(9-i));\n\t\t\tif (i < 5)\n\t\t\t\ttoListStack3.push(TestObject(i));\n\t\t}\n\n\t\tstruct weak_ordering_stack\n\t\t{\n\t\t\tstack<TestObject, list<TestObject> > stack;\n\t\t    inline std::weak_ordering operator<=>(const weak_ordering_stack& b) const { return stack <=> b.stack; }\n\t\t};\n\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack1}, weak_ordering_stack{toListStack2}) == std::weak_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack3}, weak_ordering_stack{toListStack1}) == std::weak_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack2}, weak_ordering_stack{toListStack1}) == std::weak_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack2}, weak_ordering_stack{toListStack3}) == std::weak_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack1}, weak_ordering_stack{toListStack1}) == std::weak_ordering::equivalent);\n\t}\n#endif\n\n\n\t{\n\t\tvector<TestObject> toVector;\n\t\tfor(int i = 0; i < 100; i++)\n\t\t\ttoVector.push_back(TestObject(i));\n\n\t\t// template <class Allocator>\n\t\t// stack(this_type&& x, const Allocator& allocator, typename eastl::enable_if<eastl::uses_allocator<container_type, Allocator>::value>::type* = NULL);\n\t\t//\n\t\t// explicit stack(container_type&& x);\n\t\t//\n\t\t// void push(value_type&& x);\n\t\tstack<TestObject, vector<TestObject> > toS_0;\n\t\tstack<TestObject, vector<TestObject> > toS_A(eastl::move(toS_0), toS_0.get_container().get_allocator()); // It would be better if we also tested an alternative allocator.\n\t\tEATEST_VERIFY(toS_A.size() == 0);\n\t\ttoS_A.push(TestObject(1000));\n\t\tEATEST_VERIFY(toS_A.size() == 1);\n\n\t\tstack<TestObject, vector<TestObject> > toS_B(eastl::move(toS_A), toS_A.get_container().get_allocator()); // It would be better if we also tested an alternative allocator.\n\t\tEATEST_VERIFY((toS_B.size() == 1) && toS_A.empty());\n\n\t\teastl::vector<TestObject> toVectorM(toVector);\n\t\tstack<TestObject, vector<TestObject> > toS_C(eastl::move(toVectorM));\n\t\tEATEST_VERIFY((toS_C.size() == toVector.size()) && toVectorM.empty());\n\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED() // emplace_back: was declared deprecated\n\t\t{\n\t\t\t// template <class... Args>\n\t\t\t// void emplace_back(Args&&... args);\n\t\t\tstack<TestObject, vector<TestObject>> toS_D;\n\t\t\ttoS_D.emplace_back(0, 1, 2);\n\t\t\tEATEST_VERIFY(toS_D.size() == 1) && (toS_D.top() == TestObject(0, 1, 2));\n\t\t}\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED() // emplace_back: was declared deprecated\n\n\t\t{\n\t\t\t// template <class... Args>\n\t\t\t// decltype(auto) emplace(Args&&... args);\n\t\t\tstack<TestObject, vector<TestObject>> toS_D;\n\t\t\tauto it = toS_D.emplace(0, 1, 2);\n\t\t\tEATEST_VERIFY(toS_D.size() == 1) && (toS_D.top() == TestObject(0, 1, 2));\n\t\t\tEATEST_VERIFY(it == TestObject(0, 1, 2));\n\t\t}\n\t}\n\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\nstruct Size0\n{\n\t// Empty\n};\n\nstruct Size4\n{\n\tuint32_t m32;\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestCompressedPair\n//\nstatic int TestCompressedPair()\n{\n\tint nErrorCount = 0;\n\n\tcompressed_pair<Size0, Size0> cp00;\n\tcompressed_pair<Size0, Size4> cp04;\n\tcompressed_pair<Size4, Size0> cp40;\n\tcompressed_pair<Size4, Size4> cp44;\n\n\tEATEST_VERIFY(sizeof(cp00) <= 4);\n\tEATEST_VERIFY(sizeof(cp04) <= 4);\n\tEATEST_VERIFY(sizeof(cp40) <= 4);\n\tEATEST_VERIFY(sizeof(cp44) <= 8);\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\ntemplate <typename T>\nstruct CallTraitsContainer\n{\n   typedef typename eastl::call_traits<T>::param_type       param_type;\n   typedef typename eastl::call_traits<T>::reference        reference;\n   typedef typename eastl::call_traits<T>::const_reference  const_reference;\n   typedef typename eastl::call_traits<T>::value_type       result_type;\n   typedef T                                                value_type;\n\npublic:\n   value_type mValue;\n   \n\n   CallTraitsContainer() { }\n   CallTraitsContainer(param_type p) : mValue(p) { }\n\n   CallTraitsContainer<T>& operator=(const CallTraitsContainer<T>&) { } // Defined simply to prevent possible compiler warnings.\n\n   result_type value() { return mValue; }\n\n   reference       get()             { return mValue; }\n   const_reference const_get() const { return mValue; }\n\n   void call(param_type p){ }\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestCallTraits\n//\nstatic int TestCallTraits()\n{\n\tint nErrorCount = 0;\n\n\tCallTraitsContainer<int>    ctcInt;\n\tCallTraitsContainer<int*>   ctcIntPtr;\n\tCallTraitsContainer<int&>   ctcVoid(nErrorCount);\n\tCallTraitsContainer<int[3]> ctcIntArray;\n\n\tconst int kBufferSize = 128;\n\tchar buffer[kBufferSize];\n\tEA::StdC::Snprintf(buffer, kBufferSize, \"%p %p %p %p\", &ctcInt, &ctcIntPtr, &ctcVoid, &ctcIntArray);\n\n\treturn nErrorCount;\n}\n\n\nstatic int AccumulateMultiply(int x, int y)\n{\n\treturn (x * y);\n}\n\nstatic eastl::string AccumulateString(eastl::string s, int x)\n{\n\ts += '0' + static_cast<char>(x);\n\treturn s;\n}\n \n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestNumeric\n//\nstatic int TestNumeric()\n{\n\tint nErrorCount = 0;\n\n\t//template <typename InputIterator, typename T>\n\t//T accumulate(InputIterator first, InputIterator last, T init);\n\teastl::vector<int> v(5, 0);\n\teastl::generate(v.begin(), v.end(), GenerateIncrementalIntegers<int>(1));\n\n\tint sum = eastl::accumulate(v.begin(), v.end(), 100);\n\tEATEST_VERIFY(sum == (100 + 1 + 2 + 3 + 4 + 5));\n\n\n\t// template <typename InputIterator, typename T, typename BinaryOperation>\n\t//T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);\n\n\teastl::generate(v.begin(), v.end(), GenerateIncrementalIntegers<int>(1));\n\tint product = eastl::accumulate(v.begin(), v.end(), 100, AccumulateMultiply);\n\tEATEST_VERIFY(product == (100 * 1 * 2 * 3 * 4 * 5));\n\n\teastl::generate(v.begin(), v.end(), GenerateIncrementalIntegers<int>(1));\n\teastl::string s = eastl::accumulate(v.begin(), v.end(), eastl::string(\"0\"), AccumulateString);\n\tEATEST_VERIFY(s == \"012345\");\n\n\n\t//template <typename InputIterator1, typename InputIterator2, typename T>\n\t//T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init);\n\t// To do.\n\n\t//template <typename InputIterator1, typename InputIterator2, typename T, typename BinaryOperation1, typename BinaryOperation2>\n\t//T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2)\n\t// To do.\n\n\t//template <typename InputIterator, typename OutputIterator>\n\t//OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result);\n\t// To do.\n\n\t//template <typename InputIterator, typename OutputIterator, typename BinaryOperation>\n\t//OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);\n\t// To do.\n\n\treturn nErrorCount;\n}\n\n#if defined(EA_COMPILER_CPP20_ENABLED)\n\nEA_DISABLE_VC_WARNING(4756) // warning C4756: overflow in constant arithmetic\n\ntemplate <typename T>\nstatic constexpr int SignedIntMidpoint()\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(0)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(2)) == T(1));\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(4)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(8)) == T(4));\n\tEATEST_VERIFY(eastl::midpoint(T(2), T(0)) == T(1));\n\tEATEST_VERIFY(eastl::midpoint(T(4), T(0)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(8), T(0)) == T(4));\n\n\tEATEST_VERIFY(eastl::midpoint(T(1), T(1)) == T(1));\n\tEATEST_VERIFY(eastl::midpoint(T(1), T(3)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(3), T(1)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(2), T(6)) == T(4));\n\tEATEST_VERIFY(eastl::midpoint(T(6), T(2)) == T(4));\n\n\tEATEST_VERIFY(eastl::midpoint(T(-1), T(-1)) == T(-1));\n\tEATEST_VERIFY(eastl::midpoint(T(-1), T(-3)) == T(-2));\n\tEATEST_VERIFY(eastl::midpoint(T(-3), T(-1)) == T(-2));\n\tEATEST_VERIFY(eastl::midpoint(T(-2), T(-6)) == T(-4));\n\tEATEST_VERIFY(eastl::midpoint(T(-6), T(-2)) == T(-4));\n\n\tEATEST_VERIFY(eastl::midpoint(T(-0), T(0)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(-0)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(-0), T(-0)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(-1), T(1)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(-10), T(10)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(-3), T(7)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(-7), T(3)) == T(-2));\n\tEATEST_VERIFY(eastl::midpoint(T(-2), T(6)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(-6), T(2)) == T(-2));\n\tEATEST_VERIFY(eastl::midpoint(T(2), T(-6)) == T(-2));\n\tEATEST_VERIFY(eastl::midpoint(T(6), T(-2)) == T(2));\n\n\t// If an odd sum, midpoint should round towards the LHS operand.\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(5)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(5), T(0)) == T(3));\n\tEATEST_VERIFY(eastl::midpoint(T(1), T(4)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(4), T(1)) == T(3));\n\tEATEST_VERIFY(eastl::midpoint(T(7), T(10)) == T(8));\n\tEATEST_VERIFY(eastl::midpoint(T(10), T(7)) == T(9));\n\tEATEST_VERIFY(eastl::midpoint(T(-1), T(2)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(2), T(-1)) == T(1));\n\tEATEST_VERIFY(eastl::midpoint(T(-5), T(4)) == T(-1));\n\tEATEST_VERIFY(eastl::midpoint(T(4), T(-5)) == T(0));\n\n\t// Test absolute limits\n\tconstexpr T MIN = eastl::numeric_limits<T>::min();\n\tconstexpr T MAX = eastl::numeric_limits<T>::max();\n\n\tEATEST_VERIFY(eastl::midpoint(MIN, MIN) == MIN);\n\tEATEST_VERIFY(eastl::midpoint(MAX, MAX) == MAX);\n\tEATEST_VERIFY(eastl::midpoint(MIN, MAX) == T(-1));\n\tEATEST_VERIFY(eastl::midpoint(MAX, MIN) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(MIN, T(0)) == MIN / 2);\n\tEATEST_VERIFY(eastl::midpoint(T(0), MIN) == MIN / 2);\n\tEATEST_VERIFY(eastl::midpoint(MAX, T(0)) == (MAX / 2) + 1);\n\tEATEST_VERIFY(eastl::midpoint(T(0), MAX) == (MAX / 2));\n\n\tEATEST_VERIFY(eastl::midpoint(MIN, T(10)) == (MIN / 2) + 5);\n\tEATEST_VERIFY(eastl::midpoint(T(10), MIN) == (MIN / 2) + 5);\n\tEATEST_VERIFY(eastl::midpoint(MAX, T(10)) == (MAX / 2) + 5 + 1);\n\tEATEST_VERIFY(eastl::midpoint(T(10), MAX) == (MAX / 2) + 5);\n\tEATEST_VERIFY(eastl::midpoint(MIN, T(-10)) == (MIN / 2) - 5);\n\tEATEST_VERIFY(eastl::midpoint(T(-10), MIN) == (MIN / 2) - 5);\n\tEATEST_VERIFY(eastl::midpoint(MAX, T(-10)) == (MAX / 2) - 5 + 1);\n\tEATEST_VERIFY(eastl::midpoint(T(-10), MAX) == (MAX / 2) - 5);\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nstatic constexpr int UnsignedIntMidpoint()\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(0)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(2)) == T(1));\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(4)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(8)) == T(4));\n\tEATEST_VERIFY(eastl::midpoint(T(2), T(0)) == T(1));\n\tEATEST_VERIFY(eastl::midpoint(T(4), T(0)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(8), T(0)) == T(4));\n\n\tEATEST_VERIFY(eastl::midpoint(T(1), T(1)) == T(1));\n\tEATEST_VERIFY(eastl::midpoint(T(1), T(3)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(3), T(1)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(2), T(6)) == T(4));\n\tEATEST_VERIFY(eastl::midpoint(T(6), T(2)) == T(4));\n\n\t// If an odd sum, midpoint should round towards the LHS operand.\n\tEATEST_VERIFY(eastl::midpoint(T(0), T(5)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(5), T(0)) == T(3));\n\tEATEST_VERIFY(eastl::midpoint(T(1), T(4)) == T(2));\n\tEATEST_VERIFY(eastl::midpoint(T(4), T(1)) == T(3));\n\tEATEST_VERIFY(eastl::midpoint(T(7), T(10)) == T(8));\n\tEATEST_VERIFY(eastl::midpoint(T(10), T(7)) == T(9));\n\n\t// Test absolute limits\n\tconstexpr T MIN = eastl::numeric_limits<T>::min();\n\tconstexpr T MAX = eastl::numeric_limits<T>::max();\n\n\tEATEST_VERIFY(eastl::midpoint(MIN, MIN) == MIN);\n\tEATEST_VERIFY(eastl::midpoint(MAX, MAX) == MAX);\n\tEATEST_VERIFY(eastl::midpoint(MIN, MAX) == MAX / 2);\n\tEATEST_VERIFY(eastl::midpoint(MAX, MIN) == (MAX / 2) + 1);\n\tEATEST_VERIFY(eastl::midpoint(MIN, T(0)) == T(0));\n\tEATEST_VERIFY(eastl::midpoint(T(0), MIN) == T(0));\n\n\tEATEST_VERIFY(eastl::midpoint(MIN, T(10)) == (MIN / 2) + 5);\n\tEATEST_VERIFY(eastl::midpoint(T(10), MIN) == (MIN / 2) + 5);\n\tEATEST_VERIFY(eastl::midpoint(MAX, T(10)) == (MAX / 2) + 5 + 1);\n\tEATEST_VERIFY(eastl::midpoint(T(10), MAX) == (MAX / 2) + 5);\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nstatic constexpr int FloatMidpoint()\n{\n\t// for use with floats, double, long doubles.\n\tint nErrorCount = 0;\n\tEATEST_VERIFY(eastl::midpoint(T(0.0), T(0.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::midpoint(T(0.0), T(2.0)) == T(1.0));\n\tEATEST_VERIFY(eastl::midpoint(T(0.0), T(4.0)) == T(2.0));\n\tEATEST_VERIFY(eastl::midpoint(T(2.0), T(0.0)) == T(1.0));\n\tEATEST_VERIFY(eastl::midpoint(T(4.0), T(0.0)) == T(2.0));\n\n\tEATEST_VERIFY(eastl::midpoint(T(0.5), T(0.5)) == T(0.5));\n\tEATEST_VERIFY(eastl::midpoint(T(0.0), T(0.5)) == T(0.25));\n\tEATEST_VERIFY(eastl::midpoint(T(0.5), T(0.0)) == T(0.25));\n\tEATEST_VERIFY(eastl::midpoint(T(0.5), T(1.0)) == T(0.75));\n\tEATEST_VERIFY(eastl::midpoint(T(1.0), T(0.5)) == T(0.75));\n\n\tEATEST_VERIFY(eastl::midpoint(T(-0.0), T(0.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::midpoint(T(0.0), T(-0.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::midpoint(T(-0.0), T(-0.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::midpoint(T(-1.0), T(2.0)) == T(0.5));\n\tEATEST_VERIFY(eastl::midpoint(T(-2.0), T(1)) == T(-0.5));\n\tEATEST_VERIFY(eastl::midpoint(T(-3.0), T(6.0)) == T(1.5));\n\tEATEST_VERIFY(eastl::midpoint(T(-6.0), T(3.0)) == T(-1.5));\n\n\t// Test absolute limits\n\tconst T MIN = eastl::numeric_limits<T>::min();\n\tconst T MAX = eastl::numeric_limits<T>::max();\n\n\tEATEST_VERIFY(eastl::midpoint(MIN, MIN) == MIN);\n\tEATEST_VERIFY(eastl::midpoint(MAX, MAX) == MAX);\n\tEATEST_VERIFY(eastl::midpoint(MIN, MAX) == MAX / 2);\n\tEATEST_VERIFY(eastl::midpoint(MAX, MIN) == MAX / 2);\n\tEATEST_VERIFY(eastl::midpoint(-MAX, MIN) == -MAX / 2);\n\n\tEATEST_VERIFY(eastl::midpoint(MIN, T(9.0)) == T(4.5));\n\tEATEST_VERIFY(eastl::midpoint(MIN, T(-9.0)) == T(-4.5));\n\tEATEST_VERIFY(eastl::midpoint(T(9.0), MIN) == T(4.5));\n\tEATEST_VERIFY(eastl::midpoint(T(-9.0), MIN) == T(-4.5));\n\tEATEST_VERIFY(eastl::midpoint(MAX, T(9.0)) == MAX / 2 + T(4.5));\n\tEATEST_VERIFY(eastl::midpoint(MAX, T(-9.0)) == MAX / 2 - T(4.5));\n\tEATEST_VERIFY(eastl::midpoint(T(9.0), MAX) == MAX / 2 + T(4.5));\n\tEATEST_VERIFY(eastl::midpoint(T(-9.0), MAX) == MAX / 2 - T(4.5));\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T>\nstatic constexpr int PointerMidpoint()\n{\n\tint nErrorCount = 0;\n\n\tconst T ARR[100] = {};\n\n\tEATEST_VERIFY(eastl::midpoint(ARR, ARR) == ARR);\n\tEATEST_VERIFY(eastl::midpoint(ARR, ARR + 100) == ARR + 50);\n\tEATEST_VERIFY(eastl::midpoint(ARR + 100, ARR) == ARR + 50);\n\tEATEST_VERIFY(eastl::midpoint(ARR, ARR + 25) == ARR + 12);\n\tEATEST_VERIFY(eastl::midpoint(ARR + 25, ARR) == ARR + 13);\n\tEATEST_VERIFY(eastl::midpoint(ARR, ARR + 13) == ARR + 6);\n\tEATEST_VERIFY(eastl::midpoint(ARR + 13, ARR) == ARR + 7);\n\tEATEST_VERIFY(eastl::midpoint(ARR + 50, ARR + 100) == ARR + 75);\n\tEATEST_VERIFY(eastl::midpoint(ARR + 100, ARR + 50) == ARR + 75);\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMidpoint\n//\nstatic int TestMidpoint()\n{\n\tint nErrorCount = 0;\n\n\t// template <typename T>\n\t// constexpr eastl::enable_if_t<eastl::is_arithmetic_v<T> && !eastl::is_same_v<eastl::remove_cv_t<T>, bool>, T> \n\t// midpoint(const T lhs, const T rhs) EA_NOEXCEPT\n\tnErrorCount += SignedIntMidpoint<int>();\n\tnErrorCount += SignedIntMidpoint<char>();\n\tnErrorCount += SignedIntMidpoint<short>();\n\tnErrorCount += SignedIntMidpoint<long>();\n\tnErrorCount += SignedIntMidpoint<long long>();\n\n\tnErrorCount += UnsignedIntMidpoint<unsigned int>();\n\tnErrorCount += UnsignedIntMidpoint<unsigned char>();\n\tnErrorCount += UnsignedIntMidpoint<unsigned short>();\n\tnErrorCount += UnsignedIntMidpoint<unsigned long>();\n\tnErrorCount += UnsignedIntMidpoint<unsigned long long>();\n\n\tnErrorCount += FloatMidpoint<float>();\n\tnErrorCount += FloatMidpoint<double>();\n\tnErrorCount += FloatMidpoint<long double>();\n\n\t// template <typename T>\n\t// constexpr eastl::enable_if_t<eastl::is_object_v<T>, const T*> midpoint(const T* lhs, const T* rhs)\n\tnErrorCount += PointerMidpoint<int>();\n\tnErrorCount += PointerMidpoint<char>();\n\tnErrorCount += PointerMidpoint<short>();\n\tnErrorCount += PointerMidpoint<float>();\n\tnErrorCount += PointerMidpoint<double>();\n\tnErrorCount += PointerMidpoint<long double>();\n\n\treturn nErrorCount;\n}\n\nEA_RESTORE_VC_WARNING(); // warning C4756: overflow in constant arithmetic\n\n#endif\n\ntemplate <typename T>\nstatic constexpr int FloatLerp()\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::lerp(T(0.0), T(0.0), T(0.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::lerp(T(1.0), T(0.0), T(0.0)) == T(1.0));\n\tEATEST_VERIFY(eastl::lerp(T(-1.0), T(0.0), T(0.0)) == T(-1.0));\n\tEATEST_VERIFY(eastl::lerp(T(0.0), T(1.0), T(0.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::lerp(T(0.0), T(-1.0), T(0.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::lerp(T(-1.0), T(1.0), T(1.0)) == T(1.0));\n\tEATEST_VERIFY(eastl::lerp(T(1.0), T(-1.0), T(1.0)) == T(-1.0));\n\tEATEST_VERIFY(eastl::lerp(T(-1.0), T(1.0), T(0.5)) == T(0.0));\n\tEATEST_VERIFY(eastl::lerp(T(1.0), T(-1.0), T(0.5)) == T(0.0));\n\tEATEST_VERIFY(eastl::lerp(T(5.0), T(5.0), T(0.5)) == T(5.0));\n\tEATEST_VERIFY(eastl::lerp(T(-5.0), T(-5.0), T(0.5)) == T(-5.0));\n\tEATEST_VERIFY(eastl::lerp(T(1.0), T(2.0), T(1.0)) == T(2.0));\n\tEATEST_VERIFY(eastl::lerp(T(2.0), T(1.0), T(1.0)) == T(1.0));\n\tEATEST_VERIFY(eastl::lerp(T(1.0), T(2.0), T(1.0)) == T(2.0));\n\tEATEST_VERIFY(eastl::lerp(T(1.0), T(2.0), T(2.0)) == T(3.0));\n\tEATEST_VERIFY(eastl::lerp(T(2.0), T(1.0), T(2.0)) == T(0.0));\n\tEATEST_VERIFY(eastl::lerp(T(1.0), T(-2.0), T(2.0)) == T(-5.0));\n\tEATEST_VERIFY(eastl::lerp(T(-1.0), T(2.0), T(2.0)) == T(5.0));\n\tEATEST_VERIFY(eastl::lerp(T(-1.5), T(1.5), T(0.75)) == T(0.75));\n\tEATEST_VERIFY(eastl::lerp(T(0.125), T(1.75), T(0.25)) == T(0.53125));\n\tEATEST_VERIFY(eastl::lerp(T(-0.125), T(-1.75), T(0.5)) == T(-0.9375));\n\tEATEST_VERIFY(eastl::lerp(T(-0.125), T(1.5), T(2.5)) == T(3.9375));\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestLerp\n//\nstatic int TestLerp()\n{\n\tint nErrorCount = 0;\n\n\t// template <class T>\n\t// constexpr T lerp(const T a, const T b, const T t) EA_NOEXCEPT\n\tnErrorCount += FloatLerp<float>();\n\tnErrorCount += FloatLerp<double>();\n\tnErrorCount += FloatLerp<long double>();\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestAdaptors\n//\nstatic int TestAdaptors()\n{\n\tint nErrorCount = 0;\n\n\t// reverse lvalue container\n\t{\n\t\tint int_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::vector<int> original(begin(int_data), end(int_data));\n\n\t\teastl::vector<int> reversed;\n\t\tfor(auto& e : eastl::reverse(original))\n\t\t\treversed.push_back(e);\n\n\t\teastl::reverse(begin(original), end(original));\n\t\tEATEST_VERIFY(reversed == original);\n\t}\n\n\t// reverse const lvalue container\n\t{\n\t\tint int_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\tconst eastl::vector<int> original(begin(int_data), end(int_data));\n\n\t\teastl::vector<int> reversed;\n\t\tfor(auto& e : eastl::reverse(original))\n\t\t\treversed.push_back(e);\n\n\t\teastl::vector<int> reversed_original(original);\n\t\teastl::reverse(begin(reversed_original), end(reversed_original));\n\t\tEATEST_VERIFY(reversed == reversed_original);\n\t}\n\n\t// reverse rvalue container\n\t{\n\t\tint int_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::vector<int> original(begin(int_data), end(int_data));\n\n\t\teastl::vector<int> reversed;\n\t\tfor (auto& e : eastl::reverse(eastl::vector<int>(original)))\n\t\t\treversed.push_back(e);\n\n\t\teastl::reverse(begin(original), end(original));\n\t\tEATEST_VERIFY(reversed == original);\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestExtra\n//\nint TestExtra()\n{\n\tint nErrorCount = 0;\n\t\n\tnErrorCount += TestForwardDeclarations();\n\tnErrorCount += TestQueue();\n\tnErrorCount += TestPriorityQueue();\n\tnErrorCount += TestStack();\n\tnErrorCount += TestCompressedPair();\n\tnErrorCount += TestCallTraits();\n\tnErrorCount += TestNumeric();\n\tnErrorCount += TestAdaptors();\n#if defined(EA_COMPILER_CPP20_ENABLED)\n\tnErrorCount += TestMidpoint();\n#endif\n\tnErrorCount += TestLerp();\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestFinally.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/finally.h>\n\n\nint TestFinally()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\t#if defined(EA_COMPILER_CPP17_ENABLED)\n\t\t{\n\t\t\t// requires CTAD (class template argument deduction)\n\t\t\tint a = 0;\n\t\t\t{\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\teastl::finally _([&] { a = 42; }); \n\t\t\t\tVERIFY(a == 0);\n\t\t\t}\n\t\t\tVERIFY(a == 42);\n\t\t}\n\t\t#endif\n\n\t\t{\n\t\t\tint a = 0;\n\t\t\t{\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\tauto _ = eastl::make_finally([&] { a = 42; });\n\t\t\t\tVERIFY(a == 0);\n\t\t\t}\n\t\t\tVERIFY(a == 42);\n\t\t}\n\n\t\t{\n\t\t\tint a = 0;\n\t\t\t{\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\tauto f = eastl::make_finally([&] { a = 42; });\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\tf.dismiss();\n\t\t\t\tVERIFY(a == 0);\n\t\t\t}\n\t\t\tVERIFY(a == 0);\n\t\t}\n\n\t\t{\n\t\t\tint a = 0;\n\t\t\t{\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\tauto f = eastl::make_finally([&] { a = 42; });\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\tf.execute();\n\t\t\t\tVERIFY(a == 42);\n\t\t\t}\n\t\t\tVERIFY(a == 42);\n\t\t}\n\t\t\n\t\t{\n\t\t\tint a = 0;\n\t\t\t{\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\tauto f = eastl::make_finally([&] { a = 42; });\n\t\t\t\tVERIFY(a == 0);\n\t\t\t\tf.execute();\n\t\t\t\tVERIFY(a == 42);\n\n\t\t\t\t// verify the finally object doesn't re-run the callback on scope-exit.\n\t\t\t\ta = -1;  \n\t\t\t}\n\t\t\tVERIFY(a == -1);\n\t\t}\n\n\t\t{\n\t\t\tstruct local_flag { bool b = false; };\n\n\t\t\tlocal_flag lf;\n\t\t\tVERIFY(lf.b == false);\n\n\t\t\t{ auto _ = eastl::make_finally([&] { lf.b = true; }); }\n\n\t\t\tVERIFY(lf.b);\n\t\t}\n\n\t\t// This currently does not compile by design.\n\t\t//\n\t\t// {\n\t\t//     int a = 0;\n\t\t//     auto lbda = [&a] { a = 1234; };\n\t\t//     {\n\t\t//         VERIFY(a == 0);\n\t\t//         auto _ = eastl::make_finally(lbda);  // compiler error\n\t\t//         VERIFY(a == 0);\n\t\t//     }\n\t\t//     VERIFY(a == 1234);\n\t\t// }\n\t}\n\n\treturn nErrorCount;\n}\n\n\n"
  },
  {
    "path": "test/source/TestFixedFunction.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include <EABase/eabase.h>\n#include <EAAssert/eaassert.h>\n\n// Included prior to EASTLTest.h to guard against the following bug resurfacing:\n// https://github.com/electronicarts/EASTL/issues/275\n#include <EASTL/fixed_function.h>\n\n#include \"EASTLTest.h\"\n#include <EASTL/numeric.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <functional>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionDtor\n//\nint TestFixedFunctionDtor()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\tTestObject to;\n\t\tTestObject::Reset();\n\t\t{\n\t\t\teastl::fixed_function<sizeof(TestObject), void(void)> ff = [to] {};\n\t\t\tff();\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionStdBind\n//\nint TestFixedFunctionStdBind()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\tint val = 0;\n\n\t{\n\t\tTestObject to;\n\t\tauto lambda = [to, &val] { ++val; };\n\t\tTestObject::Reset();\n\t\t{\n\t\t\teastl::fixed_function<64, void(void)> ff = std::bind(lambda);\n\t\t\tff();\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tVERIFY(val == 1);\n\t}\n\t{\n\t\tTestObject to;\n\t\tauto lambda = [to, &val] { ++val; };\n\t\tTestObject::Reset();\n\t\t{\n\t\t\teastl::fixed_function<64, void(void)> ff = nullptr;\n\t\t    ff = std::bind(lambda);\n\t\t\tff();\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tVERIFY(val == 2);\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionReferenceWrapper\n//\nint TestFixedFunctionReferenceWrapper()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\tint val = 0;\n\n\t{\n\t\tTestObject to;\n\t\tauto lambda = [to, &val] { ++val; };\n\t\tTestObject::Reset();\n\t\t{\n\t\t\teastl::fixed_function<sizeof(eastl::reference_wrapper<decltype(lambda)>), void(void)> ff = eastl::reference_wrapper<decltype(lambda)>(lambda);\n\t\t\tff();\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tVERIFY(val == 1);\n\t}\n\t{\n\t\tTestObject to;\n\t\tauto lambda = [to, &val] { ++val; };\n\t\tTestObject::Reset();\n\t\t{\n\t\t\teastl::fixed_function<sizeof(eastl::reference_wrapper<decltype(lambda)>), void(void)> ff = nullptr;\n\t\t    ff = eastl::reference_wrapper<decltype(lambda)>(lambda);\n\t\t\tff();\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tVERIFY(val == 2);\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionFunctionPointer\n//\n\nstatic void TestVoidRet(int* p)\n{\n\t*p += 1;\n}\n\nstatic int TestIntRet(int* p)\n{\n\tint ret = *p;\n\t*p += 1;\n\treturn ret;\n}\n\nint TestFixedFunctionFunctionPointer()\n{\n\tusing namespace eastl;\n\n\ttypedef int (*FuncPtrInt)(int*);\n\ttypedef void (*FuncPtrVoid)(int*);\n\n\tint nErrorCount = 0;\n\tint val = 0;\n\n\t{\n\t\teastl::fixed_function<sizeof(FuncPtrVoid), void(int*)> ff = &TestVoidRet;\n\t\tff(&val);\n\t\tVERIFY(val == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(FuncPtrVoid), void(int*)> ff;\n\t\tff = &TestVoidRet;\n\t\tff(&val);\n\t\tVERIFY(val == 2);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(FuncPtrInt), int(int*)> ff = &TestIntRet;\n\t\tint ret = ff(&val);\n\t\tVERIFY(ret == 2);\n\t\tVERIFY(val == 3);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(FuncPtrInt), int(int*)> ff;\n\t\tff = &TestIntRet;\n\t\tint ret = ff(&val);\n\t\tVERIFY(ret == 3);\n\t\tVERIFY(val == 4);\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionPointerToMemberFunction\n//\n\nint TestFixedFunctionPointerToMemberFunction()\n{\n\tusing namespace eastl;\n\n\tstruct TestVoidRet\n\t{\n\t\tTestVoidRet() : x(0) {}\n\t\t~TestVoidRet() = default;\n\n\t\tvoid IncX() const\n\t\t{\n\t\t\t++x;\n\t\t}\n\n\t\tvoid IncX()\n\t\t{\n\t\t\t++x;\n\t\t}\n\n\t\tmutable int x = 0;\n\t};\n\n\tstruct TestIntRet\n\t{\n\t\tTestIntRet() : x(0) {}\n\n\t\tint IncX() const\n\t\t{\n\t\t\treturn x++;\n\t\t}\n\n\t\tint IncX()\n\t\t{\n\t\t\treturn x++;\n\t\t}\n\n\t\tmutable int x = 0;\n\t};\n\n\tint nErrorCount = 0;\n\tTestVoidRet voidRet;\n\tTestIntRet intRet;\n\tconst TestVoidRet cvoidRet;\n\tconst TestIntRet cintRet;\n\n\ttypedef void (TestVoidRet::*PTMFSize)(void);\n\n\t{\n\t\teastl::fixed_function<sizeof(PTMFSize), void(const TestVoidRet&)> ff = static_cast<void(TestVoidRet::*)() const>(&TestVoidRet::IncX);\n\t\tff(cvoidRet);\n\t\tVERIFY(cvoidRet.x == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(PTMFSize), void(const TestVoidRet&)> ff = static_cast<void(TestVoidRet::*)() const>(&TestVoidRet::IncX);\n\t\tff(voidRet);\n\t\tVERIFY(voidRet.x == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(PTMFSize), void(TestVoidRet&)> ff = static_cast<void(TestVoidRet::*)()>(&TestVoidRet::IncX);\n\t\tff(voidRet);\n\t\tVERIFY(voidRet.x == 2);\n\t}\n\n\t{\n\t\teastl::fixed_function<sizeof(PTMFSize), int(const TestIntRet&)> ff = static_cast<int(TestIntRet::*)() const>(&TestIntRet::IncX);\n\t\tint ret = ff(cintRet);\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(cintRet.x == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(PTMFSize), int(const TestIntRet&)> ff = static_cast<int(TestIntRet::*)() const>(&TestIntRet::IncX);\n\t\tint ret = ff(intRet);\n\t\tVERIFY(ret == 0);\n\t\tVERIFY(intRet.x == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(PTMFSize), int(TestIntRet&)> ff = static_cast<int(TestIntRet::*)()>(&TestIntRet::IncX);\n\t\tint ret = ff(intRet);\n\t\tVERIFY(ret == 1);\n\t\tVERIFY(intRet.x == 2);\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionPointerToMemberData\n//\n\nint TestFixedFunctionPointerToMemberData()\n{\n\tusing namespace eastl;\n\n\tstruct Test\n\t{\n\t\tTest() : x(1) {}\n\t\tint x = 1;\n\t};\n\n\tint nErrorCount = 0;\n\n\tTest t;\n\tconst Test ct;\n\n\t{\n\t\teastl::fixed_function<sizeof(void*), int(const Test&)> ff = &Test::x;\n\t\tint ret = ff(t);\n\t\tVERIFY(ret == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(void*), int(const Test&)> ff = &Test::x;\n\t\tint ret = ff(ct);\n\t\tVERIFY(ret == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(void*), int(const Test&)> ff;\n\t\tff = &Test::x;\n\t\tint ret = ff(t);\n\t\tVERIFY(ret == 1);\n\t}\n\t{\n\t\teastl::fixed_function<sizeof(void*), int(const Test&)> ff;\n\t\tff = &Test::x;\n\t\tint ret = ff(ct);\n\t\tVERIFY(ret == 1);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionExistingClosure\n//\nint TestFixedFunctionExistingClosure()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\tTestObject to;\n\t\t{\n\t\t\tusing ff_t = eastl::fixed_function<sizeof(TestObject), void(void)>;\n\t\t\t{\n\t\t\t\tff_t ff1 = [to] {};\n\t\t\t\tff_t  ff3 = [to] {};\n\t\t\t\tTestObject::Reset();\n\t\t\t\t{\n\t\t\t\t\tff_t ff2 = ff1;\n\t\t\t\t\tff2 = ff3;  // copy over function that holds existing closure state\n\t\t\t\t}\n\t\t\t\tVERIFY(TestObject::IsClear());\n\t\t\t}\n\t\t\t{\n\t\t\t\tff_t ff1 = [to] {};\n\t\t\t\tTestObject::Reset();\n\t\t\t\tff_t ff3 = [to] {};\n\t\t\t\t{\n\t\t\t\t\tff_t ff2 = ff1;\n\t\t\t\t\tff2 = eastl::move(ff3);  // copy over function that holds existing closure state\n\t\t\t\t}\n\t\t\t\tVERIFY(TestObject::IsClear());\n\t\t\t}\n\t\t\t{\n\t\t\t\tff_t ff1 = [to] {};\n\t\t\t\tTestObject::Reset();\n\t\t\t\t{\n\t\t\t\t\tff_t ff2 = ff1;\n\t\t\t\t\tff2 = nullptr;\n\t\t\t\t}\n\t\t\t\tVERIFY(TestObject::IsClear());\n\t\t\t}\n\t\t\t{\n\t\t\t\tTestObject::Reset();\n\t\t\t\tff_t ff1 = [to] {};\n\t\t\t\t{\n\t\t\t\t\tff_t ff2 = eastl::move(ff1);\n\t\t\t\t\tff2 = nullptr;\n\t\t\t\t}\n\t\t\t\tVERIFY(TestObject::IsClear());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionCaptureless\n//\n// Tests calling a captureless (eg. function pointer) callable with variable\n// eastl::fixed_function size types.\n//\ntemplate<class FixedFunctionT>\nint TestFixedFunctionCaptureless()\n{\n\tint nErrorCount = 0;\n\n\tFixedFunctionT fn;\n\n\tEATEST_VERIFY(!fn);\n\n\tfn =  [](int in) { return in; };\n\n\tEATEST_VERIFY(!!fn);\n\n\tEATEST_VERIFY(fn(42) == 42);\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionBasic\n//\nint TestFixedFunctionBasic()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\tstruct Functor { void operator()() { return; } };\n\t\tfixed_function<24, void(void)> fn;\n\t\tfixed_function<24, void(void)> fn2 = nullptr;\n\t\tEATEST_VERIFY(!fn);\n\t\tEATEST_VERIFY(!fn2);\n\t\tEATEST_VERIFY(fn == nullptr);\n\t\tEATEST_VERIFY(fn2 == nullptr);\n\t\tEATEST_VERIFY(nullptr == fn);\n\t\tEATEST_VERIFY(nullptr == fn2);\n\t\tfn = Functor();\n\t\tfn2 = Functor();\n\t\tEATEST_VERIFY(!!fn);\n\t\tEATEST_VERIFY(!!fn2);\n\t\tEATEST_VERIFY(fn != nullptr);\n\t\tEATEST_VERIFY(fn2 != nullptr);\n\t\tEATEST_VERIFY(nullptr != fn);\n\t\tEATEST_VERIFY(nullptr != fn2);\n\t\tfn = nullptr;\n\t\tfn2 = fn;\n\t\tEATEST_VERIFY(!fn);\n\t\tEATEST_VERIFY(!fn2);\n\t\tEATEST_VERIFY(fn == nullptr);\n\t\tEATEST_VERIFY(fn2 == nullptr);\n\t\tEATEST_VERIFY(nullptr == fn);\n\t\tEATEST_VERIFY(nullptr == fn2);\n\t}\n\n\t{\n\t\tusing eastl::swap;\n\t\tstruct Functor { int operator()() { return 5; } };\n\t\tfixed_function<24, int(void)> fn = Functor();\n\t\tfixed_function<24, int(void)> fn2;\n\t\tEATEST_VERIFY(fn() == 5);\n\t\tEATEST_VERIFY(!fn2);\n\t\tfn.swap(fn2);\n\t\tEATEST_VERIFY(!fn);\n\t\tEATEST_VERIFY(fn2() == 5);\n\t\tswap(fn, fn2);\n\t\tEATEST_VERIFY(fn() == 5);\n\t\tEATEST_VERIFY(!fn2);\n\t}\n\n\t{\n\t\tstruct Functor { int operator()() { return 42; } };\n\t\tfixed_function<0, int(void)> fn = Functor();\n\t\tEATEST_VERIFY(fn() == 42);\n\t}\n\n\t{\n\t\tstruct Functor { int operator()(int in) { return in; } };\n\t\tfixed_function<0, int(int)> fn = Functor();\n\t\tEATEST_VERIFY(fn(24) == 24);\n\t}\n\n\t{\n\t\teastl::fixed_function<0, void(void)> fn;\n\n\t\tEATEST_VERIFY(!fn);\n\t\tfn =  [] {};\n\t\tEATEST_VERIFY(!!fn);\n\t}\n\n\t{\n\t\teastl::fixed_function<0, int(int)> fn = [](int param) { return param; };\n\t\tEATEST_VERIFY(fn(42) == 42);\n\t}\n\n\t{\n\t\teastl::fixed_function<0, int(int)> fn = ReturnVal;\n\t\tEATEST_VERIFY(fn(42) == 42);\n\t}\n\n\t{\n\t\teastl::fixed_function<0, int()> fn0 = ReturnZero;\n\t\teastl::fixed_function<0, int()> fn1 = ReturnOne;\n\n\t\tEATEST_VERIFY(fn0() == 0 && fn1() == 1);\n\t\tswap(fn0, fn1);\n\t\tEATEST_VERIFY(fn0() == 1 && fn1() == 0);\n\t}\n\n\t{\n\t\teastl::fixed_function<0, int()> fn0 = ReturnZero;\n\t\teastl::fixed_function<0, int()> fn1 = ReturnOne;\n\n\t\tEATEST_VERIFY(fn0() == 0 && fn1() == 1);\n\t\tfn0 = fn1;\n\t\tEATEST_VERIFY(fn0() == 1 && fn1() == 1);\n\t}\n\n\t{\n\t\teastl::fixed_function<0, int()> fn0 = ReturnZero;\n\t\teastl::fixed_function<0, int()> fn1 = ReturnOne;\n\n\t\tEATEST_VERIFY(fn0() == 0 && fn1() == 1);\n\t\tfn0 = eastl::move(fn1);\n\t\tEATEST_VERIFY(fn0() == 1 && fn1 == nullptr);\n\t}\n\n\t{\n\t\teastl::fixed_function<0, int(int)> f1(nullptr);\n\t\tEATEST_VERIFY(!f1);\n\n\t\teastl::fixed_function<0, int(int)> f2 = nullptr;\n\t\tEATEST_VERIFY(!f2);\n\t}\n\n\t{\n\t\t// test using a large lambda capture\n\t\tuint64_t a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;\n\t\tauto large_add = [=] { return a + b + c + d + e + f; };\n\n\t\t{\n\t\t\teastl::fixed_function<48, uint64_t(void)> fn = large_add;\n\t\t\tauto result = fn();\n\t\t\tEATEST_VERIFY(result == 21);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_function<sizeof(large_add), uint64_t(void)> fn = large_add;\n\t\t\tauto result = fn();\n\t\t\tEATEST_VERIFY(result == 21);\n\t\t}\n\t}\n\n\t{\n\t\tusing ff_0 = eastl::fixed_function<0, int(int)>;\n\t\tusing ff_1 = eastl::fixed_function<1, int(int)>;\n\t\tusing ff_4 = eastl::fixed_function<4, int(int)>;\n\t\tusing ff_8 = eastl::fixed_function<8, int(int)>;\n\t\tusing ff_64 = eastl::fixed_function<64, int(int)>;\n\t\tusing ff_128 = eastl::fixed_function<128, int(int)>;\n\t\tusing ff_4096 = eastl::fixed_function<4096, int(int)>;\n\n\t\tstatic_assert(sizeof(ff_0) >= sizeof(void*), \"error\");\n\t\tstatic_assert(sizeof(ff_1) >= sizeof(void*), \"error\");\n\t\tstatic_assert(sizeof(ff_4) >= sizeof(void*), \"error\");\n\t\tstatic_assert(sizeof(ff_8) >= 8, \"error\");\n\t\tstatic_assert(sizeof(ff_64) >= 64, \"error\");\n\t\tstatic_assert(sizeof(ff_128) >= 128, \"error\");\n\t\tstatic_assert(sizeof(ff_4096) >= 4096, \"error\");\n\n\t\tnErrorCount += TestFixedFunctionCaptureless<ff_0>();\n\t\tnErrorCount += TestFixedFunctionCaptureless<ff_1>();\n\t\tnErrorCount += TestFixedFunctionCaptureless<ff_4>();\n\t\tnErrorCount += TestFixedFunctionCaptureless<ff_8>();\n\t\tnErrorCount += TestFixedFunctionCaptureless<ff_64>();\n\t\tnErrorCount += TestFixedFunctionCaptureless<ff_128>();\n\t\tnErrorCount += TestFixedFunctionCaptureless<ff_4096>();\n\t}\n\n\t// Verify conversions to fixed_function<N> for sizes greater or equal to the source size.\n\t{\n\t\tuint32_t v0 = 130480, v1 = 936780302;\n\t\tconst uint32_t result = v0 + v1;\n\n\t\teastl::fixed_function<8, uint32_t(void)> ff8 = [v0, v1]\n\t\t\t{ return v0 + v1; };\n\n\t\t{\n\t\t\teastl::fixed_function<16, uint32_t(void)> ff16(ff8);\n\t\t\tVERIFY(result == ff16());\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_function<16, uint32_t(void)> ff16 = ff8;\n\t\t\tVERIFY(result == ff16());\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_function<16, uint32_t(void)> ff16; \n\t\t\tff16 = ff8;\n\t\t\tVERIFY(result == ff16());\n\t\t}\n\n\t\t{\n\t\t\tauto ff8Copy = ff8;\n\t\t\teastl::fixed_function<16, uint32_t(void)> ff16(eastl::move(ff8Copy));\n\t\t\tVERIFY(result == ff16());\n\t\t}\n\n\t\t{\n\t\t\tauto ff8Copy = ff8;\n\t\t\teastl::fixed_function<16, uint32_t(void)> ff16 = eastl::move(ff8Copy);\n\t\t\tVERIFY(result == ff16());\n\t\t}\n\n\t\t{\n\t\t\tauto ff8Copy = ff8;\n\t\t\teastl::fixed_function<16, uint32_t(void)> ff16;\n\t\t\tff16 = eastl::move(ff8Copy);\n\t\t\tVERIFY(result == ff16());\n\t\t}\n\t}\n\n\t{\n\t\t\n\t\t{\n\t\t\tTestObject::Reset();\n\t\t\tTestObject theOriginal;\n\n\t\t\teastl::fixed_function<8, void(void)> ff8_ref = [&theOriginal]() { EA_UNUSED(theOriginal); };\n\t\t\teastl::fixed_function<16, void(void)> ff16_ref(ff8_ref);\n\t\t\teastl::fixed_function<32, void(void)> ff32_ref(ff16_ref);\n\t\t\n\t\t\tVERIFY(TestObject::sTOCtorCount == 1);\n\t\t\tVERIFY(TestObject::sTODtorCount == 0);\n\n\t\t\tVERIFY(TestObject::sTOMoveAssignCount == 0);\n\t\t\tVERIFY(TestObject::sTOCopyAssignCount == 0);\n\t\t\n\t\t\tVERIFY(TestObject::sTOMoveCtorCount == 0);\n\t\t\tVERIFY(TestObject::sTOCopyCtorCount == 0);\n\t\t}\n\t\t\n\t\t{\n\t\t\tTestObject::Reset();\n\t\t\tTestObject theOriginal; \n\n\t\t\teastl::fixed_function<32, void(void)> ff32_val = [theOriginal]() { EA_UNUSED(theOriginal); }; \n\t\t\t\n\t\t\t// When passing by value the lambda creation/assigment will also do some operations which we dont want to\n\t\t\t// track, so we instead capture the state here and check the difference\n\n\t\t\tint64_t ctorDiff = TestObject::sTOCtorCount;\n\t\t\tint64_t copyCtorCount = TestObject::sTOCopyCtorCount;\n\t\t\tint64_t moveCtorCount = TestObject::sTOMoveCtorCount;\n\n\t\t\teastl::fixed_function<64, void(void)> ff64_val(ff32_val);\n\t\t\teastl::fixed_function<128, void(void)> ff128_val(ff64_val);\n\t\t\n\t\t\tVERIFY(TestObject::sTOCount == 4);\n\t\t\tVERIFY((TestObject::sTOCtorCount - ctorDiff) == 2);\n\t\t\tVERIFY((TestObject::sTOCopyCtorCount - copyCtorCount) == 2);\n\t\t\tVERIFY((TestObject::sTOMoveCtorCount - moveCtorCount) == 0);\n\t\t}\n\n\t\t{\n\t\t\tTestObject::Reset();\n\t\t\tTestObject theOriginal;\n\n\t\t\teastl::fixed_function<32, void(void)> ff32_ref = [&theOriginal]() { EA_UNUSED(theOriginal); }; \n\t\t\teastl::fixed_function<64, void(void)> ff64_ref;\n\t\t\teastl::fixed_function<128, void(void)> ff128_ref;\n\n\t\t\tff64_ref = ff32_ref;\n\t\t\tff128_ref = ff64_ref;\n\n\t\t\tVERIFY(TestObject::sTOCtorCount == 1);\n\t\t\tVERIFY(TestObject::sTODtorCount == 0);\n\n\t\t\tVERIFY(TestObject::sTOMoveAssignCount == 0);\n\t\t\tVERIFY(TestObject::sTOCopyAssignCount == 0);\n\n\t\t\tVERIFY(TestObject::sTOMoveCtorCount == 0);\n\t\t\tVERIFY(TestObject::sTOCopyCtorCount == 0);\n\n\t\t}\n\n\t\t{\n\t\t\tTestObject::Reset();\n\t\t\tTestObject theOriginal;\n\n\t\t\teastl::fixed_function<32, void(void)> ff32_val = [theOriginal]() { EA_UNUSED(theOriginal); };\n\n\t\t\t// When passing by value the lambda creation/assigment will also do some operations which we dont want to\n\t\t\t// track, so we instead capture the state here and check the difference\n\n\t\t\tint64_t ctorDiff = TestObject::sTOCtorCount;\n\t\t\tint64_t copyCtorCount = TestObject::sTOCopyCtorCount;\n\t\t\tint64_t moveCtorCount = TestObject::sTOMoveCtorCount;\n\n\t\t\teastl::fixed_function<64, void(void)> ff64_val;\n\t\t\teastl::fixed_function<128, void(void)> ff128_val;\n\n\t\t\tff64_val = ff32_val;\n\t\t\tff128_val = ff64_val;\n\n\t\t\tVERIFY(TestObject::sTOCount == 4);\n\t\t\tVERIFY((TestObject::sTOCtorCount - ctorDiff) == 2);\n\t\t\tVERIFY((TestObject::sTOCopyCtorCount - copyCtorCount) == 2);\n\t\t\tVERIFY((TestObject::sTOMoveCtorCount - moveCtorCount) == 0);\n\t\t}\n\n\t\t{\n\t\t\tTestObject::Reset();\n\t\t\tTestObject theOriginal;\n\n\t\t\teastl::fixed_function<32, void(void)> ff32_val = [theOriginal]() { EA_UNUSED(theOriginal); };\n\n\t\t\t// When passing by value the lambda creation/assigment will also do some operations which we dont want to\n\t\t\t// track, so we instead capture the state here and check the difference\n\n\t\t\tint64_t ctorDiff = TestObject::sTOCtorCount;\n\t\t\tint64_t copyCtorCount = TestObject::sTOCopyCtorCount;\n\t\t\tint64_t moveCtorCount = TestObject::sTOMoveCtorCount;\n\n\t\t\teastl::fixed_function<64, void(void)> ff64_val;\n\t\t\teastl::fixed_function<128, void(void)> ff128_val;\n\n\t\t\tff64_val = eastl::move(ff32_val);\n\t\t\tff128_val = eastl::move(ff64_val);\n\n\t\t\tVERIFY(TestObject::sTOCount == 2);\n\t\t\tVERIFY((TestObject::sTOCtorCount - ctorDiff) == 2);\n\t\t\tVERIFY((TestObject::sTOMoveCtorCount - moveCtorCount) == 2);\n\t\t\tVERIFY((TestObject::sTOCopyCtorCount - copyCtorCount) == 0);\n\t\t}\n\n\t\t{\n\t\t\tTestObject::Reset();\n\t\t\tTestObject theOriginal;\n\n\t\t\teastl::fixed_function<32, void(void)> ff32 = [theOriginal]() {EA_UNUSED(theOriginal); };\n\n\t\t\tint64_t ctorDiff = TestObject::sTOCtorCount;\n\t\t\tint64_t copyCtorCount = TestObject::sTOCopyCtorCount;\n\t\t\tint64_t moveCtorCount = TestObject::sTOMoveCtorCount;\n\n\t\t\teastl::fixed_function<64, void(void)> ff64(eastl::move(ff32));\n\t\t\teastl::fixed_function<128, void(void)> ff128(eastl::move(ff64));\n\n\t\t\tVERIFY(TestObject::sTOCount == 2);\n\t\t\tVERIFY((TestObject::sTOCtorCount - ctorDiff) == 2);         \n\t\t\tVERIFY((TestObject::sTOMoveCtorCount - moveCtorCount) == 2);\n\t\t\tVERIFY((TestObject::sTOCopyCtorCount - copyCtorCount) == 0);\n\t\t\n\t\t}\n\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFixedFunctionAllocations\n//\nint TestFixedFunctionAllocations()\n{\n\tint nErrorCount = 0;\n#if !EASTL_OPENSOURCE\n\tint allocationsBefore = gEASTLTest_TotalAllocationCount.load();\n\n\t{\n\t\tint i = 0;\n\t\teastl::fixed_function<4, int(int)> ff4 = [i](int in) mutable { return ++i + in; };\n\t\teastl::fixed_function<8, int(int)> ff8;\n\t\teastl::fixed_function<16, int(int)> ff16;\n\t\teastl::fixed_function<24, int(int)> ff24;\n\n\t\tVERIFY(ff4(1) == 2);\n\t\tff8 = ff4;\n\t\tVERIFY(ff8(1) == 3);\n\t\tff16 = ff8;\n\t\tVERIFY(ff16(1) == 4);\n\t\tff24 = ff16;\n\t\tVERIFY(ff24(1) == 5);\n\t}\n\n\t{\n\t\tint i = 0;\n\t\teastl::fixed_function<4, int(void)> ff4 = [i]() mutable { return ++i; };\n\t\tVERIFY(ff4() == 1);\n\t\teastl::fixed_function<8, int(void)> ff8(ff4);\n\t\tVERIFY(ff8() == 2);\n\t\teastl::fixed_function<16, int(void)> ff16(ff8);\n\t\tVERIFY(ff16() == 3);\n\t\teastl::fixed_function<24, int(void)> ff24(ff16);\n\t\tVERIFY(ff24() == 4);\n\t}\n\n\t{\n\t\tint i = 0;\n\t\teastl::fixed_function<4, int(int)> ff4 = [i](int in) mutable { return ++i + in; };\n\t\tVERIFY(ff4(1) == 2);\n\t\teastl::fixed_function<8, int(int)> ff8(eastl::move(ff4));\n\t\tVERIFY(ff8(1) == 3);\n\t\teastl::fixed_function<16, int(int)> ff16(eastl::move(ff8));\n\t\tVERIFY(ff16(1) == 4);\n\t\teastl::fixed_function<24, int(int)> ff24(eastl::move(ff16));\n\t\tVERIFY(ff24(1) == 5);\t\t\n\t}\n\n\t{\n\t\tint i = 0;\n\t\teastl::fixed_function<4, int(void)> ff4 = [i]() mutable { return ++i; };\n\t\teastl::fixed_function<8, int(void)> ff8;\n\t\teastl::fixed_function<16, int(void)> ff16;\n\t\teastl::fixed_function<24, int(void)> ff24;\n\n\t\tVERIFY(ff4() == 1);\n\t\tff8 = eastl::move(ff4);\n\t\tVERIFY(ff8() == 2);\n\t\tff16 = eastl::move(ff8);\n\t\tVERIFY(ff16() == 3);\n\t\tff24 = eastl::move(ff16);\n\t\tVERIFY(ff24() == 4);\n\t}\n\n\t{\n\t\tTestObject to;\n\t\teastl::fixed_function<64, void(void)> ff = [to] {};\n\t\tff();\t\n\t}\n\n\tint allocationsAfter = gEASTLTest_TotalAllocationCount.load();\n\n\t// If this triggeres the easiest method to track it down is to place a break point at the start of this test, \n\t// then enable break when gEASTLTest_TotalAllocationCount's value change s\n\tVERIFY(allocationsBefore == allocationsAfter);\n#endif\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFunctional\n//\nint TestFixedFunction()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestFixedFunctionBasic();\n\tnErrorCount += TestFixedFunctionDtor();\n\tnErrorCount += TestFixedFunctionExistingClosure();\n\tnErrorCount += TestFixedFunctionReferenceWrapper();\n\tnErrorCount += TestFixedFunctionFunctionPointer();\n\tnErrorCount += TestFixedFunctionPointerToMemberFunction();\n\tnErrorCount += TestFixedFunctionPointerToMemberData();\n\tnErrorCount += TestFixedFunctionStdBind();\n\tnErrorCount += TestFixedFunctionAllocations();\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestFixedHash.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EABase/eabase.h>\n#include \"EASTLTest.h\"\n#include \"TestMap.h\"\n#include \"TestSet.h\"\n#include \"TestAssociativeContainers.h\"\n#include <EASTL/fixed_hash_set.h>\n#include <EASTL/fixed_hash_map.h>\n#include <EASTL/fixed_vector.h>\n#include <EAStdC/EAString.h>\n#include <EASTL/functional.h>\n\n\n\n\nusing namespace eastl;\n\n\nstruct A\n{\n\tint mX;\n\tA(int x = 999) : mX(x) {}\n};\n\ninline bool operator==(const A& a1, const A& a2)\n\t{ return a1.mX == a2.mX; }\n\n\n\nnamespace eastl\n{\n\ttemplate <> \n\tstruct hash<A>\n\t{\n\t\tsize_t operator()(const A& a) const \n\t\t\t{ return static_cast<size_t>(a.mX); }\n\t};\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// For test of user-reported crash.\n//\nstruct MemoryEntry\n{\n\t  size_t mSize;\n\t  void*  mGroup;\n};\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// For test of bug reported by Dave Wall, May 14, 2008.\n//\nstruct InstanceRenderData\n{\n\tstatic const uint32_t kDataCount = 10; // Bug only occurs with this value.\n\n\tuint32_t mPad[kDataCount];\n\n\tInstanceRenderData()\n\t{\n\t\tmemset(mPad, 0, sizeof(mPad));\n\t}\n\n\tbool operator==(const InstanceRenderData &rhs) const\n\t{\n\t\tfor(uint32_t index = 0; index < kDataCount; index++)\n\t\t{\n\t\t\tif(mPad[index] != rhs.mPad[index])\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n};\n\nnamespace eastl\n{\n\ttemplate <> \n\tstruct hash<const InstanceRenderData>\n\t{\n\t\tsize_t operator()(InstanceRenderData val) const \n\t\t{\n\t\t\treturn val.mPad[0];\n\t\t}\n\t};\n\n\ttemplate <> \n\tstruct hash<InstanceRenderData>\n\t{\n\t\tsize_t operator()(InstanceRenderData val) const \n\t\t{\n\t\t\treturn val.mPad[0];\n\t\t}\n\t};\n}\n///////////////////////////////////////////////////////////////////////////////\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::fixed_hash_set<int, 1, 2>;\ntemplate class eastl::fixed_hash_map<int, int, 1, 2>;\ntemplate class eastl::fixed_hash_multiset<int, 1, 2>;\ntemplate class eastl::fixed_hash_multimap<int, int, 1, 2>;\n\ntemplate class eastl::fixed_hash_set<A, 1, 2>;\ntemplate class eastl::fixed_hash_map<A, A, 1, 2>;\ntemplate class eastl::fixed_hash_multiset<A, 1, 2>;\ntemplate class eastl::fixed_hash_multimap<A, A, 1, 2>;\n\ntemplate class eastl::fixed_hash_set<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>;\ntemplate class eastl::fixed_hash_map<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>;\ntemplate class eastl::fixed_hash_multiset<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>;\ntemplate class eastl::fixed_hash_multimap<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, true>;\n\ntemplate class eastl::fixed_hash_set<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>;\ntemplate class eastl::fixed_hash_map<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>;\ntemplate class eastl::fixed_hash_multiset<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>;\ntemplate class eastl::fixed_hash_multimap<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, true>;\n\n// Custom allocator\ntemplate class eastl::fixed_hash_set<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>;\ntemplate class eastl::fixed_hash_map<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>;\ntemplate class eastl::fixed_hash_multiset<int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>;\ntemplate class eastl::fixed_hash_multimap<int, int, 1, 2, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator>;\n\ntemplate class eastl::fixed_hash_set<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>;\ntemplate class eastl::fixed_hash_map<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>;\ntemplate class eastl::fixed_hash_multiset<A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>;\ntemplate class eastl::fixed_hash_multimap<A, A, 1, 2, true, eastl::hash<A>, eastl::equal_to<A>, false, MallocAllocator>;\n\nstruct TransparentHash {\n\tusing is_transparent = int;\n\n\ttemplate<typename T>\n\tsize_t operator()(T&& val) const\n\t{\n\t\treturn eastl::hash<eastl::remove_cvref_t<T>>{}(eastl::forward<T>(val));\n\t}\n};\n\ntemplate<typename FixedHashMap, int ELEMENT_MAX, int ITERATION_MAX>\nint TestFixedHashMapClearBuckets()\n{\n\tint nErrorCount = 0;\n\n\tFixedHashMap fixedHashMap;\n\tconst auto nPreClearBucketCount = fixedHashMap.bucket_count();\n\n\tfor (int j = 0; j < ITERATION_MAX; j++)\n\t{\n\t\t// add elements and ensure container is valid\n\t\tfor (int i = 0; i < int(nPreClearBucketCount); i++)\n\t\t\tfixedHashMap.emplace(i, i);\n\t\tVERIFY(fixedHashMap.validate());\n\t\t\n\t\t// ensure contents are expected values\n\t\tfor (int i = 0; i < int(nPreClearBucketCount); i++)\n\t\t{\n\t\t\tauto iter = fixedHashMap.find(i);\n\n\t\t\tVERIFY(iter != fixedHashMap.end());\n\t\t\tVERIFY(iter->second == i);\n\t\t}\n\n\t\t// validate container after its cleared its nodes and buckets\n\t\tfixedHashMap.clear(true);\n\t\tVERIFY(fixedHashMap.validate());\n\t\tVERIFY(fixedHashMap.size() == 0);\n\t\tVERIFY(fixedHashMap.bucket_count() == nPreClearBucketCount);\n\t}\n\n\treturn nErrorCount;\n}\n\n\nEA_DISABLE_VC_WARNING(6262)\nint TestFixedHash()\n{\n\tint nErrorCount = 0;\n\n\t{ // fixed_hash_map\n\t\t{\n\t\t\t// Test version *without* pool overflow.\n\t\t\ttypedef eastl::fixed_hash_map<int, int, 100, 100, false> FixedHashMapFalse;\n\t\t\tFixedHashMapFalse fixedHashMap;\n\n\t\t\tfixedHashMap[0] = 0;\n\t\t\tfixedHashMap.insert(FixedHashMapFalse::value_type(0, 0));\n\n\t\t\tVERIFY(fixedHashMap.max_size() == 100);\n\t\t\tVERIFY(fixedHashMap.size() == 1);\n\n\t\t\tfixedHashMap.clear();\n\t\t\tVERIFY(fixedHashMap.size() == 0);\n\n\t\t\tfor(int i = 0; i < 100; i++)\n\t\t\t\tfixedHashMap.insert(FixedHashMapFalse::value_type(i, i));\n\t\t\tVERIFY(fixedHashMap.size() == 100);\n\n\t\t\t// Verify that we allocated enough space for exactly N items. \n\t\t\t// It's possible that due to alignments, there might be room for N + 1.\n\t\t\tFixedHashMapFalse::allocator_type& allocator = fixedHashMap.get_allocator();\n\t\t\tvoid* pResult = allocator.allocate(sizeof(FixedHashMapFalse::node_type));\n\t\t\tif(pResult)\n\t\t\t{\n\t\t\t\tpResult = allocator.allocate(sizeof(FixedHashMapFalse::node_type));\n\t\t\t\tVERIFY(pResult == NULL); \n\t\t\t}\n\n\t\t\tfixedHashMap.clear(true);\n\t\t\tVERIFY(fixedHashMap.validate());\n\t\t\tVERIFY(fixedHashMap.size() == 0);\n\t\t\tVERIFY(fixedHashMap.bucket_count() == fixedHashMap.rehash_policy().GetPrevBucketCount(100));\n\t\t}\n\n\t\t{\n\t\t\t// Test version *with* pool overflow.\n\t\t\ttypedef eastl::fixed_hash_map<int, int, 100, 100, true> FixedHashMapTrue;\n\t\t\tFixedHashMapTrue fixedHashMap;\n\n\t\t\tfixedHashMap[0] = 0;\n\t\t\tfixedHashMap.insert(FixedHashMapTrue::value_type(0, 0));\n\n\t\t\tVERIFY(fixedHashMap.max_size() == 100);\n\t\t\tVERIFY(fixedHashMap.size() == 1);\n\n\t\t\tfixedHashMap.clear();\n\t\t\tVERIFY(fixedHashMap.size() == 0);\n\n\t\t\tfor(int i = 0; i < 100; i++)\n\t\t\t\tfixedHashMap.insert(FixedHashMapTrue::value_type(i, i));\n\t\t\tVERIFY(fixedHashMap.size() == 100);\n\n\t\t\tFixedHashMapTrue::allocator_type& allocator = fixedHashMap.get_allocator();\n\t\t\tvoid* pResult = allocator.allocate(sizeof(FixedHashMapTrue::node_type));\n\t\t\tVERIFY(pResult != NULL);\n\t\t\tallocator.deallocate(pResult, sizeof(FixedHashMapTrue::node_type));\n\n\t\t\tfixedHashMap.clear(true);\n\t\t\tVERIFY(fixedHashMap.validate());\n\t\t\tVERIFY(fixedHashMap.size() == 0);\n\t\t\tVERIFY(fixedHashMap.bucket_count() == fixedHashMap.rehash_policy().GetPrevBucketCount(100));\n\n\t\t\t// get_overflow_allocator / set_overflow_allocator\n\t\t\t// This is a weak test which should be improved.\n\t\t\tEASTLAllocatorType a = fixedHashMap.get_allocator().get_overflow_allocator();\n\t\t\tfixedHashMap.get_allocator().set_overflow_allocator(a);\n\t\t}\n\n\t\t// Test that fixed_hash_map (with and without overflow enabled) is usable after the node and bucket array has\n\t\t// been cleared.\n\t\t{\n\t\t\tconstexpr const int ITERATION_MAX = 5;\n\t\t\tconstexpr const int ELEMENT_MAX = 100;\n\t\t\tconstexpr const int ELEMENT_OVERFLOW_MAX = ELEMENT_MAX * 2;\n\n\t\t\tTestFixedHashMapClearBuckets<eastl::fixed_hash_map<int, int, ELEMENT_MAX, ELEMENT_MAX, false>,      ELEMENT_MAX,          ITERATION_MAX>();\n\t\t\tTestFixedHashMapClearBuckets<eastl::fixed_hash_map<int, int, ELEMENT_MAX, ELEMENT_MAX, true>,       ELEMENT_OVERFLOW_MAX, ITERATION_MAX>();\n\t\t\tTestFixedHashMapClearBuckets<eastl::fixed_hash_multimap<int, int, ELEMENT_MAX, ELEMENT_MAX, false>, ELEMENT_MAX,          ITERATION_MAX>();\n\t\t\tTestFixedHashMapClearBuckets<eastl::fixed_hash_multimap<int, int, ELEMENT_MAX, ELEMENT_MAX, true>,  ELEMENT_OVERFLOW_MAX, ITERATION_MAX>();\n\t\t}\n\t\t\n\t\t{\n\t\t\t// Test fixed_hash_map *with* overflow and ensure the underlying hashtable rehashes.\n\t\t\ttypedef eastl::fixed_hash_map<unsigned int, unsigned int, 512, 513, true,  eastl::hash<unsigned int>, eastl::equal_to<unsigned int>, false, MallocAllocator> FixedHashMap;\n\n\t\t\tFixedHashMap fixedHashMap;\n\t\t\tauto old_bucket_count = fixedHashMap.bucket_count();\n\t\t\tauto old_load_factor = fixedHashMap.load_factor();\n\t\t\t\t\t\t\n\t\t\tfor (int i = 0; i < 1000; i++)\n\t\t\t\tfixedHashMap.insert(i);\n\n\t\t\tauto new_bucket_count = fixedHashMap.bucket_count();\n\t\t\tauto new_load_factor = fixedHashMap.load_factor();\n\n\t\t\tVERIFY(new_bucket_count != old_bucket_count);\n\t\t\tVERIFY(new_bucket_count > old_bucket_count);\n\t\t\tVERIFY(new_load_factor != old_load_factor);\n\t\t\tVERIFY(fixedHashMap.get_overflow_allocator().mAllocCountAll != 0);\t\t\t\n\t\t}\n\n\t\t{\n\t\t\t// Test version with overflow and alignment requirements.\n\t\t\ttypedef fixed_hash_map<Align64, int, 1, 2, true> FixedHashMapWithAlignment;\n\t\t\ttypedef fixed_hash_multimap<Align64, int, 1, 2, true> FixedHashMultiMapWithAlignment;\n\t\t\ttypedef fixed_hash_set<Align64, 1, 2, true> FixedHashSetWithAlignment;\n\t\t\ttypedef fixed_hash_multiset<Align64, 1, 2, true> FixedHashMultiSetWithAlignment;\n\n\t\t\tFixedHashMapWithAlignment fhm;\n\t\t\tFixedHashMultiMapWithAlignment fhmm;\n\t\t\tFixedHashSetWithAlignment fhs;\n\t\t\tFixedHashMultiSetWithAlignment fhms;\n\n\t\t\tAlign64 a; a.mX = 1;\n\t\t\tAlign64 b; b.mX = 2;\n\t\t\tAlign64 c; c.mX = 3;\n\t\t\tAlign64 d; d.mX = 4;\n\t\t\tAlign64 e; e.mX = 5;\n\n\t\t\tfhm.insert(a);\n\t\t\tfhm.insert(b);\n\t\t\tfhm.insert(c);\n\t\t\tfhm.insert(d);\n\t\t\tfhm.insert(e);\n\t\t\tfor (FixedHashMapWithAlignment::const_iterator it = fhm.begin(); it != fhm.end(); ++it)\n\t\t\t{\n\t\t\t\tconst Align64* ptr = &((*it).first);\n\t\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t\t}\n\t\t\tfhmm.insert(a);\n\t\t\tfhmm.insert(b);\n\t\t\tfhmm.insert(c);\n\t\t\tfhmm.insert(d);\n\t\t\tfhmm.insert(e);\n\t\t\tfor (FixedHashMultiMapWithAlignment::const_iterator it = fhmm.begin(); it != fhmm.end(); ++it)\n\t\t\t{\n\t\t\t\tconst Align64* ptr = &((*it).first);\n\t\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t\t}\n\t\t\tfhs.insert(a);\n\t\t\tfhs.insert(b);\n\t\t\tfhs.insert(c);\n\t\t\tfhs.insert(d);\n\t\t\tfhs.insert(e);\n\t\t\tfor (FixedHashSetWithAlignment::const_iterator it = fhs.begin(); it != fhs.end(); ++it)\n\t\t\t{\n\t\t\t\tconst Align64* ptr = &(*it);\n\t\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t\t}\n\t\t\tfhms.insert(a);\n\t\t\tfhms.insert(b);\n\t\t\tfhms.insert(c);\n\t\t\tfhms.insert(d);\n\t\t\tfhms.insert(e);\n\t\t\tfor (FixedHashMultiSetWithAlignment::const_iterator it = fhms.begin(); it != fhms.end(); ++it)\n\t\t\t{\n\t\t\t\tconst Align64* ptr = &(*it);\n\t\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_map<int, A, 100, 100> FixedHashMap;\n\t\t\tFixedHashMap fixedHashMap;\n\n\t\t\tfixedHashMap[0] = A();\n\t\t\tfixedHashMap.insert(FixedHashMap::value_type(0, A()));\n\n\t\t\tVERIFY(fixedHashMap.size() == 1);\n\t\t}\n\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_map<A, int, 100, 100> FixedHashMap;\n\t\t\tFixedHashMap fixedHashMap;\n\n\t\t\tfixedHashMap[A()] = 0;\n\t\t\tfixedHashMap.insert(FixedHashMap::value_type(A(), 0));\n\n\t\t\tVERIFY(fixedHashMap.size() == 1);\n\t\t}\n\n\t\t// explicitly instantiate some templated member functions\n\t\t{\t\t\t\n\t\t\ttypedef eastl::fixed_hash_map<int, int, 100, 100, true> FixedHashMapTrue;\n\t\t\tFixedHashMapTrue::value_type testValues[] = { eastl::make_pair(0, 0), eastl::make_pair(1,1) };\n\t\t\tFixedHashMapTrue fixedHashMap(testValues, testValues + EAArrayCount(testValues));\n\t\t\tVERIFY(fixedHashMap.size() == 2);\n\t\t}\n\t}\n\n\n\t{ // fixed_hash_multimap\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_multimap<int, int, 100, 100> FixedHashMultiMap;\n\t\t\tFixedHashMultiMap fixedHashMultiMap;\n\n\t\t\tfixedHashMultiMap.insert(FixedHashMultiMap::value_type(0, 0));\n\t\t\tfixedHashMultiMap.insert(FixedHashMultiMap::value_type(0, 0));\n\n\t\t\tVERIFY(fixedHashMultiMap.max_size() == 100);\n\t\t\tVERIFY(fixedHashMultiMap.size() == 2);\n\t\t}\n\n\t\t// explicitly instantiate some templated member functions\n\t\t{\t\t\t\n\t\t\ttypedef eastl::fixed_hash_multimap<int, int, 100, 100, true> FixedHashMultiMap;\n\t\t\tFixedHashMultiMap::value_type testValues[] = { eastl::make_pair(0, 0), eastl::make_pair(1,1) };\n\t\t\tFixedHashMultiMap fixedHashMultiMap(testValues, testValues + EAArrayCount(testValues));\n\t\t\tVERIFY(fixedHashMultiMap.size() == 2);\n\t\t}\n\t}\n\n\n\t{ // fixed_hash_set\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_set<int, 100, 100> FixedHashSet;\n\t\t\tFixedHashSet fixedHashSet;\n\n\t\t\tfixedHashSet.insert(0);\n\t\t\tfixedHashSet.insert(0);\n\t\t\tVERIFY(fixedHashSet.size() == 1);\n\n\t\t\tfixedHashSet.clear();\n\t\t\tVERIFY(fixedHashSet.size() == 0);\n\n\t\t\tfor(int i = 0; i < 100; i++)\n\t\t\t\tfixedHashSet.insert(i);\n\n\t\t\tVERIFY(fixedHashSet.max_size() == 100);\n\t\t\tVERIFY(fixedHashSet.size() == 100);\n \n\t\t\tfixedHashSet.clear(true);\n\t\t\tVERIFY(fixedHashSet.validate());\n\t\t\tVERIFY(fixedHashSet.size() == 0);\n\t\t\tVERIFY(fixedHashSet.bucket_count() == 1);\n\t   }\n\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_set<A, 100, 100> FixedHashSet;\n\t\t\tFixedHashSet fixedHashSet;\n\n\t\t\tfixedHashSet.insert(A());\n\t\t\tfixedHashSet.insert(A());\n\n\t\t\tVERIFY(fixedHashSet.max_size() == 100);\n\t\t\tVERIFY(fixedHashSet.size() == 1);\n\t\t}\n\n\t\t// explicitly instantiate some templated member functions\n\t\t{\t\t\t\n\t\t\ttypedef eastl::fixed_hash_set<A, 100, 100> FixedHashSet;\n\t\t\tFixedHashSet::value_type testValues[] = { 0, 1 };\n\t\t\tFixedHashSet fixedHashSet(testValues, testValues + EAArrayCount(testValues));\n\t\t\tVERIFY(fixedHashSet.size() == 2);\n\t\t}\n\t}\n\n\n\t{ // fixed_hash_multiset\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_multiset<int, 100, 100> FixedHashMultiSet;\n\t\t\tFixedHashMultiSet fixedHashMultiSet;\n\n\t\t\tfixedHashMultiSet.insert(0);\n\t\t\tfixedHashMultiSet.insert(0);\n\n\t\t\tVERIFY(fixedHashMultiSet.size() == 2);\n\t\t}\n\t\t\n\n\t\t// explicitly instantiate some templated member functions\n\t\t{\t\t\t\n\t\t\ttypedef eastl::fixed_hash_multiset<A, 100, 100> FixedHashMultiSet;\n\t\t\tFixedHashMultiSet::value_type testValues[] = { 0, 1 };\n\t\t\tFixedHashMultiSet fixedHashMultiSet(testValues, testValues + EAArrayCount(testValues));\n\t\t\tVERIFY(fixedHashMultiSet.size() == 2);\n\t\t}\n\t}\n\n\n\t{ // Tests of various bucketCount values.\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_set<int, 1, 2> FixedHashSet;\n\t\t\tFixedHashSet fixedHashSet;\n\n\t\t\tfixedHashSet.insert(0);\n\n\t\t\tVERIFY(fixedHashSet.size() == 1);\n\t\t}\n\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_set<int, 2, 2> FixedHashSet;\n\t\t\tFixedHashSet fixedHashSet;\n\n\t\t\tfixedHashSet.insert(0);\n\t\t\tfixedHashSet.insert(1);\n\n\t\t\tVERIFY(fixedHashSet.size() == 2);\n\t\t}\n\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_set<int, 11, 11> FixedHashSet; // 11 is one of the hashtable prime numbers.\n\t\t\tFixedHashSet fixedHashSet;\n\n\t\t\tfor(int i = 0; i < 11; i++)\n\t\t\t\tfixedHashSet.insert(i);\n\n\t\t\tVERIFY(fixedHashSet.size() == 11);\n\t\t}\n\n\n\t\t{\n\t\t\ttypedef eastl::fixed_hash_set<int, 11, 11> FixedHashSet; // 11 is one of the hashtable prime numbers.\n\t\t\tFixedHashSet fixedHashSet;\n\n\t\t\tVERIFY(fixedHashSet.validate());\n\t\t\tVERIFY(fixedHashSet.size() == 0);\n\n\t\t\t// Clear a newly constructed, already empty container.\n\t\t\tfixedHashSet.clear(true);\n\t\t\tVERIFY(fixedHashSet.validate());\n\t\t\tVERIFY(fixedHashSet.size() == 0);\n\t\t\tVERIFY(fixedHashSet.bucket_count() == 1);\n\n\t\t\tfor(int i = 0; i < 11; i++)\n\t\t\t\tfixedHashSet.insert(i);\n\t\t\tVERIFY(fixedHashSet.size() == 11);\n\t\t\tVERIFY(fixedHashSet.bucket_count() > 1);\n\n\t\t\tfixedHashSet.clear(true);\n\t\t\tVERIFY(fixedHashSet.validate());\n\t\t\tVERIFY(fixedHashSet.size() == 0);\n\t\t\tVERIFY(fixedHashSet.bucket_count() == 1);\n\n\t\t\tfor(int i = 0; i < 11; i++)\n\t\t\t\tfixedHashSet.insert(i);\n\t\t\tVERIFY(fixedHashSet.size() == 11);\n\t\t}\n\t}\n\n\t{ // Test of user-reported crash.\n\n\t\t// MemoryAddressToGroupMap is a container used by one team to associate debug \n\t\t// information with memory allocations. A crash due to corruption of the \n\t\t// fixed size node pool was reported on consoles (no crash on PC platform). \n\t\tconst eastl_size_t kMemoryAddressMapNodeCount = 500000;\n\n\t\ttypedef eastl::fixed_hash_map< \n\t\t\tconst void*,                             // Key\n\t\t\tMemoryEntry,                             // Value\n\t\t\tkMemoryAddressMapNodeCount,              // Node Count\n\t\t\tkMemoryAddressMapNodeCount + 1,          // Bucket Count\n\t\t\ttrue,                                    // Enable Overflow\n\t\t\teastl::hash<const void*>,                // Hash\n\t\t\teastl::equal_to<const void*>,            // Predicate\n\t\t\tfalse,                                   // Cache Hash Code\n\t\t\teastl::allocator                         // Allocator\n\t\t> MemoryAddressToGroupMap;\n\n\t\tMemoryAddressToGroupMap* pMap = new MemoryAddressToGroupMap;\n\t\tEA::UnitTest::Rand       rng(EA::UnitTest::GetRandSeed());\n\n\t\t// We simulate the usage of MemoryAddressToGroupMap via simulated alloc/free actions.\n\t\tfor(eastl_size_t i = 0; i < kMemoryAddressMapNodeCount * 2; i++)\n\t\t{\n\t\t\tvoid* const p = (void*)(uintptr_t)rng.RandLimit(kMemoryAddressMapNodeCount);\n\n\t\t\tif(pMap->find(p) == pMap->end())\n\t\t\t\t(*pMap)[p] = MemoryEntry();\n\t\t\telse\n\t\t\t\tpMap->erase(p);\n\t\t}\n\n\t\tdelete pMap;\n\t}\n\n\n\t{  // Test of bug reported by Dave Wall, May 14, 2008.\n\t\tconst size_t kNumBuckets = 10;  // Bug only occurred with kNumBuckets == 10 or 11.\n\n\t\ttypedef eastl::fixed_hash_map<const InstanceRenderData, uint32_t, kNumBuckets, kNumBuckets + 1, false> Map;\n\n\t\tMap map;\n\t\tInstanceRenderData renderData;\n\n\t\tuint32_t count = (uint32_t)kNumBuckets;\n\n\t\twhile(count--)\n\t\t{\n\t\t\trenderData.mPad[0] = count;\n\t\t\tmap.insert(Map::value_type(renderData, count));\n\t\t}\n\n\t}\n\n\t{\n\t\t// Test construction of a container with an overflow allocator constructor argument.\n\t\tMallocAllocator overflowAllocator;\n\t\tvoid* p = overflowAllocator.allocate(1);\n\n\t\ttypedef eastl::fixed_hash_map<int, int, 64, 100, true, eastl::hash<int>, eastl::equal_to<int>, false, MallocAllocator> Container;\n\t\tContainer c(overflowAllocator);\n\n\t\tfor(int i = 0; i < 65; i++)\n\t\t\tc.insert(Container::value_type(i, i));\n\n\t\tVERIFY(c.get_overflow_allocator().mAllocCount == 2); // 1 for above, and 1 for overflowing from 64 to 65.\n\t\toverflowAllocator.deallocate(p, 1);\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestMapCpp11<eastl::fixed_hash_map<int, TestObject,  2, 7, true> >();  // Exercize a low-capacity fixed-size container.\n\t\tnErrorCount += TestMapCpp11<eastl::fixed_hash_map<int, TestObject, 32, 7, true> >();\n\t\tnErrorCount += TestMapCpp11<eastl::fixed_hash_map<int, TestObject, 32, 7, true, TransparentHash, eastl::equal_to<void>> >();\n\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::fixed_hash_map<int, NonCopyable, 2, 7, true>>();\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::fixed_hash_map<int, NonCopyable, 2, 7, true, TransparentHash, eastl::equal_to<void>>>();\n\n\t\tnErrorCount += TestSetCpp11<eastl::fixed_hash_set<TestObject,  2, 7, true> >();\n\t\tnErrorCount += TestSetCpp11<eastl::fixed_hash_set<TestObject, 32, 7, true> >();\n\t\tnErrorCount += TestSetCpp11<eastl::fixed_hash_set<TestObject, 32, 7, true, TransparentHash, eastl::equal_to<void>> >();\n\n\t\tnErrorCount += TestMultimapCpp11<eastl::fixed_hash_multimap<int, TestObject,  2, 7, true> >();\n\t\tnErrorCount += TestMultimapCpp11<eastl::fixed_hash_multimap<int, TestObject, 32, 7, true> >();\n\t\tnErrorCount += TestMultimapCpp11<eastl::fixed_hash_multimap<int, TestObject, 32, 7, true, TransparentHash, eastl::equal_to<void>> >();\n\n\t\tnErrorCount += TestMultisetCpp11<eastl::fixed_hash_multiset<TestObject,  2, 7, true> >();\n\t\tnErrorCount += TestMultisetCpp11<eastl::fixed_hash_multiset<TestObject, 32, 7, true> >();\n\t\tnErrorCount += TestMultisetCpp11<eastl::fixed_hash_multiset<TestObject, 32, 7, true, TransparentHash, eastl::equal_to<void>> >();\n\t}\n\n\t{\n\t\t// C++17 try_emplace and related functionality\n\t\tnErrorCount += TestMapCpp17<eastl::fixed_hash_map<int, TestObject,  2, 7, true>>();\n\t\tnErrorCount += TestMapCpp17<eastl::fixed_hash_map<int, TestObject, 32, 7, true> >();\n\t\tnErrorCount += TestMapCpp17<eastl::fixed_hash_map<int, TestObject, 32, 7, true, TransparentHash, eastl::equal_to<void>> >();\n\t}\n\n\t{\n\t\t// void reserve(size_type nElementCount);\n\n\t\t// test with overflow enabled.\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_set<int, 16>>()();\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_set<int, 16, 17, true, TransparentHash, eastl::equal_to<void>>>()();\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_multiset<int, 16>>()();\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_multiset<int, 16, 17, true, TransparentHash, eastl::equal_to<void>>>()();\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_map<int, int, 16>>()();\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_map<int, int, 16, 17, true, TransparentHash, eastl::equal_to<void>>>()();\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_multimap<int, int, 16>>()();\n\t\tnErrorCount += HashContainerReserveTest<fixed_hash_multimap<int, int, 16, 17, true, TransparentHash, eastl::equal_to<void>>>()();\n\n\t\t// API prevents testing fixed size hash container reservation without overflow enabled. \n\t\t//\n\t\t// nErrorCount += HashContainerReserveTest<fixed_hash_set<int, 400, 401, false>>()();\n\t\t// nErrorCount += HashContainerReserveTest<fixed_hash_multiset<int, 400, 401, false>>()();\n\t\t// nErrorCount += HashContainerReserveTest<fixed_hash_map<int, int, 400, 401, false>>()();\n\t\t// nErrorCount += HashContainerReserveTest<fixed_hash_multimap<int, int, 9000, 9001, false>>()();\n\t}\n\n\t{\n\t\t// initializer_list support.\n\t\t// fixed_hash_set(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR)\n\t\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t\t// void insert(std::initializer_list<value_type> ilist);\n\t\tfixed_hash_set<int, 11> intHashSet = { 12, 13, 14 };\n\t\tEATEST_VERIFY(intHashSet.size() == 3);\n\t\tEATEST_VERIFY(intHashSet.find(12) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(13) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(14) != intHashSet.end());\n\n\t\tintHashSet = { 22, 23, 24 };\n\t\tEATEST_VERIFY(intHashSet.size() == 3);\n\t\tEATEST_VERIFY(intHashSet.find(22) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(23) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(24) != intHashSet.end());\n\n\t\tintHashSet.insert({ 42, 43, 44 });\n\t\tEATEST_VERIFY(intHashSet.size() == 6);\n\t\tEATEST_VERIFY(intHashSet.find(42) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(43) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(44) != intHashSet.end());\n\n\t\t// hash_map(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_HASH_SET_DEFAULT_ALLOCATOR)\n\t\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t\t// void insert(std::initializer_list<value_type> ilist);\n\t\tfixed_hash_map<int, double, 11> intHashMap = { {12,12.0}, {13,13.0}, {14,14.0} };\n\t\tEATEST_VERIFY(intHashMap.size() == 3);\n\t\tEATEST_VERIFY(intHashMap.find(12) != intHashMap.end());\n\t\tEATEST_VERIFY(intHashMap.find(13) != intHashMap.end());\n\t\tEATEST_VERIFY(intHashMap.find(14) != intHashMap.end());\n\n\t\tintHashMap = { {22,22.0}, {23,23.0}, {24,24.0} };\n\t\tEATEST_VERIFY(intHashMap.size() == 3);\n\t\tEATEST_VERIFY(intHashMap.find(22) != intHashMap.end());\n\t\tEATEST_VERIFY(intHashMap.find(23) != intHashMap.end());\n\t\tEATEST_VERIFY(intHashMap.find(24) != intHashMap.end());\n\n\t\tintHashMap.insert({ {42,42.0}, {43,43.0}, {44,44.0} });\n\t\tEATEST_VERIFY(intHashMap.size() == 6);\n\t\tEATEST_VERIFY(intHashMap.find(42) != intHashMap.end());\n\t\tEATEST_VERIFY(intHashMap.find(43) != intHashMap.end());\n\t\tEATEST_VERIFY(intHashMap.find(44) != intHashMap.end());\n\t}\n\n\t{\n\t\tconstexpr int ELEM_MAX = 10;\n\t\ttypedef eastl::fixed_hash_map<int, int, ELEM_MAX, ELEM_MAX, false> FixedHashMapFalse;\n\t\tFixedHashMapFalse fixedHashMap;\n\t\tVERIFY(fixedHashMap.size() == 0);\n\n\t\tfor (int i = 0; i < ELEM_MAX; i++)\n\t\t\tfixedHashMap.insert(FixedHashMapFalse::value_type(i, i));\n\n\t\tVERIFY(fixedHashMap.validate());\n\t\tVERIFY(fixedHashMap.size() == ELEM_MAX);\n\n\t\t// Verify insert requests of nodes already in the container don't attempt to allocate memory.\n\t\t// Because the fixed_hash_map is full any attempt to allocate memory will generate an OOM error.\n\t\t{\n\t\t\tauto result = fixedHashMap.insert(FixedHashMapFalse::value_type(0, 0));\n\t\t\tVERIFY(result.second == false);\n\t\t}\n\n\t\t{\n\t\t\tauto result = fixedHashMap.insert(fixedHashMap.begin(), FixedHashMapFalse::value_type(0, 0));\n\t\t\tVERIFY(result->first == 0);\n\t\t\tVERIFY(result->second == 0);\n\t\t}\n\n\t\t{\n\t\t\tFixedHashMapFalse::value_type value(0, 0);\n\t\t\tauto result = fixedHashMap.insert(eastl::move(value));\n\t\t\tVERIFY(result.second == false);\n\t\t}\n\t\t{\n\t\t\tFixedHashMapFalse::value_type value(0, 0);\n\t\t\tauto result = fixedHashMap.insert(fixedHashMap.begin(), eastl::move(value));\n\t\t\tVERIFY(result->first == 0);\n\t\t\tVERIFY(result->second == 0);\n\t\t}\n\n\t\t{\n\t\t\tFixedHashMapFalse::value_type value(0, 0);\n\t\t\tauto result = fixedHashMap.insert(value);\n\t\t\tVERIFY(result.second == false);\n\t\t}\n\n\t\t{\n\t\t\t// emplace may allocate a node, even if there is already an element with the key in the container, but\n\t\t\t// we ensure that emplace(value_type) (regardless of const qualifier and value category) doesn't allocate a node if it already exists.\n\t\t\tFixedHashMapFalse::value_type value(0, 0);\n\t\t\tauto result = fixedHashMap.emplace(value);\n\t\t\tVERIFY(result.second == false);\n\t\t}\n\n\t\t{\n\t\t\t// OOM, fixed allocator memory is exhausted so it can't create a node for insertation testing\n\t\t\t// auto result = fixedHashMap.emplace(0, 0);  \n\t\t\t// VERIFY(result.second == false);\n\t\t}\n\n\t\t{\n\t\t\t// matches insert(P&&) rather than insert(const value_type&) or insert(value_type&&)\n\t\t\t// (note that value_type is pair<const int, int>, not pair<int, int>)\n\t\t\t// which is equivalent to emplace<pair<int, int>>() and will cause a node construction, OOM.\n\t\t\t// auto result = fixedHashMap.insert(eastl::make_pair(0, 0));\n\t\t\t// VERIFY(result.second == false);\n\t\t}\n\t}\n\n\t{ // heterogenous functions - fixed_hash_map\n\t\teastl::fixed_hash_map<ExplicitString, int, 1, 2, true, ExplicitStringHash, eastl::equal_to<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestMapHeterogeneousInsertion<decltype(m)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\t{ // heterogenous functions - fixed_hash_multimap\n\t\teastl::fixed_hash_multimap<ExplicitString, int, 1, 2, true, ExplicitStringHash, eastl::equal_to<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\t{ // heterogenous functions - hash_set\n\t\teastl::fixed_hash_set<ExplicitString, 1, 2, true, ExplicitStringHash, eastl::equal_to<void>> s{ ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // heterogenous functions - hash_multiset\n\t\teastl::fixed_hash_multiset<ExplicitString, 1, 2, true, ExplicitStringHash, eastl::equal_to<void>> s{ ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n#if EASTL_NAME_ENABLED\n\t// allocators\n\t{\n\t\t{\n\t\t\teastl::fixed_hash_map<int, int, 64> c(EASTLAllocatorType(\"test\"));\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_hash_map<int, int, 64> c(eastl::hash<int>(), eastl::equal_to<int>(), EASTLAllocatorType(\"test\"));\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_hash_map<int, int, 64> c({ { 1, 2 }, { 3, 4 } }, EASTLAllocatorType(\"test\"));\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_hash_map<int, int, 64> c(EASTLAllocatorType(\"test\"));\n\t\t\tEA_DISABLE_CLANG_WARNING(-Wself-assign-overloaded);\n\t\t\tc = c;\n\t\t\tEA_RESTORE_CLANG_WARNING();\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_hash_multimap<int, int, 64> c(EASTLAllocatorType(\"test\"));\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_hash_multimap<int, int, 64> c(eastl::hash<int>(), eastl::equal_to<int>(), EASTLAllocatorType(\"test\"));\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_hash_multimap<int, int, 64> c({ { 1, 2 }, { 3, 4 } }, EASTLAllocatorType(\"test\"));\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_hash_multimap<int, int, 64> c(EASTLAllocatorType(\"test\"));\n\t\t\tEA_DISABLE_CLANG_WARNING(-Wself-assign-overloaded);\n\t\t\tc = c;\n\t\t\tEA_RESTORE_CLANG_WARNING();\n\t\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t\t}\n\t}\n#endif\n\n\treturn nErrorCount;\n}\nEA_RESTORE_VC_WARNING()\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestFixedList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/fixed_list.h>\n#include <EAStdC/EAString.h>\n\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::fixed_list<int, 1, true,  EASTLAllocatorType>;\ntemplate class eastl::fixed_list<int, 1, false, EASTLAllocatorType>;\n\n\n/*\n// This does not compile, since the fixed_list allocator is templated on sizeof(T), \n// not just T. Thus, the full type is required at the time of instantiation, but it\n// is not available.\n// See EATech Core JIRA issue ETCR-1608 for more information.\nstruct StructWithContainerOfStructs\n{\n\teastl::fixed_list<StructWithContainerOfStructs,4> children;\n};\n*/\n\n\nnamespace FixedListTest\n{\n\tstruct Item\n\t{\n\t   char mName[5];\n\t};\n}\n\n\nEA_DISABLE_VC_WARNING(6262)\nint TestFixedList()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\t// Test version *without* pool overflow.\n\t\ttypedef fixed_list<int, 64, false> FixedListInt64False;\n\n\t\tFixedListInt64False listInt64;\n\t\tVERIFY(listInt64.empty());\n\t\tVERIFY(listInt64.size() == 0);\n\t\tVERIFY(listInt64.max_size() == 64);\n\n\t\tlistInt64.push_back(1);\n\t\tVERIFY(!listInt64.empty());\n\t\tVERIFY(listInt64.size() == 1);\n\n\t\tlistInt64.resize(3, 2);\n\t\tVERIFY(!listInt64.empty());\n\t\tVERIFY(listInt64.size() == 3);\n\n\t\tFixedListInt64False::iterator i = listInt64.begin();\n\t\tVERIFY(*i == 1); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(i == listInt64.end());\n\n\t\tlistInt64.resize(0);\n\t\tVERIFY(listInt64.empty());\n\t\tVERIFY(listInt64.size() == 0);\n\n\t\twhile(listInt64.size() < 64)\n\t\t\tlistInt64.push_back(0);\n\n\t\t// Verify that we allocated enough space for exactly N items. \n\t\t// It's possible that due to alignments, there might be room for N + 1.\n\t\tFixedListInt64False::allocator_type& allocator = listInt64.get_allocator();\n\t\tvoid* pResult = allocator.allocate(sizeof(FixedListInt64False::node_type));\n\t\tif(pResult)\n\t\t{\n\t\t\tpResult = allocator.allocate(sizeof(FixedListInt64False::node_type));\n\t\t\tVERIFY(pResult == NULL); \n\t\t}\n\t}\n\n\n\t{\n\t\t// Test version *with* pool overflow.\n\t\ttypedef fixed_list<int, 64, true> FixedListInt64True;\n\n\t\tFixedListInt64True listInt64;\n\t\tVERIFY(listInt64.empty());\n\t\tVERIFY(listInt64.size() == 0);\n\n\t\tlistInt64.push_back(1);\n\t\tVERIFY(!listInt64.empty());\n\t\tVERIFY(listInt64.size() == 1);\n\n\t\tlistInt64.resize(3, 2);\n\t\tVERIFY(!listInt64.empty());\n\t\tVERIFY(listInt64.size() == 3);\n\n\t\tFixedListInt64True::iterator i = listInt64.begin();\n\t\tVERIFY(*i == 1); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(i == listInt64.end());\n\n\t\tlistInt64.resize(0);\n\t\tVERIFY(listInt64.empty());\n\t\tVERIFY(listInt64.size() == 0);\n\n\t\twhile(listInt64.size() < 64 + 16)\n\t\t\tlistInt64.push_back(0);\n\n\t\tFixedListInt64True::allocator_type& allocator = listInt64.get_allocator();\n\t\tvoid* pResult = allocator.allocate(sizeof(FixedListInt64True::node_type));\n\t\tVERIFY(pResult != NULL);\n\t\tallocator.deallocate(pResult, sizeof(FixedListInt64True::node_type));\n\n\t\t// get_overflow_allocator / set_overflow_allocator\n\t\t// This is a weak test which should be improved.\n\t\tEASTLAllocatorType a = listInt64.get_allocator().get_overflow_allocator();\n\t\tlistInt64.get_allocator().set_overflow_allocator(a);\n\t}\n\n\n\t{\n\t\t// Test version *with* pool overflow with a custom overlow allocator specification.\n\t\ttypedef fixed_list<int, 64, true, MallocAllocator> FixedListInt64TrueMalloc;\n\n\t\tFixedListInt64TrueMalloc listInt64;\n\t\tVERIFY(listInt64.empty());\n\t\tVERIFY(listInt64.size() == 0);\n\n\t\tlistInt64.push_back(1);\n\t\tVERIFY(!listInt64.empty());\n\t\tVERIFY(listInt64.size() == 1);\n\n\t\tlistInt64.resize(3, 2);\n\t\tVERIFY(!listInt64.empty());\n\t\tVERIFY(listInt64.size() == 3);\n\n\t\tFixedListInt64TrueMalloc::iterator i = listInt64.begin();\n\t\tVERIFY(*i == 1); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(i == listInt64.end());\n\n\t\tlistInt64.resize(0);\n\t\tVERIFY(listInt64.empty());\n\t\tVERIFY(listInt64.size() == 0);\n\n\t\twhile(listInt64.size() < 64 + 16)\n\t\t\tlistInt64.push_back(0);\n\n\t\tFixedListInt64TrueMalloc::allocator_type& allocator = listInt64.get_allocator();\n\t\tvoid* pResult = allocator.allocate(sizeof(FixedListInt64TrueMalloc::node_type));\n\t\tVERIFY(pResult != NULL);\n\t\tallocator.deallocate(pResult, sizeof(FixedListInt64TrueMalloc::node_type));\n\t}\n\n\t{\n\t\t// Test fixed list with overflow and alignment requirements.\n\t\ttypedef fixed_list<Align64, 1, true, CustomAllocator> FixedListWithAlignment;\n\n\t\tFixedListWithAlignment fl;\n\n\t\tAlign64 a;\n\n\t\tfl.push_back(a);\n\t\tfl.push_back(a);\n\t\tfl.push_back(a);\n\t\tfl.push_back(a);\n\t\tfl.push_back(a);\n\t\tfor (FixedListWithAlignment::const_iterator it = fl.begin(); it != fl.end(); ++it)\n\t\t{\n\t\t\tconst Align64* ptr = &(*it);\n\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t}\n\t}\n\n\t{\n\t\t// swap\n\n\t\tfixed_list<int, 64>* pListInt64A = new fixed_list<int, 64>;\n\t\tfixed_list<int, 64>* pListInt64B = new fixed_list<int, 64>;\n\n\t\tpListInt64A->push_back(0);\n\t\tpListInt64B->push_back(0);\n\n\t\tswap(*pListInt64A, *pListInt64B);\n\n\t\tdelete pListInt64A;\n\t\tdelete pListInt64B;\n\t}\n\n\n\t{\n\t\t// operator=\n\n\t\tfixed_list<int, 64>* pListInt64A = new fixed_list<int, 64>;\n\t\tfixed_list<int, 64>* pListInt64B = new fixed_list<int, 64>;\n\n\t\tpListInt64A->push_back(0);\n\t\tpListInt64B->push_back(0);\n\n\t\t*pListInt64A = *pListInt64B;\n\n\t\tdelete pListInt64A;\n\t\tdelete pListInt64B;\n\t}\n\n\n\t{\n\t\t// bool empty() const\n\t\t// bool has_overflowed() const\n\t\t// size_type size() const;\n\t\t// size_type max_size() const\n\n\t\t// Test a list that has overflow disabled.\n\t\tfixed_list<int, 5, false> listInt5;\n\n\t\tVERIFY(listInt5.max_size() == 5);\n\t\tVERIFY(listInt5.size() == 0);\n\t\tVERIFY(listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_back(37);\n\t\tlistInt5.push_back(37);\n\t\tlistInt5.push_back(37);\n\n\t\tVERIFY(listInt5.size() == 3);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_back(37);\n\t\tlistInt5.push_back(37);\n\n\t\tVERIFY(listInt5.size() == 5);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.pop_back();\n\n\t\tVERIFY(listInt5.size() == 4);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\t}\n\n\n\t{\n\t\t// bool empty() const\n\t\t// bool has_overflowed() const\n\t\t// size_type size() const;\n\t\t// size_type max_size() const\n\n\t\t// Test a list that has overflow enabled.\n\t\tfixed_list<int, 5, true> listInt5;\n\n\t\tVERIFY(listInt5.max_size() == 5);\n\t\tVERIFY(listInt5.size() == 0);\n\t\tVERIFY(listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_back(37);\n\t\tlistInt5.push_back(37);\n\t\tlistInt5.push_back(37);\n\n\t\tVERIFY(listInt5.size() == 3);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_back(37);\n\t\tlistInt5.push_back(37);\n\n\t\tVERIFY(listInt5.size() == 5);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_back(37);\n\n\t\tVERIFY(listInt5.size() == 6);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(listInt5.has_overflowed());\n\n\t\tlistInt5.pop_back();\n\n\t\tVERIFY(listInt5.size() == 5);\n\t\tVERIFY(!listInt5.empty());\n\t  //VERIFY(listInt5.has_overflowed());  Disabled because currently has_overflowed can't detect this situation in non-debug builds.\n\t}\n\n\t{\n\t\t//template <typename Compare>\n\t\t//void merge(this_type& x, Compare compare);\n\t\t//void unique();\n\t\t//template <typename BinaryPredicate>\n\t\t//void unique(BinaryPredicate);\n\t\t//void sort();\n\t\t//template<typename Compare>\n\t\t//void sort(Compare compare);\n\n\t\tconst int A[] = {1, 2, 3, 4, 5, 6};\n\t\tconst int B[] = {12, 15, 13, 14, 11};\n\t\tconst int C[] = {11, 12, 13, 14, 15};\n\t\tconst int D[] = {1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6};\n\t\tconst int N = sizeof(A) / sizeof(A[0]);\n\t\tconst int M = sizeof(B) / sizeof(B[0]);\n\t\tconst int Q = sizeof(D) / sizeof(D[0]);\n\n\t\tfixed_list<int, 32, true> list0401(A, A + N);\n\t\tfixed_list<int, 32, true> list0402(B, B + M);\n\t\tfixed_list<int, 32, true> list0403(C, C + M);\n\t\tfixed_list<int, 32, true> list0404(D, D + Q);\n\t\tfixed_list<int, 32, true> list0405(A, A + N);\n\n\t\tlist0402.sort(eastl::less<int>());\n\t\tVERIFY(list0402 == list0403);\n\n\t\tlist0401.merge(list0402, eastl::less<int>());\n\t\tlist0404.sort();\n\n\t\t//merge and isn't yet working for fixed_list.\n\t\t//VERIFY(list0401 == list0404);\n\n\t\tVERIFY(list0401.validate());\n\t\tVERIFY(list0402.validate());\n\t\tVERIFY(list0403.validate());\n\t\tVERIFY(list0404.validate());\n\t\tVERIFY(list0405.validate());\n\t}\n\n\n\t{\n\t\t// void sort()\n\t\t// void sort(Compare compare)\n\n\t\tconst int kSize = 10;\n\t\tconst int A[kSize] = { 1, 9, 2, 3, 5, 7, 4, 6, 8, 0 };\n\n\t\tfixed_list<int, 32, true> listEmpty;\n\t\tVERIFY(VerifySequence(listEmpty.begin(), listEmpty.end(), int(), \"fixed_list::sort\", -1));\n\t\tlistEmpty.sort();\n\t\tVERIFY(VerifySequence(listEmpty.begin(), listEmpty.end(), int(), \"fixed_list::sort\", -1));\n\n\t\tfixed_list<int, 32, true> list1(A, A + 1);\n\t\tVERIFY(VerifySequence(list1.begin(), list1.end(), int(), \"fixed_list::sort\", 1, -1));\n\t\tlist1.sort();\n\t\tVERIFY(VerifySequence(list1.begin(), list1.end(), int(), \"fixed_list::sort\", 1, -1));\n\n\t\tfixed_list<int, 32, true> list4(A, A + 4);\n\t\tVERIFY(VerifySequence(list4.begin(), list4.end(), int(), \"fixed_list::sort\", 1, 9, 2, 3, -1));\n\t\tlist4.sort();\n\t\tVERIFY(VerifySequence(list4.begin(), list4.end(), int(), \"fixed_list::sort\", 1, 2, 3, 9, -1));\n\n\t\tfixed_list<int, 32, true> listA(A, A + kSize);\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::sort\", 1, 9, 2, 3, 5, 7, 4, 6, 8, 0, -1));\n\t\tlistA.sort();\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::sort\", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));\n\n\t\tlistA.assign(A, A + kSize);\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::sort\", 1, 9, 2, 3, 5, 7, 4, 6, 8, 0, -1));\n\t\tlistA.sort(eastl::less<int>());\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::sort\", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));\n\t}\n\n\n\t{\n\t\t// void merge(this_type& x);\n\t\t// void merge(this_type& x, Compare compare);\n\n\t\tconst int kSize = 8;\n\t\tconst int A[kSize] = { 1, 2, 3, 4, 4, 5, 9, 9 };\n\t\tconst int B[kSize] = { 1, 2, 3, 4, 4, 5, 9, 9 };\n\n\t\tfixed_list<int, 32, true> listA(A, A + kSize);\n\t\tfixed_list<int, 32, true> listB(B, B + kSize);\n\n\t\tlistA.merge(listB);\n\n\t\t//merge and isn't yet working for fixed_list.\n\t\t//VERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::merge\", 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 9, 9, 9, 9, -1));\n\t\t//VERIFY(VerifySequence(listB.begin(), listB.end(), int(), \"fixed_list::merge\", -1));\n\t}\n\n\n\t{\n\t\t// void splice(iterator position, this_type& x);\n\t\t// void splice(iterator position, this_type& x, iterator i);\n\t\t// void splice(iterator position, this_type& x, iterator first, iterator last);\n\n\t\tconst int kSize = 8;\n\t\tconst int A[kSize] = { 1, 2, 3, 4, 4, 5, 9, 9 };\n\t\tconst int B[kSize] = { 1, 2, 3, 4, 4, 5, 9, 9 };\n\n\t\tfixed_list<int, 32, true> listA(A, A + kSize);\n\t\tfixed_list<int, 32, true> listB(B, B + kSize);\n\t\tfixed_list<int, 32, true>::iterator it;\n\n\t\t// void splice(iterator position, this_type& x);\n\t\tit = listA.begin(); eastl::advance(it, 2);\n\t\tlistA.splice(it, listB); // move listB into listA at position it.\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::splice\", 1, 2, 1, 2, 3, 4, 4, 5, 9, 9, 3, 4, 4, 5, 9, 9, -1));\n\t\tVERIFY(VerifySequence(listB.begin(), listB.end(), int(), \"fixed_list::splice\", -1));\n\n\t\t// void splice(iterator position, this_type& x, iterator i);\n\t\tit = listA.begin(); eastl::advance(it, 6);\n\t\tlistB.splice(listB.begin(), listA, it);     // move listA's it (6th element) into the front of listB.\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::splice\", 1, 2, 1, 2, 3, 4, 5, 9, 9, 3, 4, 4, 5, 9, 9, -1));\n\t\tVERIFY(VerifySequence(listB.begin(), listB.end(), int(), \"fixed_list::splice\", 4, -1));\n\n\t\t// void splice(iterator position, this_type& x, iterator first, iterator last);\n\t\tlistA.splice(listA.end(), listB, listB.begin(), listB.end()); // move listB into listA at the end of listA.\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::splice\", 1, 2, 1, 2, 3, 4, 5, 9, 9, 3, 4, 4, 5, 9, 9, 4, -1));\n\t\tVERIFY(VerifySequence(listB.begin(), listB.end(), int(), \"fixed_list::splice\", -1));\n\t}\n\n\n\t{\n\t\t// void unique();\n\t\t// void unique(BinaryPredicate);\n\n\t\tconst int kSize = 8;\n\t\tconst int A[kSize] = { 1, 2, 3, 4, 4, 5, 9, 9 };\n\t\tconst int B[kSize] = { 1, 2, 3, 4, 4, 5, 9, 9 };\n\n\t\tfixed_list<int, 32, true> listA(A, A + kSize);\n\t\tlistA.unique();\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::unique\", 1, 2, 3, 4, 5, 9, -1));\n\n\t\tfixed_list<int, 32, true> listB(B, B + kSize);\n\t\tlistB.unique(eastl::equal_to<int>());\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"fixed_list::unique\", 1, 2, 3, 4, 5, 9, -1));\n\t}\n\n\n\t{\n\t\t// fixed_list(this_type&& x);\n\t\t// fixed_list(this_type&&, const allocator_type&);\n\t\t// this_type& operator=(this_type&& x);\n\t\tfixed_list<TestObject, 16> list3TO33(3, TestObject(33));\n\t\tfixed_list<TestObject, 16> toListA(eastl::move(list3TO33));\n\t\tEATEST_VERIFY((toListA.size() == 3) && (toListA.front().mX == 33) /* && (list3TO33.size() == 0) fixed_list usually can't honor the move request. */);\n\n\t\t// The following is not as strong a test of this ctor as it could be. A stronger test would be to use IntanceAllocator with different instances.\n\t\tfixed_list<TestObject, 16, true, MallocAllocator> list4TO44(4, TestObject(44));\n\t\tfixed_list<TestObject, 16, true, MallocAllocator> toListB(eastl::move(list4TO44), MallocAllocator());\n\t\tEATEST_VERIFY((toListB.size() == 4) && (toListB.front().mX == 44) /* && (list4TO44.size() == 0) fixed_list usually can't honor the move request. */);\n\n\t\tfixed_list<TestObject, 16, true, MallocAllocator> list5TO55(5, TestObject(55));\n\t\ttoListB = eastl::move(list5TO55);\n\t\tEATEST_VERIFY((toListB.size() == 5) && (toListB.front().mX == 55) /* && (list5TO55.size() == 0) fixed_list usually can't honor the move request. */);\n\t}\n\n\n\t{\n\t\t// template <class... Args>\n\t\t// void emplace_front(Args&&... args);\n\n\t\t// template <class... Args>\n\t\t// void emplace_back(Args&&... args);\n\n\t\t// template <class... Args>\n\t\t// iterator emplace(const_iterator position, Args&&... args);\n\n\t\tTestObject::Reset();\n\n\t\tfixed_list<TestObject, 16> toListA;\n\n\t\ttoListA.emplace_front(1, 2, 3); // This uses the TestObject(int x0, int x1, int x2, bool bThrowOnCopy) constructor.\n\t\tEATEST_VERIFY((toListA.size() == 1) && (toListA.front().mX == (1+2+3)) && (TestObject::sTOCtorCount == 1));\n\n\t\ttoListA.emplace_back(2, 3, 4);\n\t\tEATEST_VERIFY((toListA.size() == 2) && (toListA.back().mX == (2+3+4)) && (TestObject::sTOCtorCount == 2));\n\n\t\ttoListA.emplace(toListA.begin(), 3, 4, 5);\n\t\tEATEST_VERIFY((toListA.size() == 3) && (toListA.front().mX == (3+4+5)) && (TestObject::sTOCtorCount == 3));\n\n\n\t\t// This test is similar to the emplace pathway above. \n\t\tTestObject::Reset();\n\n\t\t// void push_front(T&& x);\n\t\t// void push_back(T&& x);\n\t\t// iterator insert(const_iterator position, T&& x);\n\n\t\tfixed_list<TestObject, 16> toListC;\n\n\t\ttoListC.push_front(TestObject(1, 2, 3));\n\t\tEATEST_VERIFY((toListC.size() == 1) && (toListC.front().mX == (1+2+3)) && (TestObject::sTOMoveCtorCount == 1));\n\n\t\ttoListC.push_back(TestObject(2, 3, 4));\n\t\tEATEST_VERIFY((toListC.size() == 2) && (toListC.back().mX == (2+3+4)) && (TestObject::sTOMoveCtorCount == 2));\n\n\t\ttoListC.insert(toListC.begin(), TestObject(3, 4, 5));\n\t\tEATEST_VERIFY((toListC.size() == 3) && (toListC.front().mX == (3+4+5)) && (TestObject::sTOMoveCtorCount == 3));\n\t}\n\n\n\t{\n\t\t// list(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_LIST_DEFAULT_ALLOCATOR);\n\t\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t\t// void assign(std::initializer_list<value_type> ilist);\n\t\t// iterator insert(iterator position, std::initializer_list<value_type> ilist);\n\t\tlist<int> intList = { 0, 1, 2 };\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"list std::initializer_list\", 0, 1, 2, -1));\n\n\t\tintList = { 13, 14, 15 };\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"list std::initializer_list\", 13, 14, 15, -1));\n\n\t\tintList.assign({ 16, 17, 18 });\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"list std::initializer_list\", 16, 17, 18, -1));\n\n\t\tintList.insert(intList.begin(), { 14, 15 });\n\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"list std::initializer_list\", 14, 15, 16, 17, 18, -1));\n\t}\n\n\n\t{   // Regression of user test\n\t\tstruct Dummy\n\t\t{\n\t\t   typedef eastl::fixed_list<FixedListTest::Item, 10, false> TCollection;\n\n\t\t   TCollection mCollection1;\n\t\t   TCollection mCollection2;\n\t\t};\n\n\t\tDummy d;\n\t\tVERIFY(d.mCollection1.size() == d.mCollection2.size());\n\t}\n\n\n\t{\n\t\t// Test construction of a container with an overflow allocator constructor argument.\n\t\tMallocAllocator overflowAllocator;\n\t\tvoid* p = overflowAllocator.allocate(1);\n\t\tfixed_list<int, 64, true, MallocAllocator> c(overflowAllocator);\n\t\tc.resize(65);\n\t\tVERIFY(c.get_overflow_allocator().mAllocCount == 2); // 1 for above, and 1 for overflowing from 64 to 65.\n\t\toverflowAllocator.deallocate(p, 1);\n\t}\n\n#if EASTL_NAME_ENABLED\n\t// allocators\n\t{\n\t\tfixed_list<int, 64> c(EASTLAllocatorType(\"test\"));\n\t\tVERIFY(EA::StdC::Strcmp(c.get_allocator().get_name(), \"test\") == 0);\n\t}\n#endif\n\n\n\t// We can't do this, due to how Reset is used above:\n\t//   EATEST_VERIFY(TestObject::IsClear());\n\tEATEST_VERIFY(TestObject::sMagicErrorCount == 0);\n\tTestObject::Reset();\n\n\n\treturn nErrorCount;\n}\nEA_RESTORE_VC_WARNING()\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestFixedMap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include \"TestMap.h\"\n#include <EASTL/fixed_map.h>\n#include \"TestAssociativeContainers.h\"\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <map>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::fixed_map     <int,        float,      1>;\ntemplate class eastl::fixed_multimap<float,      int,        1>;\ntemplate class eastl::fixed_map     <int,        TestObject, 1>;\ntemplate class eastl::fixed_multimap<TestObject, int,        1>;\n\ntemplate class eastl::fixed_map     <int,        float,      1, true, eastl::less<int>,        MallocAllocator>;\ntemplate class eastl::fixed_multimap<float,      int,        1, true, eastl::less<float>,      MallocAllocator>;\ntemplate class eastl::fixed_map     <int,        TestObject, 1, true, eastl::less<int>,        MallocAllocator>;\ntemplate class eastl::fixed_multimap<TestObject, int,        1, true, eastl::less<TestObject>, MallocAllocator>;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// typedefs\n//\n\tconst eastl_size_t kContainerSize = 1000;\n\ntypedef eastl::fixed_map<int, int, kContainerSize> VM1;\ntypedef eastl::fixed_map<TestObject, TestObject, kContainerSize> VM4;\ntypedef eastl::fixed_multimap<int, int, kContainerSize> VMM1;\ntypedef eastl::fixed_multimap<TestObject, TestObject, kContainerSize> VMM4;\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\ttypedef std::map<int, int> VM3;\n\ttypedef std::map<TestObject, TestObject> VM6;\n\ttypedef std::multimap<int, int> VMM3;\n\ttypedef std::multimap<TestObject, TestObject> VMM6;\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\n\nEA_DISABLE_VC_WARNING(6262)\nint TestFixedMap()\n{\n\tint nErrorCount = 0;\n\n\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t{   // Test construction\n\t\t\tnErrorCount += TestMapConstruction<VM1, VM3, false>();\n\t\t\tnErrorCount += TestMapConstruction<VM4, VM6, false>();\n\t\t\tnErrorCount += TestMapConstruction<eastl::fixed_map<int, int, kContainerSize, true, eastl::less<void>>, std::map<int, int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestMapConstruction<VMM1, VMM3, true>();\n\t\t\tnErrorCount += TestMapConstruction<VMM4, VMM6, true>();\n\t\t\tnErrorCount += TestMapConstruction<eastl::fixed_multimap<int, int, kContainerSize, true, eastl::less<void>>, std::multimap<int, int, std::less<void>>, true>();\n\t\t}\n\n\n\t\t{   // Test mutating functionality.\n\t\t\tnErrorCount += TestMapMutation<VM1, VM3, false>();\n\t\t\tnErrorCount += TestMapMutation<VM4, VM6, false>();\n\t\t\tnErrorCount += TestMapMutation<eastl::fixed_map<int, int, kContainerSize, true, eastl::less<void>>, std::map<int, int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestMapMutation<VMM1, VMM3, true>();\n\t\t\tnErrorCount += TestMapMutation<VMM4, VMM6, true>();\n\t\t\tnErrorCount += TestMapMutation<eastl::fixed_multimap<int, int, kContainerSize, true, eastl::less<void>>, std::multimap<int, int, std::less<void>>, true>();\n\t\t}\n\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n\t{   // Test searching functionality.\n\t\tnErrorCount += TestMapSearch<VM1, false>();\n\t\tnErrorCount += TestMapSearch<VM4, false>();\n\t\tnErrorCount += TestMapSearch<eastl::fixed_map<int, int, kContainerSize, true, eastl::less<void>>, false>();\n\n\t\tnErrorCount += TestMapSearch<VMM1, true>();\n\t\tnErrorCount += TestMapSearch<VMM4, true>();\n\t\tnErrorCount += TestMapSearch<eastl::fixed_multimap<int, int, kContainerSize, true, eastl::less<void>>, true>();\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestMapCpp11<eastl::fixed_map<int, TestObject, 32> >();\n\t\tnErrorCount += TestMapCpp11<eastl::fixed_map<int, TestObject, 32, true, eastl::less<void>>>();\n\n\t\tnErrorCount += TestMultimapCpp11<eastl::fixed_multimap<int, TestObject, 32> >();\n\t\tnErrorCount += TestMultimapCpp11<eastl::fixed_multimap<int, TestObject, 32, true, eastl::less<void>>>();\n\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::fixed_map<int, NonCopyable, 32>>();\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::fixed_map<int, NonCopyable, 32, true, eastl::less<void>>>();\n\t}\n\n\t{\n\t\t// C++17 try_emplace and related functionality\n\t\tnErrorCount += TestMapCpp17<eastl::fixed_map<int, TestObject, 32>>();\n\t\tnErrorCount += TestMapCpp17<eastl::fixed_map<int, TestObject, 32, true, eastl::less<void>>>();\n\t}\n\n\n\t{ // Test functionality specific to fixed size containers.\n\n\t\tVM1  vm1;\n\t\tVMM1 vmm1;\n\n\t\tVERIFY(vm1.max_size() == kContainerSize);\n\t\tVERIFY(vmm1.max_size() == kContainerSize);\n\t}\n\n\n\t{   // Regression of bug report by Eric Turmel, May 20, 2008\n\t\ttypedef eastl::fixed_map<int, TestObject, 37, false> FixedMap;\n\t\tVERIFY(FixedMap::kMaxSize == 37);\n\n\t\tFixedMap fixedMap;\n\t\tFixedMap::fixed_allocator_type& a = fixedMap.get_allocator();\n\n\t\tfor(int i = 0; i < FixedMap::kMaxSize; i++)\n\t\t{\n\t\t\tVERIFY(a.can_allocate());\n\n\t\t\tfixedMap.insert(FixedMap::value_type(i, TestObject(i)));\n\n\t\t\t#if EASTL_FIXED_SIZE_TRACKING_ENABLED\n\t\t\t\t// Disabled because mPool is (mistakenly) inaccessible.\n\t\t\t\t// VERIFY((a.mPool.mnCurrentSize == a.mPool.mnPeakSize) && (a.mPool.mnCurrentSize == i));\n\t\t\t#endif\n\t\t}\n\n\t\tVERIFY(!a.can_allocate());\n\t}\n\n\t{\n\t\t// Test fixed set with overflow and alignment requirements.\n\t\ttypedef fixed_map<Align64, int, 1, true> FixedMapWithAlignment;\n\t\ttypedef fixed_multimap<Align64, int, 1, true> FixedMultiMapWithAlignment;\n\n\t\tFixedMapWithAlignment fm;\n\t\tFixedMultiMapWithAlignment fmm;\n\n\t\tAlign64 a; a.mX = 1;\n\t\tAlign64 b; b.mX = 2;\n\t\tAlign64 c; c.mX = 3;\n\t\tAlign64 d; d.mX = 4;\n\t\tAlign64 e; e.mX = 5;\n\n\t\tfm.insert(a);\n\t\tfm.insert(b);\n\t\tfm.insert(c);\n\t\tfm.insert(d);\n\t\tfm.insert(e);\n\t\tfor (FixedMapWithAlignment::const_iterator it = fm.begin(); it != fm.end(); ++it)\n\t\t{\n\t\t\tconst Align64* ptr = &((*it).first);\n\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t}\n\n\t\tfmm.insert(a);\n\t\tfmm.insert(b);\n\t\tfmm.insert(c);\n\t\tfmm.insert(d);\n\t\tfmm.insert(e);\n\t\tfor (FixedMultiMapWithAlignment::const_iterator it = fmm.begin(); it != fmm.end(); ++it)\n\t\t{\n\t\t\tconst Align64* ptr = &((*it).first);\n\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t}\n\t}\n\n\t{ // heterogenous functions - fixed_map\n\t\tfixed_map<ExplicitString, int, 1, true, eastl::less<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestMapHeterogeneousInsertion<decltype(m)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\t{ // heterogenous functions - fixed_multimap\n\t\tfixed_multimap<ExplicitString, int, 1, true, eastl::less<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(m);\n\n\t\tVERIFY(m.equal_range_small(\"not found\") == eastl::make_pair(m.lower_bound(\"not found\"), m.upper_bound(\"not found\")));\n\t\tVERIFY(m.equal_range_small(\"found\") == eastl::make_pair(m.lower_bound(\"found\"), m.upper_bound(\"found\")));\n\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\n\treturn nErrorCount;\n}\nEA_RESTORE_VC_WARNING()\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestFixedSList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/fixed_slist.h>\n#include <EABase/eabase.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n\n#include <stdio.h>\n\n#if defined(_MSC_VER)\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::fixed_slist<int, 1, true,  EASTLAllocatorType>;\ntemplate class eastl::fixed_slist<int, 1, false, EASTLAllocatorType>;\n\n\n/*\n// This does not compile, since the fixed_slist allocator is templated on sizeof(T), \n// not just T. Thus, the full type is required at the time of instantiation, but it\n// is not available.\n// See EATech Core JIRA issue ETCR-1608 for more information.\nstruct StructWithContainerOfStructs\n{\n\teastl::fixed_slist<StructWithContainerOfStructs,4> children;\n};\n*/\n\n\nint TestFixedSList()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tfixed_slist<int, 64> list0101;\n\t\tVERIFY(list0101.empty());\n\t\tVERIFY(list0101.size() == 0);\n\t\tVERIFY(list0101.max_size() == 64);\n\n\t\tlist0101.push_front(1);\n\t\tVERIFY(!list0101.empty());\n\t\tVERIFY(list0101.size() == 1);\n\n\t\tlist0101.resize(3, 2);\n\t\tVERIFY(!list0101.empty());\n\t\tVERIFY(list0101.size() == 3);\n\n\t\tfixed_slist<int, 64>::iterator i = list0101.begin();\n\t\tVERIFY(*i == 1); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(i == list0101.end());\n\n\t\tlist0101.resize(0);\n\t\tVERIFY(list0101.empty());\n\t\tVERIFY(list0101.size() == 0);\n\t}\n\n\t{\n\t\tfixed_slist<int, 64, true, MallocAllocator> list0101;\n\t\tVERIFY(list0101.empty());\n\t\tVERIFY(list0101.size() == 0);\n\t\tVERIFY(list0101.max_size() == 64);\n\n\t\tlist0101.push_front(1);\n\t\tVERIFY(!list0101.empty());\n\t\tVERIFY(list0101.size() == 1);\n\n\t\tlist0101.resize(3, 2);\n\t\tVERIFY(!list0101.empty());\n\t\tVERIFY(list0101.size() == 3);\n\n\t\tfixed_slist<int, 64>::iterator i = list0101.begin();\n\t\tVERIFY(*i == 1); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(*i == 2); ++i;\n\t\tVERIFY(i == list0101.end());\n\n\t\twhile(list0101.size() < 64 + 16)\n\t\t\tlist0101.push_front(0);\n\n\t\tlist0101.resize(0);\n\t\tVERIFY(list0101.empty());\n\t\tVERIFY(list0101.size() == 0);\n\t}\n\n\t{\n\t\t// Test fixed slist with overflow and alignment requirements.\n\t\ttypedef fixed_slist<Align64, 1, true, CustomAllocator> FixedSListWithAlignment;\n\n\t\tFixedSListWithAlignment fsl;\n\n\t\tAlign64 a;\n\n\t\tfsl.push_front(a);\n\t\tfsl.push_front(a);\n\t\tfsl.push_front(a);\n\t\tfsl.push_front(a);\n\t\tfsl.push_front(a);\n\t\tfor (FixedSListWithAlignment::const_iterator it = fsl.begin(); it != fsl.end(); ++it)\n\t\t{\n\t\t\tconst Align64* ptr = &(*it);\n\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t}\n\t}\n\n\t{\n\t\t// bool empty() const\n\t\t// bool has_overflowed() const\n\t\t// size_type size() const;\n\t\t// size_type max_size() const\n\n\t\t// Test a list that has overflow disabled.\n\t\tfixed_slist<int, 5, false> listInt5;\n\n\t\tVERIFY(listInt5.max_size() == 5);\n\t\tVERIFY(listInt5.size() == 0);\n\t\tVERIFY(listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_front(37);\n\t\tlistInt5.push_front(37);\n\t\tlistInt5.push_front(37);\n\n\t\tVERIFY(listInt5.size() == 3);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_front(37);\n\t\tlistInt5.push_front(37);\n\n\t\tVERIFY(listInt5.size() == 5);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.pop_front();\n\n\t\tVERIFY(listInt5.size() == 4);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\t}\n\n\n\t{\n\t\t// bool empty() const\n\t\t// bool has_overflowed() const\n\t\t// size_type size() const;\n\t\t// size_type max_size() const\n\n\t\t// Test a list that has overflow enabled.\n\t\tfixed_slist<int, 5, true> listInt5;\n\n\t\tVERIFY(listInt5.max_size() == 5);\n\t\tVERIFY(listInt5.size() == 0);\n\t\tVERIFY(listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_front(37);\n\t\tlistInt5.push_front(37);\n\t\tlistInt5.push_front(37);\n\n\t\tVERIFY(listInt5.size() == 3);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_front(37);\n\t\tlistInt5.push_front(37);\n\n\t\tVERIFY(listInt5.size() == 5);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(!listInt5.has_overflowed());\n\n\t\tlistInt5.push_front(37);\n\n\t\tVERIFY(listInt5.size() == 6);\n\t\tVERIFY(!listInt5.empty());\n\t\tVERIFY(listInt5.has_overflowed());\n\n\t\tlistInt5.pop_front();\n\n\t\tVERIFY(listInt5.size() == 5);\n\t\tVERIFY(!listInt5.empty());\n\t  //VERIFY(listInt5.has_overflowed());  Disabled because currently has_overflowed can't detect this situation in non-debug builds.\n\t}\n\n\n\t{\n\t\t// fixed_slist(this_type&& x);\n\t\t// fixed_slist(this_type&&, const allocator_type&);\n\t\t// this_type& operator=(this_type&& x);\n\n\t\tfixed_slist<TestObject, 16> slist3TO33(3, TestObject(33));\n\t\tfixed_slist<TestObject, 16> toListA(eastl::move(slist3TO33));\n\t\tEATEST_VERIFY((toListA.size() == 3) && (toListA.front().mX == 33) /* && (slist3TO33.size() == 0) fixed_list usually can't honor the move request. */);\n\n\t\t// The following is not as strong a test of this ctor as it could be. A stronger test would be to use IntanceAllocator with different instances.\n\t\tfixed_slist<TestObject, 16, true, MallocAllocator> slist4TO44(4, TestObject(44));\n\t\tfixed_slist<TestObject, 16, true, MallocAllocator> toListB(eastl::move(slist4TO44), MallocAllocator());\n\t\tEATEST_VERIFY((toListB.size() == 4) && (toListB.front().mX == 44) /* && (slist4TO44.size() == 0) fixed_list usually can't honor the move request. */);\n\n\t\tfixed_slist<TestObject, 16, true, MallocAllocator> slist5TO55(5, TestObject(55));\n\t\ttoListB = eastl::move(slist5TO55);\n\t\tEATEST_VERIFY((toListB.size() == 5) && (toListB.front().mX == 55) /* && (slist5TO55.size() == 0) fixed_list usually can't honor the move request. */);\n\t}\n\n\n\t{\n\t\t// template <class... Args>\n\t\t// void emplace_front(Args&&... args);\n\n\t\t// template <class... Args>\n\t\t// iterator emplace_after(const_iterator position, Args&&... args);\n\n\t\tTestObject::Reset();\n\n\t\tfixed_slist<TestObject, 16> toListA;\n\n\t\ttoListA.emplace_front(1, 2, 3); // This uses the TestObject(int x0, int x1, int x2, bool bThrowOnCopy) constructor.\n\t\tEATEST_VERIFY((toListA.size() == 1) && (toListA.front().mX == (1+2+3)) && (TestObject::sTOCtorCount == 1));\n\n\t\ttoListA.emplace_after(toListA.before_begin(), 3, 4, 5);\n\t\tEATEST_VERIFY((toListA.size() == 2) && (toListA.front().mX == (3+4+5)) && (TestObject::sTOCtorCount == 2));\n\n\n\t\t// This test is similar to the emplace pathway above. \n\t\tTestObject::Reset();\n\n\t\t// void push_front(T&& x);\n\t\t// iterator insert(const_iterator position, T&& x);\n\n\t\tfixed_slist<TestObject, 16> toListC;\n\n\t\ttoListC.push_front(TestObject(1, 2, 3));\n\t\tEATEST_VERIFY((toListC.size() == 1) && (toListC.front().mX == (1+2+3)) && (TestObject::sTOMoveCtorCount == 1));\n\n\t\ttoListC.insert_after(toListC.before_begin(), TestObject(3, 4, 5));\n\t\tEATEST_VERIFY((toListC.size() == 2) && (toListC.front().mX == (3+4+5)) && (TestObject::sTOMoveCtorCount == 2));\n\t}\n\n\n\t{\n\t\t// slist(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_SLIST_DEFAULT_ALLOCATOR);\n\t\t// this_type& operator=(std::initializer_list<value_type>);\n\t\t// void assign(std::initializer_list<value_type> ilist);\n\t\t// iterator insert_after(iterator position, std::initializer_list<value_type> ilist);\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\tfixed_slist<int, 8> intList = { 0, 1, 2 };\n\t\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fixed_slist std::initializer_list\", 0, 1, 2, -1));\n\n\t\t\tintList = { 13, 14, 15 };\n\t\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fixed_slist std::initializer_list\", 13, 14, 15, -1));\n\n\t\t\tintList.assign({ 16, 17, 18 });\n\t\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fixed_slist std::initializer_list\", 16, 17, 18, -1));\n\n\t\t\tfixed_slist<int, 8>::iterator it = intList.insert_after(intList.before_begin(), { 14, 15 });\n\t\t\tEATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), \"fixed_slist std::initializer_list\", 14, 15, 16, 17, 18, -1));\n\t\t\tEATEST_VERIFY(*it == 15); // Note that slist::insert_after returns the last inserted element, not the first as with list::insert.\n\t\t#endif\n\t}\n\n\n\t{\n\t\t// Test construction of a container with an overflow allocator constructor argument.\n\t\t//\n\t\t// GCC 4.4 has a hard time compiling this code correctly in optimized builds as it \n\t\t// omits the increment of the mAllocCount field when calling overflowAllocator.allocate.\n\t\t#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION == 4004)\n\t\t\tMallocAllocator overflowAllocator;\n\t\t\tfixed_slist<int, 64, true, MallocAllocator> c(overflowAllocator);\n\t\t\tc.resize(65);\n\t\t\tVERIFY(c.get_overflow_allocator().mAllocCount == 1); // 1 for overflowing from 64 to 65.\n\t\t#else\n\t\t\tMallocAllocator overflowAllocator;\n\t\t\tvoid* p = overflowAllocator.allocate(1);\n\t\t\tfixed_slist<int, 64, true, MallocAllocator> c(overflowAllocator);\n\t\t\tc.resize(65);\n\t\t\tVERIFY(c.get_overflow_allocator().mAllocCount == 2); // 1 for above, and 1 for overflowing from 64 to 65.\n\t\t\toverflowAllocator.deallocate(p, 1);\n\t\t#endif\n\t}\n\n\n\t// We can't do this, due to how Reset is used above:\n\t//   EATEST_VERIFY(TestObject::IsClear());\n\tEATEST_VERIFY(TestObject::sMagicErrorCount == 0);\n\tTestObject::Reset();\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestFixedSet.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include \"TestSet.h\"\n#include <EASTL/fixed_set.h>\n#include \"TestAssociativeContainers.h\"\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <set>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::fixed_set     <int,        1>;\ntemplate class eastl::fixed_multiset<float,      1>;\ntemplate class eastl::fixed_set     <Align64,    1>;\ntemplate class eastl::fixed_multiset<TestObject, 1>;\n\n\ntemplate class eastl::fixed_set     <int,        1, true, eastl::less<int>,        MallocAllocator>;\ntemplate class eastl::fixed_multiset<float,      1, true, eastl::less<float>,      MallocAllocator>;\ntemplate class eastl::fixed_set     <Align64,    1, true, eastl::less<Align64>,    MallocAllocator>;\ntemplate class eastl::fixed_multiset<TestObject, 1, true, eastl::less<TestObject>, MallocAllocator>;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// typedefs\n//\nconst eastl_size_t kContainerSize = 1000;\n\ntypedef eastl::fixed_set<int, kContainerSize> VS1;\ntypedef eastl::fixed_set<TestObject, kContainerSize> VS4;\ntypedef eastl::fixed_multiset<int, kContainerSize> VMS1;\ntypedef eastl::fixed_multiset<TestObject, kContainerSize> VMS4;\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\ttypedef std::set<int> VS3;\n\ttypedef std::set<TestObject> VS6;\n\ttypedef std::multiset<int> VMS3;\n\ttypedef std::multiset<TestObject> VMS6;\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\n\nEA_DISABLE_VC_WARNING(6262)\nint TestFixedSet()\n{\n\tint nErrorCount = 0;\n\n\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t{   // Test construction\n\t\t\tnErrorCount += TestSetConstruction<VS1, VS3, false>();\n\t\t\tnErrorCount += TestSetConstruction<VS4, VS6, false>();\n\t\t\tnErrorCount += TestSetConstruction<eastl::fixed_set<int, kContainerSize, true, eastl::less<void>>, std::set<int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestSetConstruction<VMS1, VMS3, true>();\n\t\t\tnErrorCount += TestSetConstruction<VMS4, VMS6, true>();\n\t\t\tnErrorCount += TestSetConstruction<eastl::fixed_multiset<int, kContainerSize, true, eastl::less<void>>, std::multiset<int, std::less<void>>, true>();\n\t\t}\n\n\n\t\t{   // Test mutating functionality.\n\t\t\tnErrorCount += TestSetMutation<VS1, VS3, false>();\n\t\t\tnErrorCount += TestSetMutation<VS4, VS6, false>();\n\t\t\tnErrorCount += TestSetMutation<eastl::fixed_set<int, kContainerSize, true, eastl::less<void>>, std::set<int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestSetMutation<VMS1, VMS3, true>();\n\t\t\tnErrorCount += TestSetMutation<VMS4, VMS6, true>();\n\t\t\tnErrorCount += TestSetMutation<eastl::fixed_multiset<int, kContainerSize, true, eastl::less<void>>, std::multiset<int, std::less<void>>, true>();\n\t\t}\n\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n\t{   // Test searching functionality.\n\t\tnErrorCount += TestSetSearch<VS1, false>();\n\t\tnErrorCount += TestSetSearch<VS4, false>();\n\t\tnErrorCount += TestSetSearch<eastl::fixed_set<int, kContainerSize, true, eastl::less<void>>, false>();\n\n\t\tnErrorCount += TestSetSearch<VMS1, true>();\n\t\tnErrorCount += TestSetSearch<VMS4, true>();\n\t\tnErrorCount += TestSetSearch<eastl::fixed_multiset<int, kContainerSize, true, eastl::less<void>>, true>();\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestSetCpp11<eastl::fixed_set<TestObject, 32> >();\n\t\tnErrorCount += TestSetCpp11<eastl::fixed_set<TestObject, 32, true, eastl::less<void>>>();\n\n\t\tnErrorCount += TestMultisetCpp11<eastl::fixed_multiset<TestObject, 32> >();\n\t\tnErrorCount += TestMultisetCpp11<eastl::fixed_multiset<TestObject, 32, true, eastl::less<void>>>();\n\t}\n\n\n\t{ // Test functionality specific to fixed size containers.\n\n\t\tVS1  vs1;\n\t\tVMS1 vms1;\n\n\t\tVERIFY(vs1.max_size() == kContainerSize);\n\t\tVERIFY(vms1.max_size() == kContainerSize);\n\t}\n\n\n\t{\n\t\t// Test version *without* pool overflow.\n\t\ttypedef eastl::fixed_set<int, 100, false> FixedSetFalse;\n\t\tFixedSetFalse fixedSet;\n\n\t\tfixedSet.insert(FixedSetFalse::value_type(0));\n\t\tVERIFY(fixedSet.size() == 1);\n\n\t\tfixedSet.clear();\n\t\tVERIFY(fixedSet.size() == 0);\n\n\t\tfor(int i = 0; fixedSet.size() < 100; i++)\n\t\t\tfixedSet.insert(FixedSetFalse::value_type(i));\n\t\tVERIFY(fixedSet.size() == 100);\n\n\t\t// Verify that we allocated enough space for exactly N items. \n\t\t// It's possible that due to alignments, there might be room for N + 1.\n\t\tFixedSetFalse::allocator_type& allocator = fixedSet.get_allocator();\n\t\tvoid* pResult = allocator.allocate(sizeof(FixedSetFalse::node_type));\n\t\tif(pResult)\n\t\t{\n\t\t\tpResult = allocator.allocate(sizeof(FixedSetFalse::node_type));\n\t\t\tVERIFY(pResult == NULL); \n\t\t}\n\t}\n\n\n\t{\n\t\t// Test version *with* pool overflow.\n\t\ttypedef eastl::fixed_set<int, 100, true> FixedSetTrue;\n\t\tFixedSetTrue fixedSet;\n\n\t\tfixedSet.insert(FixedSetTrue::value_type(0));\n\t\tVERIFY(fixedSet.size() == 1);\n\n\t\tfixedSet.clear();\n\t\tVERIFY(fixedSet.size() == 0);\n\n\t\tfor(int i = 0; fixedSet.size() < 100; i++)\n\t\t\tfixedSet.insert(FixedSetTrue::value_type(i));\n\t\tVERIFY(fixedSet.size() == 100);\n\n\t\tFixedSetTrue::allocator_type& allocator = fixedSet.get_allocator();\n\t\tvoid* pResult = allocator.allocate(sizeof(FixedSetTrue::node_type));\n\t\tVERIFY(pResult != NULL);\n\t\tallocator.deallocate(pResult, sizeof(FixedSetTrue::node_type));\n\n\t\t// get_overflow_allocator / set_overflow_allocator\n\t\t// This is a weak test which should be improved.\n\t\tEASTLAllocatorType a = fixedSet.get_allocator().get_overflow_allocator();\n\t\tfixedSet.get_allocator().set_overflow_allocator(a);\n\t}\n\n\t{\n\t\t// Test fixed set with overflow and alignment requirements.\n\t\ttypedef fixed_set<Align64, 1, true> FixedSetWithAlignment;\n\t\ttypedef fixed_multiset<Align64, 1, true> FixedMultiSetWithAlignment;\n\n\t\tFixedSetWithAlignment fs;\n\t\tFixedMultiSetWithAlignment fms;\n\n\t\tAlign64 a; a.mX = 1;\n\t\tAlign64 b; b.mX = 2;\n\t\tAlign64 c; c.mX = 3;\n\t\tAlign64 d; d.mX = 4;\n\t\tAlign64 e; e.mX = 5;\n\n\t\tfs.insert(a);\n\t\tfs.insert(b);\n\t\tfs.insert(c);\n\t\tfs.insert(d);\n\t\tfs.insert(e);\n\t\tfor (FixedSetWithAlignment::const_iterator it = fs.begin(); it != fs.end(); ++it)\n\t\t{\n\t\t\tconst Align64* ptr = &(*it);\n\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t}\n\t\tfms.insert(a);\n\t\tfms.insert(b);\n\t\tfms.insert(c);\n\t\tfms.insert(d);\n\t\tfms.insert(e);\n\t\tfor (FixedMultiSetWithAlignment::const_iterator it = fms.begin(); it != fms.end(); ++it)\n\t\t{\n\t\t\tconst Align64* ptr = &(*it);\n\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t}\n\t}\n\n\t{ // heterogenous functions - fixed_set\n\t\tfixed_set<ExplicitString, 1, true, eastl::less<void>> s{ ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestSetHeterogeneousInsertion<decltype(s)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // heterogenous functions - fixed_multiset\n\t\tfixed_multiset<ExplicitString, 1, true, eastl::less<void>> s{ ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\treturn nErrorCount;\n}\nEA_RESTORE_VC_WARNING()\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestFixedString.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EABase/eabase.h>\nEA_DISABLE_GCC_WARNING(-Warray-bounds)\n\n#include \"EASTLTest.h\"\n#include <EASTL/fixed_string.h>\n#include <EASTL/fixed_substring.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n\n#include <string.h>\n\n#if defined(_MSC_VER)\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace eastl;\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::fixed_string<char8_t,    1,  true>;\ntemplate class eastl::fixed_string<char16_t,   1,  true>;\ntemplate class eastl::fixed_string<char32_t,   1,  true>;\n\ntemplate class eastl::fixed_string<char8_t,  128, false>;\ntemplate class eastl::fixed_string<char16_t, 128, false>;\ntemplate class eastl::fixed_string<char32_t, 128, false>;\n\ntemplate class eastl::fixed_string<char8_t,  128,  true, MallocAllocator>;\ntemplate class eastl::fixed_string<char16_t, 128,  true, MallocAllocator>;\ntemplate class eastl::fixed_string<char32_t, 128,  true, MallocAllocator>;\n\ntemplate class eastl::fixed_string<char8_t,  128, false, MallocAllocator>;\ntemplate class eastl::fixed_string<char16_t, 128, false, MallocAllocator>;\ntemplate class eastl::fixed_string<char32_t, 128, false, MallocAllocator>;\n\ntemplate class eastl::fixed_substring<char8_t>;\ntemplate class eastl::fixed_substring<char16_t>;\n\n\n\n\n/*\n// This does not compile, since the fixed_string allocator (among other things) is\n// templated on sizeof(T), not just T. Thus, the full type is required at the time \n// of instantiation, but it is not available.\n// See EATech Core JIRA issue ETCR-1608 for more information.\nstruct StructWithContainerOfStructs\n{\n\teastl::fixed_string<StructWithContainerOfStructs,4> children;\n};\n*/\n\n\nint TestFixedSubstring()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tconst char* pSource1 = \"hello world\";\n\t\tconst char* pSource2 = \"hola mundo\";\n\n\t\tbasic_string<char>    str(pSource1);\n\t\tfixed_substring<char> sub(str, 2, 5);\n\n\t\tEATEST_VERIFY(sub.size() == 5);\n\t\tEATEST_VERIFY(sub[0] == 'l');\n\t\tEATEST_VERIFY(sub == \"llo w\");\n\n\t\tsub.assign(pSource2);\n\t\tEATEST_VERIFY(sub.size() == 10);\n\t\tEATEST_VERIFY(sub[0] == pSource2[0]);\n\t\tEATEST_VERIFY(sub == pSource2);\n\n\t\tfixed_substring<char> sub2(sub);\n\t\tEATEST_VERIFY(sub2.size() == 10);\n\t\tEATEST_VERIFY(sub2[0] == pSource2[0]);\n\t\tEATEST_VERIFY(sub2 == pSource2);\n\n\t\tsub.assign(sub2, 1, 3);\n\t\tEATEST_VERIFY(sub.size() == 3);\n\t\tEATEST_VERIFY(sub == \"ola\");\n\n\t\tsub.assign(pSource2, 3);\n\t\tEATEST_VERIFY(sub.size() == 3);\n\t\tEATEST_VERIFY(sub == \"hol\");\n\n\t\tsub.assign(pSource2, pSource2 + 4);\n\t\tEATEST_VERIFY(sub.size() == 4);\n\t\tEATEST_VERIFY(sub == \"hola\");\n\n\t\tsub = pSource1;\n\t\tEATEST_VERIFY(sub.size() == strlen(pSource1));\n\t\tEATEST_VERIFY(sub == pSource1);\n\t}\n\n\n\t{   // Test fixed_substring with a C character array\n\t\tchar                  pArray[256];\n\t\tfixed_substring<char> str(pArray, 255);\n\n\t\tstr.resize(5);\n\t\tEATEST_VERIFY(str.size() == 5);\n\n\t\tstr[0] = 'a';\n\t\tEATEST_VERIFY(str[0] == 'a');\n\n\t\tstr.sprintf(\"Hello %s\", \"world\");\n\t\tEATEST_VERIFY(str == \"Hello world\");\n\n\t\tstr += \" Hola mundo\";\n\t\tEATEST_VERIFY(str == \"Hello world Hola mundo\");\n\n\t\tstr.pop_back();\n\t\tEATEST_VERIFY(str == \"Hello world Hola mund\");\n\n\t\tstr.replace(6, 5, \"abcdefghijlk\");\n\t\tEATEST_VERIFY(str == \"Hello abcdefghijlk Hola mund\");\n\n\t\tstr.clear();\n\t\tEATEST_VERIFY(str.empty());\n\t\tEATEST_VERIFY(str == \"\");\n\t}\n\n\n\t{\n\t\t// Check that copies/moves don't become independent strings.\n\t\t// They should all point to the same sub-string.\n\t\tstring str = \"hello world\";\n\t\tfixed_substring<char> sub(str, 2, 5);\n\n\t\tEATEST_VERIFY(sub.size() == 5);\n\t\tEATEST_VERIFY(sub[0] == 'l');\n\t\tEATEST_VERIFY(sub == \"llo w\");\n\n\t\tvector<fixed_substring<char>> v;\n\t\tfor (eastl_size_t i = 0; i < 1000; ++i) {\n\t\t\tv.push_back(sub);\n\t\t}\n\n\t\tsub[0] = 'g';\n\t\tEATEST_VERIFY(str == \"heglo world\");\n\t\tEATEST_VERIFY(sub == \"glo w\");\n\n\t\tfor (const auto& s : v){\n\t\t\tEATEST_VERIFY(s == \"glo w\");\n\t\t}\n\n\t\t// copy construct\n\t\tfixed_substring<char> sub2 = sub;\n\n\t\t// copy assign\n\t\tfixed_substring<char> sub3;\n\t\tsub3 = sub;\n\n\t\t// move construct\n\t\tfixed_substring<char> sub4 = eastl::move(sub);\n\n\t\t// move assign\n\t\tfixed_substring<char> sub_again(str, 2, 5);\n\t\tfixed_substring<char> sub5;\n\t\tsub5 = eastl::move(sub_again);\n\n\t\tEATEST_VERIFY(sub2 == \"glo w\");\n\t\tEATEST_VERIFY(sub3 == \"glo w\");\n\t\tEATEST_VERIFY(sub4 == \"glo w\");\n\t\tEATEST_VERIFY(sub5 == \"glo w\");\n\n\t\tstr[5] = 'g';\n\t\tEATEST_VERIFY(sub2 == \"glogw\");\n\t\tEATEST_VERIFY(sub3 == \"glogw\");\n\t\tEATEST_VERIFY(sub4 == \"glogw\");\n\t\tEATEST_VERIFY(sub5 == \"glogw\");\n\n\t}\n\n\treturn nErrorCount;\n}\n\n\nint TestFixedString()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tfixed_string<char, 64>::CtorSprintf cs;\n\n\t\tfixed_string<char, 64> s8(cs, \"hello world %d.\", 1);\n\t\tEATEST_VERIFY(s8 == \"hello world 1.\");\n\t\tEATEST_VERIFY(s8.capacity() == 63); // 63 because the 64 includes the terminating 0, but capacity() subtracts the terminating 0 usage.\n\t\tEATEST_VERIFY(s8.max_size() == 63);\n\n\t\ts8.append_sprintf(\" More hello %d.\", 2);\n\t\tEATEST_VERIFY(s8 == \"hello world 1. More hello 2.\");\n\t\tEATEST_VERIFY(s8.capacity() == 63);\n\t}\n\n\n\t{\n\t\tfixed_string<wchar_t, 64>::CtorSprintf cs;\n\n\t\tfixed_string<wchar_t, 64> sW(cs, L\"hello world %d.\", 1);\n\t\tEATEST_VERIFY(sW == L\"hello world 1.\");\n\t\tEATEST_VERIFY(sW.capacity() == 63); // 63 because the 64 includes the terminating 0, but capacity() subtracts the terminating 0 usage.\n\n\t\tsW.append_sprintf(L\" More hello %d.\", 2);\n\t\tEATEST_VERIFY(sW == L\"hello world 1. More hello 2.\");\n\t\tEATEST_VERIFY(sW.capacity() == 63); // 63 because the 64 includes the terminating 0, but capacity() subtracts the terminating 0 usage.\n\t}\n\n\t{\n\t\tstring s(\"frost\");\n\t\tsize_t sHash = eastl::hash<string>{}(s);\n\n\t\t// char\n\t\tfixed_string<char, 64> fsc1(\"frost\");\n\t\tfixed_string<char, 64> fsc2(\"bite\");\n\t\tfixed_string<char, 64> fsc3(\"bite\");\n\n\t\tsize_t fsc1Hash = eastl::hash<fixed_string<char, 64>>{}(fsc1);\n\t\tsize_t fsc2Hash = eastl::hash<fixed_string<char, 64>>{}(fsc2);\n\t\tsize_t fsc3Hash = eastl::hash<fixed_string<char, 64>>{}(fsc3);\n\n\t\tEATEST_VERIFY(fsc1Hash == sHash);\n\t\tEATEST_VERIFY(fsc1Hash != fsc2Hash);\n\t\tEATEST_VERIFY(fsc2Hash == fsc3Hash);\n\n\t\t// wchar_t\n\t\tfixed_string<wchar_t, 64> fswc1(L\"frost\");\n\t\tfixed_string<wchar_t, 64> fswc2(L\"bite\");\n\t\tfixed_string<wchar_t, 64> fswc3(L\"bite\");\n\n\t\tsize_t fswc1Hash = eastl::hash<fixed_string<wchar_t, 64>>{}(fswc1);\n\t\tsize_t fswc2Hash = eastl::hash<fixed_string<wchar_t, 64>>{}(fswc2);\n\t\tsize_t fswc3Hash = eastl::hash<fixed_string<wchar_t, 64>>{}(fswc3);\n\n\t\tEATEST_VERIFY(fswc1Hash == sHash);\n\t\tEATEST_VERIFY(fswc1Hash != fswc2Hash);\n\t\tEATEST_VERIFY(fswc2Hash == fswc3Hash);\n\n\t\t// char8_t\n\t\tfixed_string<char8_t, 64> fsc81(\"frost\");\n\t\tfixed_string<char8_t, 64> fsc82(\"bite\");\n\t\tfixed_string<char8_t, 64> fsc83(\"bite\");\n\n\t\tsize_t fsc81Hash = eastl::hash<fixed_string<char8_t, 64>>{}(fsc81);\n\t\tsize_t fsc82Hash = eastl::hash<fixed_string<char8_t, 64>>{}(fsc82);\n\t\tsize_t fsc83Hash = eastl::hash<fixed_string<char8_t, 64>>{}(fsc83);\n\n\t\tEATEST_VERIFY(fsc81Hash == sHash);\n\t\tEATEST_VERIFY(fsc81Hash != fsc82Hash);\n\t\tEATEST_VERIFY(fsc82Hash == fsc83Hash);\n\t}\n\n\n\t{\n\t\ttypedef fixed_string<char8_t, 64, true>  FixedString64;\n\t\ttypedef fixed_string<char8_t, 64, false> FixedString64NoOverflow;\n\t\tFixedString64::CtorSprintf               cs;\n\t\tFixedString64::CtorDoNotInitialize       cdni;\n\n\t\t// fixed_string();\n\t\tFixedString64 fs1;\n\t\tEATEST_VERIFY(fs1.size() == 0);\n\t\tEATEST_VERIFY(fs1.capacity() == 63);\n\n\t\tFixedString64NoOverflow fsNo;\n\t\tEATEST_VERIFY(fs1.can_overflow() == true);\n\t\tEATEST_VERIFY(fsNo.can_overflow() == false);\n\t\tEATEST_VERIFY(fs1.full() == false);\n\t\tEATEST_VERIFY(fs1.has_overflowed() == false);\n\n\t\tconst char8_t* pCStr = fs1.c_str();\n\t\tEATEST_VERIFY(*pCStr == 0);\n\n\t\t// fixed_string(const this_type& x);\n\t\tFixedString64 fs2(fs1);\n\t\tEATEST_VERIFY(fs2.size() == 0);\n\t\tEATEST_VERIFY(fs2.capacity() == 63);\n\n\t\tfs1 = EA_CHAR8(\"abc\");\n\t\tFixedString64 fs3(fs1);\n\t\tEATEST_VERIFY(fs3.size() == 3);\n\t\tEATEST_VERIFY(fs3.capacity() == 63);\n\t\tEATEST_VERIFY(fs3 == EA_CHAR8(\"abc\"));\n\n\t\t// fixed_string(const this_type& x, size_type position, size_type n = npos);\n\t\tFixedString64 fs4(fs1, 1, 2);\n\t\tEATEST_VERIFY(fs4.size() == 2);\n\t\tEATEST_VERIFY(fs4.capacity() == 63);\n\t\tEATEST_VERIFY(fs4 == EA_CHAR8(\"bc\"));\n\n\t\t// fixed_string(const value_type* p, size_type n);\n\t\tFixedString64 fs5(EA_CHAR8(\"abcdef\"), 6);\n\t\tEATEST_VERIFY(fs5.size() == 6);\n\t\tEATEST_VERIFY(fs5.capacity() == 63);\n\t\tEATEST_VERIFY(fs5 == EA_CHAR8(\"abcdef\"));\n\n\t\t// fixed_string(const value_type* p);\n\t\tFixedString64 fs6(EA_CHAR8(\"abcdef\"));\n\t\tEATEST_VERIFY(fs6.size() == 6);\n\t\tEATEST_VERIFY(fs6.capacity() == 63);\n\t\tEATEST_VERIFY(fs6 == EA_CHAR8(\"abcdef\"));\n\n\t\t// fixed_string(size_type n, const value_type& value);\n\t\tFixedString64 fs7(8, 'a');\n\t\tEATEST_VERIFY(fs7.size() == 8);\n\t\tEATEST_VERIFY(fs7.capacity() == 63);\n\t\tEATEST_VERIFY(fs7 == EA_CHAR8(\"aaaaaaaa\"));\n\n\t\t// fixed_string(const value_type* pBegin, const value_type* pEnd);\n\t\tFixedString64 fs8(&fs6[0], &fs6[5]);\n\t\tEATEST_VERIFY(fs8.size() == 5);\n\t\tEATEST_VERIFY(fs8.capacity() == 63);\n\t\tEATEST_VERIFY(fs8 == EA_CHAR8(\"abcde\"));\n\n\t\t// fixed_string(CtorDoNotInitialize, size_type n);\n\t\tFixedString64 fs9(cdni, 7);\n\t\tEATEST_VERIFY(fs9.size() == 7);\n\t\tEATEST_VERIFY(fs9.capacity() == 63);\n\n\t\t// fixed_string(CtorSprintf, const value_type* pFormat, ...);\n\t\tFixedString64 fs10(cs, EA_CHAR8(\"%d\"), 37);\n\t\tEATEST_VERIFY(fs10.size() == 2);\n\t\tEATEST_VERIFY(fs10.capacity() == 63);\n\t\tEATEST_VERIFY(fs10 == EA_CHAR8(\"37\"));\n\n\t\t// this_type& operator=(const const value_type* p);\n\t\t// this_type& operator=(const this_type& x);\n\t\tfs9 = EA_CHAR8(\"hello\");\n\t\tEATEST_VERIFY(fs9 == EA_CHAR8(\"hello\"));\n\n\t\tfs9 = fs10;\n\t\tEATEST_VERIFY(fs9 == fs10);\n\t\tEATEST_VERIFY(fs9 == EA_CHAR8(\"37\"));\n\n\t\t// void swap(this_type& x);\n\t\tswap(fs7, fs9);\n\t\tEATEST_VERIFY(fs7 == EA_CHAR8(\"37\"));\n\t\tEATEST_VERIFY(fs9 == EA_CHAR8(\"aaaaaaaa\"));\n\n\t\t// void set_capacity(size_type n);\n\t\tfs9.set_capacity(100);\n\t\tEATEST_VERIFY(fs9.size() == 8);\n\t\tEATEST_VERIFY(fs9.capacity() == 100);\n\t\tEATEST_VERIFY(fs9.full() == true);\n\t\tEATEST_VERIFY(fs9.has_overflowed() == true);\n\n\t\tfs9.set_capacity(100); // EATEST_VERIFY that this has no effect.\n\t\tEATEST_VERIFY(fs9.size() == 8);\n\t\tEATEST_VERIFY(fs9.capacity() == 100);\n\t\tEATEST_VERIFY(fs9.full() == true);\n\t\tEATEST_VERIFY(fs9.has_overflowed() == true);\n\n\t\tfs9.resize(100);\n\t\tfs9.set_capacity(100);\n\t\tEATEST_VERIFY(fs9.size() == 100);\n\t\tEATEST_VERIFY(fs9.capacity() == 100);\n\t\tEATEST_VERIFY(fs9.full() == true);\n\t\tEATEST_VERIFY(fs9.has_overflowed() == true);\n\n\t\tfs9.set_capacity(1);\n\t\tEATEST_VERIFY(fs9.size() == 1);\n\t\tEATEST_VERIFY(fs9.capacity() < fs9.max_size()); // We don't test for capacity == 1, because with fixed_strings, the fixed-size capacity is the lowest it ever gets.\n\t\tEATEST_VERIFY(fs9.full() == false);\n\t\tEATEST_VERIFY(fs9.has_overflowed() == false);\n\n\t\tfs9.set_capacity(0);\n\t\tEATEST_VERIFY(fs9.size() == 0);\n\t\tEATEST_VERIFY(fs9.capacity() < fs9.max_size()); // We don't test for capacity == 1, because with fixed_strings, the fixed-size capacity is the lowest it ever gets.\n\t\tEATEST_VERIFY(fs9.full() == false);\n\t\tEATEST_VERIFY(fs9.has_overflowed() == false);\n\n\t\t// Exercise the freeing of memory in set_capacity.\n\t\tfixed_string<char8_t, 64, true> fs88;\n\t\teastl_size_t capacity = fs88.capacity();\n\t\tfs88.resize(capacity);\n\t\tfs88.set_capacity(capacity * 2);\n\t\tEATEST_VERIFY(fs88.capacity() >= (capacity * 2));\n\n\t\t// void reset_lose_memory();\n\t\tfs6.reset_lose_memory();\n\t\tEATEST_VERIFY(fs6.size() == 0);\n\t\tEATEST_VERIFY(fs5.capacity() == 63);\n\n\t\t// size_type max_size() const;\n\t\tEATEST_VERIFY(fs7.max_size() == 63);\n\n\n\t\t// global operator +\n\t\t{\n\t\t\t// fixed_string operator+(const fixed_string& a, const fixed_string& b);\n\t\t\t// fixed_string operator+(value_type* p, const fixed_string& b);\n\t\t\t// fixed_string operator+(value_type c, const fixed_string& b);\n\t\t\t// fixed_string operator+(const fixed_string& a, const value_type* p);\n\t\t\t// fixed_string operator+(const fixed_string& a, value_type c);\n\n\t\t\ttypedef fixed_string<char, 8, true> FSTest; // Make it a small size so it's easily overflowed when we want.\n\n\t\t\tFSTest a(\"abc\");\n\t\t\tFSTest b(\"def\");\n\t\t\tFSTest c(a + b);\n\t\t\tEATEST_VERIFY(c == \"abcdef\");\n\t\t\tc = a + \"ghi\";\n\t\t\tEATEST_VERIFY(c == \"abcghi\");\n\t\t\tc = \"ghi\" + a;\n\t\t\tEATEST_VERIFY(c == \"ghiabc\");\n\t\t\tc = a + 'g';\n\t\t\tEATEST_VERIFY(c == \"abcg\");\n\t\t\tc = 'g' + a;\n\t\t\tEATEST_VERIFY(c == \"gabc\");\n\n\t\t\t// fixed_string operator+(fixed_string&& a,    fixed_string&& b);\n\t\t\t// fixed_string operator+(fixed_string&& a,    const fixed_string& b);\n\t\t\t// fixed_string operator+(const value_type* p, fixed_string&& b);\n\t\t\t// fixed_string operator+(fixed_string&& a,    const value_type* p);\n\t\t\t// fixed_string operator+(fixed_string&& a,    value_type b);\n\n\t\t\tc = eastl::move(a) + eastl::move(b);\n\t\t\tEATEST_VERIFY(c == \"abcdef\");\n\t\t\tc.clear();\n\n\t\t\tFSTest a1(\"abc\");\n\t\t\tFSTest b1(\"def\");\n\t\t\tc = eastl::move(a1) + b1;\n\t\t\tEATEST_VERIFY(c == \"abcdef\");\n\t\t\tc.clear();\n\n\t\t\tFSTest b2(\"def\");\n\t\t\tc = \"abc\" + eastl::move(b2);\n\t\t\tEATEST_VERIFY(c == \"abcdef\");\n\t\t\tc.clear();\n\n\t\t\tFSTest a3(\"abc\");\n\t\t\tc = eastl::move(a3) + \"def\";\n\t\t\tEATEST_VERIFY(c == \"abcdef\");\n\t\t\tc.clear();\n\n\t\t\tFSTest a4(\"abc\");\n\t\t\tc = eastl::move(a4) + 'd';\n\t\t\tEATEST_VERIFY(c == \"abcd\");\n\t\t\tc.clear();\n\t\t}\n\n\n\t\t// bool operator==(const fixed_string<& a, const fixed_string& b)\n\t\t// bool operator!=(const fixed_string<& a, const fixed_string& b)\n\t\tEATEST_VERIFY(  fs7 != fs8);\n\t\tEATEST_VERIFY(!(fs7 == fs8));\n\t\tfs7 = fs8;\n\t\tEATEST_VERIFY(  fs7 == fs8);\n\t\tEATEST_VERIFY(!(fs7 != fs8));\n\t}\n\n\n\t{   // Test overflow allocator specification\n\t\t\n\t\ttypedef fixed_string<char8_t, 64, true, MallocAllocator> FixedString64Malloc;\n\n\t\tFixedString64Malloc fs;\n\n\t\tfs.push_back('a');\n\t\tEATEST_VERIFY(fs.size() == 1);\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\n\t\tfs.resize(95);\n\t\tfs[94] = 'b';\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\t\tEATEST_VERIFY(fs[94] == 'b');\n\t\tEATEST_VERIFY(fs.size() == 95);\n\n\t\tfs.clear();\n\t\tEATEST_VERIFY(fs.empty());\n\n\t\tfs.push_back('a');\n\t\tEATEST_VERIFY(fs.size() == 1);\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\n\t\tfs.resize(195);\n\t\tfs[194] = 'b';\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\t\tEATEST_VERIFY(fs[194] == 'b');\n\t\tEATEST_VERIFY(fs.size() == 195);\n\t}\n\n\t{\n\t\t// Test construction of a container with an overflow allocator constructor argument.\n\t\tMallocAllocator overflowAllocator;\n\t\tvoid* p = overflowAllocator.allocate(1);\n\t\tfixed_string<char8_t, 64, true, MallocAllocator> c(overflowAllocator);\n\t\tc.resize(65);\n\t\tEATEST_VERIFY(c.get_overflow_allocator().mAllocCount == 2); // 1 for above, and 1 for overflowing from 64 to 65.\n\t\toverflowAllocator.deallocate(p, 1);\n\t}\n\n\t{\n\t\t// Regression for compile failure when EASTL_NO_RVALUE_REFERENCES is 0.\n\t\ttypedef eastl::fixed_string<char, 32, true, MallocAllocator> TestString;\n\n\t\tTestString ts1;\n\t\tTestString ts2(ts1 + \"Test\");\n\n\t\tEATEST_VERIFY(ts1.empty() && ts2.size() == 4);\n\t}\n\n\t{\n\t\t// Test equality tests of differently-sized fixed_strings.\n\n\t\t/* Disabled because this isn't currently supported by fixed_string.\n\t\ttypedef fixed_string<char8_t, 64, true, MallocAllocator> FixedString64Malloc;\n\t\ttypedef fixed_string<char8_t, 32>                        FixedString32;\n\n\t\tFixedString64Malloc s64M;\n\t\tFixedString32       s32;\n\n\t\tEATEST_VERIFY(s64M == s32);\n\t\t*/\n\t}\n\n\tnErrorCount += TestFixedSubstring();\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestFixedTupleVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// TestFixedTupleVector.cpp\n//\n// Copyright (c) 2018, Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n\n#include <EASTL/bonus/fixed_tuple_vector.h>\n\n#include <EASTL/sort.h>\n\nusing namespace eastl;\n\ntemplate <size_t nodeCount, bool bEnableOverflow>\nint TestFixedTupleVectorVariant()\n{\n\tint nErrorCount = 0;\n\n\t// Test uninit'ed push-backs\n\t{\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int> singleElementVec;\n\t\tEATEST_VERIFY(singleElementVec.size() == 0);\n\t\tEATEST_VERIFY(singleElementVec.capacity() == nodeCount);\n\t\tEATEST_VERIFY(singleElementVec.empty() == true);\n\t\tEATEST_VERIFY(singleElementVec.validate());\n\t\tsingleElementVec.push_back_uninitialized();\n\t\tsingleElementVec.push_back(5);\n\t\tEATEST_VERIFY(singleElementVec.size() == 2);\n\t\tEATEST_VERIFY(singleElementVec.template get<0>()[1] == 5);\n\t\tEATEST_VERIFY(singleElementVec.template get<int>()[1] == 5);\n\t\tEATEST_VERIFY(singleElementVec.empty() == false);\n\t\tEATEST_VERIFY(singleElementVec.validate());\n\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, float, bool> complexVec;\n\t\tcomplexVec.reserve(5);\n\t\t{\n\t\t\t// need to call an overload of push_back that specifically grabs lvalue candidates - providing constants tend to prefer rvalue path\n\t\t\tint intArg = 3;\n\t\t\tfloat floatArg = 2.0f;\n\t\t\tbool boolArg = true;\n\t\t\tcomplexVec.push_back(intArg, floatArg, boolArg);\n\t\t}\n\t\tcomplexVec.push_back(1, 4.0f, false);\n\t\tcomplexVec.push_back(2, 1.0f, true);\n\t\t{\n\t\t\ttuple<int, float, bool> complexTup(4, 3.0f, false);\n\t\t\tcomplexVec.push_back(complexTup);\n\t\t}\n\t\tcomplexVec.push_back();\n\t\tEATEST_VERIFY((!complexVec.has_overflowed() && complexVec.capacity() == nodeCount) || complexVec.capacity() == 5);\n\t\tEATEST_VERIFY(*(complexVec.template get<0>()) == 3);\n\t\tEATEST_VERIFY(complexVec.template get<float>()[1] == 4.0f);\n\t\tEATEST_VERIFY(complexVec.template get<2>()[2] == complexVec.template get<bool>()[2]);\n\t\tEATEST_VERIFY(complexVec.validate());\n\n\t\ttuple<int, float, bool> defaultComplexTup;\n\t\tEATEST_VERIFY(complexVec.at(4) == defaultComplexTup);\n\t\t\n\t\ttuple<int*, float*, bool*> complexPtrTuple = complexVec.data();\n\t\tEATEST_VERIFY(get<0>(complexPtrTuple) != nullptr);\n\t\tEATEST_VERIFY(get<2>(complexPtrTuple)[2] == complexVec.template get<2>()[2]);\n\n\t\ttuple<int&, float&, bool&> complexRefTuple = complexVec.at(2);\n\t\ttuple<int&, float&, bool&> complexRefTupleBracket = complexVec[2];\n\t\ttuple<int&, float&, bool&> complexRefTupleFront = complexVec.front();\n\t\ttuple<int&, float&, bool&> complexRefTupleBack = complexVec.back();\n\t\tEATEST_VERIFY(get<2>(complexRefTuple) == complexVec.template get<2>()[2]);\n\t\tEATEST_VERIFY(get<1>(complexRefTupleBracket) == 1.0f);\n\t\tEATEST_VERIFY(get<1>(complexRefTupleFront) == 2.0f);\n\t\tEATEST_VERIFY(get<1>(complexRefTupleBack) == 0.0f);\n\n\t\t// verify the equivalent accessors for the const container exist/compile\n\t\t{\n\t\t\tconst fixed_tuple_vector<nodeCount, bEnableOverflow, int, float, bool>& constVec = complexVec;\n\n\t\t\tEATEST_VERIFY(constVec.size() == 5);\n\t\t\tEATEST_VERIFY(constVec.capacity() >= constVec.size());\n\t\t\tEATEST_VERIFY(constVec.empty() == false);\n\t\t\tEATEST_VERIFY(constVec.template get<1>() == constVec.template get<float>());\n\n\t\t\ttuple<const int*, const float*, const bool*> constPtrTuple = constVec.data();\n\t\t\tEATEST_VERIFY(get<0>(constPtrTuple) != nullptr);\n\t\t\tEATEST_VERIFY(get<2>(constPtrTuple)[2] == constVec.template get<2>()[2]);\n\n\t\t\ttuple<const int&, const float&, const bool&> constRefTuple = constVec.at(2);\n\t\t\ttuple<const int&, const float&, const bool&> constRefTupleBracket = constVec[2];\n\t\t\ttuple<const int&, const float&, const bool&> constRefTupleFront = constVec.front();\n\t\t\ttuple<const int&, const float&, const bool&> constRefTupleBack = constVec.back();\n\t\t\tEATEST_VERIFY(get<2>(constRefTuple) == constVec.template get<2>()[2]);\n\t\t\tEATEST_VERIFY(get<1>(constRefTupleBracket) == 1.0f);\n\t\t\tEATEST_VERIFY(get<1>(constRefTupleFront) == 2.0f);\n\t\t\tEATEST_VERIFY(get<1>(constRefTupleBack) == 0.0f);\n\n\t\t\t// check that return types of const-version of begin and cbegin (etc) match\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.begin()), decltype(constVec.cbegin())>::value, \"error\");\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.end()), decltype(constVec.cend())>::value, \"error\");\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.rbegin()), decltype(constVec.crbegin())>::value, \"error\");\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.rend()), decltype(constVec.crend())>::value, \"error\");\n\n\t\t\t// check that return type of non-const version of begin and cbegin (etc) do _not_ match\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.begin()), decltype(complexVec.cbegin())>::value, \"error\");\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.end()), decltype(complexVec.cend())>::value, \"error\");\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.rbegin()), decltype(complexVec.crbegin())>::value, \"error\");\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.rend()), decltype(complexVec.crend())>::value, \"error\");\n\t\t}\n\t}\n\n\t// test the memory layouts work for aligned structures\n\t{\n\t\tstruct EA_ALIGN(16) AlignTestVec4\n\t\t{\n\t\t\tfloat a[4];\n\t\t\tAlignTestVec4() :a{ 1.0f, 2.0f, 3.0f, 4.0f } {}\n\t\t};\n\n\t\tstruct AlignTestByte3\n\t\t{\n\t\t\tchar a[3];\n\t\t\tAlignTestByte3() : a{1, 2, 3} {}\n\t\t};\n\n\t\tstruct EA_ALIGN(8) AlignTestFourByte\n\t\t{\n\t\t\tint a[5];\n\t\t\tAlignTestFourByte() : a{-1, -2, -3, -4, -5} {}\n\t\t};\n\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, AlignTestVec4, AlignTestByte3, AlignTestFourByte> alignElementVec;\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\n\t\tEATEST_VERIFY((uintptr_t)alignElementVec.template get<AlignTestVec4>() % 16 == 0);\n\t\tEATEST_VERIFY((uintptr_t)alignElementVec.template get<AlignTestFourByte>() % 8 == 0);\n\t}\n\n\t// Test various modifications\n\t{\n\t\tTestObject::Reset();\n\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\t\ttestVec.reserve(10);\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\ttestVec.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t}\n\t\ttestVec.pop_back();\n\t\tEATEST_VERIFY(testVec.size() == 9);\n\n\t\t// test resize that does destruction of objects\n\t\ttestVec.resize(5);\n\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 5);\n\t\tEATEST_VERIFY((!testVec.has_overflowed() && testVec.capacity() == nodeCount) || testVec.capacity() == 10);\n\n\t\t// test resize that does default construction of objects\n\t\ttestVec.resize(10);\n\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 10);\n\n\t\t// test resize with args that does destruction of objects\n\t\ttestVec.resize(5, true, TestObject(5), 5.0f);\n\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 5);\n\n\t\t// test resize with args that does construction of objects\n\t\ttestVec.resize(10, true, TestObject(5), 5.0f);\n\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 10);\n\t\tEATEST_VERIFY(testVec.validate());\n\t\tfor (unsigned int i = 5; i < 10; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(testVec.template get<0>()[i] == true);\n\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == TestObject(5));\n\t\t\tEATEST_VERIFY(testVec.template get<2>()[i] == 5.0f);\n\t\t}\n\n\t\t{\n\t\t\ttuple<bool, TestObject, float> resizeTup(true, TestObject(10), 10.0f);\n\t\t\t// test resize with tuple that does destruction of objects\n\t\t\ttestVec.resize(10, resizeTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10 + 1);\n\n\t\t\t// test resize with tuple that does construction of objects\n\t\t\ttestVec.resize(15, resizeTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15 + 1);\n\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 5; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(testVec.template get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t\tfor (unsigned int i = 10; i < 15; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<0>()[i] == get<0>(resizeTup));\n\t\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == get<1>(resizeTup));\n\t\t\t\tEATEST_VERIFY(testVec.template get<2>()[i] == get<2>(resizeTup));\n\t\t\t}\n\t\t}\n\n\t\t// test other modifiers\n\t\ttestVec.pop_back();\n\t\tEATEST_VERIFY(testVec.size() == 14);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 14); // down 2 from last sTOCount check - resizeTup dtor and pop_back\n\t\t\n\t\tif (testVec.can_overflow())\n\t\t{\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == testVec.size());\n\t\t}\n\t\tEATEST_VERIFY(testVec.validate());\n\n\t\ttestVec.clear();\n\t\tEATEST_VERIFY(testVec.empty());\n\t\tEATEST_VERIFY(testVec.validate());\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\n\t\tif (testVec.has_overflowed())\n\t\t{\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 0);\n\t\t}\n\t\tEATEST_VERIFY(testVec.validate());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test insert\n\t{\n\t\tTestObject::Reset();\n\n\t\t// test insert with n values and lvalue args\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\t\t\tbool boolArg = true;\n\t\t\tTestObject toArg = TestObject(0);\n\t\t\tfloat floatArg = 0.0f;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttoArg = TestObject(3);\n\t\t\tfloatArg = 3.0f;\n\t\t\tauto insertIter = testVec.insert(testVec.begin(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(insertIter == testVec.begin());\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(5);\n\t\t\tfloatArg = 5.0f;\n\t\t\tinsertIter = testVec.insert(testVec.end(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\tEATEST_VERIFY(insertIter == testVec.begin() + 3);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(4);\n\t\t\tfloatArg = 4.0f;\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttoArg = TestObject(6);\n\t\t\tfloatArg = 6.0f;\n\t\t\ttestVec.insert(testVec.end(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttoArg = TestObject(1);\n\t\t\tfloatArg = 1.0f;\n\t\t\ttestVec.insert(testVec.begin(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttoArg = TestObject(2);\n\t\t\tfloatArg = 2.0f;\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == TestObject(i / 3 + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with lvalue args\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\t\t\tbool boolArg = true;\n\t\t\tTestObject toArg = TestObject(0);\n\t\t\tfloat floatArg = 0.0f;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttoArg = TestObject(3);\n\t\t\tfloatArg = 3.0f;\n\t\t\ttestVec.insert(testVec.begin(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(5);\n\t\t\tfloatArg = 5.0f;\n\t\t\ttestVec.insert(testVec.end(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(4);\n\t\t\tfloatArg = 4.0f;\n\t\t\ttestVec.insert(testVec.begin() + 1, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttoArg = TestObject(6);\n\t\t\tfloatArg = 6.0f;\n\t\t\ttestVec.insert(testVec.end(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttoArg = TestObject(1);\n\t\t\tfloatArg = 1.0f;\n\t\t\ttestVec.insert(testVec.begin(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttoArg = TestObject(2);\n\t\t\tfloatArg = 2.0f;\n\t\t\ttestVec.insert(testVec.begin() + 1, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with n and tuple\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\t\t\ttuple<bool, TestObject, float> testTup;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(3), 3.0f);\n\t\t\ttestVec.insert(testVec.begin(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(5), 5.0f);\n\t\t\ttestVec.insert(testVec.end(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(4), 4.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(6), 6.0f);\n\t\t\ttestVec.insert(testVec.end(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(1), 1.0f);\n\t\t\ttestVec.insert(testVec.begin(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15 || testVec.capacity() == nodeCount);\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(2), 2.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == TestObject(i / 3 + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with tuple\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\t\t\ttuple<bool, TestObject, float> testTup;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(3), 3.0f);\n\t\t\ttestVec.insert(testVec.begin(), testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(5), 5.0f);\n\t\t\ttestVec.insert(testVec.end(), testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(4), 4.0f);\n\t\t\ttestVec.insert(testVec.begin() + 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(6), 6.0f);\n\t\t\ttestVec.insert(testVec.end(), 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(1), 1.0f);\n\t\t\ttestVec.insert(testVec.begin(), 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(2), 2.0f);\n\t\t\ttestVec.insert(testVec.begin() + 1, 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with initList\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\t\t\ttuple<bool, TestObject, float> testTup;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(3), 3.0f);\n\t\t\ttestVec.insert(testVec.begin(), {\n\t\t\t\t{true, TestObject(3), 3.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(3), 3.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(5), 5.0f);\n\t\t\ttestVec.insert(testVec.end(), {\n\t\t\t\t{true, TestObject(5), 5.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(5), 5.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(4), 4.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, {\n\t\t\t\t{true, TestObject(4), 4.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(4), 4.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(6), 6.0f);\n\t\t\ttestVec.insert(testVec.end(), {\n\t\t\t\t{true, TestObject(6), 6.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(6), 6.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(1), 1.0f);\n\t\t\ttestVec.insert(testVec.begin(), {\n\t\t\t\t{true, TestObject(1), 1.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(1), 1.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(2), 2.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, {\n\t\t\t\t{true, TestObject(2), 2.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(2), 2.0f\n\t\t\t} });\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<1>()[i] == TestObject(i / 3 + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with rvalue args\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> testVec;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin(), 3, MoveOnlyType(3), TestObject(3));\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.end(), 5, MoveOnlyType(5), TestObject(5));\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin() + 1, 4, MoveOnlyType(4), TestObject(4));\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestVec.insert(testVec.end(), 6, MoveOnlyType(6), TestObject(6));\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin(), 1, MoveOnlyType(1), TestObject(1));\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin() + 1, 2, MoveOnlyType(2), TestObject(2));\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<2>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with rvalue tuple\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> testVec;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin(), forward_as_tuple(3, MoveOnlyType(3), TestObject(3)));\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.end(), forward_as_tuple(5, MoveOnlyType(5), TestObject(5)));\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin() + 1, forward_as_tuple(4, MoveOnlyType(4), TestObject(4)));\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestVec.insert(testVec.end(), forward_as_tuple(6, MoveOnlyType(6), TestObject(6)));\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin(), forward_as_tuple(1, MoveOnlyType(1), TestObject(1)));\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin() + 1, forward_as_tuple(2, MoveOnlyType(2), TestObject(2)));\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<2>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with iterator range \n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin(), srcVec.begin() + 6, srcVec.begin() + 9);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.end(), srcVec.begin() + 12, srcVec.begin() + 15);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin() + 3, srcVec.begin() + 9, srcVec.begin() + 12);\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestVec.insert(testVec.end(), srcVec.begin() + 15, srcVec.begin() + 18);\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin(), srcVec.begin(), srcVec.begin() + 3);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15 || testVec.capacity() == nodeCount);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin() + 3, srcVec.begin() + 3, srcVec.begin() + 6);\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test assign\n\t{\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\n\t\t\t// test assign that grows the capacity\n\t\t\ttestVec.assign(20, true, TestObject(1), 1.0f);\n\t\t\tEATEST_VERIFY(testVec.size() == 20);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(1), 1.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 20);\n\n\t\t\t// test assign that shrinks the vector\n\t\t\ttestVec.assign(10, true, TestObject(2), 2.0f);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(2), 2.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10);\n\n\t\t\t// test assign for when there's enough capacity\n\t\t\ttestVec.assign(15, true, TestObject(3), 3.0f);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(3), 3.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15);\n\t\t}\n\n\t\t{\n\t\t\ttuple<bool, TestObject, float> srcTup;\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\n\t\t\t// test assign from tuple that grows the capacity\n\t\t\tsrcTup = make_tuple(true, TestObject(1), 1.0f);\n\t\t\ttestVec.assign(20, srcTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 20);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcTup);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 20 + 1);\n\n\t\t\t// test assign from tuple that shrinks the vector\n\t\t\tsrcTup = make_tuple(true, TestObject(2), 2.0f);\n\t\t\ttestVec.assign(10, srcTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcTup);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10 + 1);\n\n\t\t\t// test assign from tuple for when there's enough capacity\n\t\t\tsrcTup = make_tuple(true, TestObject(3), 3.0f);\n\t\t\ttestVec.assign(15, srcTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcTup);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15 + 1);\n\t\t}\n\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\n\t\t\t// test assign from iter range that grows the capacity\n\t\t\ttestVec.assign(srcVec.begin() + 5, srcVec.begin() + 15);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcVec[i+5]);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10 + 20);\n\n\t\t\t// test assign from iter range that shrinks the vector\n\t\t\ttestVec.assign(srcVec.begin() + 2, srcVec.begin() + 7);\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcVec[i + 2]);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 5 + 20);\n\n\t\t\t// test assign from iter range for when there's enough capacity\n\t\t\ttestVec.assign(srcVec.begin() + 5, srcVec.begin() + 15);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcVec[i + 5]);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10 + 20);\n\t\t}\n\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\n\t\t\t// test assign from initList that grows the capacity\n\t\t\ttestVec.assign({\n\t\t\t\t{ true, TestObject(1), 1.0f },\n\t\t\t\t{ true, TestObject(1), 1.0f },\n\t\t\t\t{ true, TestObject(1), 1.0f }\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(1), 1.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 3);\n\n\t\t\t// test assign from initList that shrinks the vector\n\t\t\ttestVec.assign({\n\t\t\t\t{ true, TestObject(2), 2.0f }\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(2), 2.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 1);\n\n\t\t\t// test assign from initList for when there's enough capacity\n\t\t\ttestVec.assign({\n\t\t\t\t{ true, TestObject(3), 3.0f },\n\t\t\t\t{ true, TestObject(3), 3.0f }\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(3), 3.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 2);\n\t\t}\n\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test erase functions\n\t{\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\n\t\t\t// test erase on an iter range\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\tauto eraseIter = testVec.erase(testVec.begin() + 5, testVec.begin() + 10);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 5)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 5), (float)(i + 5)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15 + 20);\n\n\t\t\t// test erase on one position\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase(testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 5)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 1), (float)(i + 1)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\n\t\t\t// test erase_unsorted\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase_unsorted(testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i != 5)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(19), (float)(19)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\t\t}\n\n\t\t// test erase again but with reverse iterators everywhere\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> testVec;\n\n\t\t\t// test erase on an iter range\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\tauto eraseIter = testVec.erase(testVec.rbegin() + 5, testVec.rbegin() + 10);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 10)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 5), (float)(i + 5)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15 + 20);\n\n\t\t\t// test erase on one position\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase(testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 14)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 1), (float)(i + 1)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\n\t\t\t// test erase_unsorted\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase_unsorted(testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i != 14)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(19), (float)(19)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test multitude of constructors\n\t{\n\t\tEASTLAllocatorType ma;\n\t\tEASTLAllocatorType otherMa;\n\t\tTestObject::Reset();\n\n\t\t// test ctor via initlist to prime srcVec. Equivalent to ...\n\t\t//\t\tfor (int i = 0; i < 10; ++i)\n\t\t//\t\t\tsrcVec.push_back(i % 3 == 0, TestObject(i), (float)i);\n\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> srcVec({\n\t\t\t{ true,  TestObject(0), 0.0f},\n\t\t\t{ false, TestObject(1), 1.0f},\n\t\t\t{ false, TestObject(2), 2.0f},\n\t\t\t{ true,  TestObject(3), 3.0f},\n\t\t\t{ false, TestObject(4), 4.0f},\n\t\t\t{ false, TestObject(5), 5.0f},\n\t\t\t{ true,  TestObject(6), 6.0f},\n\t\t\t{ false, TestObject(7), 7.0f},\n\t\t\t{ false, TestObject(8), 8.0f},\n\t\t\t{ true,  TestObject(9), 9.0f}\n\t\t\t});\n\n\t\t// copy entire tuple_vector in ctor\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorFromConstRef(srcVec);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.template get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.template get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.template get<2>()[i] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// copy entire tuple_vector via assignment\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorFromAssignment;\n\t\t\tctorFromAssignment = srcVec;\n\t\t\tEATEST_VERIFY(ctorFromAssignment.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromAssignment.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.template get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.template get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.template get<2>()[i] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// copy entire tuple_vector via assignment of init-list\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorFromAssignment;\n\t\t\tctorFromAssignment = {\n\t\t\t\t{ true,  TestObject(0), 0.0f},\n\t\t\t\t{ false, TestObject(1), 1.0f},\n\t\t\t\t{ false, TestObject(2), 2.0f},\n\t\t\t\t{ true,  TestObject(3), 3.0f},\n\t\t\t\t{ false, TestObject(4), 4.0f},\n\t\t\t\t{ false, TestObject(5), 5.0f},\n\t\t\t\t{ true,  TestObject(6), 6.0f},\n\t\t\t\t{ false, TestObject(7), 7.0f},\n\t\t\t\t{ false, TestObject(8), 8.0f},\n\t\t\t\t{ true,  TestObject(9), 9.0f}\n\t\t\t};\n\t\t\tEATEST_VERIFY(ctorFromAssignment.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromAssignment.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.template get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.template get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.template get<2>()[i] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with iterator range\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorFromIters(srcVec.begin() + 2, srcVec.begin() + 7);\n\t\t\tEATEST_VERIFY(ctorFromIters.size() == 5);\n\t\t\tEATEST_VERIFY(ctorFromIters.validate());\n\t\t\tfor (int i = 2; i < 7; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromIters.template get<0>()[i - 2] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromIters.template get<1>()[i - 2] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromIters.template get<2>()[i - 2] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with initial size\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorFromFill(10);\n\t\t\tEATEST_VERIFY(ctorFromFill.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFill.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFill.template get<0>()[i] == false);\n\t\t\t\tEATEST_VERIFY(ctorFromFill.template get<1>()[i] == TestObject());\n\t\t\t\tEATEST_VERIFY(ctorFromFill.template get<2>()[i] == 0.0f);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with initial size and args\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorFromFillArgs(10, true, TestObject(5), 5.0f);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.template get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.template get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.template get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with initial size and tuple\n\t\t{\n\t\t\ttuple<bool, TestObject, float> tup(true, TestObject(5), 5.0f);\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorFromFillTup(10, tup);\n\t\t\tEATEST_VERIFY(ctorFromFillTup.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFillTup.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFillTup.template get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(ctorFromFillTup.template get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(ctorFromFillTup.template get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_Vector with custom mallocator\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorWithAlloc(ma);\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> ctorDefault;\n\n\t\t\tctorWithAlloc.push_back();\n\t\t\tctorDefault.push_back();\n\n\t\t\tEATEST_VERIFY(ctorWithAlloc == ctorDefault);\n\t\t\tEATEST_VERIFY(ctorWithAlloc.validate());\n\t\t}\n\n\t\t// ctor fixed_tuple_vector_alloc with copy (from diff. allocator)\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow,bool, TestObject, float> ctorFromConstRef(srcVec, ma);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.template get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.template get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.template get<2>()[i] == (float)i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(ctorFromConstRef.validate());\n\t\t}\n\n\t\t// ctor tuple_vector with initial size and args\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow,bool, TestObject, float> ctorFromFillArgs(10, true, TestObject(5), 5.0f, ma);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.template get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.template get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.template get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t}\n\t\n\t\t// ctor tuple_vector via move\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> srcMoveVec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tsrcMoveVec.emplace_back(move(i), MoveOnlyType(i), TestObject(i));\n\t\t\t}\n\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> ctorFromMove(move(srcMoveVec));\n\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(srcMoveVec.size() == 0);\n\t\t\tEATEST_VERIFY(srcMoveVec.validate());\n\t\t}\n\n\t\t// ctor tuple_vector via move (from diff. allocator)\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow,int, MoveOnlyType, TestObject> srcMoveVec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tsrcMoveVec.emplace_back(move(i), MoveOnlyType(i), TestObject(i));\n\t\t\t}\n\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> ctorFromMove(move(srcMoveVec), otherMa);\n\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(srcMoveVec.size() == 0);\n\t\t\tEATEST_VERIFY(srcMoveVec.validate());\n\n\t\t\t// bonus test for specifying a custom allocator, but using the same one as above\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> ctorFromMoveSameAlloc(move(ctorFromMove), otherMa);\n\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.template get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.template get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.template get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 0);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t}\n\n\t\t// ctor tuple_vector via move-iters\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> srcMoveVec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tsrcMoveVec.emplace_back(move(i), MoveOnlyType(i), TestObject(i));\n\t\t\t}\n\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> ctorFromMove(make_move_iterator(srcMoveVec.begin() + 2), make_move_iterator(srcMoveVec.begin() + 7));\n\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 5);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t\tfor (int i = 2; i < 7; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<0>()[i-2] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<1>()[i-2] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMove.template get<2>()[i-2] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(srcMoveVec.size() == 10);\n\t\t\tEATEST_VERIFY(srcMoveVec.validate());\n\t\t\tfor (int i = 0; i < 2; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tfor (int i = 2; i < 7; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<0>()[i] == i); // int's just get copied because they're POD\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<1>()[i] == MoveOnlyType(0));\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<2>()[i] == TestObject(0));\n\t\t\t}\n\t\t\tfor (int i = 7; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(srcMoveVec.template get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t}\n\n\t\tsrcVec.clear();\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\n\t\tTestObject::Reset();\n\t}\n\n\t// Test swap\n\t{\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, float, bool> complexVec;\n\t\tcomplexVec.push_back(3, 2.0f, true);\n\t\tcomplexVec.push_back(1, 4.0f, false);\n\t\tcomplexVec.push_back(2, 1.0f, true);\n\t\tcomplexVec.push_back(4, 3.0f, false);\n\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, float, bool> otherComplexVec;\n\t\tcomplexVec.swap(otherComplexVec);\n\n\t\tEATEST_VERIFY(complexVec.size() == 0);\n\t\tEATEST_VERIFY(complexVec.validate());\n\t\tEATEST_VERIFY(otherComplexVec.validate());\n\t\tEATEST_VERIFY(otherComplexVec.template get<0>()[0] == 3);\n\t\tEATEST_VERIFY(otherComplexVec.template get<float>()[1] == 4.0f);\n\n\t\tcomplexVec.push_back(10, 10.0f, true);\n\t\tswap(complexVec, otherComplexVec);\n\n\t\tEATEST_VERIFY(complexVec.validate());\n\t\tEATEST_VERIFY(*(complexVec.template get<0>()) == 3);\n\t\tEATEST_VERIFY(complexVec.template get<float>()[1] == 4.0f);\n\n\t\tEATEST_VERIFY(otherComplexVec.validate());\n\t\tEATEST_VERIFY(otherComplexVec.template get<float>()[0] == 10.0f);\n\t\tEATEST_VERIFY(otherComplexVec.size() == 1);\n\n\t}\n\n\n\t// Test tuple_Vector in a ranged for, and other large-scale iterator testing\n\t{\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, float, int> tripleElementVec;\n\t\ttripleElementVec.push_back(1, 2.0f, 6);\n\t\ttripleElementVec.push_back(2, 3.0f, 7);\n\t\ttripleElementVec.push_back(3, 4.0f, 8);\n\t\ttripleElementVec.push_back(4, 5.0f, 9);\n\t\ttripleElementVec.push_back(5, 6.0f, 10);\n\n\n\t\t// test copyConstructible, copyAssignable, swappable, prefix inc, !=, reference convertible to value_type (InputIterator!)\n\t\t{\n\t\t\ttypename fixed_tuple_vector<nodeCount, bEnableOverflow, int, float, int>::iterator iter = tripleElementVec.begin();\n\t\t\t++iter;\n\t\t\tauto copiedIter(iter);\n\t\t\tEATEST_VERIFY(get<2>(*copiedIter) == 7);\n\t\t\tEATEST_VERIFY(copiedIter == iter);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(copiedIter) != isf_none);\n\n\t\t\t++iter;\n\t\t\tcopiedIter = iter;\n\t\t\tEATEST_VERIFY(get<2>(*copiedIter) == 8);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(copiedIter) != isf_none);\n\n\t\t\t++iter;\n\t\t\tswap(iter, copiedIter);\n\t\t\tEATEST_VERIFY(get<2>(*iter) == 8);\n\t\t\tEATEST_VERIFY(get<2>(*copiedIter) == 9);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(copiedIter) != isf_none);\n\n\t\t\tEATEST_VERIFY(copiedIter != iter);\n\n\t\t\ttuple<const int&, const float&, const int&> ref(*iter);\n\t\t\ttuple<int, float, int> value(*iter);\n\t\t\tEATEST_VERIFY(get<2>(ref) == get<2>(value));\n\t\t}\n\n\t\t// test postfix increment, default constructible (ForwardIterator)\n\t\t{\n\t\t\ttypename fixed_tuple_vector<nodeCount, bEnableOverflow, int, float, int>::iterator iter = tripleElementVec.begin();\n\t\t\tauto prefixIter = ++iter;\n\n\t\t\ttypename fixed_tuple_vector<nodeCount, bEnableOverflow, int, float, int>::iterator postfixIter;\n\t\t\tpostfixIter = iter++;\n\t\t\tEATEST_VERIFY(prefixIter == postfixIter);\n\t\t\tEATEST_VERIFY(get<2>(*prefixIter) == 7);\n\t\t\tEATEST_VERIFY(get<2>(*iter) == 8);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(prefixIter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(postfixIter) != isf_none);\n\t\t}\n\n\t\t// test prefix decrement and postfix decrement (BidirectionalIterator)\n\t\t{\n\t\t\ttypename fixed_tuple_vector<nodeCount, bEnableOverflow, int, float, int>::iterator iter = tripleElementVec.end();\n\t\t\tauto prefixIter = --iter;\n\n\t\t\ttypename fixed_tuple_vector<nodeCount, bEnableOverflow, int, float, int>::iterator postfixIter;\n\t\t\tpostfixIter = iter--;\n\t\t\tEATEST_VERIFY(prefixIter == postfixIter);\n\t\t\tEATEST_VERIFY(get<2>(*prefixIter) == 10);\n\t\t\tEATEST_VERIFY(get<2>(*iter) == 9);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(prefixIter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(postfixIter) != isf_none);\n\t\t}\n\n\t\t// test many arithmetic operations (RandomAccessIterator)\n\t\t{\n\t\t\ttypename fixed_tuple_vector<nodeCount, bEnableOverflow, int, float, int>::iterator iter = tripleElementVec.begin();\n\t\t\tauto symmetryOne = iter + 2;\n\t\t\tauto symmetryTwo = 2 + iter;\n\t\t\titer += 2;\n\t\t\tEATEST_VERIFY(symmetryOne == symmetryTwo);\n\t\t\tEATEST_VERIFY(symmetryOne == iter);\n\n\t\t\tsymmetryOne = iter - 2;\n\t\t\tsymmetryTwo = 2 - iter;\n\t\t\titer -= 2;\n\t\t\tEATEST_VERIFY(symmetryOne == symmetryTwo);\n\t\t\tEATEST_VERIFY(symmetryOne == iter);\n\n\t\t\titer += 2;\n\t\t\tEATEST_VERIFY(iter - symmetryOne == 2);\n\n\t\t\ttuple<int&, float&, int&> symmetryRef = symmetryOne[2];\n\t\t\tEATEST_VERIFY(get<2>(symmetryRef) == get<2>(*iter));\n\n\t\t\tEATEST_VERIFY(symmetryOne < iter);\n\t\t\tEATEST_VERIFY(iter > symmetryOne);\n\t\t\tEATEST_VERIFY(symmetryOne >= symmetryTwo && iter >= symmetryOne);\n\t\t\tEATEST_VERIFY(symmetryOne <= symmetryTwo && symmetryOne <= iter);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(symmetryOne) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(symmetryTwo) != isf_none);\n\t\t}\n\n\t\t// test simple iteration, and reverse iteration\n\t\t{\n\t\t\tfloat i = 0;\n\t\t\tint j = 0;\n\t\t\tEATEST_VERIFY(&get<0>(*tripleElementVec.begin()) == tripleElementVec.template get<0>());\n\t\t\tEATEST_VERIFY(&get<1>(*tripleElementVec.begin()) == tripleElementVec.template get<1>());\n\t\t\tfor (auto iter : tripleElementVec)\n\t\t\t{\n\t\t\t\ti += get<1>(iter);\n\t\t\t\tj += get<2>(iter);\n\t\t\t}\n\t\t\tEATEST_VERIFY(i == 20.0f);\n\t\t\tEATEST_VERIFY(j == 40);\n\n\t\t\tfloat reverse_i = 0;\n\t\t\tint reverse_j = 0;\n\n\t\t\teastl::for_each(tripleElementVec.rbegin(), tripleElementVec.rend(),\n\t\t\t\t[&](const tuple<int, float, int> tup)\n\t\t\t\t{\n\t\t\t\t\treverse_i += get<1>(tup);\n\t\t\t\t\treverse_j += get<2>(tup);\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(i == reverse_i);\n\t\t\tEATEST_VERIFY(j == reverse_j);\n\t\t\tEATEST_VERIFY(get<0>(*tripleElementVec.rbegin()) == 5);\n\t\t}\n\t}\n\n\t// Test move operations\n\t{\n\t\tTestObject::Reset();\n\n\t\t// test emplace \n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> testVec;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test emplace on empty vector that doesn't cause growth\n\t\t\ttestVec.emplace(testVec.begin(), 3, MoveOnlyType(3), TestObject(3));\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test emplace to end of vector that doesn't cause growth\n\t\t\ttestVec.emplace(testVec.end(), 5, MoveOnlyType(5), TestObject(5));\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test emplace to middle of vector that doesn't cause growth\n\t\t\ttestVec.emplace(testVec.begin() + 1, 4, MoveOnlyType(4), TestObject(4));\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3 || testVec.capacity() == nodeCount);\n\n\t\t\t// test emplace to end of vector that causes growth\n\t\t\ttestVec.emplace(testVec.end(), 6, MoveOnlyType(6), TestObject(6));\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4 || testVec.capacity() == nodeCount);\n\n\t\t\t// test emplace to beginning of vector that causes growth\n\t\t\ttestVec.emplace(testVec.begin(), 1, MoveOnlyType(1), TestObject(1));\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5 || testVec.capacity() == nodeCount);\n\n\t\t\t// test emplace to middle of vector that causes growth\n\t\t\ttestVec.emplace(testVec.begin() + 1, 2, MoveOnlyType(2), TestObject(2));\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\tif (testVec.has_overflowed())\n\t\t\t{\n\t\t\t\ttestVec.shrink_to_fit();\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6 || testVec.capacity() == nodeCount);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.template get<2>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test some other miscellania around rvalues, including...\n\t\t// push_back with rvalue args, push_back with rvalue tuple,\n\t\t// emplace_back with args, and emplace_back with tup\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> v1;\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, int, MoveOnlyType, TestObject> v2;\n\t\t\t// add some data in the vector so we can move it to the other vector.\n\t\t\tv1.reserve(5);\n\t\t\tauto emplacedTup = v1.emplace_back(1, MoveOnlyType(1), TestObject(1));\n\t\t\tEATEST_VERIFY(emplacedTup == v1.back());\n\t\t\tv1.push_back(3, MoveOnlyType(3), TestObject(3));\n\t\t\tv1.emplace_back(forward_as_tuple(5, MoveOnlyType(5), TestObject(5)));\n\t\t\tv1.push_back(forward_as_tuple(6, MoveOnlyType(6), TestObject(6)));\n\t\t\tv1.emplace(v1.begin() + 1, 2, MoveOnlyType(2), TestObject(2));\n\t\t\tv1.emplace(v1.begin() + 3, make_tuple(4, MoveOnlyType(4), TestObject(4)));\n\n\t\t\ttuple<int&, MoveOnlyType&, TestObject&> movedTup = v1.at(0);\n\t\t\tEATEST_VERIFY(v1.validate());\n\t\t\tEATEST_VERIFY(get<0>(movedTup) == 1);\n\t\t\tEATEST_VERIFY(get<0>(*v1.begin()) == 1);\n\n\t\t\tfor (int i = 0; i < static_cast<int>(v1.size()); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(v1.template get<0>()[i] == i + 1);\n\t\t\t}\n\t\t\tEATEST_VERIFY(!v1.empty() && v2.empty());\n\t\t\tv2 = eastl::move(v1);\n\t\t\tEATEST_VERIFY(v2.validate());\n\t\t\tEATEST_VERIFY(v1.empty() && !v2.empty());\n\t\t\tv1.swap(v2);\n\t\t\tEATEST_VERIFY(v1.validate());\n\t\t\tEATEST_VERIFY(v2.validate());\n\t\t\tEATEST_VERIFY(!v1.empty() && v2.empty());\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test comparisons\n\t{\n\n\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float> equalsVec1, equalsVec2;\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\tequalsVec1.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t\tequalsVec2.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t}\n\t\tEATEST_VERIFY(equalsVec1 == equalsVec2);\n\n\t\tusing ftv = fixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float>;\n\t\ttypename ftv::overflow_allocator_type otherAlloc;\n\t\tftv smallSizeVec(5);\n\t\tftv lessThanVec(10);\n\t\tftv greaterThanVec(10, otherAlloc);\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\tlessThanVec.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t\tgreaterThanVec.push_back(i % 3 == 0, TestObject(i * 2), (float)i * 2);\n\t\t}\n\t\tEATEST_VERIFY(equalsVec1 != smallSizeVec);\n\t\tEATEST_VERIFY(equalsVec1 != lessThanVec);\n\t\tEATEST_VERIFY(equalsVec1 != greaterThanVec);\n\t\tEATEST_VERIFY(lessThanVec < greaterThanVec);\n\t\tEATEST_VERIFY(greaterThanVec > lessThanVec);\n\t\tEATEST_VERIFY(lessThanVec <= greaterThanVec);\n\t\tEATEST_VERIFY(equalsVec1 <= equalsVec2);\n\t\tEATEST_VERIFY(equalsVec1 >= equalsVec2);\n\t}\n\n\t// Test partition\n\t{\n\t\t{\n\t\t\tfixed_tuple_vector<nodeCount, bEnableOverflow, bool, TestObject, float, MoveOnlyType> vec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tvec.push_back(i % 3 == 0, TestObject(i), (float)i, MoveOnlyType(i));\n\t\t\t}\n\n\t\t\teastl::partition(vec.begin(), vec.end(), [](tuple<bool&, TestObject&, float&, MoveOnlyType&> a)\n\t\t\t{ return get<0>(a) == true; });\n\n\t\t\t// partition will split the array into 4 elements where the bool property is true, and 6 where it's false\n\t\t\tfor (int i = 0; i < 4; ++i)\n\t\t\t\tEATEST_VERIFY(vec.template get<0>()[i] == true);\n\t\t\tfor (int i = 4; i < 10; ++i)\n\t\t\t\tEATEST_VERIFY(vec.template get<0>()[i] == false);\n\n\t\t\tEATEST_VERIFY(vec.validate());\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10);\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t}\n\treturn nErrorCount;\n}\n\nint TestFixedTupleVector()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestFixedTupleVectorVariant<2, true>();\n\tnErrorCount += TestFixedTupleVectorVariant<16, true>();\n\tnErrorCount += TestFixedTupleVectorVariant<64, false>();\n\n\treturn nErrorCount;\n}\n\n\n"
  },
  {
    "path": "test/source/TestFixedVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/fixed_vector.h>\n#include <EASTL/unique_ptr.h>\n#include <EAStdC/EAMemory.h>\n#include <new>\n\n#if defined(EA_COMPILER_CPP17_ENABLED) && __has_include(<variant>)\n#include <variant> //Variant not present in older standards\n#endif\n\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::fixed_vector<int,        1,  true>;\ntemplate class eastl::fixed_vector<Align64,    1,  true>;\ntemplate class eastl::fixed_vector<TestObject, 1,  true>;\n\ntemplate class eastl::fixed_vector<int,        1, false>;\ntemplate class eastl::fixed_vector<Align64,    1, false>;\ntemplate class eastl::fixed_vector<TestObject, 1, false>;\n\n/*\n// This does not compile, since the fixed_vector allocator is templated on sizeof(T), \n// not just T. Thus, the full type is required at the time of instantiation, but it\n// is not available.\n// See EATech Core JIRA issue ETCR-1608 for more information.\nstruct StructWithContainerOfStructs\n{\n\teastl::fixed_vector<StructWithContainerOfStructs,4> children;\n};\n*/\n\n\nnamespace\n{\n\t// Aligned objects should be CustomAllocator instead of the default, because the \n\t// EASTL default might be unable to do aligned allocations, but CustomAllocator always can.\n\ttypedef fixed_vector<Align64, 3, true, CustomAllocator> VA64;\n\n\tVA64      vA64;\n\tAlign64   a64(5);\n\tAlign64*  pA64 = &a64;\n}\n\n\nint TestFixedVector()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{ // Test the aligned_buffer template\n\t\t{\n\t\t\teastl::aligned_buffer<sizeof(TestObject), EASTL_ALIGN_OF(TestObject)> toAlignedBuffer;\n\t\t\tTestObject* const pTO = new(toAlignedBuffer.buffer) TestObject;\n\t\t\t#if !defined(__GNUC__) // GCC complains about strict aliasing here.\n\t\t\t\tEATEST_VERIFY(pTO->mX == ((TestObject*)&toAlignedBuffer.buffer[0])->mX);\n\t\t\t#endif\n\t\t\tpTO->~TestObject();\n\t\t}\n\n\t\t{\n\t\t\teastl::aligned_buffer<sizeof(Align64), EASTL_ALIGN_OF(Align64)> a64AlignedBuffer;\n\t\t\tAlign64* const pAlign64 = new(a64AlignedBuffer.buffer) Align64;\n\t\t\t#if !defined(__GNUC__) // GCC complains about strict aliasing here.\n\t\t\t\tEATEST_VERIFY(pAlign64->mX == ((Align64*)&a64AlignedBuffer.buffer[0])->mX);\n\t\t\t#endif\n\t\t\tpAlign64->~Align64();\n\t\t}\n\t}\n\n\t{\n\t\t// fixed_vector();\n\t\t// size_type max_size() const;\n\t\tfixed_vector<int, 1, true> v;\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"fixed_vector\", -1));\n\t\tEATEST_VERIFY(v.max_size() == 1);\n\n\t\t// fixed_vector();\n\t\ttypedef fixed_vector<int, 8, false> FixedVectorInt8;\n\t\tFixedVectorInt8 fv1;\n\t\tEATEST_VERIFY(fv1.size() == 0);\n\t\tEATEST_VERIFY(fv1.capacity() == 8);\n\n\t\t// this_type& operator=(const base_type& x);\n\t\tFixedVectorInt8 fv2 = fv1;\n\t\tEATEST_VERIFY(fv2.size() == 0);\n\t\tEATEST_VERIFY(fv2.capacity() == 8);\n\n\t\t// fixed_vector(const base_type& x);\n\t\tFixedVectorInt8 fv3(fv1);\n\t\tEATEST_VERIFY(fv3.size() == 0);\n\t\tEATEST_VERIFY(fv3.capacity() == 8);\n\n\t\t// explicit fixed_vector(size_type n);\n\t\tFixedVectorInt8 fv4(5);\n\t\tEATEST_VERIFY(fv4.size() == 5);\n\t\tEATEST_VERIFY(fv4.capacity() == 8);\n\t\tEATEST_VERIFY((fv4[0] == 0) && (fv4[4] == 0));\n\n\t\t// fixed_vector(size_type n, const value_type& value);\n\t\tFixedVectorInt8 fv5((eastl_size_t)5, (int)3);\n\t\tEATEST_VERIFY(fv5.size() == 5);\n\t\tEATEST_VERIFY(fv5.capacity() == 8);\n\t\tEATEST_VERIFY((fv5[0] == 3) && (fv5[4] == 3));\n\n\t\t// fixed_vector(InputIterator first, InputIterator last);\n\t\tconst int intArray[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };\n\t\tFixedVectorInt8 fv6(intArray, intArray + 8);\n\t\tEATEST_VERIFY(fv6.size() == 8);\n\t\tEATEST_VERIFY(fv5.capacity() == 8);\n\t\tEATEST_VERIFY((fv6[0] == 0) && (fv6[7] == 7));\n\n\t\t// void reset_lose_memory();\n\t\tfv6.reset_lose_memory();\n\t\tEATEST_VERIFY(fv6.size() == 0);\n\t\tEATEST_VERIFY(fv6.capacity() == 8);\n\n\t\t// void set_capacity(size_type);\n\t\tfv6.set_capacity(100);  // overflow is disabled, so this should have no effect.\n\t\tEATEST_VERIFY(fv6.size() == 0);\n\t\tEATEST_VERIFY(fv6.capacity() == 8); // EATEST_VERIFY that the capacity is unchanged.\n\n\t\tfv6.resize(8);\n\t\tEATEST_VERIFY(fv6.size() == 8);\n\t\tfv6.set_capacity(1);\n\t\tEATEST_VERIFY(fv6.size() == 1);\n\t\tEATEST_VERIFY(fv6.capacity() == 8);\n\n\t\t// Exercise the freeing of memory in set_capacity.\n\t\tfixed_vector<int, 8, true> fv88;\n\t\teastl_size_t capacity = fv88.capacity();\n\t\tfv88.resize(capacity);\n\t\tfv88.set_capacity(capacity * 2);\n\t\tEATEST_VERIFY(fv88.capacity() >= (capacity * 2));\n\n\t\t// void swap(this_type& x);\n\t\t// FixedVectorInt8 fv7(5, 3);  // MSVC-ARM64 generated an internal compiler error on this line.\n\t\tFixedVectorInt8 fv7 = {3, 3, 3, 3, 3};\n\t\tFixedVectorInt8 fv8(intArray, intArray + 8);\n\n\t\tswap(fv7, fv8);\n\t\tEATEST_VERIFY(fv7.size() == 8);\n\t\tEATEST_VERIFY((fv7[0] == 0) && (fv7[7] == 7));\n\t\tEATEST_VERIFY(fv8.size() == 5);\n\t\tEATEST_VERIFY((fv8[0] == 3) && (fv8[4] == 3));\n\n\t\tfv7.swap(fv8);\n\t\tEATEST_VERIFY(fv8.size() == 8);\n\t\tEATEST_VERIFY((fv8[0] == 0) && (fv8[7] == 7));\n\t\tEATEST_VERIFY(fv7.size() == 5);\n\t\tEATEST_VERIFY((fv7[0] == 3) && (fv7[4] == 3));\n\n\t\t// Test a recent optimization we added, which was to do a pointer swap of the fixed_vector pointers\n\t\t// for the case that both fixed_vectors were overflowed and using the heap instead of their fixed buffers.\n\t\tfixed_vector<int8_t, 4, true> fvo5;\n\t\tfixed_vector<int8_t, 4, true> fvo6;\n\t\tfvo5.resize(5, 5);\n\t\tEATEST_VERIFY(fvo5.has_overflowed());\n\t\tfvo6.resize(6, 6);\n\t\tEATEST_VERIFY(fvo6.has_overflowed());\n\t\tfvo5.swap(fvo6);\n\t\tEATEST_VERIFY(fvo5.size() == 6); // Verify that sizes are swapped.\n\t\tEATEST_VERIFY(fvo6.size() == 5);\n\t\tEATEST_VERIFY(EA::StdC::Memcheck8(fvo5.data(), 6, fvo5.size()) == NULL); // Verify that contents are swapped.\n\t\tEATEST_VERIFY(EA::StdC::Memcheck8(fvo6.data(), 5, fvo6.size()) == NULL);\n\n\t\t// global operators\n\t\tEATEST_VERIFY(  fv7 != fv8);\n\t\tEATEST_VERIFY(!(fv7 == fv8));\n\t\tfv7 = fv8;\n\t\tEATEST_VERIFY(  fv7 == fv8);\n\t\tEATEST_VERIFY(!(fv7 != fv8));\n\t\tEATEST_VERIFY(fv7.validate());\n\t\tEATEST_VERIFY(fv8.validate());\n\t}\n\n\n\t{\n\t\t// POD types\n\t\ttypedef fixed_vector<int, 1, true> vInt;\n\n\t\tvInt    v;\n\t\tint     n = 5;\n\t\tint*    pN = &n;\n\n\t\tv.insert(v.begin(), pN, pN + 1);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"fixed_vector\", 5, -1));\n\t\tEATEST_VERIFY(v.validate());\n\t}\n\n\n\t{\n\t\t// non POD types\n\t\ttypedef fixed_vector<TestObject, 1, true> VTO;\n\n\t\tVTO              v;\n\t\tTestObject       to(5);\n\t\tTestObject*      pTO = &to;\n\n\t\tv.insert(v.begin(), pTO, pTO + 1);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"fixed_vector\", 5, -1));\n\t\tEATEST_VERIFY(v.validate());\n\t}\n\n\n\t{\n\t\t// non POD types\n\n\t\t// The variables used here are declared above in the global space.\n\t\tvA64.insert(vA64.begin(), pA64, pA64 + 1);\n\t\tEATEST_VERIFY(VerifySequence(vA64.begin(), vA64.end(), int(), \"fixed_vector\", 5, -1));\n\t\tEATEST_VERIFY(((uintptr_t)&a64 % alignof(Align64)) == 0);\n\t\tEATEST_VERIFY(((uintptr_t)vA64.data() % alignof(Align64)) == 0);\n\t\tEATEST_VERIFY(((uintptr_t)&vA64[0] % alignof(Align64)) == 0);\n\t\tEATEST_VERIFY(vA64.max_size() == 3);\n\t\tEATEST_VERIFY(vA64.validate());\n\t}\n\n\t{\n\t\t// push_back()\n\n\t\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT)\n\t\t\ttypedef eastl::fixed_vector<int, 128, false> FixedVector;\n\t\t\tFixedVector v;\n\t\t\tv.push_back(); // value initialized.\n\t\t\tEATEST_VERIFY(v.back() == 0);\n#endif\n\t\t}\n\n\t\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT)\n\t\t\ttypedef eastl::fixed_vector<int, 128, true> FixedVector;\n\t\t\tFixedVector v;\n\t\t\tv.push_back(); // value initialized.\n\t\t\tEATEST_VERIFY(v.back() == 0);\n#endif\n\t\t}\n\t}\n\n\n\t{\n\t\t// Test for potential bug reported Sep. 19, 2006.\n\t\ttypedef eastl::fixed_vector<void*, 160, false> FixedVector;\n\t\tFixedVector v;\n\t\tint arr[100] = {};\n\t\tint* p = arr;\n\n\t\tfor(int i = 0; i < 100; i++, p++)\n\t\t\tv.push_back(p);\n\n\t\tEATEST_VERIFY(v.size() == 100);\n\t\tEATEST_VERIFY(eastl::unique(v.begin(), v.end()) == v.end());\n\n\t\tFixedVector::iterator it = eastl::lower_bound(v.begin(), v.end(), p - 30);\n\t\tEATEST_VERIFY(v.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\tEATEST_VERIFY((*it) == (p - 30));\n\n\t\tv.erase(it);\n\n\t\tEATEST_VERIFY(v.size() == 99);\n\t\tEATEST_VERIFY(eastl::unique(v.begin(), v.end()) == v.end());\n\t}\n\n\t{\n\t\ttypedef fixed_vector<Align64, 4, true, CustomAllocator> FixedVectorWithAlignment;\n\n\t\tFixedVectorWithAlignment fv;\n\n\t\tAlign64 a;\n\n\t\tfv.push_back(a);\n\t\tfv.push_back(a);\n\t\tfv.push_back(a);\n\t\tfv.push_back(a);\n\t\tfv.push_back(a);\n\t\tfor (FixedVectorWithAlignment::const_iterator it = fv.begin(); it != fv.end(); ++it)\n\t\t{\n\t\t\tconst Align64* ptr = &(*it);\n\t\t\tEATEST_VERIFY((uint64_t)ptr % EASTL_ALIGN_OF(Align64) == 0);\n\t\t}\n\t}\n\n\t{   // Test overflow allocator specification\n\t\ttypedef fixed_vector<char8_t, 64, true, MallocAllocator> FixedString64Malloc;\n\n\t\tFixedString64Malloc fs;\n\n\t\tfs.push_back('a');\n\t\tEATEST_VERIFY(fs.size() == 1);\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\n\t\tfs.resize(95);\n\t\tfs[94] = 'b';\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\t\tEATEST_VERIFY(fs[94] == 'b');\n\t\tEATEST_VERIFY(fs.size() == 95);\n\t\tEATEST_VERIFY(fs.validate());\n\n\t\tfs.clear();\n\t\tEATEST_VERIFY(fs.empty());\n\n\t\tfs.push_back('a');\n\t\tEATEST_VERIFY(fs.size() == 1);\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\t\tEATEST_VERIFY(fs.validate());\n\n\t\tfs.resize(195);\n\t\tfs[194] = 'b';\n\t\tEATEST_VERIFY(fs[0] == 'a');\n\t\tEATEST_VERIFY(fs[194] == 'b');\n\t\tEATEST_VERIFY(fs.size() == 195);\n\t\tEATEST_VERIFY(fs.validate());\n\n\t\t// get_overflow_allocator / set_overflow_allocator\n\t\tfs.set_capacity(0); // This should free all memory allocated by the existing (overflow) allocator.\n\t\tEATEST_VERIFY(fs.validate());\n\t\tMallocAllocator a;\n\t\tfs.get_allocator().set_overflow_allocator(a);\n\t\tEATEST_VERIFY(fs.validate());\n\t\tfs.resize(400);\n\t\tEATEST_VERIFY(fs.validate());\n\t}\n\n\n\t{\n\t\t//Test clear(bool freeOverflow)\n\t\tconst size_t nodeCount = 4;\n\t\ttypedef fixed_vector<int, nodeCount, true> vInt4;\n\t\tvInt4 fv;\n\t\tfor (int i = 0; (unsigned)i < nodeCount+1; i++)\n\t\t{\n\t\t\tfv.push_back(i);\n\t\t}\n\t\tvInt4::size_type capacity = fv.capacity();\n\t\tEATEST_VERIFY(capacity >= nodeCount+1);\n\t\tfv.clear(false);\n\t\tEATEST_VERIFY(fv.size() == 0);\n\t\tEATEST_VERIFY(fv.capacity() == capacity);\n\t\tfv.push_back(1);\n\t\tfv.clear(true);\n\t\tEATEST_VERIFY(fv.size() == 0);\n\t\tEATEST_VERIFY(fv.capacity() == nodeCount);\n\t}\n\n\n\t{\n\t\t// bool empty() const\n\t\t// bool has_overflowed() const\n\t\t// size_type size() const;\n\t\t// size_type max_size() const\n\n\t\t// Test a vector that has overflow disabled.\n\t\tfixed_vector<int, 5, false> vInt5;\n\n\t\tEATEST_VERIFY(vInt5.max_size() == 5);\n\t\tEATEST_VERIFY(vInt5.size() == 0);\n\t\tEATEST_VERIFY(vInt5.empty());\n\t\tEATEST_VERIFY(!vInt5.has_overflowed());\n\n\t\tvInt5.push_back(37);\n\t\tvInt5.push_back(37);\n\t\tvInt5.push_back(37);\n\n\t\tEATEST_VERIFY(vInt5.size() == 3);\n\t\tEATEST_VERIFY(!vInt5.empty());\n\t\tEATEST_VERIFY(!vInt5.has_overflowed());\n\n\t\tvInt5.push_back(37);\n\t\tvInt5.push_back(37);\n\n\t\tEATEST_VERIFY(vInt5.size() == 5);\n\t\tEATEST_VERIFY(!vInt5.empty());\n\t\tEATEST_VERIFY(!vInt5.has_overflowed());\n\n\t\tvInt5.pop_back();\n\n\t\tEATEST_VERIFY(vInt5.size() == 4);\n\t\tEATEST_VERIFY(!vInt5.empty());\n\t\tEATEST_VERIFY(!vInt5.has_overflowed());\n\t\tEATEST_VERIFY(vInt5.validate());\n\t}\n\n\n\t{\n\t\t// bool empty() const\n\t\t// bool has_overflowed() const\n\t\t// size_type size() const;\n\t\t// size_type max_size() const\n\n\t\t// Test a list that has overflow enabled.\n\t\tfixed_vector<int, 5, true> vInt5;\n\n\t\tEATEST_VERIFY(vInt5.max_size() == 5);\n\t\tEATEST_VERIFY(vInt5.size() == 0);\n\t\tEATEST_VERIFY(vInt5.empty());\n\t\tEATEST_VERIFY(!vInt5.has_overflowed());\n\n\t\tvInt5.push_back(37);\n\t\tvInt5.push_back(37);\n\t\tvInt5.push_back(37);\n\n\t\tEATEST_VERIFY(vInt5.size() == 3);\n\t\tEATEST_VERIFY(!vInt5.empty());\n\t\tEATEST_VERIFY(!vInt5.has_overflowed());\n\n\t\tvInt5.push_back(37);\n\t\tvInt5.push_back(37);\n\n\t\tEATEST_VERIFY(vInt5.size() == 5);\n\t\tEATEST_VERIFY(!vInt5.empty());\n\t\tEATEST_VERIFY(!vInt5.has_overflowed());\n\n\t\tvInt5.push_back(37);\n\n\t\tEATEST_VERIFY(vInt5.size() == 6);\n\t\tEATEST_VERIFY(!vInt5.empty());\n\t\tEATEST_VERIFY(vInt5.has_overflowed());\n\n\t\tvInt5.clear();\n\n\t\tEATEST_VERIFY(vInt5.size() == 0);\n\t\tEATEST_VERIFY(vInt5.empty());\n\t\tEATEST_VERIFY(vInt5.has_overflowed());           // Note that we declare the container full, as it is no longer using the fixed-capacity.\n\t\tEATEST_VERIFY(vInt5.validate());\n\t}\n\n\t{\n\t\t// void* push_back_uninitialized();\n\n\t\tint64_t toCount0 = TestObject::sTOCount;\n\n\t\teastl::fixed_vector<TestObject, 32, false> vTO1;         // <-- bEnableOverflow = false\n\t\tEATEST_VERIFY(TestObject::sTOCount == toCount0);\n\n\t\tfor(int i = 0; i < 25; i++) // 25 is simply a number that is <= 32.\n\t\t{\n\t\t\tvoid* pTO1 = vTO1.push_back_uninitialized();\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == (toCount0 + i));\n\n\t\t\tnew(pTO1) TestObject(i);\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == (toCount0 + i + 1));\n\t\t\tEATEST_VERIFY(vTO1.back().mX == i);\n\t\t\tEATEST_VERIFY(vTO1.validate());\n\t\t}\n\t}\n\n\t{\n\t\t// void* push_back_uninitialized();\n\n\t\tint64_t toCount0 = TestObject::sTOCount;\n\n\t\teastl::fixed_vector<TestObject, 15, true> vTO2;         // <-- bEnableOverflow = true\n\t\tEATEST_VERIFY(TestObject::sTOCount == toCount0);\n\n\t\tfor(int i = 0; i < 25; i++) // 25 is simply a number that is > 15.\n\t\t{\n\t\t\tvoid* pTO2 = vTO2.push_back_uninitialized();\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == (toCount0 + i));\n\n\t\t\tnew(pTO2) TestObject(i);\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == (toCount0 + i + 1));\n\t\t\tEATEST_VERIFY(vTO2.back().mX == i);\n\t\t\tEATEST_VERIFY(vTO2.validate());\n\t\t}\n\t}\n\n\t{ // Try to repro user report that fixed_vector on the stack crashes.\n\t\teastl::fixed_vector<int,        10, false> fvif;\n\t\teastl::fixed_vector<int,        10, true>  fvit;\n\t\teastl::fixed_vector<TestObject, 10, false> fvof;\n\t\teastl::fixed_vector<TestObject, 10, true>  fvot;\n\t\teastl::fixed_vector<int,        10, false, MallocAllocator> fvimf;\n\t\teastl::fixed_vector<int,        10, true,  MallocAllocator> fvimt;\n\t\teastl::fixed_vector<TestObject, 10, false, MallocAllocator> fvomf;\n\t\teastl::fixed_vector<TestObject, 10, true,  MallocAllocator> fvomt;\n\n\t\tfvif.push_back(1);\n\t\tfvit.push_back(1);\n\t\tfvimf.push_back(1);\n\t\tfvimt.push_back(1);\n\n\t\tfvif.clear();\n\t\tfvit.clear();\n\t\tfvimf.clear();\n\t\tfvimt.clear();\n\t}\n\n\t{\n\t\t// Test construction of a container with an overflow allocator constructor argument.\n\t\tMallocAllocator overflowAllocator;\n\t\tvoid* p = overflowAllocator.allocate(1);\n\t\tfixed_vector<int, 64, true, MallocAllocator> c(overflowAllocator);\n\t\tc.resize(65);\n\t\tEATEST_VERIFY(c.get_overflow_allocator().mAllocCount == 2); // 1 for above, and 1 for overflowing from 64 to 65.\n\t\toverflowAllocator.deallocate(p, 1);\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\n\t{   // Test for crash bug reported by Arpit Baldeva.\n\t\teastl::fixed_vector<void*, 1, true> test;\n\n\t\ttest.push_back(NULL);\n\t\ttest.push_back(NULL);\n\t\ttest.erase(eastl::find(test.begin(), test.end(), (void*)NULL));\n\t\ttest.erase(eastl::find(test.begin(), test.end(), (void*)NULL));\n\t\tEATEST_VERIFY(test.empty());\n\t\tEATEST_VERIFY(test.validate());\n\n\t\ttest.set_capacity(0);    // \"Does nothing currently.\"\n\t\tEATEST_VERIFY(test.capacity() == 1);\n\t\tEATEST_VERIFY(test.validate());\n\n\t}   // \"Crash here.\"\n\n\t{\n\t\tconst int FV_SIZE = 100;\n\t\tfixed_vector<unique_ptr<unsigned int>, FV_SIZE> fvmv1; // to move via move assignment operator\n\t\tfixed_vector<unique_ptr<unsigned int>, FV_SIZE> fvmv2; // to move via move copy constructor\n\n\t\tfor (unsigned int i = 0; i < FV_SIZE; ++i) // populate fvmv1\n\t\t\tfvmv1.push_back(make_unique<unsigned int>(i));\n\n\t\tfvmv2 = eastl::move(fvmv1); // Test move assignment operator\n\n\t\tfor (unsigned int i = 0; i < FV_SIZE; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(!fvmv1[i]);\n\t\t\tEATEST_VERIFY(*fvmv2[i] == i);\n\t\t}\n\t\tEATEST_VERIFY(fvmv2.validate());\n\t\t\n\t\tswap(fvmv1, fvmv2); // Test swap with move-only objects\n\t\tfor (unsigned int i = 0; i < FV_SIZE; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(*fvmv1[i] == i);\n\t\t\tEATEST_VERIFY(!fvmv2[i]);\n\t\t}\n\t\tEATEST_VERIFY(fvmv1.validate());\n\t\tEATEST_VERIFY(fvmv2.validate());\n\n\t\tfixed_vector<unique_ptr<unsigned int>, FV_SIZE> fvmv3 = eastl::move(fvmv1); // Test move copy constructor\n\t\tfor (unsigned int i = 0; i < FV_SIZE; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(!fvmv1[i]);\n\t\t\tEATEST_VERIFY(*fvmv3[i] == i);\n\t\t}\n\t\tEATEST_VERIFY(fvmv3.validate());\n\n\t\tfixed_vector<unique_ptr<unsigned int>, FV_SIZE> fvmv4{eastl::move(fvmv3), fvmv3.get_overflow_allocator()};\n\t\tfor (unsigned int i = 0; i < FV_SIZE; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(!fvmv3[i]);\n\t\t\tEATEST_VERIFY(*fvmv4[i] == i);\n\t\t}\n\t\tEATEST_VERIFY(fvmv4.validate());\n\n\t\tfvmv4.push_back(make_unique<unsigned int>(FV_SIZE));\n\t\tEATEST_VERIFY(fvmv4.has_overflowed());\n\n\t\tfixed_vector<unique_ptr<unsigned int>, FV_SIZE> fvmv5{eastl::move(fvmv4), fvmv4.get_overflow_allocator()};\n\t\tfor (unsigned int i = 0; i <= FV_SIZE; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(!fvmv4[i]);\n\t\t\tEATEST_VERIFY(*fvmv5[i] == i);\n\t\t}\n\t\tEATEST_VERIFY(fvmv5.validate());\n\t\tEATEST_VERIFY(fvmv5.has_overflowed());\n\t}\n\n\t{ // Test that ensures that move ctor that triggers realloc (e.g. > capacity) does so via move code path\n\t\teastl::fixed_vector<TestObject, 1, true> fv1;\n\t\tfv1.push_back(TestObject(0));\n\t\tfv1.push_back(TestObject(0));\n\t\tint64_t copyCtorCount0 = TestObject::sTOCopyCtorCount, moveCtorCount0 = TestObject::sTOMoveCtorCount;\n\t\tdecltype(fv1) fv2 = eastl::move(fv1);\n\t\tEATEST_VERIFY(TestObject::sTOCopyCtorCount == copyCtorCount0 && TestObject::sTOMoveCtorCount == (moveCtorCount0 + 2));\n\t}\n\t{ // Same as above but with custom statefull allocator\n\t\tstruct MyAlloc : public eastl::allocator\n\t\t{\n\t\t\tMyAlloc()=default;\n\t\t\tMyAlloc(int i) : dummy(i) {}\n\t\t\tint dummy;\n\t\t};\n\t\teastl::fixed_vector<TestObject, 1, true, MyAlloc> fv1;\n\t\tfv1.push_back(TestObject(0));\n\t\tfv1.push_back(TestObject(0));\n\t\tint64_t copyCtorCount0 = TestObject::sTOCopyCtorCount, moveCtorCount0 = TestObject::sTOMoveCtorCount;\n\t\tdecltype(fv1) fv2(eastl::move(fv1), MyAlloc(123));\n\t\tEATEST_VERIFY(TestObject::sTOCopyCtorCount == copyCtorCount0 && TestObject::sTOMoveCtorCount == (moveCtorCount0 + 2));\n\t\tEATEST_VERIFY(fv2.get_overflow_allocator().dummy == 123);\n\t}\n\n\t#if defined(EA_COMPILER_CPP17_ENABLED) && __has_include(<variant>)\n\t//Test pairing of std::variant with fixed_vector\n\t{\n\t\teastl::fixed_vector<std::variant<int>, 4> v;\n\t\teastl::fixed_vector<std::variant<int>, 4> b = eastl::move(v);\n\t}\n\t#endif\n\n\t// eastl::erase / eastl::erase_if tests\n\t{\n\t\t{\n\t\t\teastl::fixed_vector<int, 5> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t\tauto numErased = eastl::erase(v, 5);\n\t\t\tVERIFY((v == eastl::fixed_vector<int, 5> {1, 2, 3, 4, 6, 7, 8, 9}));\n\t\t\tVERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(v, 2);\n\t\t\tVERIFY((v == eastl::fixed_vector<int, 5> {1, 3, 4, 6, 7, 8, 9}));\n\t\t\tVERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(v, 9);\n\t\t\tVERIFY((v == eastl::fixed_vector<int, 5> {1, 3, 4, 6, 7, 8}));\n\t\t\tVERIFY(numErased == 1);\n\t\t}\n\n\t\t{\n\t\t\teastl::fixed_vector<int, 15> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tauto numErased = eastl::erase_if(v, [](auto i) { return i % 2 == 0; });\n\t\t\tVERIFY((v == eastl::fixed_vector<int, 15>{1, 3, 5, 7, 9}));\n\t\t\tVERIFY(numErased == 4);\n\t\t}\n\t}\n\n\t// Tests for erase_unordered\n\t{\n\t\t{\n\t\t\teastl::fixed_vector<int, 5> vec = {0, 1, 2, 3};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 1);\n\t\t\tEATEST_VERIFY(numErased == 1);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 3, 2}, \"erase_unordered\") );\n\t\t}\n\t\t{\n\t\t\teastl::fixed_vector<int, 5> vec = {};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 42);\n\t\t\tEATEST_VERIFY(numErased == 0);\n\t\t\tEATEST_VERIFY(vec.size() == 0);\n\t\t}\n\t\t// The following test checks that the correct implementation is called for fixed_vector by checking the order\n\t\t// of the remaining values. It is not a strict requirement that they have this order but it\n\t\t// is expected to be the result based on that it minimizes the amount of work.\n\t\t{\n\t\t\teastl::fixed_vector<int, 5> vec = {0, 1, 2, 3, 1, 5, 6, 1, 8, 9};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 1);\n\t\t\tEATEST_VERIFY(numErased == 3);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 9, 2, 3, 8, 5, 6}, \"erase_unordered\") );\n\t\t}\n\t}\n\n\t// Tests for erase_unordered_if\n\t{\n\t\t{\n\t\t\teastl::fixed_vector<int, 5> vec = {0, 1, 2, 3};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 2);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 2}, \"erase_unordered_if\") );\n\t\t}\n\t\t{\n\t\t\teastl::fixed_vector<int, 5> vec = {};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 0);\n\t\t\tEATEST_VERIFY(vec.size() == 0);\n\t\t}\n\t\t// The following test checks that the correct implementation is called for fixed_vector by checking the order\n\t\t// of the remaining values. It is not a strict requirement that they have this order but it\n\t\t// is expected to be the result based on that it minimizes the amount of work.\n\t\t{\n\t\t\teastl::fixed_vector<int, 5> vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 5);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 8, 2, 6, 4}, \"erase_unordered_if\") );\n\t\t}\n\t}\n\treturn nErrorCount;\n}\n\n"
  },
  {
    "path": "test/source/TestFlags.cpp",
    "content": "#include \"EASTLTest.h\"\n\n#include <EASTL/bonus/flags.h>\n\n\n// we will be directly comparing the mask, bit-by-bit. thus we\n// will need to turn on bits manually, based off a flag value\n#define BIT(flag) (1 << static_cast<std::underlying_type_t<decltype(flag)>>(flag))\n\n// we also need to take a pre-shifted flag to its integral type\n#define MASKBIT(flag) static_cast<std::underlying_type_t<decltype(flag)>>(flag)\n\n\n\n//\n//  begin testing\n//\n\nenum class Wizards : uint64_t { Brilliant, Imbecile, Evil, Blase };\nenum class Knights : uint32_t { Happy, Drunk, Depressed };\nenum class Maidens : uint16_t { Angry = 1, Charismatic = 2, Cheerful = 4, Distressed = 8, LactoseIntolerant = 16 };\n\nEASTL_DECLARE_BITFLAGS_ENUM_CLASS(DragonFlags, Dragons)\n{\n\tEarth, Fire, Wind, Water, Heart\n};\n\nEASTL_DECLARE_BITFLAGS(WizardFlags, Wizards);\n\nEASTL_DECLARE_BITFLAGS(KnightFlags, Knights);\n\nEASTL_DECLARE_MASKFLAGS(MaidenFlags, Maidens);\n\nEASTL_DECLARE_MASKFLAGS_ENUM_CLASS_SIZED(uint8_t, SquireFlags, Squires)\n{\n\tBored = 1, Churlish = 2, Keen = 4\n};\n\n\nstatic void TestFlags_test_static_typetraits()\n{\n\tstatic_assert(std::is_same_v<DragonFlags::mask_type, uint32_t>,\n\t\t\"We'd expect the underlying-type of Dragons (int) to mean the \"\n\t\t\"mask_type of the resulting basic_flags structure is uint32_t \"\n\t\t\"(on LP64/LLP64 data-models)\");\n\n\tstatic_assert(std::is_same_v<WizardFlags::mask_type, uint64_t>,\n\t\t\"We'd expect the underlying-type of Wizards (uint64_t) to also be the \"\n\t\t\"mask_type of the resulting basic_flags structure\");\n\n\tstatic_assert(std::is_same_v<KnightFlags::mask_type, uint32_t>,\n\t\t\"We'd expect the underlying-type of Knights (uint32_t) to also be the \"\n\t\t\"mask_type of the resulting basic_flags structure\");\n\n\tstatic_assert(std::is_same_v<MaidenFlags::mask_type, uint16_t>,\n\t\t\"We'd expect the underlying-type of Maidens (uint16_t) to also be the \"\n\t\t\"mask_type of the resulting basic_flags structure\");\n\n\tstatic_assert(std::is_same_v<SquireFlags::mask_type, uint8_t>,\n\t\t\"We'd expect the underlying-type of Squires (uint8_t) to also be the \"\n\t\t\"mask_type of the resulting basic_flags structure\");\n\n\t// marshaller::to_mask should be resulting in mask_type\n\tstatic_assert(std::is_same_v<SquireFlags::mask_type, decltype(SquireFlags::marshaller_type::to_mask(Squires{}))>,\n\t\t\"basic_flags<>::marshaller_type::to_mask should result in type basic_flags<>::mask_type.\");\n}\n\n\nstatic int TestFlags_bitflags()\n{\n\tint nErrorCount = 0;\n\n\n\t// default construction\n\t{\n\t\tDragonFlags dragons;\n\n\t\tstatic_assert(sizeof(dragons) == sizeof(Dragons),\n\t\t\t\"basic_flags is not precisely the size of its constituent enum\");\n\n\t\t// test implicit conversion to bool (false-case)\n\t\tVERIFY(!dragons);\n\t\t\n\t\tauto mask = eastl::mask_of(dragons);\n\t\tVERIFY(mask == 0);\n\t}\n\n\t// direct construction\n\t{\n\t\tDragonFlags dragons{Dragons::Fire, Dragons::Water};\n\n\t\t// test implicit conversion to bool (true-case)\n\t\tVERIFY(dragons);\n\n\t\tauto mask = eastl::mask_of(dragons);\n\t\tVERIFY(~mask ^ BIT(Dragons::Earth)); //  no\n\t\tVERIFY( mask & BIT(Dragons::Fire));  // yes\n\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\tVERIFY( mask & BIT(Dragons::Water)); // yes\n\t\tVERIFY(~mask ^ BIT(Dragons::Heart)); //  no\n\t}\n\n\t// operator or-assignment\n\t{\n\t\tDragonFlags dragons;\n\t\t\n\t\t// singular value\n\t\tdragons |= Dragons::Fire;\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Earth)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Fire));  // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Heart)); //  no\n\t\t}\n\n\t\t// non-destructive sequential operations\n\t\tdragons |= Dragons::Wind;\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Earth)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Fire));  // yes\n\t\t\tVERIFY( mask & BIT(Dragons::Wind));  // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Heart)); //  no\n\t\t}\n\n\t\t// same value (Fire) again doesn't change anything\n\t\tdragons |= Dragons::Fire;\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Earth)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Fire));  // yes\n\t\t\tVERIFY( mask & BIT(Dragons::Wind));  // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Heart)); //  no\n\t\t}\n\n\t\t// multi-value\n\t\tdragons |= (Dragons::Heart | Dragons::Water);\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Earth)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Fire));  // yes\n\t\t\tVERIFY( mask & BIT(Dragons::Wind));  // yes\n\t\t\tVERIFY( mask & BIT(Dragons::Water)); // yes\n\t\t\tVERIFY( mask & BIT(Dragons::Heart)); // yes\n\t\t}\n\t}\n\n\t// operator and-assignment\n\t{\n\t\tDragonFlags dragons{Dragons::Earth, Dragons::Fire, Dragons::Heart};\n\n\t\t// multi-value\n\t\tdragons &= (Dragons::Earth | Dragons::Heart);\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY( mask & BIT(Dragons::Earth)); // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Fire));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Heart)); // yes\n\t\t}\n\n\t\t// repeated operation performs no change\n\t\tdragons &= (Dragons::Earth | Dragons::Heart);\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY( mask & BIT(Dragons::Earth)); // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Fire));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Heart)); // yes\n\t\t}\n\n\t\t// singular value\n\t\tdragons &= Dragons::Earth;\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY( mask & BIT(Dragons::Earth)); // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Fire));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Heart)); //  no\n\t\t}\n\n\t\t// non-seen value doesn't get flipped\n\t\tdragons &= Dragons::Heart;\n\t\t{\n\t\t\tVERIFY(!dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Earth)); //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Fire));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Heart)); //  no\n\t\t}\n\t}\n\n\t// operator xor-assignment\n\t{\n\t\tDragonFlags dragons{Dragons::Earth, Dragons::Fire, Dragons::Heart};\n\n\t\t// multi-value\n\t\tdragons ^= (Dragons::Earth | Dragons::Water);\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Earth)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Fire));  // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Water)); // yes\n\t\t\tVERIFY( mask & BIT(Dragons::Heart)); // yes\n\t\t}\n\n\t\t// repeated value flips flags\n\t\tdragons ^= (Dragons::Earth | Dragons::Water);\n\t\t{\n\t\t\tVERIFY(dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY( mask & BIT(Dragons::Earth)); // yes\n\t\t\tVERIFY( mask & BIT(Dragons::Fire));  // yes\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Wind));  //  no\n\t\t\tVERIFY(~mask ^ BIT(Dragons::Water)); //  no\n\t\t\tVERIFY( mask & BIT(Dragons::Heart)); // yes\n\t\t}\n\n\t\t// xor us to zero\n\t\tdragons ^= DragonFlags{dragons};\n\t\t{\n\t\t\tVERIFY(!dragons);\n\n\t\t\tauto mask = eastl::mask_of(dragons);\n\t\t\tVERIFY(mask == 0);\n\t\t}\n\t}\n\n\t// nonmember and-operator\n\t{\n\t\tKnightFlags knights{Knights::Happy, Knights::Drunk};\n\n\t\t// rhs is a flag\n\t\tauto happiness = knights & Knights::Happy;\n\t\tauto drunkeness = knights & Knights::Drunk;\n\t\tauto depression = knights & Knights::Depressed;\n\t\tstatic_assert(std::is_same_v<decltype(happiness), decltype(knights)>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\t\t\n\t\t// rhs is basic_flags\n\t\tauto confused = knights & (Knights::Happy | Knights::Depressed);\n\t\tstatic_assert(std::is_same_v<decltype(confused), decltype(knights)>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\n\t\tVERIFY(happiness);\n\t\tVERIFY(drunkeness);\n\t\tVERIFY(!depression);\n\n\t\t// verify and-operator was non-destructive\n\t\t{\n\t\t\tauto mask = eastl::mask_of(knights);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY( mask & BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\n\t\t// verify each of our resultant flags\n\t\t{\n\t\t\tauto mask = eastl::mask_of(happiness);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(drunkeness);\n\t\t\tVERIFY(~mask ^ BIT(Knights::Happy));\n\t\t\tVERIFY( mask & BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(depression);\n\t\t\tVERIFY(~mask ^ BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(confused);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t}\n\n\t// nonmember or-operator\n\t{\n\t\tKnightFlags knights{Knights::Happy};\n\n\t\t// rhs is a flag\n\t\tauto happiness = (knights | Knights::Happy);\n\t\tauto drunkeness = (knights | Knights::Drunk);\n\t\tauto depression = (knights | Knights::Depressed);\n\t\tstatic_assert(std::is_same_v<decltype(happiness), decltype(knights)>,\n\t\t\t\"operator 'or' should result in a flags structure\");\n\n\t\t// rhs is basic_flags\n\t\tauto confused = knights | (Knights::Happy | Knights::Depressed);\n\t\tstatic_assert(std::is_same_v<decltype(confused), decltype(knights)>,\n\t\t\t\"operator 'or' should result in a flags structure\");\n\n\t\tVERIFY(happiness);\n\t\tVERIFY(drunkeness);\n\t\tVERIFY(depression);\n\t\tVERIFY(confused);\n\n\t\t// verify and-operator was non-destructive\n\t\t{\n\t\t\tauto mask = eastl::mask_of(knights);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\n\t\t// verify each of our resultant flags\n\t\t{\n\t\t\tauto mask = eastl::mask_of(happiness);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(drunkeness);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY( mask & BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(depression);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY( mask & BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(confused);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY( mask & BIT(Knights::Depressed));\n\t\t}\n\t}\n\n\t// nonmember xor-operator\n\t{\n\t\tKnightFlags knights{Knights::Happy};\n\n\t\t// rhs is a flag\n\t\tauto happiness = (knights ^ Knights::Happy);\n\t\tauto drunkeness = (knights ^ Knights::Drunk);\n\t\tauto depression = (knights ^ Knights::Depressed);\n\t\tstatic_assert(std::is_same_v<decltype(happiness), decltype(knights)>,\n\t\t\t\"operator 'xor' should result in a flags structure\");\n\n\t\t// rhs is basic_flags\n\t\tauto confused = knights ^ (Knights::Happy | Knights::Depressed);\n\t\tstatic_assert(std::is_same_v<decltype(confused), decltype(knights)>,\n\t\t\t\"operator 'xor' should result in a flags structure\");\n\n\t\tVERIFY(!happiness);\n\t\tVERIFY(drunkeness);\n\t\tVERIFY(depression);\n\t\tVERIFY(confused);\n\n\t\t// verify and-operator was non-destructive\n\t\t{\n\t\t\tauto mask = eastl::mask_of(knights);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\n\t\t// verify each of our resultant flags\n\t\t{\n\t\t\tauto mask = eastl::mask_of(happiness);\n\t\t\tVERIFY(~mask ^ BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(drunkeness);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY( mask & BIT(Knights::Drunk));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(depression);\n\t\t\tVERIFY( mask & BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY( mask & BIT(Knights::Depressed));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(confused);\n\t\t\tVERIFY(~mask ^ BIT(Knights::Happy));\n\t\t\tVERIFY(~mask ^ BIT(Knights::Drunk));\n\t\t\tVERIFY( mask & BIT(Knights::Depressed));\n\t\t}\n\t}\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nstatic int TestFlags_maskflags()\n{\n\tint nErrorCount = 0;\n\n\t// default construction\n\t{\n\t\tMaidenFlags maidens;\n\n\t\tstatic_assert(sizeof(maidens) == sizeof(Maidens),\n\t\t\t\"basic_flags is not precisely the size of its constituent enum\");\n\n\t\t// test implicit conversion to bool (false-case)\n\t\tVERIFY(!maidens);\n\t\t\n\t\tauto mask = eastl::mask_of(maidens);\n\t\tVERIFY(mask == 0);\n\t}\n\n\t// direct construction\n\t{\n\t\tMaidenFlags maidens{Maidens::Charismatic, Maidens::Cheerful};\n\n\t\t// test implicit conversion to bool (true-case)\n\t\tVERIFY(maidens);\n\n\t\tauto mask = eastl::mask_of(maidens);\n\t\tVERIFY(~mask ^ MASKBIT(Maidens::Angry));\n\t\tVERIFY( mask & MASKBIT(Maidens::Charismatic));\n\t\tVERIFY( mask & MASKBIT(Maidens::Cheerful));\n\t\tVERIFY(~mask ^ MASKBIT(Maidens::Distressed));\n\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t}\n\n\t\n\t// operator or-assignment\n\t{\n\t\tMaidenFlags maidens;\n\t\t\n\t\t// singular value\n\t\tmaidens |= Maidens::Charismatic;\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Angry));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// non-destructive sequential operations\n\t\tmaidens |= Maidens::Distressed;\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Angry));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// same value (Charismatic) again doesn't change anything\n\t\tmaidens |= Maidens::Charismatic;\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Angry));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// multi-value\n\t\tmaidens |= (Maidens::Angry | Maidens::Distressed);\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Angry));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\t}\n\n\t// operator and-assignment\n\t{\n\t\tMaidenFlags maidens{Maidens::Angry, Maidens::Cheerful, Maidens::LactoseIntolerant};\n\t\t\n\t\t// multi-value\n\t\tmaidens &= (Maidens::Angry | Maidens::Cheerful);\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Angry));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// repeated operation performs no change\n\t\tmaidens &= (Maidens::Angry | Maidens::Cheerful);\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Angry));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// singular value\n\t\tmaidens &= Maidens::Cheerful;\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Angry));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// non-seen value doesn't get flipped\n\t\tmaidens &= Maidens::Distressed;\n\t\t{\n\t\t\tVERIFY(!maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Angry));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\t}\n\n\t// operator xor-assignment\n\t{\n\t\tMaidenFlags maidens{Maidens::Angry, Maidens::Charismatic, Maidens::LactoseIntolerant};\n\n\t\t// multi-value\n\t\tmaidens ^= (Maidens::Charismatic | Maidens::Distressed);\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Angry));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// repeated value flips flags\n\t\tmaidens ^= (Maidens::Charismatic | Maidens::Distressed);\n\t\t{\n\t\t\tVERIFY(maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Angry));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::Charismatic));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Cheerful));\n\t\t\tVERIFY(~mask ^ MASKBIT(Maidens::Distressed));\n\t\t\tVERIFY( mask & MASKBIT(Maidens::LactoseIntolerant));\n\t\t}\n\n\t\t// xor us to zero\n\t\tmaidens ^= MaidenFlags{maidens};\n\t\t{\n\t\t\tVERIFY(!maidens);\n\n\t\t\tauto mask = eastl::mask_of(maidens);\n\t\t\tVERIFY(mask == 0);\n\t\t}\n\t}\n\n\n\t// nonmember or-operator\n\t{\n\t\tSquireFlags const squires{Squires::Bored, Squires::Churlish};\n\n\t\t// rhs is a flag\n\t\tauto boredom = squires | Squires::Bored;\n\t\tauto beligerence = squires | Squires::Churlish;\n\t\tauto excitement = squires | Squires::Keen;\n\t\tstatic_assert(std::is_same_v<decltype(boredom), std::remove_const_t<decltype(squires)>>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\t\t\n\t\t// rhs is basic_flags\n\t\tauto anticipation = squires | (Squires::Bored | Squires::Keen);\n\t\tstatic_assert(std::is_same_v<decltype(anticipation), std::remove_const_t<decltype(squires)>>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\n\t\tVERIFY(boredom);\n\t\tVERIFY(beligerence);\n\t\tVERIFY(excitement);\n\t\tVERIFY(anticipation);\n\n\t\t// verify and-operator was non-destructive\n\t\t{\n\t\t\tauto mask = eastl::mask_of(squires);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\n\t\t// verify each of our resultant flags\n\t\t{\n\t\t\tauto mask = eastl::mask_of(boredom);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(beligerence);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(excitement);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(anticipation);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Keen));\n\t\t}\n\t}\n\t\n\t// nonmember and-operator\n\t{\n\t\tSquireFlags const squires{Squires::Bored, Squires::Churlish};\n\n\t\t// rhs is a flag\n\t\tauto boredom = squires & Squires::Bored;\n\t\tauto beligerence = squires & Squires::Churlish;\n\t\tauto excitement = squires & Squires::Keen;\n\t\tstatic_assert(std::is_same_v<decltype(boredom), std::remove_const_t<decltype(squires)>>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\t\t\n\t\t// rhs is basic_flags\n\t\tauto anticipation = squires & (Squires::Bored | Squires::Keen);\n\t\tstatic_assert(std::is_same_v<decltype(anticipation), std::remove_const_t<decltype(squires)>>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\n\t\tVERIFY(boredom);\n\t\tVERIFY(beligerence);\n\t\tVERIFY(!excitement);\n\n\t\t// verify and-operator was non-destructive\n\t\t{\n\t\t\tauto mask = eastl::mask_of(squires);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\n\t\t// verify each of our resultant flags\n\t\t{\n\t\t\tauto mask = eastl::mask_of(boredom);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(beligerence);\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(excitement);\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Bored));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(anticipation);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t}\n\n\t// nonmember xor-operator\n\t{\n\t\tSquireFlags const squires{Squires::Bored, Squires::Churlish};\n\n\t\t// rhs is a flag\n\t\tauto boredom = squires ^ Squires::Bored;\n\t\tauto beligerence = squires ^ Squires::Churlish;\n\t\tauto excitement = squires ^ Squires::Keen;\n\t\tstatic_assert(std::is_same_v<decltype(boredom), std::remove_const_t<decltype(squires)>>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\t\t\n\t\t// rhs is basic_flags\n\t\tauto anticipation = squires ^ (Squires::Bored | Squires::Keen);\n\t\tstatic_assert(std::is_same_v<decltype(anticipation), std::remove_const_t<decltype(squires)>>,\n\t\t\t\"operator 'and' should result in a flags structure\");\n\n\t\tVERIFY(boredom);\n\t\tVERIFY(beligerence);\n\t\tVERIFY(excitement);\n\n\t\t// verify and-operator was non-destructive\n\t\t{\n\t\t\tauto mask = eastl::mask_of(squires);\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\n\t\t// verify each of our resultant flags\n\t\t{\n\t\t\tauto mask = eastl::mask_of(boredom);\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(beligerence);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Churlish));\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(excitement);\n\t\t\tVERIFY( mask & MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Keen));\n\t\t}\n\t\t{\n\t\t\tauto mask = eastl::mask_of(anticipation);\n\t\t\tVERIFY(~mask ^ MASKBIT(Squires::Bored));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Churlish));\n\t\t\tVERIFY( mask & MASKBIT(Squires::Keen));\n\t\t}\n\t}\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n//\n// very quickly test namespace-style enums. if it compiles then\n// the behaviour is identical to the very-tested enum classes above\n//\n\nnamespace Colours\n{\n\tenum Enum\n\t{\n\t\tRed = 1, Green = 2, Blue = 4,\n\t\tCyan = Blue | Green,\n\t\tYellow = Green | Red,\n\t\tMagenta = Red | Blue,\n\t\tWhite = Blue | Green | Red\n\t};\n}\n\n// test macro with namespace-style enums\nEASTL_DECLARE_MASKFLAGS(ColourFlags, Colours::Enum);\n\nstatic int TestFlags_namespace_style_enums()\n{\n\tint nErrorCount = 0;\n\n\n\t// set\n\t{\n\t\tColourFlags flags;\n\t\tflags.set(Colours::Red);\n\t\tflags.set(Colours::Green);\n\n\t\tVERIFY(eastl::mask_of(flags) == MASKBIT(Colours::Yellow));\n\t}\n\t// set(_, false)\n\t{\n\t\tColourFlags flags{Colours::Red, Colours::Green};\n\n\t\tflags.set(Colours::Green, false);\n\t\tVERIFY(eastl::mask_of(flags) == MASKBIT(Colours::Red));\n\n\t\tflags.set(Colours::Green, true);\n\t\tVERIFY(eastl::mask_of(flags) == (MASKBIT(Colours::Red) | MASKBIT(Colours::Green)));\n\t}\n\t// unset\n\t{\n\t\tColourFlags flags{Colours::Red, Colours::Green};\n\t\tflags.unset(Colours::Green);\n\n\t\tVERIFY(eastl::mask_of(flags) == MASKBIT(Colours::Red));\n\t}\n\t// toggle\n\t{\n\t\tColourFlags flags{Colours::Red, Colours::Green};\n\t\tflags.toggle(Colours::Green)\n\t\t\t.toggle(Colours::Blue);\n\n\t\tVERIFY(eastl::mask_of(flags) == MASKBIT(Colours::Magenta));\n\t}\n\n\n\t// assignment operator\n\t{\n\t\tColourFlags flags{Colours::Red, Colours::Green};\n\t\tflags = Colours::Blue;\n\n\t\tVERIFY(eastl::mask_of(flags) == MASKBIT(Colours::Blue));\n\t}\n\t// assignment operator for basic_flags\n\t{\n\t\tColourFlags flags{Colours::Red, Colours::Green};\n\t\tColourFlags flags2{Colours::Blue};\n\t\tflags = flags2;\n\n\t\tVERIFY(eastl::mask_of(flags) == MASKBIT(Colours::Blue));\n\t}\n\n\n\t// bitwise not\n\t{\n\t\tColourFlags flags{Colours::Red, Colours::Green};\n\t\tauto flags2 = ~flags;\n\n\t\tVERIFY((eastl::mask_of(flags2) & eastl::mask_of(Colours::Red | Colours::Green)) == 0);\n\t}\n\n\n\t// comparison operators\n\t{\n\t\t// equality flags <-> flags\n\t\t{\n\t\t\tColourFlags flags{Colours::Red, Colours::Green};\n\t\t\tColourFlags flags2{Colours::Red, Colours::Green};\n\t\t\tVERIFY(flags == flags2);\n\t\t}\n\t\t// equality flags <-> enum\n\t\t{\n\t\t\tColourFlags flags{Colours::Red};\n\t\t\tVERIFY(flags == Colours::Red);\n\t\t}\n\t\t// equality enum <-> flags\n\t\t{\n\t\t\tColourFlags flags{Colours::Red};\n\t\t\tVERIFY(Colours::Red == flags);\n\t\t}\n\n\t\t// inequality flags <-> flags\n\t\t{\n\t\t\tColourFlags flags{Colours::Red, Colours::Green};\n\t\t\tColourFlags flags2{Colours::Blue};\n\t\t\tVERIFY(flags != flags2);\n\t\t}\n\t\t// inequality flags <-> enum\n\t\t{\n\t\t\tColourFlags flags{Colours::Red};\n\t\t\tVERIFY(flags != Colours::Green);\n\t\t}\n\t\t// inequality enum <-> flags\n\t\t{\n\t\t\tColourFlags flags{Colours::Red};\n\t\t\tVERIFY(Colours::Green != flags);\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestFlags()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestFlags_bitflags();\n\tnErrorCount += TestFlags_maskflags();\n\tnErrorCount\t+= TestFlags_namespace_style_enums();\n\n\tTestFlags_test_static_typetraits();\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestFunctional.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EABase/eabase.h>\n#include <EAAssert/eaassert.h>\n#include \"EASTLTest.h\"\n#include <EASTL/memory.h>\n#include <EASTL/functional.h>\n#include <EASTL/hash_set.h>\n#include <EASTL/set.h>\n#include <EASTL/list.h>\n#include <EASTL/type_traits.h>\n#include <EAStdC/EAString.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <functional>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4512 4626);\n\nnamespace\n{\n\n\t// Used for eastl::function tests\n\tstatic int TestIntRet(int* p)\n\t{\n\t\tint ret = *p;\n\t\t*p += 1;\n\t\treturn ret;\n\t}\n\n\t// Used for str_less tests below.\n\ttemplate <typename T>\n\tstruct Results\n\t{\n\t\tconst T* p1;\n\t\tconst T* p2;\n\t\tbool     expectedResult; // The expected result of the expression (p1 < p2)\n\t};\n\n\n\t// Used for mem_fn tests below.\n\tstruct TestClass\n\t{\n\t\tmutable int mX;\n\n\t\tTestClass() : mX(37) { }\n\n\t\tvoid Increment()\n\t\t{\n\t\t\tmX++;\n\t\t}\n\n\t\tvoid IncrementConst() const\n\t\t{\n\t\t\tmX++;\n\t\t}\n\n\t\tint MultiplyBy(int x)\n\t\t{\n\t\t\treturn mX * x;\n\t\t}\n\n\t\tint MultiplyByConst(int x) const\n\t\t{\n\t\t\treturn mX * x;\n\t\t}\n\t};\n}\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntypedef eastl::basic_string<char8_t,  MallocAllocator> String8MA;\ntypedef eastl::basic_string<char16_t, MallocAllocator> String16MA;\n\ntemplate struct eastl::string_hash<String8MA>;\ntemplate struct eastl::string_hash<String16MA>;\n\ntemplate class eastl::hash_set<String8MA,  eastl::string_hash<String8MA> >;\ntemplate class eastl::hash_set<String16MA, eastl::string_hash<String16MA> >;\n\n\n// Helper function for testing our default hash implementations for pod types which\n// simply returns the static_cast<size_t> of the val passed in\ntemplate<typename T>\nint TestHashHelper(T val)\n{\n\tint nErrorCount = 0;\n\n\tif (!std::is_floating_point_v<T>)\n\t{\n\t\t// Default hash implementation for floating-point types is not static_cast<size_t>\n\t\tEATEST_VERIFY(eastl::hash<T>()(val) == static_cast<size_t>(val));\n\t}\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestFunctional\n//\nint TestFunctional()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\t// str_equal_to\n\t\tchar p0[] = \"\";\n\t\tchar p1[] = \"hello\";\n\t\tchar p2[] = \"world\";\n\t\tchar p3[] = \"helllllo\";\n\t\tchar p4[] = \"hello\"; // Intentionally the same value as p1.\n\n\t\t// str_equal_to\n\t\ttypedef hash_set<const char*, hash<const char*>, str_equal_to<const char*> > StringHashSet;\n\t\tStringHashSet shs;\n\n\t\tshs.insert(p1);\n\t\tshs.insert(p2);\n\t\tshs.insert(p3);\n\n\t\tStringHashSet::iterator it = shs.find(p0);\n\t\tEATEST_VERIFY(it == shs.end());\n\n\t\tit = shs.find(p1);\n\t\tEATEST_VERIFY(it != shs.end());\n\n\t\tit = shs.find(p2);\n\t\tEATEST_VERIFY(it != shs.end());\n\n\t\tit = shs.find(p4);\n\t\tEATEST_VERIFY(it != shs.end());\n\t}\n\n\t{\n\t\t// str_less<const char8_t*>\n\t\tResults<char> results8[] =\n\t\t{\n\t\t\t{      \"\",          \"\", false },\n\t\t\t{      \"\",         \"a\",  true },\n\t\t\t{      \"a\",         \"\", false },\n\t\t\t{      \"a\",        \"a\", false },\n\t\t\t{      \"a\",        \"b\",  true },\n\t\t\t{  \"____a\",    \"____a\", false },\n\t\t\t{  \"____a\",    \"____b\",  true },\n\t\t\t{  \"____b\",    \"____a\", false },\n\t\t\t{  \"_\\xff\",       \"_a\", false },    // Test high values, which exercises the signed/unsiged comparison behavior.\n\t\t\t{     \"_a\",    \"_\\xff\",  true }\n\t\t};\n\n\t\tstr_less<const char*> sl8;\n\t\tfor(size_t i = 0; i < EAArrayCount(results8); i++)\n\t\t{\n\t\t\t// Verify that our test is in line with the strcmp function.\n\t\t\tbool bResult = (EA::StdC::Strcmp(results8[i].p1, results8[i].p2) < 0);\n\t\t\tEATEST_VERIFY_F(bResult == results8[i].expectedResult, \"Strcmp failure, test %zu. Expected \\\"%s\\\" to be %sless than \\\"%s\\\"\", i, results8[i].p1, results8[i].expectedResult ? \"\" : \"not \", results8[i].p2);\n\n\t\t\t// Verify that str_less achieves the expected results.\n\t\t\tbResult = sl8(results8[i].p1, results8[i].p2);\n\t\t\tEATEST_VERIFY_F(bResult == results8[i].expectedResult, \"str_less test failure, test %zu. Expected \\\"%s\\\" to be %sless than \\\"%s\\\"\", i, results8[i].p1, results8[i].expectedResult ? \"\" : \"not \", results8[i].p2);\n\t\t}\n\n\t\t// str_less<const wchar_t*>\n\t\tResults<wchar_t> resultsW[] =\n\t\t{\n\t\t\t{        L\"\",            L\"\", false },\n\t\t\t{        L\"\",           L\"a\",  true },\n\t\t\t{        L\"a\",           L\"\", false },\n\t\t\t{        L\"a\",          L\"a\", false },\n\t\t\t{        L\"a\",          L\"b\",  true },\n\t\t\t{    L\"____a\",      L\"____a\", false },\n\t\t\t{    L\"____a\",      L\"____b\",  true },\n\t\t\t{    L\"____b\",      L\"____a\", false },\n\t\t\t{  L\"_\\xffff\",         L\"_a\", false },   // Test high values, which exercises the signed/unsiged comparison behavior.\n\t\t\t{       L\"_a\",    L\"_\\xffff\",  true }\n\t\t};\n\n\t\tstr_less<const wchar_t*> slW;\n\t\tfor(size_t i = 0; i < EAArrayCount(resultsW); i++)\n\t\t{\n\t\t\t// Verify that our test is in line with the strcmp function.\n\t\t\tbool bResult = (EA::StdC::Strcmp(resultsW[i].p1, resultsW[i].p2) < 0);\n\t\t\tEATEST_VERIFY_F(bResult == resultsW[i].expectedResult, \"Strcmp failure, test %zu. Expected \\\"%s\\\" to be %sless than \\\"%s\\\"\", i, results8[i].p1, results8[i].expectedResult ? \"\" : \"not \", results8[i].p2);\n\n\t\t\t// Verify that str_less achieves the expected results.\n\t\t\tbResult = slW(resultsW[i].p1, resultsW[i].p2);\n\t\t\tEATEST_VERIFY_F(bResult == resultsW[i].expectedResult, \"str_less test failure, test %zu. Expected \\\"%ls\\\" to be %sless than \\\"%ls\\\"\", i, resultsW[i].p1, resultsW[i].expectedResult ? \"\" : \"not \", resultsW[i].p2);\n\t\t}\n\t}\n\n\t{\n\t\t// str_less\n\t\tchar p0[] = \"\";\n\t\tchar p1[] = \"hello\";\n\t\tchar p2[] = \"world\";\n\t\tchar p3[] = \"helllllo\";\n\t\tchar p4[] = \"hello\"; // Intentionally the same value as p1.\n\n\t\ttypedef set<const char*, str_less<const char*> > StringSet;\n\t\tStringSet ss;\n\n\t\tss.insert(p1);\n\t\tss.insert(p2);\n\t\tss.insert(p3);\n\n\t\tStringSet::iterator it = ss.find(p0);\n\t\tEATEST_VERIFY(it == ss.end());\n\n\t\tit = ss.find(p1);\n\t\tEATEST_VERIFY(it != ss.end());\n\n\t\tit = ss.find(p2);\n\t\tEATEST_VERIFY(it != ss.end());\n\n\t\tit = ss.find(p4);\n\t\tEATEST_VERIFY(it != ss.end());\n\t}\n\n\n\t{\n\t\t// mem_fn (no argument version)\n\t\tTestClass  tc0, tc1, tc2;\n\t\tTestClass* tcArray[3] = { &tc0, &tc1, &tc2 };\n\n\t\tfor_each(tcArray, tcArray + 3, mem_fn(&TestClass::Increment));\n\t\tEATEST_VERIFY((tc0.mX == 38) && (tc1.mX == 38) && (tc2.mX == 38));\n\n\t\tfor_each(tcArray, tcArray + 3, mem_fn(&TestClass::IncrementConst));\n\t\tEATEST_VERIFY((tc0.mX == 39) && (tc1.mX == 39) && (tc2.mX == 39));\n\t}\n\n\n\t{\n\t\t// mem_fn (one argument version)\n\t\tTestClass  tc0, tc1, tc2;\n\t\tTestClass* tcArray[3]  = { &tc0, &tc1, &tc2 };\n\t\tint        intArray1[3] = { -1,  0,  2 };\n\t\tint        intArray2[3] = { -9, -9, -9 };\n\n\t\ttransform(tcArray, tcArray + 3, intArray1, intArray2, mem_fn(&TestClass::MultiplyBy));\n\t\tEATEST_VERIFY((intArray2[0] == -37) && (intArray2[1] == 0) && (intArray2[2] == 74));\n\n\t\tintArray2[0] = intArray2[1] = intArray2[2] = -9;\n\t\ttransform(tcArray, tcArray + 3, intArray1, intArray2, mem_fn(&TestClass::MultiplyByConst));\n\t\tEATEST_VERIFY((intArray2[0] == -37) && (intArray2[1] == 0) && (intArray2[2] == 74));\n\t}\n\n\n\t{\n\t\t// mem_fn (no argument version)\n\t\tTestClass tcArray[3];\n\n\t\tfor_each(tcArray, tcArray + 3, mem_fn(&TestClass::Increment));\n\t\tEATEST_VERIFY((tcArray[0].mX == 38) && (tcArray[1].mX == 38) && (tcArray[2].mX == 38));\n\n\t\tfor_each(tcArray, tcArray + 3, mem_fn(&TestClass::IncrementConst));\n\t\tEATEST_VERIFY((tcArray[0].mX == 39) && (tcArray[1].mX == 39) && (tcArray[2].mX == 39));\n\t}\n\n\n\t{\n\t\t// mem_fn (one argument version)\n\t\tTestClass tcArray[3];\n\t\tint       intArray1[3] = { -1,  0,  2 };\n\t\tint       intArray2[3] = { -9, -9, -9 };\n\n\t\ttransform(tcArray, tcArray + 3, intArray1, intArray2, mem_fn(&TestClass::MultiplyBy));\n\t\tEATEST_VERIFY((intArray2[0] == -37) && (intArray2[1] == 0) && (intArray2[2] == 74));\n\n\t\tintArray2[0] = intArray2[1] = intArray2[2] = -9;\n\t\ttransform(tcArray, tcArray + 3, intArray1, intArray2, mem_fn(&TestClass::MultiplyByConst));\n\t\tEATEST_VERIFY((intArray2[0] == -37) && (intArray2[1] == 0) && (intArray2[2] == 74));\n\t}\n\n\n\t{\n\t\t// Template instantations.\n\t\t// These tell the compiler to compile all the functions for the given class.\n\t\teastl::hash_set<String8MA,  eastl::string_hash<String8MA> >  hs8;\n\t\teastl::hash_set<String16MA, eastl::string_hash<String16MA> > hs16;\n\n\t\tEATEST_VERIFY(hs8.empty());\n\t\tEATEST_VERIFY(hs16.empty());\n\t}\n\n\t{\n\t\tnErrorCount += TestHashHelper<int>(4330);\n\t\tnErrorCount += TestHashHelper<bool>(true);\n\t\tnErrorCount += TestHashHelper<char>('E');\n\t\tnErrorCount += TestHashHelper<signed char>('E');\n\t\tnErrorCount += TestHashHelper<unsigned char>('E');\n\t\tnErrorCount += TestHashHelper<char8_t>('E');\n\t\tnErrorCount += TestHashHelper<char16_t>(0xEAEA);\n\t\tnErrorCount += TestHashHelper<char32_t>(0x00EA4330);\n\t\t#if !defined(EA_WCHAR_T_NON_NATIVE)\n\t\t\tnErrorCount += TestHashHelper<wchar_t>(L'E');\n\t\t#endif\n\t\tnErrorCount += TestHashHelper<signed short>(4330);\n\t\tnErrorCount += TestHashHelper<unsigned short>(4330u);\n\t\tnErrorCount += TestHashHelper<signed int>(4330);\n\t\tnErrorCount += TestHashHelper<unsigned int>(4330u);\n\t\tnErrorCount += TestHashHelper<signed long>(4330l);\n\t\tnErrorCount += TestHashHelper<unsigned long>(4330ul);\n\t\tnErrorCount += TestHashHelper<signed long long>(4330ll);\n\t\tnErrorCount += TestHashHelper<unsigned long long>(4330ll);\n\t\tnErrorCount += TestHashHelper<float>(4330.099999f);\n\t\tnErrorCount += TestHashHelper<double>(4330.055);\n\t\tnErrorCount += TestHashHelper<long double>(4330.0654l);\n\n\t\t{\n\t\t\tenum hash_enum_test { e1, e2, e3 };\n\t\t\tnErrorCount += TestHashHelper<hash_enum_test>(e1);\n\t\t\tnErrorCount += TestHashHelper<hash_enum_test>(e2);\n\t\t\tnErrorCount += TestHashHelper<hash_enum_test>(e3);\n\t\t}\n\t}\n\n\n#if defined(EA_COMPILER_CPP11_ENABLED) && EASTL_VARIADIC_TEMPLATES_ENABLED\n\t// On platforms do not support variadic templates the eastl::invoke (eastl::mem_fn is built on eastl::invoke)\n\t// implementation is extremely basic and does not hold up.  A significant amount of code would have to be written\n\t// and I don't believe the investment is justified at this point.  If you require this functionality on older\n\t// compilers please contact us.\n\t//\n\n\t// eastl::invoke\n\t{\n\t\tstruct TestStruct\n\t\t{\n\t\t\tTestStruct(int inValue) : value(inValue) {}\n\t\t\tvoid Add(int addAmount) { value += addAmount; }\n\t\t\tint GetValue() { return value; }\n\t\t\tint& GetValueReference() { return value; }\n\t\t\tvoid NoThrow(int) EA_NOEXCEPT {}\n\t\t\tint value;\n\t\t};\n\n\t\tstruct TestFunctor\n\t\t{\n\t\t\tvoid operator()() { called = true; }\n\t\t\tbool called = false;\n\t\t};\n\n\t\tstruct TestFunctorNoThrow\n\t\t{\n\t\t\tvoid operator()() EA_NOEXCEPT { called = true; }\n\t\t\tbool called = false;\n\t\t};\n\n\t\tstruct TestFunctorArguments\n\t\t{\n\t\t\tvoid operator()(int i) { value = i; }\n\t\t\tint value = 0;\n\t\t};\n\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\teastl::invoke(&TestStruct::Add, a, 10);\n\t\t\tEATEST_VERIFY(a.value == 52);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::Add), TestStruct, int>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::Add), TestStruct, int>::value, \"incorrect value for is_invocable\");\n\t\t\tstatic_assert(eastl::is_nothrow_invocable<decltype(&TestStruct::NoThrow), TestStruct, int>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t\tstatic_assert(!eastl::is_nothrow_invocable<decltype(&TestStruct::Add), TestStruct, int>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\teastl::invoke(&TestStruct::Add, &a, 10);\n\t\t\tEATEST_VERIFY(a.value == 52);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::Add), TestStruct *, int>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::Add), TestStruct *, int>::value, \"incorrect value for is_invocable\");\n\t\t\tstatic_assert(eastl::is_nothrow_invocable<decltype(&TestStruct::NoThrow), TestStruct *, int>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t\tstatic_assert(!eastl::is_nothrow_invocable<decltype(&TestStruct::Add), TestStruct *, int>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\teastl::reference_wrapper<TestStruct> r(a);\n\t\t\teastl::invoke(&TestStruct::Add, r, 10);\n\t\t\tEATEST_VERIFY(a.value == 52);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::Add), eastl::reference_wrapper<TestStruct>, int>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::Add), eastl::reference_wrapper<TestStruct>, int>::value, \"incorrect value for is_invocable\");\n\t\t\tstatic_assert(eastl::is_nothrow_invocable<decltype(&TestStruct::NoThrow), eastl::reference_wrapper<TestStruct>, int>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t\tstatic_assert(!eastl::is_nothrow_invocable<decltype(&TestStruct::Add), eastl::reference_wrapper<TestStruct>, int>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\teastl::invoke(&TestStruct::GetValueReference, a) = 43;\n\t\t\tEATEST_VERIFY(a.value == 43);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::GetValueReference), TestStruct &>::type, int &>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::GetValueReference), TestStruct &>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\tEATEST_VERIFY(eastl::invoke(&TestStruct::value, a) == 42);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::value), TestStruct &>::type, int &>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::value), TestStruct &>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\teastl::invoke(&TestStruct::value, a) = 43;\n\t\t\tEATEST_VERIFY(a.value == 43);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::value), TestStruct &>::type, int &>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::value), TestStruct &>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\teastl::invoke(&TestStruct::value, &a) = 43;\n\t\t\tEATEST_VERIFY(a.value == 43);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::value), TestStruct *>::type, int &>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::value), TestStruct *>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\teastl::reference_wrapper<TestStruct> r(a);\n\t\t\teastl::invoke(&TestStruct::value, r) = 43;\n\t\t\tEATEST_VERIFY(a.value == 43);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::value), eastl::reference_wrapper<TestStruct>>::type, int &>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::GetValue), eastl::reference_wrapper<TestStruct>>::value, \"incorrect value for is_invocable\");\n\t\t}\n\n\t\t#ifndef EA_COMPILER_GNUC\n\t\t{\n\t\t\tTestStruct a(42);\n\t\t\tEATEST_VERIFY(eastl::invoke(&TestStruct::GetValue, a) == 42);\n\n\t\t\tstatic_assert(\n\t\t\t    eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::GetValue), TestStruct*>::type, int>::value,\n\t\t\t    \"incorrect type for invoke_result\");\n\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestStruct::GetValue), TestStruct*>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t#endif\n\t\t{\n\t\t\tTestFunctor f;\n\t\t\teastl::invoke(f);\n\t\t\tEATEST_VERIFY(f.called);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(f)>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(f)>::value, \"incorrect value for is_invocable\");\n\t\t\tstatic_assert(!eastl::is_nothrow_invocable<decltype(f)>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestFunctorNoThrow f;\n\t\t\teastl::invoke(f);\n\t\t\tEATEST_VERIFY(f.called);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(f)>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(f)>::value, \"incorrect value for is_invocable\");\n\t\t\tstatic_assert(eastl::is_nothrow_invocable<decltype(f)>::value, \"incorrect value for is_nothrow_invocable\");\n\t\t}\n\t\t{\n\t\t\tTestFunctorArguments f;\n\t\t\teastl::invoke(f, 42);\n\t\t\tEATEST_VERIFY(f.value == 42);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(f), int>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(f), int>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tstruct TestInvokeConstAccess\n\t\t\t{\n\t\t\t\tvoid ConstMemberFunc(int) const {}\n\t\t\t\tvoid ConstVolatileMemberFunc(int) const volatile {}\n\n\t\t\t\tint mI;\n\t\t\t};\n\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestInvokeConstAccess::ConstMemberFunc), const TestInvokeConstAccess*, int>::value, \"incorrect value for is_invocable\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(&TestInvokeConstAccess::ConstVolatileMemberFunc), const volatile TestInvokeConstAccess*, int>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tstruct TestReferenceWrapperInvoke\n\t\t\t{\n\t\t\t\tint NonConstMemberFunc(int i) { return i; }\n\t\t\t\tint ConstMemberFunc(int i) const { return i; }\n\n\t\t\t\tint mI = 1;\n\t\t\t\tconst int mIC = 1;\n\t\t\t};\n\n\t\t\tTestReferenceWrapperInvoke testStruct;\n\t\t\tint ret;\n\n\t\t\tret = eastl::invoke(&TestReferenceWrapperInvoke::NonConstMemberFunc, eastl::ref(testStruct), 1);\n\t\t\tEATEST_VERIFY(ret == 1);\n\n\t\t\tret = eastl::invoke(&TestReferenceWrapperInvoke::ConstMemberFunc, eastl::ref(testStruct), 1);\n\t\t\tEATEST_VERIFY(ret == 1);\n\n\t\t\tret = eastl::invoke(&TestReferenceWrapperInvoke::mI, eastl::ref(testStruct));\n\t\t\tEATEST_VERIFY(ret == 1);\n\n\t\t\tret = eastl::invoke(&TestReferenceWrapperInvoke::mIC, eastl::ref(testStruct));\n\t\t\tEATEST_VERIFY(ret == 1);\n\t\t}\n\t\t{\n\t\t\tstatic bool called = false;\n\t\t\tauto f = [] {called = true;};\n\t\t\teastl::invoke(f);\n\t\t\tEATEST_VERIFY(called);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(f)>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(f)>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tstatic int value = 0;\n\t\t\tauto f = [](int i) {value = i;};\n\t\t\teastl::invoke(f, 42);\n\t\t\tEATEST_VERIFY(value == 42);\n\n\t\t\tstatic_assert(eastl::is_same<typename eastl::invoke_result<decltype(f), int>::type, void>::value, \"incorrect type for invoke_result\");\n\t\t\tstatic_assert(eastl::is_invocable<decltype(f), int>::value, \"incorrect value for is_invocable\");\n\t\t}\n\t\t{\n\t\t\tstruct A {};\n\t\t\tstruct B : public A {};\n\t\t\tstruct C : public A {};\n\n\t\t\tstruct TestStruct\n\t\t\t{\n\t\t\t\tA a() { return A(); };\n\t\t\t\tB b() { return B(); };\n\t\t\t\tC c() EA_NOEXCEPT { return C(); };\n\t\t\t};\n\n\t\t\tstatic_assert(!eastl::is_invocable_r<B, decltype(&TestStruct::a), TestStruct>::value, \"incorrect value for is_invocable_r\");\n\t\t\tstatic_assert(eastl::is_invocable_r<A, decltype(&TestStruct::b), TestStruct>::value, \"incorrect value for is_invocable_r\");\n\t\t\tstatic_assert(eastl::is_invocable_r<B, decltype(&TestStruct::b), TestStruct>::value, \"incorrect value for is_invocable_r\");\n\t\t\tstatic_assert(!eastl::is_nothrow_invocable_r<B, decltype(&TestStruct::b), TestStruct>::value, \"incorrect value for is_nothrow_invocable_r\");\n\t\t\tstatic_assert(eastl::is_nothrow_invocable_r<C, decltype(&TestStruct::c), TestStruct>::value, \"incorrect value for is_nothrow_invocable_r\");\n\t\t}\n\t}\n\n\t// eastl::mem_fn\n\t{\n\t\tstruct AddingStruct\n\t\t{\n\t\t\tAddingStruct(int inValue) : value(inValue) {}\n\t\t\tvoid Add(int addAmount) { value += addAmount; }\n\t\t\tvoid Add2(int add1, int add2) { value += (add1 + add2); }\n\t\t\tint value;\n\t\t};\n\n\t\tstruct OverloadedStruct\n\t\t{\n\t\t\tOverloadedStruct(int inValue) : value(inValue) {}\n\t\t\tint &Value() { return value; }\n\t\t\tconst int &Value() const { return value; }\n\t\t\tint value;\n\t\t};\n\n\t\t{\n\t\t\tAddingStruct a(42);\n\t\t\teastl::mem_fn(&AddingStruct::Add)(a, 6);\n\t\t\tEATEST_VERIFY(a.value == 48);\n\t\t}\n\t\t{\n\t\t\tAddingStruct a(42);\n\t\t\teastl::mem_fn(&AddingStruct::Add2)(a, 3, 3);\n\t\t\tEATEST_VERIFY(a.value == 48);\n\t\t}\n\t\t{\n\t\t\tAddingStruct a(42);\n\t\t\tauto fStructAdd = eastl::mem_fn(&AddingStruct::Add);\n\t\t\tfStructAdd(a,6);\n\t\t\tEATEST_VERIFY(a.value == 48);\n\t\t}\n\t\t{\n\t\t\tOverloadedStruct a(42);\n\t\t\tEATEST_VERIFY(eastl::mem_fn<int &()>(&OverloadedStruct::Value)(a) == 42);\n\t\t\tEATEST_VERIFY(eastl::mem_fn<const int &() const>(&OverloadedStruct::Value)(a) == 42);\n\t\t}\n\t}\n#endif\n\n\t// eastl::function\n\t{\n\t\t{\n\t\t\t{\n\t\t\t\tstruct Functor { int operator()() { return 42; } };\n\t\t\t\teastl::function<int(void)> fn = Functor();\n\t\t\t\tEATEST_VERIFY(fn() == 42);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tstruct Functor { int operator()(int in) { return in; } };\n\t\t\t\teastl::function<int(int)> fn = Functor();\n\t\t\t\tEATEST_VERIFY(fn(24) == 24);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tint val = 0;\n\t\t\tauto lambda = [&val] { ++val; };\n\t\t\t{\n\t\t\t\teastl::function<void(void)> ff = std::bind(lambda);\n\t\t\t\tff();\n\t\t\t\tVERIFY(val == 1);\n\t\t\t}\n\t\t\t{\n\t\t\t\teastl::function<void(void)> ff = nullptr;\n\t\t\t\tff = std::bind(lambda);\n\t\t\t\tff();\n\t\t\t\tVERIFY(val == 2);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tint val = 0;\n\t\t\t{\n\t\t\t\teastl::function<int(int*)> ff = &TestIntRet;\n\t\t\t\tint ret = ff(&val);\n\t\t\t\tEATEST_VERIFY(ret == 0);\n\t\t\t\tEATEST_VERIFY(val == 1);\n\t\t\t}\n\t\t\t{\n\t\t\t\teastl::function<int(int*)> ff;\n\t\t\t\tff = &TestIntRet;\n\t\t\t\tint ret = ff(&val);\n\t\t\t\tEATEST_VERIFY(ret == 1);\n\t\t\t\tEATEST_VERIFY(val == 2);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tstruct Test { int x = 1; };\n\t\t\tTest t;\n\t\t\tconst Test ct;\n\n\t\t\t{\n\t\t\t\teastl::function<int(const Test&)> ff = &Test::x;\n\t\t\t\tint ret = ff(t);\n\t\t\t\tEATEST_VERIFY(ret == 1);\n\t\t\t}\n\t\t\t{\n\t\t\t\teastl::function<int(const Test&)> ff = &Test::x;\n\t\t\t\tint ret = ff(ct);\n\t\t\t\tEATEST_VERIFY(ret == 1);\n\t\t\t}\n\t\t\t{\n\t\t\t\teastl::function<int(const Test&)> ff;\n\t\t\t\tff = &Test::x;\n\t\t\t\tint ret = ff(t);\n\t\t\t\tEATEST_VERIFY(ret == 1);\n\t\t\t}\n\t\t\t{\n\t\t\t\teastl::function<int(const Test&)> ff;\n\t\t\t\tff = &Test::x;\n\t\t\t\tint ret = ff(ct);\n\t\t\t\tEATEST_VERIFY(ret == 1);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tstruct TestVoidRet\n\t\t\t{\n\t\t\t\tvoid IncX() const\n\t\t\t\t{\n\t\t\t\t\t++x;\n\t\t\t\t}\n\n\t\t\t\tvoid IncX()\n\t\t\t\t{\n\t\t\t\t\t++x;\n\t\t\t\t}\n\n\t\t\t\tmutable int x = 0;\n\t\t\t};\n\n\t\t\tTestVoidRet voidRet;\n\t\t\tconst TestVoidRet cvoidRet;\n\n\t\t\t{\n\t\t\t\teastl::function<void(const TestVoidRet&)> ff = static_cast<void(TestVoidRet::*)() const>(&TestVoidRet::IncX);\n\t\t\t\tff(cvoidRet);\n\t\t\t\tVERIFY(cvoidRet.x == 1);\n\t\t\t}\n\t\t\t{\n\t\t\t\teastl::function<void(const TestVoidRet&)> ff = static_cast<void(TestVoidRet::*)() const>(&TestVoidRet::IncX);\n\t\t\t\tff(voidRet);\n\t\t\t\tVERIFY(voidRet.x == 1);\n\t\t\t}\n\t\t\t{\n\t\t\t\teastl::function<void(TestVoidRet&)> ff = static_cast<void(TestVoidRet::*)()>(&TestVoidRet::IncX);\n\t\t\t\tff(voidRet);\n\t\t\t\tVERIFY(voidRet.x == 2);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tint val = 0;\n\t\t\tstruct Functor { void operator()(int* p) { *p += 1; } };\n\t\t\tFunctor functor;\n\t\t\t{\n\t\t\t\teastl::function<void(int*)> ff = eastl::reference_wrapper<Functor>(functor);\n\t\t\t\tff(&val);\n\t\t\t\tEATEST_VERIFY(val == 1);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<void(int*)> ff;\n\t\t\t\tff = eastl::reference_wrapper<Functor>(functor);\n\t\t\t\tff(&val);\n\t\t\t\tEATEST_VERIFY(val == 2);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t{\n\t\t\t\tauto lambda = []{};\n\t\t\t\tEA_UNUSED(lambda);\n\t\t\t\tstatic_assert(internal::is_functor_inplace_allocatable<decltype(lambda), EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE>::value == true, \"lambda equivalent to function pointer does not fit in eastl::function local memory.\");\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<void(void)> fn;\n\n\t\t\t\tEATEST_VERIFY(!fn);\n\t\t\t\tfn =  [] {};\n\t\t\t\tEATEST_VERIFY(!!fn);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<int(int)> fn = [](int param) { return param; };\n\t\t\t\tEATEST_VERIFY(fn(42) == 42);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<int(int)> fn = ReturnVal;\n\t\t\t\tEATEST_VERIFY(fn(42) == 42);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<int()> fn0 = ReturnZero;\n\t\t\t\teastl::function<int()> fn1 = ReturnOne;\n\n\t\t\t\tEATEST_VERIFY(fn0() == 0 && fn1() == 1);\n\t\t\t\tswap(fn0, fn1);\n\t\t\t\tEATEST_VERIFY(fn0() == 1 && fn1() == 0);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<int()> fn0 = ReturnZero;\n\t\t\t\teastl::function<int()> fn1 = ReturnOne;\n\n\t\t\t\tEATEST_VERIFY(fn0() == 0 && fn1() == 1);\n\t\t\t\tfn0 = fn1;\n\t\t\t\tEATEST_VERIFY(fn0() == 1 && fn1() == 1);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<int()> fn0 = ReturnZero;\n\t\t\t\teastl::function<int()> fn1 = ReturnOne;\n\n\t\t\t\tEATEST_VERIFY(fn0() == 0 && fn1() == 1);\n\t\t\t\tfn0 = eastl::move(fn1);\n\t\t\t\tEATEST_VERIFY(fn0() == 1 && fn1 == nullptr);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::function<int(int)> f1(nullptr);\n\t\t\t\tEATEST_VERIFY(!f1);\n\n\t\t\t\teastl::function<int(int)> f2 = nullptr;\n\t\t\t\tEATEST_VERIFY(!f2);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t// test the default allocator path by using a lambda capture too large to fit into the eastl::function local\n\t\t\t// storage.\n\t\t\tuint64_t a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;\n\t\t\teastl::function<uint64_t(void)> fn = [=] { return a + b + c + d + e + f; };\n\t\t\tauto result = fn();\n\t\t\tEATEST_VERIFY(result == 21);\n\t\t}\n\n\t\t{\n\t\t\tstruct Functor { void operator()() { return; } };\n\t\t\teastl::function<void(void)> fn;\n\t\t\teastl::function<void(void)> fn2 = nullptr;\n\t\t\tEATEST_VERIFY(!fn);\n\t\t\tEATEST_VERIFY(!fn2);\n\t\t\tEATEST_VERIFY(fn == nullptr);\n\t\t\tEATEST_VERIFY(fn2 == nullptr);\n\t\t\tEATEST_VERIFY(nullptr == fn);\n\t\t\tEATEST_VERIFY(nullptr == fn2);\n\t\t\tfn = Functor();\n\t\t\tfn2 = Functor();\n\t\t\tEATEST_VERIFY(!!fn);\n\t\t\tEATEST_VERIFY(!!fn2);\n\t\t\tEATEST_VERIFY(fn != nullptr);\n\t\t\tEATEST_VERIFY(fn2 != nullptr);\n\t\t\tEATEST_VERIFY(nullptr != fn);\n\t\t\tEATEST_VERIFY(nullptr != fn2);\n\t\t\tfn = nullptr;\n\t\t\tfn2 = fn;\n\t\t\tEATEST_VERIFY(!fn);\n\t\t\tEATEST_VERIFY(!fn2);\n\t\t\tEATEST_VERIFY(fn == nullptr);\n\t\t\tEATEST_VERIFY(fn2 == nullptr);\n\t\t\tEATEST_VERIFY(nullptr == fn);\n\t\t\tEATEST_VERIFY(nullptr == fn2);\n\t\t}\n\n\t\t{\n\t\t\tusing eastl::swap;\n\t\t\tstruct Functor { int operator()() { return 5; } };\n\t\t\teastl::function<int(void)> fn = Functor();\n\t\t\teastl::function<int(void)> fn2;\n\t\t\tEATEST_VERIFY(fn() == 5);\n\t\t\tEATEST_VERIFY(!fn2);\n\t\t\tfn.swap(fn2);\n\t\t\tEATEST_VERIFY(!fn);\n\t\t\tEATEST_VERIFY(fn2() == 5);\n\t\t\tswap(fn, fn2);\n\t\t\tEATEST_VERIFY(fn() == 5);\n\t\t\tEATEST_VERIFY(!fn2);\n\t\t}\n\n\t\t{\n\t\t\tuint64_t a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;\n\t\t\teastl::function<uint64_t(void)> fn([=] { return a + b + c + d + e + f; });\n\n\t\t\tauto result = fn();\n\t\t\tEATEST_VERIFY(result == 21);\n\t\t}\n\n\t\t// user regression \"self assigment\" tests\n\t\t{\n\t\t\teastl::function<int(void)> fn = [cache = 0] () mutable  { return cache++; };\n\n\t\t\tEATEST_VERIFY(fn() == 0);\n\t\t\tEATEST_VERIFY(fn() == 1);\n\t\t\tEATEST_VERIFY(fn() == 2);\n\n\t\t\tEA_DISABLE_CLANG_WARNING(-Wunknown-pragmas)\n\t\t\tEA_DISABLE_CLANG_WARNING(-Wunknown-warning-option)\n\t\t\tEA_DISABLE_CLANG_WARNING(-Wself-assign-overloaded)\n\t\t\tfn = fn;\n\t\t\tEA_RESTORE_CLANG_WARNING()\n\t\t\tEA_RESTORE_CLANG_WARNING()\n\t\t\tEA_RESTORE_CLANG_WARNING()\n\n\t\t\tEATEST_VERIFY(fn() == 3);\n\t\t\tEATEST_VERIFY(fn() == 4);\n\t\t\tEATEST_VERIFY(fn() == 5);\n\n\t\t\tfn = eastl::move(fn);\n\n\t\t\tEATEST_VERIFY(fn() == 6);\n\t\t\tEATEST_VERIFY(fn() == 7);\n\t\t\tEATEST_VERIFY(fn() == 8);\n\t\t}\n\n\t\t// user regression for memory leak when re-assigning an eastl::function which already holds a large closure.\n\t\t{\n\t\t\t\tstatic int sCtorCount = 0;\n\t\t\t\tstatic int sDtorCount = 0;\n\n\t\t\t\t{\n\t\t\t\t\tstruct local\n\t\t\t\t\t{\n\t\t\t\t\t\tlocal() { sCtorCount++; }\n\t\t\t\t\t\tlocal(const local&) {  sCtorCount++; }\n\t\t\t\t\t\tlocal(local&&)  {  sCtorCount++; }\n\t\t\t\t\t\t~local() { sDtorCount++; }\n\n\t\t\t\t\t\tvoid operator=(const local&) = delete; // suppress msvc warning\n\t\t\t\t\t} l;\n\n\t\t\t\t\teastl::function<bool()> f;\n\n\t\t\t\t\tf = [l]() { return false; };\n\n\t\t\t\t\t// ensure closure resources are cleaned up when assigning to a non-null eastl::function.\n\t\t\t\t\tf = [l]() { return true; };\n\t\t\t\t}\n\n\t\t\t\tEATEST_VERIFY(sCtorCount == sDtorCount);\n\t\t}\n\n\t\t#ifdef __cpp_deduction_guides\n\t\t// eastl::function deduction guides\n\t\t{\n\t\t\t// Function pointer\n\t\t\t{\n\t\t\t\teastl::function f{TestIntRet};\n\t\t\t\tstatic_assert(eastl::is_same_v<decltype(f), eastl::function<int(int*)>>, \"unexpected deduced function type.\");\n\t\t\t}\n\n\t\t\t// Member function pointer\n\t\t\t{\n\t\t\t\t// No ref-qualifiers\n\t\t\t\t{\n\t\t\t\t\tstruct CallableType\n\t\t\t\t\t{\n\t\t\t\t\t\tbool operator()(int*)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} callable;\n\t\t\t\t\t\n\t\t\t\t\teastl::function f{callable};\n\t\t\t\t\tstatic_assert(eastl::is_same_v<decltype(f), eastl::function<bool(int*)>>, \"unexpected deduced function type.\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t#define CHECK_DEDUCED_TYPE(QUALIFIERS) \\\n\t\t\t\t{ \\\n\t\t\t\t\tstruct CallableType \\\n\t\t\t\t\t{ \\\n\t\t\t\t\t\tbool operator()(int*) QUALIFIERS \\\n\t\t\t\t\t\t{ \\\n\t\t\t\t\t\t\treturn false; \\\n\t\t\t\t\t\t} \\\n\t\t\t\t\t} callable; \\\n\t\t\t\t\teastl::function f{callable}; \\\n\t\t\t\t\tstatic_assert(eastl::is_same_v<decltype(f), eastl::function<bool(int*)>>, \"unexpected deduced function type.\"); \\\n\t\t\t\t}\n\n\t\t\t\t// Some of the following tests are disabled because you cannot create an eastl::function out of a callable with those qualifiers.\n\t\t\t\t// The problem isn't due to the deduction guides themselves but the implementation of eastl::function and eastl::invoke_impl.\n\t\t\t\t// TODO: as soon as all of this permutations are working, we should be able to use EASTL_GENERATE_MEMBER_FUNCTION_VARIANTS in\n\t\t\t\t// function_detail.h to generate all of those.\n\t\t\t\tCHECK_DEDUCED_TYPE(const)\n\t\t\t\tCHECK_DEDUCED_TYPE(volatile)\n\t\t\t\tCHECK_DEDUCED_TYPE(const volatile)\n\t\t\t\t// CHECK_RETURN_TYPE(&)\n\t\t\t\tCHECK_DEDUCED_TYPE(const&)\n\t\t\t\t// CHECK_RETURN_TYPE(volatile&)\n\t\t\t\t// CHECK_RETURN_TYPE(const volatile&)\n\t\t\t\t// CHECK_RETURN_TYPE(&&)\n\t\t\t\t// CHECK_RETURN_TYPE(const&&)\n\t\t\t\t// CHECK_RETURN_TYPE(volatile&&)\n\t\t\t\t// CHECK_RETURN_TYPE(const volatile&&)\n\t\t\t\tCHECK_DEDUCED_TYPE(noexcept)\n\t\t\t\tCHECK_DEDUCED_TYPE(const noexcept)\n\t\t\t\tCHECK_DEDUCED_TYPE(volatile noexcept)\n\t\t\t\tCHECK_DEDUCED_TYPE(const volatile noexcept)\n\t\t\t\t// CHECK_RETURN_TYPE(& noexcept)\n\t\t\t\tCHECK_DEDUCED_TYPE(const& noexcept)\n\t\t\t\t// CHECK_RETURN_TYPE(volatile& noexcept)\n\t\t\t\t// CHECK_RETURN_TYPE(const volatile& noexcept)\n\t\t\t\t// CHECK_RETURN_TYPE(&& noexcept)\n\t\t\t\t// CHECK_RETURN_TYPE(const&& noexcept)\n\t\t\t\t// CHECK_RETURN_TYPE(volatile&& noexcept)\n\t\t\t\t// CHECK_RETURN_TYPE(const volatile&& noexcept)\n\t\t\t\n\t\t\t\t#undef CHECK_DEDUCED_TYPE\n\t\t\t}\n\t\t}\n\t\t#endif // __cpp_deduction_guides\n\n\t\t#if EASTL_RTTI_ENABLED\n\t\t{\n\t\t\tstruct Functor { int operator()() { return 42; } };\n\t\t\tstruct Functor2 { int operator()() { return 43; } };\n\n\t\t\teastl::function<int(void)> fn = Functor();\n\n\t\t\tconst std::type_info& type = typeid(Functor);\n\t\t\tconst std::type_info& targetType = fn.target_type();\n\t\t\tEATEST_VERIFY(targetType == type);\n\n\n\t\t\tFunctor* target = fn.target<Functor>();\n\t\t\tEATEST_VERIFY(target != nullptr);\n\n\t\t\tFunctor2* target2 = fn.target<Functor2>();\n\t\t\tEATEST_VERIFY(target2 == nullptr);\n\n\t\t\t// This tests the `const` overloads\n\t\t\tconst auto& constFn = fn;\n\n\t\t\tconst Functor* constTarget = constFn.target<Functor>();\n\t\t\tEATEST_VERIFY(constTarget != nullptr);\n\n\t\t\tconst Functor2* constTarget2 = constFn.target<Functor2>();\n\t\t\tEATEST_VERIFY(constTarget2 == nullptr);\n\t\t}\n\t\t#endif\n\t}\n\n\t// Checking _MSC_EXTENSIONS is required because the Microsoft calling convention classifiers are only available when\n\t// compiler specific C/C++ language extensions are enabled.\n\t#if defined(EA_PLATFORM_MICROSOFT) && defined(_MSC_EXTENSIONS)\n\t{\n\t\t// no arguments\n\t\ttypedef void(__stdcall * StdCallFunction)();\n\t\ttypedef void(__cdecl * CDeclFunction)();\n\n\t\t// only varargs\n\t\ttypedef void(__stdcall * StdCallFunctionWithVarargs)(...);\n\t\ttypedef void(__cdecl * CDeclFunctionWithVarargs)(...);\n\n\t\t// arguments and varargs\n\t\ttypedef void(__stdcall * StdCallFunctionWithVarargsAtEnd)(int, int, int, ...);\n\t\ttypedef void(__cdecl * CDeclFunctionWithVarargsAtEnd)(int, short, long, ...);\n\n\t\tstatic_assert(!eastl::is_function<StdCallFunction>::value, \"is_function failure\");\n\t\tstatic_assert(!eastl::is_function<CDeclFunction>::value, \"is_function failure\");\n\t\tstatic_assert(eastl::is_function<typename eastl::remove_pointer<StdCallFunction>::type>::value, \"is_function failure\");\n\t\tstatic_assert(eastl::is_function<typename eastl::remove_pointer<CDeclFunction>::type>::value, \"is_function failure\");\n\t\tstatic_assert(eastl::is_function<typename eastl::remove_pointer<StdCallFunctionWithVarargs>::type>::value, \"is_function failure\");\n\t\tstatic_assert(eastl::is_function<typename eastl::remove_pointer<CDeclFunctionWithVarargs>::type>::value, \"is_function failure\");\n\t\tstatic_assert(eastl::is_function<typename eastl::remove_pointer<StdCallFunctionWithVarargsAtEnd>::type>::value, \"is_function failure\");\n\t\tstatic_assert(eastl::is_function<typename eastl::remove_pointer<CDeclFunctionWithVarargsAtEnd>::type>::value, \"is_function failure\");\n\t}\n\t#endif\n\n\t// Test Function Objects\n\t#if defined(EA_COMPILER_CPP14_ENABLED)\n\t{\n\t\t// eastl::plus<void>\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::plus<>{}(40, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 42);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::plus<>{}(40.0, 2.0);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 42.0);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::plus<>{}(eastl::string(\"4\"), \"2\");\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == \"42\");\n\t\t\t}\n\t\t}\n\n\t\t// eastl::minus<void>\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::minus<>{}(6, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 4);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::minus<>{}(6.0, 2.0);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 4.0);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::multiplies\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::multiplies<>{}(6, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 12);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::multiplies<>{}(6.0, 2.0);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 12.0);\n\t\t\t}\n\t\t}\n\n\n\t\t// eastl::divides\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::divides<>{}(6, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 3);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::divides<>{}(6.0, 2.0);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 3.0);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::modulus\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::modulus<>{}(6, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 0);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::modulus<>{}(7, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == 1);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::negate\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::negate<>{}(42);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == -42);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::negate<>{}(42.0);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result == -42.0);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::equal_to\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::equal_to<>{}(40, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(!result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::equal_to<>{}(40, 40);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::not_equal_to\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::not_equal_to<>{}(40, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::not_equal_to<>{}(40, 40);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(!result);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::greater<void>\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::greater<>{}(40, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::greater<>{}(1, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(!result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::greater<>{}(eastl::string(\"4\"), \"2\");\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::less<void>\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::less<>{}(40, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(!result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::less<>{}(1, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::less<>{}(eastl::string(\"4\"), \"2\");\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(!result);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::greater_equal<void>\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::greater_equal<>{}(40, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::greater_equal<>{}(40, 40);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::greater_equal<>{}(40, 43);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(!result);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::less_equal<void>\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::less_equal<>{}(40, 2);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(!result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::less_equal<>{}(40, 40);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::less_equal<>{}(40, 43);\n\t\t\t\tEA_UNUSED(result);\n\t\t\t\tEATEST_VERIFY(result);\n\t\t\t}\n\t\t}\n\n\t\t// eastl::logical_and\n\t\t{\n\t\t\tauto result = eastl::logical_and<>{}(true, true);\n\t\t\tEATEST_VERIFY(result);\n\t\t\tresult = eastl::logical_and<>{}(true, false);\n\t\t\tEATEST_VERIFY(!result);\n\t\t\tresult = eastl::logical_and<>{}(false, true);\n\t\t\tEATEST_VERIFY(!result);\n\t\t\tresult = eastl::logical_and<>{}(false, false);\n\t\t\tEATEST_VERIFY(!result);\n\n\t\t\tbool b = false;\n\t\t\tresult = eastl::logical_and<>{}(b, false);\n\t\t\tEATEST_VERIFY(!result);\n\t\t}\n\n\t\t// eastl::logical_or\n\t\t{\n\t\t\tauto result = eastl::logical_or<>{}(true, true);\n\t\t\tEATEST_VERIFY(result);\n\t\t\tresult = eastl::logical_or<>{}(true, false);\n\t\t\tEATEST_VERIFY(result);\n\t\t\tresult = eastl::logical_or<>{}(false, true);\n\t\t\tEATEST_VERIFY(result);\n\t\t\tresult = eastl::logical_or<>{}(false, false);\n\t\t\tEATEST_VERIFY(!result);\n\n\t\t\tbool b = false;\n\t\t\tresult = eastl::logical_or<>{}(b, false);\n\t\t\tEATEST_VERIFY(!result);\n\t\t\tresult = eastl::logical_or<>{}(b, true);\n\t\t\tEATEST_VERIFY(result);\n\t\t}\n\n\t\t// eastl::logical_not\n\t\t{\n\t\t\tauto result = eastl::logical_not<>{}(true);\n\t\t\tEATEST_VERIFY(!result);\n\t\t\tresult = eastl::logical_not<>{}(result);\n\t\t\tEATEST_VERIFY(result);\n\t\t\tresult = eastl::logical_not<>{}(false);\n\t\t\tEATEST_VERIFY(result);\n\t\t}\n\n\t\t// eastl::bit_and\n\t\t{\n\t\t\tEATEST_VERIFY(eastl::bit_and<char>{}(0x00, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_and<char>{}(0x11, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_and<char>{}(0x01, 0x10) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_and<char>{}(0x11, 0x01) == 0x01);\n\t\t\tEATEST_VERIFY(eastl::bit_and<char>{}(0x01, 0x11) == 0x01);\n\t\t\tEATEST_VERIFY(eastl::bit_and<char>{}(0x11, 0x11) == 0x11);\n\t\t}\n\n\t\t// eastl::bit_and<void>\n\t\t{\n\t\t\tEATEST_VERIFY(eastl::bit_and<void>{}(0x00, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_and<void>{}(0x11, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_and<void>{}(0x01, 0x10) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_and<void>{}(0x11, 0x01) == 0x01);\n\t\t\tEATEST_VERIFY(eastl::bit_and<void>{}(0x01, 0x11) == 0x01);\n\t\t\tEATEST_VERIFY(eastl::bit_and<void>{}(0x11, 0x11) == 0x11);\n\t\t}\n\n\t\t// eastl::bit_or\n\t\t{\n\t\t\tEATEST_VERIFY(eastl::bit_or<char>{}(0x00, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_or<char>{}(0x11, 0x00) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<char>{}(0x01, 0x10) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<char>{}(0x11, 0x01) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<char>{}(0x01, 0x11) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<char>{}(0x11, 0x11) == 0x11);\n\t\t}\n\n\t\t// eastl::bit_or<void>\n\t\t{\n\t\t\tEATEST_VERIFY(eastl::bit_or<void>{}(0x00, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_or<void>{}(0x11, 0x00) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<void>{}(0x01, 0x10) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<void>{}(0x11, 0x01) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<void>{}(0x01, 0x11) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_or<void>{}(0x11, 0x11) == 0x11);\n\t\t}\n\n\t\t// eastl::bit_xor\n\t\t{\n\t\t\tEATEST_VERIFY(eastl::bit_xor<char>{}(0x00, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<char>{}(0x11, 0x00) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<char>{}(0x01, 0x10) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<char>{}(0x11, 0x01) == 0x10);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<char>{}(0x01, 0x11) == 0x10);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<char>{}(0x11, 0x11) == 0x00);\n\t\t}\n\n\t\t// eastl::bit_xor<void>\n\t\t{\n\t\t\tEATEST_VERIFY(eastl::bit_xor<void>{}(0x00, 0x00) == 0x00);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<void>{}(0x11, 0x00) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<void>{}(0x01, 0x10) == 0x11);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<void>{}(0x11, 0x01) == 0x10);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<void>{}(0x01, 0x11) == 0x10);\n\t\t\tEATEST_VERIFY(eastl::bit_xor<void>{}(0x11, 0x11) == 0x00);\n\t\t}\n\n\t\t// eastl::bit_not\n\t\t{\n\t\t\tEATEST_VERIFY(eastl::bit_not<unsigned char>{}(0x0) == (unsigned char) 0xFF);\n\t\t\tEATEST_VERIFY(eastl::bit_not<unsigned char>{}(0x0F) == (unsigned char) 0xF0);\n\t\t\tEATEST_VERIFY(eastl::bit_not<unsigned char>{}(0xF0) == (unsigned char) 0x0F);\n\t\t\tEATEST_VERIFY(eastl::bit_not<unsigned char>{}(0xFF) == (unsigned char) 0x0);\n\t\t}\n\n\t\t// eastl::bit_not<void>\n\t\t{\n\t\t\tEATEST_VERIFY((unsigned char)eastl::bit_not<void>{}(0x0) == (unsigned char)0xFF);\n\t\t\tEATEST_VERIFY((unsigned char)eastl::bit_not<void>{}(0x0F) == (unsigned char)0xF0);\n\t\t\tEATEST_VERIFY((unsigned char)eastl::bit_not<void>{}(0xF0) == (unsigned char)0x0F);\n\t\t\tEATEST_VERIFY((unsigned char)eastl::bit_not<void>{}(0xFF) == (unsigned char)0x0);\n\t\t}\n\t}\n\t#endif\n\n\t// not_fn\n\t{\n\t\t{\n\t\t\tauto ft = eastl::not_fn([] { return true; });\n\t\t\tauto ff = eastl::not_fn([] { return false; });\n\n\t\t\tEATEST_VERIFY(ft() == false);\n\t\t\tEATEST_VERIFY(ff() == true);\n\t\t}\n\t}\n\n\t// reference_wrapper\n\t{\n\t\t// operator T&\n\t\t{\n\t\t\tint i = 0;\n\t\t\teastl::reference_wrapper<int> r(i);\n\t\t\tint &j = r;\n\t\t\tj = 42;\n\n\t\t\tEATEST_VERIFY(i == 42);\n\t\t}\n\n\t\t// get\n\t\t{\n\t\t\tint i = 0;\n\t\t\teastl::reference_wrapper<int> r(i);\n\t\t\tr.get() = 42;\n\n\t\t\tEATEST_VERIFY(i == 42);\n\t\t}\n\n\t\t// copy constructor\n\t\t{\n\t\t\tint i = 0;\n\t\t\teastl::reference_wrapper<int> r(i);\n\t\t\teastl::reference_wrapper<int> copy(r);\n\t\t\tcopy.get() = 42;\n\n\t\t\tEATEST_VERIFY(i == 42);\n\t\t}\n\n\t\t// assignment\n\t\t{\n\t\t\tint i = 0;\n\t\t\tint j = 0;\n\n\t\t\teastl::reference_wrapper<int> r1(i);\n\t\t\teastl::reference_wrapper<int> r2(j);\n\n\t\t\tr2 = r1; // rebind r2 to refer to i\n\t\t\tr2.get() = 42;\n\n\t\t\tEATEST_VERIFY(i == 42);\n\t\t\tEATEST_VERIFY(j == 0);\n\t\t}\n\n\t\t// invoke\n\t\t{\n\t\t\tstruct Functor\n\t\t\t{\n\t\t\t\tbool called = false;\n\t\t\t\tvoid operator()() {called = true;}\n\t\t\t};\n\n\t\t\tFunctor f;\n\t\t\teastl::reference_wrapper<Functor> r(f);\n\t\t\tr();\n\n\t\t\tEATEST_VERIFY(f.called == true);\n\t\t}\n\n\t\t// ref/cref\n\t\t{\n\t\t\t{\n\t\t\t\tint i = 0;\n\t\t\t\teastl::reference_wrapper<int> r1 = eastl::ref(i);\n\t\t\t\tr1.get() = 42;\n\n\t\t\t\teastl::reference_wrapper<int> r2 = eastl::ref(r1);\n\n\t\t\t\tEATEST_VERIFY(i == 42);\n\t\t\t\tEATEST_VERIFY(r2 == 42);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tint i = 1337;\n\t\t\t\teastl::reference_wrapper<const int> r1 = eastl::cref(i);\n\t\t\t\tEATEST_VERIFY(r1 == 1337);\n\n\t\t\t\teastl::reference_wrapper<const int> r2 = eastl::cref(r1);\n\t\t\t\tEATEST_VERIFY(r2 == 1337);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\n// Test that we can instantiate invoke_result with incorrect argument types.\n// This should be instantiable, but should not have a `type` typedef.\nstruct TestInvokeResult\n{\n\tint f(int i) {return i;}\n};\n\ntemplate struct eastl::invoke_result<decltype(&TestInvokeResult::f), TestInvokeResult, void>;\n\nstatic_assert(!eastl::is_invocable<decltype(&TestInvokeResult::f), TestInvokeResult, void>::value, \"incorrect value for is_invocable\");\nstatic_assert(!eastl::is_invocable<decltype(&TestInvokeResult::f), TestInvokeResult, int, int>::value, \"incorrect value for is_invocable\");\nstatic_assert(eastl::is_invocable<decltype(&TestInvokeResult::f), TestInvokeResult, int>::value, \"incorrect value for is_invocable\");\n\nstatic_assert(!eastl::is_invocable_r<int, decltype(&TestInvokeResult::f), TestInvokeResult, void>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(!eastl::is_invocable_r<void, decltype(&TestInvokeResult::f), TestInvokeResult, int, int>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(eastl::is_invocable_r<void, decltype(&TestInvokeResult::f), TestInvokeResult, int>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(eastl::is_invocable_r<int, decltype(&TestInvokeResult::f), TestInvokeResult, int>::value, \"incorrect value for is_invocable_r\");\n\nstruct TestCallableInvokeResult\n{\n\tint operator()(int i) {return i;}\n};\n\ntemplate struct eastl::invoke_result<TestCallableInvokeResult, void>;\n\nstatic_assert(!eastl::is_invocable<TestCallableInvokeResult, void>::value, \"incorrect value for is_invocable\");\nstatic_assert(!eastl::is_invocable<TestCallableInvokeResult, int, int>::value, \"incorrect value for is_invocable\");\nstatic_assert(eastl::is_invocable<TestCallableInvokeResult, int>::value, \"incorrect value for is_invocable\");\n\nstatic_assert(!eastl::is_invocable_r<int, TestCallableInvokeResult, void>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(!eastl::is_invocable_r<void, TestCallableInvokeResult, int, int>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(eastl::is_invocable_r<void, TestCallableInvokeResult, int>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(eastl::is_invocable_r<int, TestCallableInvokeResult, int>::value, \"incorrect value for is_invocable_r\");\n\ntypedef decltype(eastl::ref(eastl::declval<TestCallableInvokeResult&>())) TestCallableRefInvokeResult;\n\nstatic_assert(!eastl::is_invocable<TestCallableRefInvokeResult, void>::value, \"incorrect value for is_invocable\");\nstatic_assert(!eastl::is_invocable<TestCallableRefInvokeResult, int, int>::value, \"incorrect value for is_invocable\");\nstatic_assert(eastl::is_invocable<TestCallableRefInvokeResult, int>::value, \"incorrect value for is_invocable\");\n\nstatic_assert(!eastl::is_invocable_r<int, TestCallableRefInvokeResult, void>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(!eastl::is_invocable_r<void, TestCallableRefInvokeResult, int, int>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(eastl::is_invocable_r<void, TestCallableRefInvokeResult, int>::value, \"incorrect value for is_invocable_r\");\nstatic_assert(eastl::is_invocable_r<int, TestCallableRefInvokeResult, int>::value, \"incorrect value for is_invocable_r\");\n\nEA_RESTORE_VC_WARNING();\n"
  },
  {
    "path": "test/source/TestHash.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include \"TestMap.h\"\n#include \"TestSet.h\"\n#include \"TestAssociativeContainers.h\"\n#include <EASTL/hash_set.h>\n#include <EASTL/hash_map.h>\n#include <EASTL/unordered_set.h>\n#include <EASTL/unordered_map.h>\n#include <EASTL/map.h>\n#include <EASTL/string.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/sort.h>\n#include <EASTL/vector.h>\n#include <EASTL/unique_ptr.h>\n\n#include <eathread/eathread_thread.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <string.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\nusing namespace eastl;\n\nnamespace eastl\n{\n\ttemplate <> \n\tstruct hash<Align32>\n\t{\n\t\tsize_t operator()(const Align32& a32) const \n\t\t\t{ return static_cast<size_t>(a32.mX); }\n\t};\n\n\t// extension to hash an eastl::pair\n\ttemplate <typename T1, typename T2>\n\tstruct hash<pair<T1, T2>>\n\t{\n\t\tsize_t operator()(const pair<T1, T2>& c) const\n\t\t{\n\t\t\treturn static_cast<size_t>(hash<T1>()(c.first) ^ hash<T2>()(c.second));\n\t\t}\n\t};\n}\n\n// For regression code below.\nclass HashRegressionA { public: int x; };\nclass HashRegressionB { public: int y; };\n\n\n// For regression code below.\nstruct Struct {\n\tchar8_t name[128];\n};\n\n\n// For regression code below.\ntemplate<class HashType>\nstruct HashTest\n{\n\ttemplate<typename... Args>\n\tauto operator()(Args&&... args)\n\t{\n\t\treturn eastl::hash<HashType>{}(eastl::forward<Args>(args)...);\n\t}\n};\n\n\n\n// What we are doing here is creating a special case of a hashtable where the key compare\n// function is not the same as the value operator==. 99% of the time when you create a \n// hashtable the key compare (predicate) is simply key_equal or something else that's\n// identical to operator== for the hashtable value type. But for some tests we want\n// to exercise the case that these aren't different. A result of this difference is that\n// you can lookup an element in a hash table and the returned value is not == to the \n// value you looked up, because it succeeds the key compare but not operator==.\nstruct HashtableValue\n{\n\tHashtableValue(eastl_size_t d = 0, eastl_size_t e = 0) : mData(d), mExtra(e){}\n\tvoid Set(eastl_size_t d, eastl_size_t e = 0) { mData = d; mExtra = e; }\n\n\teastl_size_t mData;\n\teastl_size_t mExtra;\n};\n\nbool operator==(const HashtableValue& htv1, const HashtableValue& htv2)\n{\n\treturn (htv1.mData == htv2.mData) && (htv1.mExtra == htv2.mExtra); // Fully compare the HashTableValue.\n}\n\nstruct HashtableValuePredicate\n{\n\tbool operator()(const HashtableValue& htv1, const HashtableValue& htv2) const\n\t\t{ return (htv1.mData == htv2.mData); } // Compare just the mData portion of HashTableValue.\n};\n\nstruct HashtableValueHash\n{\n\tsize_t operator()(const HashtableValue& htv) const \n\t\t{ return static_cast<size_t>(htv.mData); }\n};\n\nstruct EA_REMOVE_AT_2025_OCT ExplicitStringHashNonTransparent {\n\tsize_t operator()(const ExplicitString& str) const\n\t{\n\t\treturn eastl::hash<char*>{}(str.mString.c_str());\n\t}\n\n\tsize_t operator()(const char* p) const\n\t{\n\t\treturn eastl::hash<char*>{}(p);\n\t}\n};\n\nstruct StringHash {\n\ttypedef int is_transparent;\n\n\tsize_t operator()(const eastl::string& str) const\n\t{\n\t\treturn eastl::hash<char*>{}(str.c_str());\n\t}\n\n\tsize_t operator()(const char* p) const\n\t{\n\t\treturn eastl::hash<char*>{}(p);\n\t}\n};\n\n\n\n// Explicit Template instantiations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::hashtable<int,\n                                eastl::pair<const int, int>,\n                                eastl::allocator,\n                                eastl::use_first<eastl::pair<const int, int>>,\n                                eastl::equal_to<int>,\n                                eastl::hash<int>,\n                                mod_range_hashing,\n                                default_ranged_hash,\n                                prime_rehash_policy,\n                                true, // bCacheHashCode\n                                true, // bMutableIterators\n                                true  // bUniqueKeys\n                                >;\ntemplate class eastl::hashtable<int,\n\t\t\t\t\t\t\t\teastl::pair<const int, int>,\n\t\t\t\t\t\t\t\teastl::allocator,\n\t\t\t\t\t\t\t\teastl::use_first<eastl::pair<const int, int>>,\n\t\t\t\t\t\t\t\teastl::equal_to<int>,\n\t\t\t\t\t\t\t\teastl::hash<int>,\n\t\t\t\t\t\t\t\tmod_range_hashing,\n\t\t\t\t\t\t\t\tdefault_ranged_hash,\n\t\t\t\t\t\t\t\tprime_rehash_policy,\n\t\t\t\t\t\t\t\tfalse, // bCacheHashCode\n\t\t\t\t\t\t\t\ttrue,  // bMutableIterators\n\t\t\t\t\t\t\t\ttrue   // bUniqueKeys\n\t\t\t\t\t\t\t\t>;\n// TODO(rparolin): known compiler error, we should fix this.\n// template class eastl::hashtable<int,\n//                                 eastl::pair<const int, int>,\n//                                 eastl::allocator,\n//                                 eastl::use_first<eastl::pair<const int, int>>,\n//                                 eastl::equal_to<int>,\n//                                 eastl::hash<int>,\n//                                 mod_range_hashing,\n//                                 default_ranged_hash,\n//                                 prime_rehash_policy,\n//                                 false, // bCacheHashCode\n//                                 true,  // bMutableIterators\n//                                 false  // bUniqueKeys\n//                                 >;\n\n// Note these will only compile non-inherited functions.  We provide explicit\n// template instantiations for the hashtable base class above to get compiler\n// coverage of those inherited hashtable functions.\ntemplate class eastl::hash_set<int>;\ntemplate class eastl::hash_multiset<int>;\ntemplate class eastl::hash_map<int, int>;\ntemplate class eastl::hash_multimap<int, int>;\ntemplate class eastl::hash_set<Align32>;\ntemplate class eastl::hash_multiset<Align32>;\ntemplate class eastl::hash_map<Align32, Align32>;\ntemplate class eastl::hash_multimap<Align32, Align32>;\n\n// validate static assumptions about hashtable core types\ntypedef eastl::hash_node<int, false> HashNode1;\ntypedef eastl::hash_node<int, true> HashNode2;\nstatic_assert(eastl::is_default_constructible<HashNode1>::value, \"hash_node static error\");\nstatic_assert(eastl::is_default_constructible<HashNode2>::value, \"hash_node static error\");\nstatic_assert(eastl::is_copy_constructible<HashNode1>::value, \"hash_node static error\");\nstatic_assert(eastl::is_copy_constructible<HashNode2>::value, \"hash_node static error\");\nstatic_assert(eastl::is_move_constructible<HashNode1>::value, \"hash_node static error\");\nstatic_assert(eastl::is_move_constructible<HashNode2>::value, \"hash_node static error\");\n\n// A custom hash function that has a high number of collisions is used to ensure many keys share the same hash value.\nstruct colliding_hash\n{\n\tsize_t operator()(const int& val) const \n\t\t{ return static_cast<size_t>(val % 3); }\n};\n\nstruct TransparentHash {\n\tusing is_transparent = int;\n\n\ttemplate<typename T>\n\tsize_t operator()(T&& val) const\n\t{\n\t\treturn eastl::hash<eastl::remove_cvref_t<T>>{}(eastl::forward<T>(val));\n\t}\n};\n\nvoid TestHashTable_MT();\n\nint TestHash()\n{   \n\n\tTestHashTable_MT();\n\n\tint nErrorCount = 0;\n\n\t{  // Test declarations\n\t\thash_set<int>           hashSet;\n\t\thash_multiset<int>      hashMultiSet;\n\t\thash_map<int, int>      hashMap;\n\t\thash_multimap<int, int> hashMultiMap;\n\n\t\thash_set<int> hashSet2(hashSet);\n\t\tEATEST_VERIFY(hashSet2.size() == hashSet.size());\n\t\tEATEST_VERIFY(hashSet2 == hashSet);\n\n\t\thash_multiset<int> hashMultiSet2(hashMultiSet);\n\t\tEATEST_VERIFY(hashMultiSet2.size() == hashMultiSet.size());\n\t\tEATEST_VERIFY(hashMultiSet2 == hashMultiSet);\n\n\t\thash_map<int, int> hashMap2(hashMap);\n\t\tEATEST_VERIFY(hashMap2.size() == hashMap.size());\n\t\tEATEST_VERIFY(hashMap2 == hashMap);\n\n\t\thash_multimap<int, int> hashMultiMap2(hashMultiMap);\n\t\tEATEST_VERIFY(hashMultiMap2.size() == hashMultiMap.size());\n\t\tEATEST_VERIFY(hashMultiMap2 == hashMultiMap);\n\n\n\t\t// allocator_type& get_allocator();\n\t\t// void            set_allocator(const allocator_type& allocator);\n\t\thash_set<int>::allocator_type& allocator = hashSet.get_allocator();\n\t\thashSet.set_allocator(EASTLAllocatorType());\n\t\thashSet.set_allocator(allocator);\n\t\t// To do: Try to find something better to test here.\n\n\n\t\t// const key_equal& key_eq() const;\n\t\t// key_equal&       key_eq();\n\t\thash_set<int>       hs;\n\t\tconst hash_set<int> hsc;\n\n\t\tconst hash_set<int>::key_equal& ke = hsc.key_eq();\n\t\ths.key_eq() = ke;\n\n\n\t\t// const char*     get_name() const;\n\t\t// void            set_name(const char* pName);\n\t\t#if EASTL_NAME_ENABLED\n\t\t\thashMap.get_allocator().set_name(\"test\");\n\t\t\tconst char* pName = hashMap.get_allocator().get_name();\n\t\t\tEATEST_VERIFY(equal(pName, pName + 5, \"test\"));\n\t\t#endif\n\t}\n\n\n\t{\n\t\thash_set<int> hashSet;\n\n\t\t// Clear a newly constructed, already empty container.\n\t\thashSet.clear(true);\n\t\tEATEST_VERIFY(hashSet.validate());\n\t\tEATEST_VERIFY(hashSet.size() == 0);\n\t\tEATEST_VERIFY(hashSet.bucket_count() == 1);\n\n\t\tfor(int i = 0; i < 100; ++i)\n\t\t\thashSet.insert(i);\n\t\tEATEST_VERIFY(hashSet.validate());\n\t\tEATEST_VERIFY(hashSet.size() == 100);\n\n\t\thashSet.clear(true);\n\t\tEATEST_VERIFY(hashSet.validate());\n\t\tEATEST_VERIFY(hashSet.size() == 0);\n\t\tEATEST_VERIFY(hashSet.bucket_count() == 1);\n\n\t\tfor(int i = 0; i < 100; ++i)\n\t\t\thashSet.insert(i);\n\t\tEATEST_VERIFY(hashSet.validate());\n\t\tEATEST_VERIFY(hashSet.size() == 100);\n\n\t\thashSet.clear(true);\n\t\tEATEST_VERIFY(hashSet.validate());\n\t\tEATEST_VERIFY(hashSet.size() == 0);\n\t\tEATEST_VERIFY(hashSet.bucket_count() == 1);\n\t}\n\n\n\t{   // Test hash_set\n\n\t\t// size_type          size() const\n\t\t// bool               empty() const\n\t\t// insert_return_type insert(const value_type& value);\n\t\t// insert_return_type insert(const value_type& value, hash_code_t c, node_type* pNodeNew = NULL);\n\t\t// iterator           insert(const_iterator, const value_type& value);\n\t\t// iterator           find(const key_type& k);\n\t\t// const_iterator     find(const key_type& k) const;\n\t\t// size_type          count(const key_type& k) const;\n\n\t\ttypedef hash_set<int> HashSetInt;\n\n\t\tHashSetInt hashSet;\n\t\tconst HashSetInt::size_type kCount = 10000;\n\n\t\tEATEST_VERIFY(hashSet.empty());\n\t\tEATEST_VERIFY(hashSet.size() == 0);\n\t\tEATEST_VERIFY(hashSet.count(0) == 0);\n\n\t\tfor(int i = 0; i < (int)kCount; i++)\n\t\t\thashSet.insert(i);\n\n\t\tEATEST_VERIFY(!hashSet.empty());\n\t\tEATEST_VERIFY(hashSet.size() == kCount);\n\t\tEATEST_VERIFY(hashSet.count(0) == 1);\n\n\t\tfor(HashSetInt::iterator it = hashSet.begin(); it != hashSet.end(); ++it)\n\t\t{\n\t\t\tint value = *it;\n\t\t\tEATEST_VERIFY(value < (int)kCount);\n\t\t}\n\n\t\tfor(int i = 0; i < (int)kCount * 2; i++)\n\t\t{\n\t\t\tHashSetInt::iterator it = hashSet.find(i);\n\n\t\t\tif(i < (int)kCount)\n\t\t\t\tEATEST_VERIFY(it != hashSet.end());\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == hashSet.end());\n\t\t}\n\n\t\t// insert_return_type insert(const value_type& value, hash_code_t c, node_type* pNodeNew = NULL);\n\t\tHashSetInt::node_type* pNode = hashSet.allocate_uninitialized_node();\n\t\tHashSetInt::insert_return_type r = hashSet.insert(eastl::hash<int>()(999999), pNode, 999999);\n\t\tEATEST_VERIFY(r.second == true);\n\t\tpNode = hashSet.allocate_uninitialized_node();\n\t\tr = hashSet.insert(eastl::hash<int>()(999999), pNode, 999999);\n\t\tEATEST_VERIFY(r.second == false);\n\t\thashSet.free_uninitialized_node(pNode);\n\t\thashSet.erase(999999);\n\n\n\t\t// iterator       begin();\n\t\t// const_iterator begin() const;\n\t\t// iterator       end();\n\t\t// const_iterator end() const;\n\n\t\tint* const pIntArray = new int[kCount];\n\t\tmemset(pIntArray, 0, kCount * sizeof(int)); // We want to make sure each element is present only once.\n\t\tint nCount = 0;\n\n\t\tfor(HashSetInt::iterator it = hashSet.begin(); it != hashSet.end(); ++it, ++nCount)\n\t\t{\n\t\t\tint i = *it;\n\n\t\t\tEATEST_VERIFY((i >= 0) && (i < (int)kCount) && (pIntArray[i] == 0));\n\t\t\tpIntArray[i] = 1;\n\t\t}\n\n\t\tEATEST_VERIFY(nCount == (int)kCount);\n\t\tdelete[] pIntArray;\n\t}\n\n\n\t{\n\t\t// size_type bucket_count() const\n\t\t// size_type bucket_size(size_type n) const\n\t\t// float load_factor() const\n\t\t// float get_max_load_factor() const;\n\t\t// void  set_max_load_factor(float fMaxLoadFactor);\n\t\t// void rehash(size_type n);\n\t\t// const RehashPolicy& rehash_policy() const\n\t\t// void  rehash_policy(const RehashPolicy& rehashPolicy);\n\n\t\ttypedef hash_set<int> HashSetInt;\n\n\t\tHashSetInt hashSet;\n\n\t\tfloat fLoadFactor = hashSet.load_factor();\n\t\tEATEST_VERIFY(fLoadFactor == 0.f);\n\n\t\thashSet.set_max_load_factor(65536.f * 512.f);\n\t\tfloat fMaxLoadFactor = hashSet.get_max_load_factor();\n\t\tEATEST_VERIFY(fMaxLoadFactor == (65536.f * 512.f));\n\n\t\thashSet.rehash(20);\n\t\tHashSetInt::size_type n = hashSet.bucket_count();\n\t\tEATEST_VERIFY((n >= 20) && (n < 25));\n\t\t\n\t\tfor(int i = 0; i < 100000; i++)\n\t\t\thashSet.insert(i); // This also tests for high loading.\n\n\t\tHashSetInt::size_type n2 = hashSet.bucket_count();\n\t\tEATEST_VERIFY(n2 == n); // Verify no rehashing has occured, due to our high load factor.\n\n\t\tn = hashSet.bucket_size(0);\n\t\tEATEST_VERIFY(n >= ((hashSet.size() / hashSet.bucket_count()) / 2)); // It will be some high value. We divide by 2 to give it some slop.\n\t\tEATEST_VERIFY(hashSet.validate());\n\n\t\thash_set<int>::rehash_policy_type rp = hashSet.rehash_policy();\n\t\trp.mfGrowthFactor = 1.5f;\n\t\thashSet.rehash_policy(rp);\n\t\tEATEST_VERIFY(hashSet.validate());\n\n\n\t\t// local_iterator       begin(size_type n);\n\t\t// local_iterator       end(size_type n);\n\t\t// const_local_iterator begin(size_type n) const;\n\t\t// const_local_iterator end(size_type n) const;\n\n\t\tHashSetInt::size_type b = hashSet.bucket_count() - 1;\n\t\thash<int> IntHash;\n\t\tfor(HashSetInt::const_local_iterator cli = hashSet.begin(b); cli != hashSet.end(b); ++cli)\n\t\t{\n\t\t\tint v = *cli;\n\t\t\tEATEST_VERIFY((IntHash(v) % hashSet.bucket_count()) == b);\n\t\t}\n\n\n\t\t// clear();\n\n\t\thashSet.clear();\n\t\tEATEST_VERIFY(hashSet.validate());\n\t\tEATEST_VERIFY(hashSet.empty());\n\t\tEATEST_VERIFY(hashSet.size() == 0);\n\t\tEATEST_VERIFY(hashSet.count(0) == 0);\n\n\t\thashSet.clear(true);\n\t\tEATEST_VERIFY(hashSet.validate());\n\t\tEATEST_VERIFY(hashSet.bucket_count() == 1);\n\t}\n\n\n\t{\n\t\t// void reserve(size_type nElementCount);\n\t\tnErrorCount += HashContainerReserveTest<hash_set<int>>()();\n\t\tnErrorCount += HashContainerReserveTest<hash_multiset<int>>()();\n\t\tnErrorCount += HashContainerReserveTest<hash_map<int, int>>()();\n\t\tnErrorCount += HashContainerReserveTest<hash_multimap<int, int>>()();\n\t}\n\n\n\t{   // Test hash_set with cached hash code.\n\n\t\t// insert_return_type insert(const value_type& value) ;\n\t\t// iterator       find(const key_type& k);\n\t\t// const_iterator find(const key_type& k) const;\n\n\t\ttypedef hash_set<int, hash<int>, equal_to<int>, EASTLAllocatorType, true> HashSetIntC;\n\n\t\tHashSetIntC hashSet;\n\t\tconst int kCount = 10000;\n\n\t\tfor(int i = 0; i < kCount; i++)\n\t\t\thashSet.insert(i);\n\n\t\tfor(HashSetIntC::iterator it = hashSet.begin(); it != hashSet.end(); ++it)\n\t\t{\n\t\t\tint value = *it;\n\t\t\tEATEST_VERIFY(value < kCount);\n\t\t}\n\n\t\tfor(int i = 0; i < kCount * 2; i++)\n\t\t{\n\t\t\tHashSetIntC::iterator it = hashSet.find(i);\n\t\t\tif(i < kCount)\n\t\t\t\tEATEST_VERIFY(it != hashSet.end());\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == hashSet.end());\n\t\t}\n\t}\n\n\t{\n\t\t// ENABLE_IF_HASHCODE_U32(HashCodeT, iterator)       find_by_hash(HashCodeT c)\n\t\t// ENABLE_IF_HASHCODE_U32(HashCodeT, const_iterator) find_by_hash(HashCodeT c) const\n\t\t{\n\t\t\t// NOTE(rparolin):\n\t\t\t// these overloads of find_by_hash contains a static assert that forces a compiler error in the event it is\n\t\t\t// used with a hashtable configured to not cache the hash value in the node.\n\t\t}\n\n\t\t// iterator                                          find_by_hash(const key_type& k, hash_code_t c)\n\t\t// const_iterator                                    find_by_hash(const key_type& k, hash_code_t c) const\n\t\t#ifdef EA_COMPILER_CPP14_ENABLED \n\t\t{\n\t\t\tauto FindByHashTest = [&nErrorCount](auto& hashSet)\n\t\t\t{\n\t\t\t\tconst int kCount = 10000;\n\t\t\t\tfor(int i = 0; i < kCount; i++)\n\t\t\t\t\thashSet.insert(i);\n\n\t\t\t\tfor(int i = 0; i < kCount * 2; i++)\n\t\t\t\t{\n\t\t\t\t\tauto it = hashSet.find_by_hash(i, i);\n\n\t\t\t\t\tif(i < kCount)\n\t\t\t\t\t\tEATEST_VERIFY(it != hashSet.end());\n\t\t\t\t\telse\n\t\t\t\t\t\tEATEST_VERIFY(it == hashSet.end());\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t{\n\t\t\t\ttypedef hash_set<int, hash<int>, equal_to<int>, EASTLAllocatorType, true> HashSetIntC;\n\t\t\t\tHashSetIntC hashSetC;\n\t\t\t\tFindByHashTest(hashSetC);\n\n\t\t\t\ttypedef hash_set<int, hash<int>, equal_to<int>, EASTLAllocatorType, false> HashSetInt;\n\t\t\t\tHashSetInt hashSet;\n\t\t\t\tFindByHashTest(hashSet);\n\t\t\t}\n\t\t}\n\t\t#endif\n\t}\n\n\n\t{\n\t\t// hash_set(const allocator_type& allocator);\n\t\t// hashtable& operator=(const this_type& x);\n\t\t// bool validate() const;\n\n\t\thash_set<int> hashSet1(EASTLAllocatorType(\"hash_set name\"));\n\t\thash_set<int> hashSet2(hashSet1);\n\n\t\tfor(int i = 0; i < 10; i++)\n\t\t{\n\t\t\thashSet1.insert(i);\n\t\t\thashSet2.insert(i);\n\t\t}\n\n\t\thashSet1 = hashSet2;\n\n\t\tEATEST_VERIFY(hashSet1.validate());\n\t\tEATEST_VERIFY(hashSet2.validate());\n\t}\n\n\n\t{\n\t\t// hash_set(size_type nBucketCount, const Hash& hashFunction = Hash(), const Predicate& predicate = Predicate(), const allocator_type& allocator);\n\t\t// hashtable(const hashtable& x);\n\t\t// hashtable& operator=(const this_type& x);\n\t\t// void swap(this_type& x);\n\t\t// bool validate() const;\n\t\t{\n\t\t\thash_set<int> hashSet3(0);\n\t\t\thash_set<int> hashSet4(1);\n\t\t\thash_set<int> hashSet5(2);\n\t\t\thash_set<int> hashSet6(3);\n\t\t\thash_set<int> hashSet7(4);\n\n\t\t\thashSet4 = hashSet3;\n\t\t\thashSet6 = hashSet5;\n\t\t\thashSet3 = hashSet7;\n\n\t\t\tfor(int i = 0; i < 10; i++)\n\t\t\t{\n\t\t\t\thashSet3.insert(i);\n\t\t\t\thashSet4.insert(i);\n\t\t\t\thashSet5.insert(i);\n\t\t\t\thashSet6.insert(i);\n\t\t\t\thashSet7.insert(i);\n\t\t\t}\n\n\t\t\thashSet4 = hashSet3;\n\t\t\thashSet6 = hashSet5;\n\t\t\thashSet3 = hashSet7;\n\n\t\t\tEATEST_VERIFY(hashSet3.validate());\n\t\t\tEATEST_VERIFY(hashSet4.validate());\n\t\t\tEATEST_VERIFY(hashSet5.validate());\n\t\t\tEATEST_VERIFY(hashSet6.validate());\n\t\t\tEATEST_VERIFY(hashSet7.validate());\n\n\t\t\tswap(hashSet4, hashSet3);\n\t\t\tswap(hashSet6, hashSet5);\n\t\t\tswap(hashSet3, hashSet7);\n\n\t\t\tEATEST_VERIFY(hashSet3.validate());\n\t\t\tEATEST_VERIFY(hashSet4.validate());\n\t\t\tEATEST_VERIFY(hashSet5.validate());\n\t\t\tEATEST_VERIFY(hashSet6.validate());\n\t\t\tEATEST_VERIFY(hashSet7.validate());\n\n\t\t\thash_set<int> hashSet8(hashSet6);\n\t\t\thash_set<int> hashSet9(hashSet7);\n\t\t\thash_set<int> hashSet10(hashSet8);\n\n\t\t\tEATEST_VERIFY(hashSet8.validate());\n\t\t\tEATEST_VERIFY(hashSet9.validate());\n\t\t\tEATEST_VERIFY(hashSet10.validate());\n\t\t}\n\t\t\n\t\t// test hashtable::swap using different allocator instances\n\t\t{\n\t\t\t{\n\t\t\t\ttypedef hash_set<int, eastl::hash<int>, eastl::equal_to<int>, InstanceAllocator> HS;\n\t\t\t\tHS hashSet1(InstanceAllocator(\"hash_set1 name\", 111));\n\t\t\t\tHS hashSet2(InstanceAllocator(\"hash_set2 name\", 222));\n\n\t\t\t\tfor (int i = 0; i < 10; i++)\n\t\t\t\t{\n\t\t\t\t\thashSet1.insert(i);\n\t\t\t\t\thashSet2.insert(i + 10);\n\t\t\t\t}\n\n\t\t\t\thashSet2.swap(hashSet1);\n\n\t\t\t\tEATEST_VERIFY(hashSet1.validate());\n\t\t\t\tEATEST_VERIFY(hashSet2.validate());\n\n\t\t\t\tEATEST_VERIFY(hashSet1.get_allocator().mInstanceId == 222);\n\t\t\t\tEATEST_VERIFY(hashSet2.get_allocator().mInstanceId == 111);\n\n\t\t\t\tEATEST_VERIFY(eastl::all_of(eastl::begin(hashSet2), eastl::end(hashSet2), [](int i) { return i < 10; }));\n\t\t\t\tEATEST_VERIFY(eastl::all_of(eastl::begin(hashSet1), eastl::end(hashSet1), [](int i) { return i >= 10; }));\n\n\t\t\t\t// destroying containers to invoke InstanceAllocator::deallocate() checks\n\t\t\t}\n\n\t\t\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t\t\t                  \"Container elements should be deallocated by the allocator that allocated it.\");\n\t\t}\n\t}\n\n\n\t{\n\t\t// hash_set(InputIterator first, InputIterator last, size_type nBucketCount = 8, const Hash& hashFunction = Hash(), const Predicate& predicate = Predicate(), const allocator_type& allocator);\n\t\t// bool validate() const;\n\n\t\tvector<int> intArray;\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tintArray.push_back(i);\n\n\t\thash_set<int> hashSet1(intArray.begin(), intArray.end(), 0);\n\t\thash_set<int> hashSet2(intArray.begin(), intArray.end(), 1);\n\t\thash_set<int> hashSet3(intArray.begin(), intArray.end(), 2);\n\t\thash_set<int> hashSet4(intArray.begin(), intArray.end(), 3);\n\n\t\tEATEST_VERIFY(hashSet1.validate());\n\t\tEATEST_VERIFY(hashSet2.validate());\n\t\tEATEST_VERIFY(hashSet3.validate());\n\t\tEATEST_VERIFY(hashSet4.validate());\n\n\n\t\t// bool validate_iterator(const_iterator i) const;\n\t\thash_set<int>::iterator it;\n\t\tint result = hashSet1.validate_iterator(it);\n\t\tEATEST_VERIFY(result == isf_none);\n\n\t\tit = hashSet1.begin();\n\t\tresult = hashSet2.validate_iterator(it);\n\t\tEATEST_VERIFY(result == isf_none);\n\t\tresult = hashSet1.validate_iterator(it);\n\t\tEATEST_VERIFY(result == (isf_valid | isf_current | isf_can_dereference));\n\n\t\tit = hashSet1.end();\n\t\tresult = hashSet1.validate_iterator(it);\n\t\tEATEST_VERIFY(result == (isf_valid | isf_current));\n\n\n\t\t// void reset_lose_memory();\n\t\thashSet1.reset_lose_memory();\n\t\thashSet1 = hashSet2;\n\n\t\tEATEST_VERIFY(hashSet1.validate());\n\t\tEATEST_VERIFY(hashSet2.validate());\n\n\t\thashSet3.reset_lose_memory();\n\t\thashSet4 = hashSet3;\n\n\t\tEATEST_VERIFY(hashSet3.validate());\n\t\tEATEST_VERIFY(hashSet4.validate());\n\n\t\thashSet2.reset_lose_memory();\n\t\thashSet3.reset_lose_memory();\n\t\tswap(hashSet2, hashSet3);\n\n\t\tEATEST_VERIFY(hashSet3.validate());\n\t\tEATEST_VERIFY(hashSet4.validate());\n\n\t\thashSet2 = hashSet3;\n\t\tEATEST_VERIFY(hashSet2.validate());\n\t}\n\n\n\t{\n\t\t// void insert(InputIterator first, InputIterator last);\n\t\tvector<int> intArray1;\n\t\tvector<int> intArray2;\n\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t{\n\t\t\tintArray1.push_back(i + 0);\n\t\t\tintArray2.push_back(i + 500);\n\t\t}\n\n\t\thash_set<int> hashSet1(intArray1.begin(), intArray1.end());\n\t\thashSet1.insert(intArray2.begin(), intArray2.end());\n\t\tEATEST_VERIFY(hashSet1.validate());\n\n\t\thash_set<int> hashSet2;\n\t\thashSet2.insert(intArray1.begin(), intArray1.end());\n\t\thashSet2.insert(intArray2.begin(), intArray2.end());\n\t\tEATEST_VERIFY(hashSet2.validate());\n\n\t\tEATEST_VERIFY(hashSet1 == hashSet2);\n\n\n\t\t// insert_return_type insert(const_iterator, const value_type& value)\n\t\tfor(int j = 0; j < 1000; j++)\n\t\t\thashSet1.insert(hashSet1.begin(), j);\n\n\t\tinsert_iterator< hash_set<int> > ii(hashSet1, hashSet1.begin());\n\t\tfor(int j = 0; j < 1000; j++)\n\t\t\t*ii++ = j;\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestMapCpp11<eastl::hash_map<int, TestObject>>();\n\t\tnErrorCount += TestMapCpp11<eastl::unordered_map<int, TestObject>>();\n\t\tnErrorCount += TestMapCpp11<eastl::unordered_map<int, TestObject, TransparentHash, eastl::equal_to<void>>>();\n\n\t\tnErrorCount += TestSetCpp11<eastl::hash_set<TestObject>>();\n\t\tnErrorCount += TestSetCpp11<eastl::unordered_set<TestObject>>();\n\t\tnErrorCount += TestSetCpp11<eastl::unordered_set<TestObject, TransparentHash, eastl::equal_to<void>>>();\n\n\t\tnErrorCount += TestMultimapCpp11<eastl::hash_multimap<int, TestObject>>();\n\t\tnErrorCount += TestMultimapCpp11<eastl::unordered_multimap<int, TestObject>>();\n\t\tnErrorCount += TestMultimapCpp11<eastl::unordered_multimap<int, TestObject, TransparentHash, eastl::equal_to<void>>>();\n\n\t\tnErrorCount += TestMultisetCpp11<eastl::hash_multiset<TestObject>>();\n\t\tnErrorCount += TestMultisetCpp11<eastl::unordered_multiset<TestObject>>();\n\t\tnErrorCount += TestMultisetCpp11<eastl::unordered_multiset<TestObject, TransparentHash, eastl::equal_to<void>>>();\n\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::hash_map<int, NonCopyable>>();\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::unordered_map<int, NonCopyable>>();\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::unordered_map<int, NonCopyable, TransparentHash, eastl::equal_to<void>>>();\n\t}\n\n\t{\n\t\t// C++17 try_emplace and related functionality\n\t\tnErrorCount += TestMapCpp17<eastl::hash_map<int, TestObject>>();\n\t\tnErrorCount += TestMapCpp17<eastl::unordered_map<int, TestObject>>();\n\t\tnErrorCount += TestMapCpp17<eastl::unordered_map<int, TestObject, TransparentHash, eastl::equal_to<void>>>();\n\t}\n\n\n\t{\n\t\t// initializer_list support.\n\t\t// hash_set(std::initializer_list<value_type> ilist, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t//            const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR)\n\t\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t\t// void insert(std::initializer_list<value_type> ilist);\n\t\thash_set<int> intHashSet = { 12, 13, 14 };\n\t\tEATEST_VERIFY(intHashSet.size() == 3);\n\t\tEATEST_VERIFY(intHashSet.find(12) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(13) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(14) != intHashSet.end());\n\n\t\tintHashSet = { 22, 23, 24 };\n\t\tEATEST_VERIFY(intHashSet.size() == 3);\n\t\tEATEST_VERIFY(intHashSet.find(22) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(23) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(24) != intHashSet.end());\n\n\t\tintHashSet.insert({ 42, 43, 44 });\n\t\tEATEST_VERIFY(intHashSet.size() == 6);\n\t\tEATEST_VERIFY(intHashSet.find(42) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(43) != intHashSet.end());\n\t\tEATEST_VERIFY(intHashSet.find(44) != intHashSet.end());\n\t}\n\n\t{\n\t\t// eastl::pair<iterator, iterator>             equal_range(const key_type& k);\n\t\t// eastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;\n\t\t// const_iterator  erase(const_iterator, const_iterator);\n\t\t// size_type       erase(const key_type&);\n\t\t// To do.\n\t}\n\n\n\t{ // hash_set erase_if\n\t\thash_set<int> m = {0, 1, 2, 3, 4};\n\t\tauto numErased = eastl::erase_if(m, [](auto i) { return i % 2 == 0; });\n\t\tVERIFY((m == hash_set<int>{1, 3}));\n\t    VERIFY(numErased == 3);\n\t}\n\n\t{ // hash_multiset erase_if\n\t\thash_multiset<int> m = {0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4};\n\t\tauto numErased = eastl::erase_if(m, [](auto i) { return i % 2 == 0; });\n\t\tVERIFY((m == hash_multiset<int>{1, 1, 1, 3}));\n\t    VERIFY(numErased == 12);\n\t}\n\n\n\n\n\n\n\t{   // Test hash_map\n\n\t\t// insert_return_type insert(const value_type& value);\n\t\t// insert_return_type insert(const key_type& key);\n\t\t// iterator       find(const key_type& k);\n\t\t// const_iterator find(const key_type& k) const;\n\n\t\ttypedef hash_map<int, int> HashMapIntInt;\n\t\tHashMapIntInt hashMap;\n\t\tconst int kCount = 10000;\n\n\t\tfor(int i = 0; i < kCount; i++)\n\t\t{\n\t\t\tHashMapIntInt::value_type vt(i, i);\n\t\t\thashMap.insert(vt);\n\t\t}\n\n\t\tconst HashMapIntInt const_hashMap = hashMap; // creating a const version to test for const correctness\n\n\t\tfor(auto& e : hashMap)\n\t\t{\n\t\t\tint k = e.first;\n\t\t\tint v = e.second;\n\t\t\tEATEST_VERIFY(k < kCount);\n\t\t\tEATEST_VERIFY(v == k);\n\t\t\tEATEST_VERIFY(hashMap.at(k) == k);\n\t\t\tEATEST_VERIFY(const_hashMap.at(k) == k);\n\t\t\thashMap.at(k) = k << 4;\n\t\t}\n\n\t\tfor(auto& e : hashMap)\n\t\t{\n\t\t\tint k = e.first;\n\t\t\tint v = e.second;\n\t\t\tEATEST_VERIFY(k < kCount);\n\t\t\tEATEST_VERIFY(v == (k << 4));\n\t\t}\n\n\t\tfor(int i = 0; i < kCount * 2; i++)\n\t\t{\n\t\t\tHashMapIntInt::iterator it = hashMap.find(i);\n\n\t\t\tif(i < kCount)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(it != hashMap.end());\n\n\t\t\t\tint k = (*it).first;\n\t\t\t\tint v = (*it).second;\n\t\t\t\tEATEST_VERIFY(v == (k << 4));\n\t\t\t}\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == hashMap.end());\n\t\t}\n\n\t\tfor(int i = 0; i < kCount; i++)\n\t\t{\n\t\t\tint v = hashMap.at(i);\n\t\t\tEATEST_VERIFY(v == (i << 4));\n\t\t}\n\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry\n\t\t\t{\n\t\t\t\thashMap.at(kCount);\n\t\t\t\tEASTL_ASSERT_MSG(false, \"at accessor did not throw out_of_range exception\");\n\t\t\t}\n\t\t\tcatch(const std::out_of_range) { }\n\t\t\tcatch(const std::exception& e)\n\t\t\t{\n\t\t\t\tstring e_msg(e.what());\n\t\t\t\tstring msg = \"wrong exception with message \\\"\" + e_msg + \"\\\" thrown\";\n\t\t\t\tEASTL_ASSERT_MSG(false, msg.c_str());\n\t\t\t}\n\t\t#endif\n\t\tHashMapIntInt::insert_return_type result = hashMap.insert(88888);\n\t\tEATEST_VERIFY(result.second == true);\n\t\tresult = hashMap.insert(88888);\n\t\tEATEST_VERIFY(result.second == false);\n\t\tresult.first->second = 0;\n\n\t\t// const_iterator erase(const_iterator);\n\t\tsize_t nExpectedSize = hashMap.size();\n\n\t\tHashMapIntInt::iterator it50 = hashMap.find(50);\n\t\tEATEST_VERIFY(it50 != hashMap.end());\n\n\t\tHashMapIntInt::iterator itNext = hashMap.erase(it50);\n\t\tnExpectedSize--;\n\t\tEATEST_VERIFY(itNext != hashMap.end()); // Strictly speaking, this isn't guaranteed to be so. But statistically it is very likely. We'll fix this if it becomes a problem.\n\t\tEATEST_VERIFY(hashMap.size() == nExpectedSize);\n\n\t\tHashMapIntInt::size_type n = hashMap.erase(10);\n\t\tnExpectedSize--;\n\t\tEATEST_VERIFY(n == 1);\n\t\tEATEST_VERIFY(hashMap.size() == nExpectedSize);\n\n\t\tHashMapIntInt::iterator it60 = hashMap.find(60);\n\t\tEATEST_VERIFY(itNext != hashMap.end());\n\n\t\tHashMapIntInt::iterator it60Incremented(it60);\n\t\tfor(int i = 0; (i < 5) && (it60Incremented != hashMap.end()); ++i)\n\t\t{\n\t\t\t++it60Incremented;\n\t\t\t--nExpectedSize;\n\t\t}\n\n\t\thashMap.erase(it60, it60Incremented);\n\t\tEATEST_VERIFY(hashMap.size() == nExpectedSize);\n\n\n\t\t// insert_return_type insert(const value_type& value, hash_code_t c, node_type* pNodeNew = NULL);\n\t\tHashMapIntInt::node_type* pNode = hashMap.allocate_uninitialized_node();\n\t\tHashMapIntInt::insert_return_type r = hashMap.insert(eastl::hash<int>()(999999), pNode, HashMapIntInt::value_type(999999, 999999));\n\t\tEATEST_VERIFY(r.second == true);\n\t\tpNode = hashMap.allocate_uninitialized_node();\n\t\tr = hashMap.insert(eastl::hash<int>()(999999), pNode, HashMapIntInt::value_type(999999, 999999));\n\t\tEATEST_VERIFY(r.second == false);\n\t\thashMap.free_uninitialized_node(pNode);\n\t\thashMap.erase(999999);\n\n\n\t\t// mapped_type& operator[](const key_type& key)\n\t\t// hash_map is unique among the map/set containers in having this function.\n\t\thashMap.clear();\n\n\t\tint x = hashMap[0]; // A default-constructed int (i.e. 0) should be returned.\n\t\tEATEST_VERIFY(x == 0); \n   \n\t\thashMap[1] = 1;\n\t\tx = hashMap[1];\n\t\tEATEST_VERIFY(x == 1);     // Verify that the value we assigned is returned and a default-constructed value is not returned.\n\t \n\t\thashMap[0] = 10;    // Overwrite our previous 0 with 10.\n\t\thashMap[1] = 11;\n\t\tx = hashMap[0];\n\t\tEATEST_VERIFY(x == 10);    // Verify the value is as expected.\n\t\tx = hashMap[1];\n\t\tEATEST_VERIFY(x == 11);\n\t}\n\n\n\t{\n\t\t// Test default hash function for floating-type types\n\t\tvector<float> floatVals\n\t\t{\n\t\t\t-2.0f, -1.9f, -1.8f, -1.7f, -1.6f, -1.5f, -1.4f, -1.3f, -1.2f, -1.1f,\n\t\t\t-1.0f, -0.9f, -0.8f, -0.7f, -0.6f, -0.5f, -0.4f, -0.3f, -0.2f, -0.1f,\n\t\t\t0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f,\n\t\t\t1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f\n\t\t};\n\n\t\tvector<size_t> hashVec;\n\t\tconst eastl::hash<float> hashFunc;\n\n\t\teastl::for_each(floatVals.begin(), floatVals.end(), [&](float& val)\n\t\t{\n\t\t\thashVec.push_back(hashFunc(val));\n\t\t});\n\n\t\tsort(floatVals.begin(), floatVals.end());\n\t\tEATEST_VERIFY(eastl::adjacent_find(floatVals.begin(), floatVals.end()) == floatVals.end());\n\n\t\t// Negative zero is hardcoded to have the same hash as positive zero\n\t\tEATEST_VERIFY(hashFunc(-0.0) == hashFunc(0.0));\n\t}\n\n\n\t{   // Test hash_map\n\n\t\t// Aligned objects should be CustomAllocator instead of the default, because the \n\t\t// EASTL default might be unable to do aligned allocations, but CustomAllocator always can.\n\t\thash_map<Align32, int, eastl::hash<Align32>, eastl::equal_to<Align32>, CustomAllocator> hashMap;\n\t\tconst int kCount = 10000;\n\n\t\tfor(int i = 0; i < kCount; i++)\n\t\t{\n\t\t\tAlign32 a32(i); // GCC 2.x doesn't like the Align32 object being created in the ctor below.\n\t\t\thash_map<Align32, int>::value_type vt(a32, i);\n\t\t\thashMap.insert(vt);\n\t\t}\n\n\t\tfor(hash_map<Align32, int>::iterator it = hashMap.begin(); it != hashMap.end(); ++it)\n\t\t{\n\t\t\tconst Align32& k = (*it).first;\n\t\t\tint            v = (*it).second;\n\t\t\tEATEST_VERIFY(k.mX < 10000);\n\t\t\tEATEST_VERIFY(v == k.mX);\n\t\t}\n\n\t\tfor(int i = 0; i < kCount * 2; i++)\n\t\t{\n\t\t\thash_map<Align32, int>::iterator it = hashMap.find(Align32(i));\n\n\t\t\tif(i < kCount)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(it != hashMap.end());\n\n\t\t\t\tconst Align32& k = (*it).first;\n\t\t\t\tint            v = (*it).second;\n\t\t\t\tEATEST_VERIFY(v == k.mX);\n\t\t\t}\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == hashMap.end());\n\t\t}\n\t}\n\n\t{ // hash_map erase_if\n\t\thash_map<int, int> m = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};\n\t\tauto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });\n\t\tVERIFY((m == hash_map<int, int>{{1, 1}, {3, 3}}));\n\t    VERIFY(numErased == 3);\n\t}\n\n\t{ // hash_multimap erase_if\n\t\thash_multimap<int, int> m = {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2},\n\t\t                             {2, 2}, {2, 2}, {2, 2}, {3, 3}, {3, 3}, {4, 4}};\n\t\tauto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });\n\t\tVERIFY((m == hash_multimap<int, int>{{1, 1}, {3, 3}, {3, 3}}));\n\t    VERIFY(numErased == 9);\n\t}\n\n\n\n\t{   \n\t\t// template <typename U, typename UHash, typename BinaryPredicate>\n\t\t// iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate);\n\t\t// template <typename U, typename UHash, typename BinaryPredicate>\n\t\t// const_iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate) const;\n\t\t// template <typename U>\n\t\t// iterator find_as(const U& u);\n\t\t// template <typename U>\n\t\t// const_iterator find_as(const U& u) const;\n\n\t\ttypedef hash_set<string> HashSetString;\n\n\t\tHashSetString hashSet;\n\t\tconst int kCount = 100;\n\n\t\tfor(int i = 0; i < kCount; i++)\n\t\t{\n\t\t\tstring::CtorSprintf cs; // GCC 2.x doesn't like this value being created in the ctor below.\n\t\t\tstring s(cs, \"%d\", i);\n\t\t\thashSet.insert(s);\n\t\t}\n\n\t\tfor(int i = 0; i < kCount * 2; i++)\n\t\t{\n\t\t\tconst int kBufferSize = 32;\n\t\t\tchar pString[kBufferSize];\n\t\t\tEA::StdC::Snprintf(pString, kBufferSize, \"%d\", i);\n\n\t\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\t\tHashSetString::iterator it = hashSet.find_as(pString);\n\t\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t\t\tif(i < kCount)\n\t\t\t\tEATEST_VERIFY(it != hashSet.end());\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == hashSet.end());\n\n\t\t\tit = hashSet.find_as(pString, hash<const char*>(), equal_to<>());\n\t\t\tif(i < kCount)\n\t\t\t\tEATEST_VERIFY(it != hashSet.end());\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == hashSet.end());\n\n\t\t\tstring::CtorSprintf cs;\n\t\t    string s(cs, \"%d\", i);\n\n\t\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\t\tit = hashSet.find_as(s);\n\t\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\t\t    if (i < kCount)\n\t\t\t    EATEST_VERIFY(it != hashSet.end());\n\t\t    else\n\t\t\t    EATEST_VERIFY(it == hashSet.end());\n\t\t}\n\t}\n\n\n\t{\n\t\t// Test const containers.\n\t\tconst hash_set<int> constHashSet;\n\n\t\thash_set<int>::const_iterator i = constHashSet.begin();\n\t\thash_set<int>::const_iterator i3 = i;\n\t\thash_set<int>::iterator i2;\n\t\ti3 = i2;\n\n\t\tEATEST_VERIFY(i3 == i2);\n\n\t\t//const std::tr1::unordered_set<int> constUSet;\n\t\t//std::tr1::unordered_set<int>::const_iterator i = constUSet.begin();\n\t\t//*i = 0;\n\t}\n\n\t{\n\t\t// global operator ==, !=\n\t\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\t\tconst eastl_size_t kIterationCount = 100;\n\t\tconst eastl_size_t kDataRange = 50;\n\n\t\t{\n\t\t\ttypedef hash_set<HashtableValue, HashtableValueHash, HashtableValuePredicate> HashSet;\n\t\t\tHashtableValue value;\n\n\t\t\tHashSet h1;\n\t\t\tHashSet h2;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\tfor(eastl_size_t i = 0; i < kIterationCount; i++)\n\t\t\t{\n\t\t\t\tvalue.mData = rng.RandLimit(kDataRange);\n\t\t\t\th1.insert(value);  // Leave value.mExtra as 0.\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h1;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\t// Test the case of the containers being the same size but having a single different value, despite that it's key compare yields equal.\n\t\t\tHashSet h2Saved(h2);\n\t\t\tHashSet::iterator it = h2.find(value);\n\t\t\tHashtableValue valueModified(value.mData, 1);\n\t\t\th2.erase(it);\n\t\t\th2.insert(valueModified);\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\t// Test the case of the containers being the same size but having a single different key.\n\t\t\th2Saved = h2;\n\t\t\th2.erase(h2.find(value));\n\t\t\th2.insert(kDataRange); // Insert something that could not have been in h2.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\th1.erase(h1.find(value)); // Erase from h1 whatever the last value was.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t}\n\n\t\t{\n\t\t\ttypedef hash_multiset<HashtableValue, HashtableValueHash, HashtableValuePredicate> HashSet;\n\t\t\tHashtableValue value;\n\n\t\t\tHashSet h1;\n\t\t\tHashSet h2;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\tfor(eastl_size_t i = 0; i < kIterationCount; i++)\n\t\t\t{\n\t\t\t\tvalue.mData = rng.RandLimit(kDataRange);\n\t\t\t\th1.insert(value);  // Leave value.mExtra as 0.\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h1;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\t// Test the case of the containers being the same size but having a single different value, despite that it's key compare yields equal.\n\t\t\tHashSet h2Saved(h2);\n\t\t\tHashSet::iterator it = h2.find(value);\n\t\t\tHashtableValue valueModified(value.mData, 1);\n\t\t\th2.erase(it);\n\t\t\th2.insert(valueModified);\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\t// Test the case of the containers being the same size but having a single different key.\n\t\t\th2Saved = h2;\n\t\t\th2.erase(h2.find(value));\n\t\t\th2.insert(kDataRange); // Insert something that could not have been in h2.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\th1.erase(h1.find(value)); // Erase from h1 whatever the last value was.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t}\n\n\t\t{\n\t\t\t// For simplicity we duplicate the HashtableValue::mData member as the hash map key.\n\t\t\ttypedef hash_map<eastl_size_t, HashtableValue, HashtableValueHash, HashtableValuePredicate> HashMap;\n\t\t\tHashtableValue value;\n\n\t\t\tHashMap h1;\n\t\t\tHashMap h2;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\tfor(eastl_size_t i = 0; i < kIterationCount; i++)\n\t\t\t{\n\t\t\t\tvalue.mData = rng.RandLimit(kDataRange);\n\t\t\t\th1.insert(HashMap::value_type(value.mData, value));  // Leave value.mExtra as 0.\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h1;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\t// Test the case of the containers being the same size but having a single different value, despite that it's key compare yields equal.\n\t\t\tHashMap h2Saved(h2);\n\t\t\tHashMap::iterator it = h2.find(value.mData); // We are using value.mData as the key as well, so we can do a find via it.\n\t\t\tHashtableValue valueModified(value.mData, 1);\n\t\t\th2.erase(it);\n\t\t\th2.insert(HashMap::value_type(valueModified.mData, valueModified));\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\t// Test the case of the containers being the same size but having a single different key.\n\t\t\th2Saved = h2;\n\t\t\th2.erase(h2.find(value.mData));\n\t\t\th2.insert(HashMap::value_type(kDataRange, HashtableValue(kDataRange))); // Insert something that could not have been in h2.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\th1.erase(h1.find(value.mData)); // Erase from h1 whatever the last value was.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t}\n\n\t\t{\n\t\t\t// For simplicity we duplicate the HashtableValue::mData member as the hash map key.\n\t\t\ttypedef hash_multimap<eastl_size_t, HashtableValue, HashtableValueHash, HashtableValuePredicate> HashMap;\n\t\t\tHashtableValue value;\n\n\t\t\tHashMap h1;\n\t\t\tHashMap h2;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\tfor(eastl_size_t i = 0; i < kIterationCount; i++)\n\t\t\t{\n\t\t\t\tvalue.mData = rng.RandLimit(kDataRange);\n\t\t\t\th1.insert(HashMap::value_type(value.mData, value));  // Leave value.mExtra as 0.\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h1;\n\t\t\tEATEST_VERIFY(h1 == h2);\n\n\t\t\t// Test the case of the containers being the same size but having a single different value, despite that it's key compare yields equal.\n\t\t\tHashMap h2Saved(h2);\n\t\t\tHashMap::iterator it = h2.find(value.mData); // We are using value.mData as the key as well, so we can do a find via it.\n\t\t\tHashtableValue valueModified(value.mData, 1);\n\t\t\th2.erase(it);\n\t\t\th2.insert(HashMap::value_type(valueModified.mData, valueModified));\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\t// Test the case of the containers being the same size but having a single different key.\n\t\t\th2Saved = h2;\n\t\t\th2.erase(h2.find(value.mData));\n\t\t\th2.insert(HashMap::value_type(kDataRange, HashtableValue(kDataRange))); // Insert something that could not have been in h2.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t\th2 = h2Saved;\n\n\t\t\th1.erase(h1.find(value.mData)); // Erase from h1 whatever the last value was.\n\t\t\tEATEST_VERIFY(h1 != h2);\n\t\t}\n\t}\n\n\t{\n\t\ttypedef eastl::hash_multiset<int> HashMultisetInt;\n\n\t\tHashMultisetInt hashMultiSet;\n\n\t\t// insert_return_type insert(const value_type& value, hash_code_t c, node_type* pNodeNew = NULL);\n\t\tHashMultisetInt::node_type* pNode = hashMultiSet.allocate_uninitialized_node();\n\t\tHashMultisetInt::iterator it1 = hashMultiSet.insert(eastl::hash<int>()(999999), pNode, 999999);\n\t\tEATEST_VERIFY(it1 != hashMultiSet.end());\n\t\tpNode = hashMultiSet.allocate_uninitialized_node();\n\t\tHashMultisetInt::iterator it2 = hashMultiSet.insert(eastl::hash<int>()(999999), pNode, 999999);\n\t\tEATEST_VERIFY(it2 != hashMultiSet.end() && it2 != it1);\n\t}\n\n\t{ \n\t\t// Regression of compiler warning reported by Jeff Litz/Godfather regarding \n\t\t// strict aliasing (EASTL 1.09.01) December 2007).\n\t\ttypedef eastl::hash_multimap<uint32_t, uint32_t*> Map;\n\t\tMap* pMap = new Map;\n\t\tdelete pMap;\n\t}\n\n\t{ \n\t\t// Regression of user-reported crash.\n\t\teastl::hash_map<int, eastl::string*>* _hmTextureList;\n\t\t_hmTextureList = new eastl::hash_map<int, eastl::string*>();\n\t\teastl::string* a = NULL;\n\t\t(*_hmTextureList)[0] = a;\n\t\tdelete _hmTextureList;\n\t}\n\n\t{\n\t\t// Regression of user-reported Android compiler error.\n\t\ttypedef eastl::hash_multimap<HashRegressionA*, HashRegressionB> HMM;\n\t\tHMM m_hash;\n\n\t\t// Section 1\n\t\tfor (HMM::iterator it = m_hash.begin(); it != m_hash.end(); it++)\n\t\t\tit->second.y = 1;\n\n\t\t// Section 2\n\t\tHashRegressionA* pA = NULL;\n\t\teastl::pair<HMM::iterator, HMM::iterator> pair = m_hash.equal_range(pA);\n\t\t(void)pair;\n\t}\n\n\t{\n\t\t// Regression of user-reported GCC 4.8 compile failure.\n\t\ttypedef eastl::hash_map<int64_t, Struct> AuditByBlazeIdMap;\n\n\t\tAuditByBlazeIdMap auditBlazeIds;\n\t\tAuditByBlazeIdMap tempAuditBlazeIds;\n\n\t\tauditBlazeIds.swap(tempAuditBlazeIds); // This line was generating an unexpected compiler failure.\n\t\tEATEST_VERIFY(auditBlazeIds.empty() && tempAuditBlazeIds.empty());\n\t}\n\n\t{\n\t\t// This test is designed to designed to use the find_range_by_hash method to walk over all keys in a hash bucket (located by a hash value).\n\t\t\n\t\t// Use the 'colliding_hash' hash function to intentionally create lots of collisions in a predictable way.\n\t\ttypedef hash_map<int, int, colliding_hash> HM;\n\t\tHM hashMap;\n\n\t\t// Add some numbers to the hashMap.\n\t\tfor(int i=0; i<90; i++)\n\t\t{\n\t\t\thashMap[i] = i;\n\t\t}\n\n\t\t// Try to find a hash value that doesn't exist\n\t\t{\n\t\t\teastl::pair<HM::iterator, HM::iterator> i = hashMap.find_range_by_hash(1000);\n\t\t\tEATEST_VERIFY(i.first == hashMap.end());\n\t\t\tEATEST_VERIFY(i.second == hashMap.end());\n\t\t}\n\n\t\t{\n\t\t\tint iterations = 0;\n\t\t\tfor(eastl::pair<HM::iterator, HM::iterator> i = hashMap.find_range_by_hash(1); i.first != i.second; i.first++)\n\t\t\t{\n\t\t\t\tint nodeValue = i.first.get_node()->mValue.first;\n\t\t\t\tEATEST_VERIFY(nodeValue % 3 == 1);   // Verify the hash of the node matches the expected value\n\t\t\t\titerations++;\n\t\t\t}\n\t\t\tEATEST_VERIFY(iterations == 30);\n\t\t}\n\n\t\t{\n\t\t\tconst HM &constHashMap = hashMap;\n\t\t\tint iterations = 0;\n\t\t\tfor(eastl::pair<HM::const_iterator, HM::const_iterator> i = constHashMap.find_range_by_hash(1); i.first != i.second; i.first++)\n\t\t\t{\n\t\t\t\tint nodeValue = i.first.get_node()->mValue.first;\n\t\t\t\tEATEST_VERIFY(nodeValue % 3 == 1);   // Verify the hash of the node matches the expected value\n\t\t\t\titerations++;\n\t\t\t}\n\t\t\tEATEST_VERIFY(iterations == 30);\n\t\t}\n\t}\n\n\t// test hashtable holding move-only types\n\t#if !defined(EA_COMPILER_MSVC_2013)\n\t{\n\t\tstruct Movable\n\t\t{\n\t\t\tMovable() {}\n\t\t\tMovable(Movable&&) = default;\n\t\t\tMovable& operator=(Movable&&) = default;\n\t\t\tMovable(const Movable&) = delete;\n\t\t\tMovable& operator=(const Movable&) = delete;\n\n\t\t\tbool operator==(Movable) const { return true; }\n\n\t\t\tstruct Hash\n\t\t\t{\n\t\t\t\tsize_t operator()(Movable) const { return 0; }\n\t\t\t};\n\t\t};\n\n\t\teastl::unordered_set<Movable, Movable::Hash> a, b;\n\t\tswap(a,b);\n\t}\n\t#endif\n\n\t{\n\t\t// hashtable(this_type&& x);\n\t\t// hashtable(this_type&& x, const allocator_type& allocator);\n\t\t// this_type& operator=(this_type&& x);\n\n\t\t// template <class... Args>\n\t\t// insert_return_type emplace(Args&&... args);\n\n\t\t// template <class... Args>\n\t\t// iterator emplace_hint(const_iterator position, Args&&... args);\n\n\t\t// template <class P> // Requires that \"value_type is constructible from forward<P>(otherValue).\"\n\t\t// insert_return_type insert(P&& otherValue);\n\n\t\t// iterator insert(const_iterator hint, value_type&& value);\n\n\t\t// Regression of user reported compiler error in hashtable sfinae mechanism \n\t\t{\n\t\t\tTestObject::Reset();\n\t\t\teastl::hash_set<TestObject> toSet;\n\t\t\ttoSet.emplace(3, 4, 5);\n\t\t}\n\t}\n\n\n\n\t{\n\t\t// initializer_list support.\n\t\t// hash_map(std::initializer_list<value_type> ilist, size_type nBucketCount = 0, const Hash& hashFunction = Hash(), \n\t\t//            const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_MAP_DEFAULT_ALLOCATOR)\n\t\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t\t// void insert(std::initializer_list<value_type> ilist);\n\t\t\n\t\t// VS2013 has a known issue when dealing with std::initializer_lists\n\t\t// https://connect.microsoft.com/VisualStudio/feedback/details/792355/compiler-confused-about-whether-to-use-a-initializer-list-assignment-operator\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS) && !(defined(_MSC_VER) && _MSC_VER == 1800)\n\t\t\thash_map<int, double> intHashMap = { {12,12.0}, {13,13.0}, {14,14.0} };\n\t\t\tEATEST_VERIFY(intHashMap.size() == 3);\n\t\t\tEATEST_VERIFY(intHashMap.find(12) != intHashMap.end());\n\t\t\tEATEST_VERIFY(intHashMap.find(13) != intHashMap.end());\n\t\t\tEATEST_VERIFY(intHashMap.find(14) != intHashMap.end());\n\n\t\t\tintHashMap = { {22,22.0}, {23,23.0}, {24,24.0} };\n\t\t\tEATEST_VERIFY(intHashMap.size() == 3);\n\t\t\tEATEST_VERIFY(intHashMap.find(22) != intHashMap.end());\n\t\t\tEATEST_VERIFY(intHashMap.find(23) != intHashMap.end());\n\t\t\tEATEST_VERIFY(intHashMap.find(24) != intHashMap.end());\n\n\t\t\tintHashMap.insert({ {42,42.0}, {43,43.0}, {44,44.0} });\n\t\t\tEATEST_VERIFY(intHashMap.size() == 6);\n\t\t\tEATEST_VERIFY(intHashMap.find(42) != intHashMap.end());\n\t\t\tEATEST_VERIFY(intHashMap.find(43) != intHashMap.end());\n\t\t\tEATEST_VERIFY(intHashMap.find(44) != intHashMap.end());\n\t\t#endif\n\t}\n\n\t// Can't use move semantics with hash_map::operator[]\n\t//\n\t// GCC has a bug with overloading rvalue and lvalue function templates.\n\t// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425\n\t// \n\t// error: 'eastl::pair<T1, T2>::pair(T1&&) [with T1 = const int&; T2 = const int&]' cannot be overloaded\n\t// error: with 'eastl::pair<T1, T2>::pair(const T1&) [with T1 = const int&; T2 = const int&]'\n\t#if !defined(EA_COMPILER_GNUC)\n\t{\n\t\tEA_DISABLE_VC_WARNING(4626)\n\t\tstruct Key\n\t\t{\n\t\t\tKey() {}\n\t\t\tKey(Key&&) {}\n\t\t\tKey(const Key&) {}\n\t\t\tbool operator==(const Key&) const { return true; }\n\t\t};\n\t\tEA_RESTORE_VC_WARNING()\n\n\t\tstruct Hash\n\t\t{\n\t\t\tstd::size_t operator()(const Key&) const { return 0; }\n\t\t};\n\n\t\tKey key1, key2;\n\t\teastl::hash_map<Key, int, Hash> hm;\n\t\thm[eastl::move(key1)] = 12345;\n\n\t\tEATEST_VERIFY(hm[eastl::move(key2)] == 12345);\n\t}\n\t#endif\n\n\t{\n\t\tusing AllocatorType = CountingAllocator;\n\t\tusing String = eastl::basic_string<char8_t, AllocatorType>;\n\t\tusing StringStringMap = eastl::map<String, String, eastl::equal_to<String>, AllocatorType>;\n\t\tusing StringStringHashMap = eastl::hash_map<String, String, eastl::string_hash<String>, eastl::equal_to<String>, AllocatorType>;\n\t\tAllocatorType::resetCount();\n\n\t\t{\n\t\t\tStringStringHashMap myMap(5); // construct map with 5 buckets, so we don't rehash on insert\n\t\t\tString key(\"mykey01234567890000000000000000000000000000\");\n\t\t\tString value(\"myvalue01234567890000000000000000000000000000\");\n\t\t\tAllocatorType::resetCount();\n\n\t\t\tmyMap.insert(eastl::make_pair(eastl::move(key), eastl::move(value)));\n\t\t\tEATEST_VERIFY(AllocatorType::getTotalAllocationCount() == 1);\n\t\t}\n\t\t{\n\t\t\tStringStringHashMap myMap(5); // construct map with 5 buckets, so we don't rehash on insert\n\t\t\tString key(\"mykey01234567890000000000000000000000000000\");\n\t\t\tString value(\"myvalue01234567890000000000000000000000000000\");\n\t\t\tAllocatorType::resetCount();\n\n\t\t\tmyMap.emplace(eastl::move(key), eastl::move(value));\n\t\t\tEATEST_VERIFY(AllocatorType::getTotalAllocationCount() == 1);\n\t\t}\n\t\t{\n\t\t\tStringStringMap myMap;\n\t\t\tString key(\"mykey01234567890000000000000000000000000000\");\n\t\t\tString value(\"myvalue01234567890000000000000000000000000000\");\n\t\t\tAllocatorType::resetCount();\n\n\t\t\tmyMap.insert(eastl::make_pair(eastl::move(key), eastl::move(value)));\n\t\t\tEATEST_VERIFY(AllocatorType::getTotalAllocationCount() == 1);\n\t\t}\n\t\t{\n\t\t\tStringStringMap myMap;\n\t\t\tString key(\"mykey01234567890000000000000000000000000000\");\n\t\t\tString value(\"myvalue01234567890000000000000000000000000000\");\n\t\t\tAllocatorType::resetCount();\n\n\t\t\tmyMap.emplace(eastl::move(key), eastl::move(value));\n\t\t\tEATEST_VERIFY(AllocatorType::getTotalAllocationCount() == 1);\n\t\t}\n\t}\n\n\t\n\t{\n\t\tstruct name_equals\n\t\t{\n\t\t\tbool operator()(const eastl::pair<int, const char*>& a, const eastl::pair<int, const char*>& b) const\n\t\t\t{\n\t\t\t\tif (a.first != b.first)\n\t\t\t\t\treturn false;\n\n\t\t\t\treturn strcmp(a.second, b.second) == 0;\n\t\t\t}\n\t\t};\n\n\t\t{\n\t\t\tint n = 42;\n\t\t\tconst char* pCStrName = \"electronic arts\";\n\t\t\teastl::hash_map<eastl::pair<int, const char*>, bool, eastl::hash<eastl::pair<int, const char*>>, name_equals, eastl::allocator> m_TempNames;\n\t\t\tm_TempNames[eastl::make_pair(n, pCStrName)] = true;\n\n\t\t\tauto isFound = (m_TempNames.find(eastl::make_pair(n, pCStrName)) != m_TempNames.end());\n\t\t\tVERIFY(isFound);\n\t\t}\n\t}\n\n\t{ // User reported regression for code changes limiting hash code generated for non-arithmetic types.\n\t    { VERIFY(HashTest<char>{}('a') == size_t('a')); }\n\t    { VERIFY(HashTest<int>{}(42) == 42); }\n\t    { VERIFY(HashTest<unsigned>{}(42) == 42); }\n\t    { VERIFY(HashTest<signed>{}(42) == 42); }\n\t    { VERIFY(HashTest<short>{}(short(42)) == 42); }\n\t    { VERIFY(HashTest<unsigned short>{}((unsigned short)42) == 42); }\n\t    { VERIFY(HashTest<int>{}(42) == 42); }\n\t    { VERIFY(HashTest<unsigned int>{}(42) == 42); }\n\t    { VERIFY(HashTest<long int>{}(42) == 42); }\n\t    { VERIFY(HashTest<unsigned long int>{}(42) == 42); }\n\t    { VERIFY(HashTest<long long int>{}(42) == 42); }\n\t    { VERIFY(HashTest<unsigned long long int>{}(42) == 42); }\n\n\t#if defined(EA_HAVE_INT128) && EA_HAVE_INT128\n\t    { VERIFY(HashTest<uint128_t>{}(UINT128_C(0, 42)) == 42); }\n\t#endif\n    }\n\n\t{ // heterogenous functions - hash_map\n\t\teastl::hash_map<ExplicitString, int, ExplicitStringHash, eastl::equal_to<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestMapHeterogeneousInsertion<decltype(m)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\t{ // heterogenous functions - hash_multimap\n\t\teastl::hash_multimap<ExplicitString, int, ExplicitStringHash, eastl::equal_to<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\t{ // heterogenous functions - hash_set\n\t\teastl::hash_set<ExplicitString, ExplicitStringHash, eastl::equal_to<void>> s{ ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestSetHeterogeneousInsertion<decltype(s)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // heterogenous functions - hash_multiset\n\t\teastl::hash_multiset<ExplicitString, ExplicitStringHash, eastl::equal_to<void>> s{ ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // insert(P&&) was incorrectly defined in the hashtable base type.\n\t\t// should never have been defined for hash_set, hash_multiset.\n\t\t// it does not correctly support heterogeneous insertion (unconditionally creates a key_type).\n\t\t// this test exists purely to check that the addition of insert(KX&&) for heterogeneous keys didn't break existing (unlikely) calls to insert(P&&) that\n\t\t// shouldn't have been supported.\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\teastl::hash_set<ExplicitString, ExplicitStringHashNonTransparent, eastl::equal_to<void>> s = { ExplicitString::Create(\"a\") };\n\t\ts.insert(\"a\");\n\n\t\teastl::hash_multiset<ExplicitString, ExplicitStringHashNonTransparent, eastl::equal_to<void>> s2 = { ExplicitString::Create(\"a\") };\n\t\ts2.insert(\"a\");\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\t\teastl::hash_set<ExplicitString, ExplicitStringHash, eastl::equal_to<void>> s3 = { ExplicitString::Create(\"a\") };\n\t\ts3.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\n\t\teastl::hash_multiset<eastl::string, StringHash, eastl::equal_to<void>> s4 = { \"a\" };\n\t\ts4.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\t}\n\n\treturn nErrorCount;\n}\n\nstruct TestHashTable_MT_Data\n{\n\tEA::Thread::Semaphore mStartSema{0};\n\tEA::Thread::Semaphore mEndSema{0};\n};\n\nstatic intptr_t useHashTableFn(void* x)\n{\n\tint nErrorCount = 0;\n\tauto& data = *static_cast<TestHashTable_MT_Data*>(x);\n\n\tdata.mStartSema.Wait();\n\tfor (int loops = 0; loops < 100; ++loops)\n\t{\n\t\teastl::unordered_map<int, int> localMap;\n\n\t\t// this is a silly test, but the goal is to exercise clearing an empty hashtable on\n\t\t// different threads under TSAN.\n\n\t\t// This call to clear used to trip TSAN in a previous version of EASTL.\n\t\tlocalMap.clear();\n\n\t\tconstexpr int kEntries = 1000;\n\t\tfor (int i = 0; i < kEntries; ++i)\n\t\t{\n\t\t\tlocalMap[i] = i;\n\t\t}\n\t\tfor (int i = 0; i < kEntries; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(localMap[i] == i);\n\t\t}\n\n\t\tlocalMap.clear();\n\t}\n\n\tdata.mEndSema.Post();\n\n\t// Needed by the Thread::Begin API.\n\treturn 0;\n}\n\nvoid TestHashTable_MT()\n{\n\t// TSAN regression checking, using different hash tables on different threads should not\n\t// trigger TSAN issues.\n\n\tTestHashTable_MT_Data data;\n\tEA::Thread::Thread threads[2];\n\n\tthreads[0].Begin(useHashTableFn, static_cast<void*>(&data));\n\tthreads[1].Begin(useHashTableFn, static_cast<void*>(&data));\n\n\tdata.mStartSema.Post(2);\n\n\tdata.mEndSema.Wait();\n\tdata.mEndSema.Wait();\n}\n"
  },
  {
    "path": "test/source/TestHeap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/heap.h>\n#include <EASTL/vector.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/sort.h>\n#include <EABase/eabase.h>\n#include <algorithm> //std::pop_heap\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <algorithm>\n#endif\n\n#if defined(_MSC_VER)\n\t#pragma warning(pop)\n#endif\n\n\nusing namespace eastl;\n\n\n\n\nint VerifyHeaps(uint32_t* pArray2, uint32_t* pArray3, uint32_t nArraySize)\n{\n\tint  nErrorCount = 0;\n\tbool bResult;\n\n\tbResult = is_heap(pArray2, pArray2 + nArraySize);\n\tEATEST_VERIFY(bResult);\n\n\tbResult = is_heap(pArray3, pArray3 + nArraySize);\n\tEATEST_VERIFY(bResult);\n\n\t// bResult = (memcmp(pArray2, pArray3, nArraySize * sizeof(uint32_t)) == 0);\n\t// EATEST_VERIFY(bResult);\n\t//\n\t// The above does not work on iOS since CM added -stdlib=libc++ to the linker switch\n\t// even though it was already used in our compile switches.\n\t// It would appear that on clang or iOS the heap is actually structured in a unique way,\n\t// possibly for optimization. Iterating over the array and using pop_heap verifies\n\t// that the heaps have the same elements and are retrieved in the same manner.\n\t// The underlying storage may be different.\n\tuint32_t* pArray2_copy           = new uint32_t[nArraySize];\n\tuint32_t* pArray3_copy           = new uint32_t[nArraySize];\n\t\n\tmemcpy(pArray2_copy, pArray2, sizeof(uint32_t) * nArraySize);\n\tmemcpy(pArray3_copy, pArray3, sizeof(uint32_t) * nArraySize);\n\t\n\tfor(uint32_t i = 0; i < nArraySize; i++)\n\t{\n\t\tEATEST_VERIFY(pArray2_copy[0] == pArray3_copy[0]);\n\t\tstd::pop_heap(pArray2_copy, pArray2_copy + nArraySize - i);\n\t\tpop_heap(pArray3_copy, pArray3_copy + nArraySize - i);\n\t}\n\tdelete[] pArray2_copy;\n\tdelete[] pArray3_copy;\n\treturn nErrorCount;\n}\n\n\n\nint TestHeap()\n{\n\tint nErrorCount = 0;\n\n\t// We do a bit of our heap testing by simply doing rng operations and comparing\n\t// to a standard STL implementation of the heap functions.\n\n\t{\n\t\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\t\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\t\tconst int32_t kMinArraySize = 2;\n\t\t\tconst int32_t kMaxArraySize = 1000;\n\t\t\tconst int32_t kMinValue     = 0;\n\t\t\tconst int32_t kMaxValue     = 500;\n\n\t\t\t// To consider, instead of using 25, try conditioning on EA::UnitTest::GetSystemSpeed().\n\t\t\t// I tried this, but even though Caps and PC are the same system speed, Caps was quite slower\n\t\t\t// than PC doing 75 loops\n\t\t\tfor(int i = 0; (i < 25) && (nErrorCount == 0); i++)\n\t\t\t{\n\t\t\t\t//\n\t\t\t\t// Set up an array of data to work with as a heap.\n\t\t\t\tuint32_t  nArraySizeInitial = (uint32_t)rng.RandRange(kMinArraySize, kMaxArraySize);\n\t\t\t\tuint32_t  nArraySize        = nArraySizeInitial;\n\t\t\t\tuint32_t* pArray1           = new uint32_t[nArraySize + 1]; // Array1 is the original data. // +1 because we append an additional element in the is_heap_until test below.\n\t\t\t\tuint32_t* pArray2           = new uint32_t[nArraySize + 1]; // Array2 is the data in std::make_heap\n\t\t\t\tuint32_t* pArray3           = new uint32_t[nArraySize + 1]; // Array3 is the data in eastl::make_heap.\n\n\t\t\t\tfor(uint32_t j = 0; j < nArraySize; j++)\n\t\t\t\t\tpArray1[j] = pArray2[j] = pArray3[j] = (uint32_t)rng.RandRange(kMinValue, kMaxValue);\n\n\n\t\t\t\t// make_heap\n\t\t\t\tstd::make_heap(pArray2, pArray2 + nArraySize);\n\t\t\t\tmake_heap(pArray3, pArray3 + nArraySize);\n\t\t\t\tVerifyHeaps(pArray2, pArray3, nArraySize);\n\n\n\t\t\t\t// is_heap_until\n\t\t\t\t{\n\t\t\t\t\tpArray3[nArraySize] = kMaxValue + 1;    // Append a value which is guaranteed to break the heap.\n\t\t\t\t\tuint32_t* pUntil = is_heap_until(pArray3, pArray3 + (nArraySize + 1));\n\t\t\t\t\tEATEST_VERIFY_F(pUntil == (pArray3 + nArraySize), \"is_heap_until failure in iteration %d for array size %I32u.\", nArraySize);\n\t\t\t\t}\n\n\n\t\t\t\t// pop_heap\n\t\t\t\tconst int popCount = min<uint32_t>(200, nArraySize);\n\t\t\t\tfor(int k = 0; (k < popCount) && (nErrorCount == 0); k++, nArraySize--)\n\t\t\t\t{\n\t\t\t\t\tstd::pop_heap(pArray2, pArray2 + nArraySize);\n\t\t\t\t\tpArray2[nArraySize - 1] = 0xffffffff; // Set it to some value so we can recognize it in a debugger.\n\n\t\t\t\t\tpop_heap(pArray3, pArray3 + nArraySize);\n\t\t\t\t\tpArray3[nArraySize - 1] = 0xffffffff;\n\n\t\t\t\t\tVerifyHeaps(pArray2, pArray3, nArraySize - 1);\n\t\t\t\t}\n\n\n\t\t\t\t// push_heap\n\t\t\t\tconst int pushCount = popCount;\n\t\t\t\tfor(int m = 0; (m < pushCount) && (nErrorCount == 0); m++, nArraySize++)\n\t\t\t\t{\n\t\t\t\t\tconst uint32_t n = (uint32_t)rng.RandRange(kMinValue, kMaxValue);\n\n\t\t\t\t\tpArray2[nArraySize] = n;\n\t\t\t\t\tstd::push_heap(pArray2, pArray2 + nArraySize + 1);\n\n\t\t\t\t\tpArray3[nArraySize] = n;\n\t\t\t\t\tpush_heap(pArray3, pArray3 + nArraySize + 1);\n\n\t\t\t\t\tVerifyHeaps(pArray2, pArray3, nArraySize + 1);\n\t\t\t\t}\n\n\t\t\t\tuint32_t originalSize = nArraySize;\n\t\t\t\t// remove_heap\n\t\t\t\t// Because the heap that stdlib on iOS and other platforms differs, different elements\n\t\t\t\t// will be removed. After calling remove heap, we cannot call VerifyHeaps anymore, but\n\t\t\t\t// can still check that heap format is retained.\n\t\t\t\tconst int eraseCount = popCount;\n\t\t\t\tfor(int e = 0; (e < eraseCount) && (nErrorCount == 0); e++, nArraySize--)\n\t\t\t\t{\n\t\t\t\t\tconst uint32_t position = (uint32_t)rng.RandRange(0, nArraySize);\n\n\t\t\t\t\tremove_heap(pArray2, nArraySize, position);\n\t\t\t\t\tpArray2[nArraySize - 1] = 0xffffffff;\n\n\t\t\t\t\tremove_heap(pArray3, nArraySize, position);\n\t\t\t\t\tpArray3[nArraySize - 1] = 0xffffffff;\n\n\t\t\t\t\t//use is_heap_until to verify remove_heap is working.\n\t\t\t\t\tif(nArraySize > 1) //If we just popped last element, don't use is_heap_until\n\t\t\t\t\t{\n\t\t\t\t\t\tuint32_t* pUntil = is_heap_until(pArray2, pArray2 + (nArraySize));\n\t\t\t\t\t\tEATEST_VERIFY_F(pUntil == (pArray2 + nArraySize - 1), \"pUntil failure for pArray2 with array size %I32u.\", nArraySize);\n\t\t\t\t\t\t\n\t\t\t\t\t\tpUntil = is_heap_until(pArray3, pArray3 + (nArraySize));\n\t\t\t\t\t\tEATEST_VERIFY_F(pUntil == (pArray3 + nArraySize - 1), \"failure for pArray3 with array size %I32u.\", nArraySize);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// push_heap -- increase the heap size back to the original size.\n\t\t\t\tfor(int m = 0; (m < pushCount) && (nErrorCount == 0); m++, nArraySize++)\n\t\t\t\t{\n\t\t\t\t\tconst uint32_t n = (uint32_t)rng.RandRange(kMinValue, kMaxValue);\n\n\t\t\t\t\tpArray2[nArraySize] = n;\n\t\t\t\t\tstd::push_heap(pArray2, pArray2 + nArraySize + 1);\n\n\t\t\t\t\tpArray3[nArraySize] = n;\n\t\t\t\t\tpush_heap(pArray3, pArray3 + nArraySize + 1);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tEATEST_VERIFY_F(nArraySize == originalSize, \"Array size is %d not original size %d\", nArraySize , originalSize);\n\n\t\t\t\tuint32_t* pUntil = is_heap_until(pArray2, pArray2 + (nArraySize));\n\t\t\t\tEATEST_VERIFY_F(pUntil == (pArray2 + nArraySize), \"failure for pArray2 with array size %I32u.\", nArraySize);\n\t\t\t\tpUntil = is_heap_until(pArray3, pArray3 + (nArraySize));\n\t\t\t\tEATEST_VERIFY_F(pUntil == (pArray3 + nArraySize), \"failure for pArray3 with array size %I32u.\", nArraySize);\n\n\n\t\t\t\t// change_heap\n\t\t\t\tconst int changeCount = popCount;\n\t\t\t\tfor(int r = 0; (r < changeCount) && (nErrorCount == 0); r++, nArraySize--)\n\t\t\t\t{\n\t\t\t\t\tuint32_t position = (uint32_t)rng.RandRange(0, nArraySize);\n\t\t\t\t\tuint32_t newValue = (uint32_t)rng.RandRange(kMinValue, kMaxValue);\n\n\t\t\t\t\tif(rng.RandLimit(5) == 0) // One in five chance that we use the heap top position.\n\t\t\t\t\t\tposition = 0;\n\t\t\t\t\tif(rng.RandLimit(5) != 0) // One in five chance that we do no change.\n\t\t\t\t\t\tpArray2[position] = pArray3[position] = newValue;\n\n\t\t\t\t\t// There is no std::change_heap, so we just use ours for this test.\n\t\t\t\t\tchange_heap(pArray2, nArraySize, position);\n\t\t\t\t\tpArray2[nArraySize - 1] = 0xffffffff;\n\n\t\t\t\t\tchange_heap(pArray3, nArraySize, position);\n\t\t\t\t\tpArray3[nArraySize - 1] = 0xffffffff;\n\t\t\t\t\t\n\t\t\t\t\tif(nArraySize > 1) //If we just removed last element, don't use is_heap_until\n\t\t\t\t\t{\n\t\t\t\t\t\tuint32_t* pUntilChanged = is_heap_until(pArray2, pArray2 + (nArraySize));\n\t\t\t\t\t\tEATEST_VERIFY_F(pUntilChanged == (pArray2 + nArraySize - 1), \"failure for pArray2 with array size %I32u.\", nArraySize);\n\t\t\t\t\t\tpUntilChanged = is_heap_until(pArray3, pArray3 + (nArraySize));\n\t\t\t\t\t\tEATEST_VERIFY_F(pUntilChanged == (pArray3 + nArraySize - 1), \"failure for pArray3 with array size %I32u.\", nArraySize);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\t// sort_heap\n\t\t\t\tstd::sort_heap(pArray2, pArray2 + nArraySize);\n\t\t\t\tsort_heap(pArray3, pArray3 + nArraySize);\n\n\t\t\t\tfor(uint32_t q = 1; (q < nArraySize)  && (nErrorCount == 0); q++)\n\t\t\t\t{\n\t\t\t\t\tEATEST_VERIFY(pArray2[q-1] <= pArray2[q]);\n\t\t\t\t\tEATEST_VERIFY(pArray3[q-1] <= pArray3[q]);\n\t\t\t\t}\n\t\t\t\t// Free our heap data.\n\t\t\t\tdelete[] pArray1;\n\t\t\t\tdelete[] pArray2;\n\t\t\t\tdelete[] pArray3;\n\t\t\t}\n\n\t\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t}\n\n\t{\n\t\t// Test aligned types.\n\n\t\t// Aligned objects should be CustomAllocator instead of the default, because the \n\t\t// EASTL default might be unable to do aligned allocations, but CustomAllocator always can.\n\t\teastl::vector<Align64, CustomAllocator> heap;\n\n\t\tfor(int i = 0; i < 16; i++)\n\t\t\theap.push_back(Align64(i));\n\n\t\teastl::make_heap(heap.begin(), heap.end());\n\t\tEATEST_VERIFY(is_heap(heap.begin(), heap.end()));\n\n\t\theap.push_back(Align64(7));\n\t\teastl::push_heap(heap.begin(), heap.end());\n\t\tEATEST_VERIFY(is_heap(heap.begin(), heap.end()));\n\n\t\theap.push_back(Align64(7));\n\t\teastl::push_heap(heap.begin(), heap.end());\n\t\theap.pop_back();\n\t\tEATEST_VERIFY(is_heap(heap.begin(), heap.end()));\n\n\t\teastl::remove_heap(heap.begin(), heap.size(), (eastl_size_t)4);\n\t\theap.pop_back();\n\t\tEATEST_VERIFY(is_heap(heap.begin(), heap.end()));\n\n\t\teastl::sort_heap(heap.begin(), heap.end());\n\t\tEATEST_VERIFY(is_sorted(heap.begin(), heap.end()));\n\t}\n\n\t{\n\t\tAlign16 heap[5];\n\n\t\teastl::make_heap(heap, heap + 5);\n\t\tEATEST_VERIFY(is_heap(heap, heap + 5));\n\n\t\teastl::partial_sort(heap, heap + 3, heap + 5);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestIntrusiveHash.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/internal/intrusive_hashtable.h>\n#include <EASTL/intrusive_hash_set.h>\n#include <EASTL/intrusive_hash_map.h>\n#include <EABase/eabase.h>\n\n\n\nusing namespace eastl;\n\n\nnamespace\n{\n\tstruct SetWidget : public intrusive_hash_node\n\t{\n\t\tSetWidget(int x = 0)\n\t\t\t: mX(x) { }\n\t\tint mX;\n\t};\n\n\tinline bool operator==(const SetWidget& a, const SetWidget& b)\n\t\t{ return a.mX == b.mX; }\n\n\tstruct SWHash\n\t{\n\t\tsize_t operator()(const SetWidget& sw) const\n\t\t{\n\t\t\treturn (size_t)sw.mX;\n\t\t}\n\t};\n\n\tstruct SetWidgetComparable // Exists for the sole purpose of testing the find_as function.\n\t{\n\t\tSetWidgetComparable(int x = 0)\n\t\t\t: mX(x) { }\n\t\tint mX;\n\t};\n\n\tstruct SWCHash\n\t{\n\t\tsize_t operator()(const SetWidgetComparable& swc) const\n\t\t{\n\t\t\treturn (size_t)swc.mX;\n\t\t}\n\t};\n\n\tbool operator==(const SetWidget& a, const SetWidgetComparable& b)\n\t\t{ return a.mX == b.mX; }\n\n\n\n\tstruct MapWidget : public intrusive_hash_node_key<int>\n\t{\n\t\tMapWidget(int x = 0)\n\t\t\t: mX(x) { }\n\t\tint mX;\n\t};\n\n\tinline bool operator==(const MapWidget& a, const MapWidget& b)\n\t\t{ return a.mX == b.mX; }\n\n\t//struct MapWidgetComparable // Exists for the sole purpose of testing the find_as function.\n\t//{\n\t//    MapWidgetComparable(int x = 0)\n\t//        : mX(x) { }\n\t//    int mX;\n\t//};\n\t//\n\t//bool operator==(const SetWidget& a, const MapWidgetComparable& b)\n\t//    { return a.mX == b.mX; }\n\n\n\n\n\t// IHWidget\n\t//\n\t// Implements the intrusive node data directly instead of inheriting from intrusive_hash_node.\n\t//\n\tstruct IHWidget\n\t{\n\t\tIHWidget(int x = 0)\n\t\t\t: mX(x) { }\n\n\t\tint         mX;\n\t\tIHWidget*   mpNext;\n\t\ttypedef int key_type;\n\t\tint         mKey;\n\n\t};\n\n\tinline bool operator==(const IHWidget& a, const IHWidget& b)\n\t\t{ return a.mX == b.mX; }\n\n\tstruct IHWHash\n\t{\n\t\tsize_t operator()(const IHWidget& ihw) const\n\t\t{\n\t\t\treturn (size_t)ihw.mX;\n\t\t}\n\t};\n\n} // namespace\n\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\n//template class intrusive_hash_set<SetWidget>;\n//template class intrusive_hash_map<MapWidget>;\n\n\ntemplate class eastl::intrusive_hashtable<SetWidget, SetWidget, SWHash, eastl::equal_to<SetWidget>, 37, true, true>;\ntemplate class eastl::intrusive_hashtable<int, MapWidget, eastl::hash<int>, eastl::equal_to<int>, 37, false, true>;\n\ntemplate class eastl::intrusive_hash_set<SetWidget, 37, SWHash>;\ntemplate class eastl::intrusive_hash_multiset<SetWidget, 37, SWHash>;\n\ntemplate class eastl::intrusive_hash_map<int, MapWidget, 37>;\ntemplate class eastl::intrusive_hash_multimap<int, MapWidget, 37>;\n\ntemplate class eastl::intrusive_hash_set<IHWidget, 37, IHWHash>;\ntemplate class eastl::intrusive_hash_multiset<IHWidget, 37, IHWHash>;\n\ntemplate class eastl::intrusive_hash_map<int, IHWidget, 37, IHWHash>;\ntemplate class eastl::intrusive_hash_multimap<int, IHWidget, 37, IHWHash>;\n\n\n\n\n\nint TestIntrusiveHash()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tSetWidget sw1, sw2;\n\t\tVERIFY(sw1 == sw2);\n\n\t\tMapWidget mw1, mw2;\n\t\tVERIFY(mw1 == mw2);\n\n\t\tIHWidget iw1, iw2;\n\t\tVERIFY(iw1 == iw2);\n\n\t\tIHWHash ih1;\n\t\tVERIFY(ih1.operator()(iw1) == ih1.operator()(iw2));\n\t}\n\n\t{\n\t\t// Test intrusive_hash_set\n\n\t\tconst size_t kBucketCount = 37;\n\t\ttypedef intrusive_hash_set<SetWidget, kBucketCount, SWHash> IHM_SW;\n\n\t\tconst size_t kArraySize = 100;\n\t\tSetWidget swArray[kArraySize];\n\n\t\tint nExpectedKeySum = 0; // We use this as a checksum in order to do validity checks below.\n\n\t\tfor(size_t i = 0; i < kArraySize; i++)\n\t\t{\n\t\t\tswArray[i].mX    = (int)i;\n\t\t\tnExpectedKeySum += (int)i;\n\t\t}\n\n\n\t\t// const key_equal& key_eq() const;\n\t\t// key_equal&       key_eq();\n\t\tIHM_SW       ih;\n\t\tconst IHM_SW ihc;\n\n\t\tconst IHM_SW::key_equal& ke = ihc.key_eq();\n\t\tih.key_eq() = ke;\n\n\n\t\t// intrusive_hashtable(const Hash&, const Equal&);\n\t\t// void swap(this_type& x);\n\t\t// size_type size() const;\n\t\t// bool empty() const;\n\t\t// size_type bucket_count() const;\n\t\t// size_type bucket_size(size_type n) const;\n\t\t// float load_factor() const;\n\t\t// void clear();\n\t\t// bool validate() const;\n\n\t\tIHM_SW ihmSW1;\n\t\tIHM_SW ihmSW2;\n\n\t\tVERIFY(ihmSW1.size() == 0);\n\t\tVERIFY(ihmSW1.empty());\n\t\tVERIFY(ihmSW1.validate());\n\t\tVERIFY(ihmSW2.validate());\n\n\t\tihmSW1.swap(ihmSW2);\n\n\t\tVERIFY(ihmSW1.validate());\n\t\tVERIFY(ihmSW2.validate());\n\t\tVERIFY(ihmSW2.bucket_count() == kBucketCount);\n\t\tVERIFY(ihmSW2.bucket_size(0) == 0);\n\t\tVERIFY(ihmSW2.bucket_size(kBucketCount - 1) == 0);\n\t\tVERIFY(ihmSW1.load_factor() == 0.f);\n\t\tVERIFY(ihmSW2.load_factor() == 0.f);\n\n\t\tihmSW1.clear();\n\t\tVERIFY(ihmSW1.validate());\n\t\tVERIFY(ihmSW1.begin() == ihmSW1.end());\n\n\n\t\t// void insert(InputIterator first, InputIterator last);\n\t\t// insert_return_type insert(value_type& value);\n\t\t// void swap(this_type& x);\n\t\t// void clear();\n\n\t\tihmSW1.clear();\n\t\tihmSW1.insert(swArray, swArray + (kArraySize - 10));\n\t\tfor(int i = 0; i < 10; i++) // insert the remaining elements via the other insert function.\n\t\t{\n\t\t\tpair<IHM_SW::iterator, bool> result = ihmSW1.insert(swArray[(kArraySize - 10) + i]);\n\t\t\tVERIFY(result.second == true);\n\t\t}\n\n\t\tVERIFY(ihmSW1.size() == kArraySize);\n\t\tVERIFY(ihmSW1.validate());\n\n\t\tfor(size_t i = 0; i < kArraySize; i++)\n\t\t{\n\t\t\t// Try to re-insert the elements. All insertions should fail.\n\t\t\tpair<IHM_SW::iterator, bool> result = ihmSW1.insert(swArray[i]);\n\t\t\tVERIFY(result.second == false);\n\t\t}\n\n\t\tVERIFY(ihmSW1.size() == kArraySize);\n\t\tVERIFY(!ihmSW1.empty());\n\t\tVERIFY(ihmSW1.validate());\n\n\t\tihmSW2.clear();\n\t\tihmSW1.swap(ihmSW2);\n\n\n\t\t// size_type size() const;\n\t\t// bool empty() const;\n\t\t// size_type count(const key_type& k) const;\n\t\t// size_type bucket_size(size_type n) const;\n\t\t// float load_factor() const;\n\t\t// size_type bucket(const key_type& k) const\n\n\t\tVERIFY(ihmSW1.validate());\n\t\tVERIFY(ihmSW2.validate());\n\t\tVERIFY(ihmSW1.size() == 0);\n\t\tVERIFY(ihmSW1.empty());\n\t\tVERIFY(ihmSW2.size() == kArraySize);\n\t\tVERIFY(!ihmSW2.empty());\n\t\tVERIFY(ihmSW1.load_factor() == 0.f);\n\t\tVERIFY(ihmSW2.load_factor() > 2.f);\n\t\tVERIFY(ihmSW1.count(0) == 0);\n\t\tVERIFY(ihmSW1.count(999999) == 0);\n\t\tVERIFY(ihmSW2.count(0) == 1);\n\t\tVERIFY(ihmSW2.count(999999) == 0);\n\t\tVERIFY(ihmSW2.bucket_size(0) == 3);     // We just happen to know this should be so based on the distribution.\n\t\tVERIFY(ihmSW2.bucket(13)    == (13    % kBucketCount)); // We know this is so because our hash function simply returns n.\n\t\tVERIFY(ihmSW2.bucket(10000) == (10000 % kBucketCount)); // We know this is so because our hash function simply returns n.\n   \n\n\t\t// iterator begin();\n\t\t// const_iterator begin() const;\n\n\t\tihmSW1.swap(ihmSW2);\n\t\tint nSum = 0; \n\n\t\tfor(IHM_SW::iterator it = ihmSW1.begin(); it != ihmSW1.end(); ++it)\n\t\t{\n\t\t\tconst SetWidget& sw = *it; // Recall that set iterators are const_iterators.\n\n\t\t\tnSum += sw.mX;\n\n\t\t\tconst int iresult = ihmSW1.validate_iterator(it);\n\t\t\tVERIFY(iresult == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\tIHM_SW::iterator itf = ihmSW1.find(sw.mX);\n\t\t\tVERIFY(itf == it);\n\t\t}\n\n\t\tVERIFY(nSum == nExpectedKeySum);\n\n\n\t\t// iterator end();\n\t\t// const_iterator end() const;\n\n\t\tconst IHM_SW& ihmSW1Const = ihmSW1;\n\n\t\tfor(IHM_SW::const_iterator itc = ihmSW1Const.begin(); itc != ihmSW1Const.end(); ++itc)\n\t\t{\n\t\t\tconst SetWidget& sw = *itc;\n\n\t\t\tIHM_SW::const_iterator itf = ihmSW1.find(sw.mX);\n\t\t\tVERIFY(itf == itc);\n\t\t}\n\n\n\t\t// local_iterator begin(size_type n)\n\t\t// local_iterator end(size_type)\n\n\t\tfor(IHM_SW::local_iterator itl = ihmSW1.begin(5); itl != ihmSW1.end(5); ++itl)\n\t\t{\n\t\t\tconst SetWidget& sw = *itl; // Recall that set iterators are const_iterators.\n\n\t\t\tVERIFY((sw.mX % kBucketCount) == 5);\n\t\t}\n\n\n\t\t// const_local_iterator begin(size_type n) const\n\t\t// const_local_iterator end(size_type) const\n\n\t\tfor(IHM_SW::const_local_iterator itlc = ihmSW1Const.begin(5); itlc != ihmSW1Const.end(5); ++itlc)\n\t\t{\n\t\t\tconst SetWidget& sw = *itlc;\n\n\t\t\tVERIFY((sw.mX % kBucketCount) == 5);\n\t\t}\n\n\n\t\t// iterator       find(const key_type& k);\n\t\t// const_iterator find(const key_type& k) const;\n\n\t\tIHM_SW::iterator itf = ihmSW1.find(SetWidget(99999));\n\t\tVERIFY(itf == ihmSW1.end());\n\n\t\tIHM_SW::const_iterator itfc = ihmSW1Const.find(SetWidget(99999));\n\t\tVERIFY(itfc == ihmSW1Const.end());\n\n\n\t\t// iterator       find_as(const U& u);\n\t\t// const_iterator find_as(const U& u) const;\n\n\t\t//itf = ihmSW1.find_as(SetWidget(7)); // Can't work unless there was a default eastl::hash function for SetWidget.\n\t\t//VERIFY(itf->mX == 7);\n\n\t\t//itfc = ihmSW1Const.find_as(SetWidget(7));\n\t\t//VERIFY(itfc->mX == 7);\n\n\n\t\t// iterator       find_as(const U& u, UHash uhash, BinaryPredicate predicate);\n\t\t// const_iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate) const;\n\n\t\titf = ihmSW1.find_as(SetWidgetComparable(7), SWCHash(), eastl::equal_to<>());\n\t\tVERIFY(itf->mX == 7);\n\n\t\titfc = ihmSW1Const.find_as(SetWidgetComparable(7), SWCHash(), eastl::equal_to<>());\n\t\tVERIFY(itfc->mX == 7);\n\n\n\t\t// iterator  erase(iterator);\n\t\t// iterator  erase(iterator, iterator);\n\t\t// size_type erase(const key_type&);\n\n\t\teastl_size_t n = ihmSW1.erase(SetWidget(99999));\n\t\tVERIFY(n == 0);\n\n\t\tn = ihmSW1.erase(SetWidget(17));\n\t\tVERIFY(n == 1);\n\n\t\titf = ihmSW1.find(SetWidget(18));\n\t\tVERIFY(itf != ihmSW1.end());\n\t\tVERIFY(ihmSW1.validate_iterator(itf) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmSW1.erase(itf);\n\t\tVERIFY(itf != ihmSW1.end());\n\t\tVERIFY(ihmSW1.validate_iterator(itf) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmSW1.find(SetWidget(18));\n\t\tVERIFY(itf == ihmSW1.end());\n\n\t\titf = ihmSW1.find(SetWidget(19));\n\t\tVERIFY(itf != ihmSW1.end());\n\n\t\tIHM_SW::iterator itf2(itf);\n\t\teastl::advance(itf2, 7);\n\t\tVERIFY(itf2 != ihmSW1.end());\n\t\tVERIFY(ihmSW1.validate_iterator(itf2) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmSW1.erase(itf, itf2);\n\t\tVERIFY(itf != ihmSW1.end());\n\t\tVERIFY(ihmSW1.validate_iterator(itf) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmSW1.find(SetWidget(19));\n\t\tVERIFY(itf == ihmSW1.end());\n\n\n\t\t// eastl::pair<iterator, iterator>             equal_range(const key_type& k);\n\t\t// eastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;\n\n\t\teastl::pair<IHM_SW::iterator, IHM_SW::iterator> p = ihmSW1.equal_range(SetWidget(1));\n\t\tVERIFY(p.first != ihmSW1.end());\n\t\tVERIFY(p.second != ihmSW1.end());\n\n\t\teastl::pair<IHM_SW::const_iterator, IHM_SW::const_iterator> pc = ihmSW1Const.equal_range(SetWidget(1));\n\t\tVERIFY(pc.first != ihmSW1Const.end());\n\t\tVERIFY(pc.second != ihmSW1Const.end());\n\n\n\t\t// void clear();\n\t\t// bool validate() const;\n\t\t// int validate_iterator(const_iterator i) const;\n\n\t\tIHM_SW::iterator itTest;\n\t\tint iresult = ihmSW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == isf_none);\n\n\t\titTest = ihmSW1.begin();\n\t\tiresult = ihmSW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titTest = ihmSW1.end();\n\t\tiresult = ihmSW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == (isf_valid | isf_current));\n\n\t\tihmSW1.clear();\n\t\tihmSW2.clear();\n\t\tVERIFY(ihmSW1.validate());\n\t\tVERIFY(ihmSW2.validate());\n\n\t\titTest = ihmSW1.begin();\n\t\tiresult = ihmSW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == (isf_valid | isf_current));\n\t}\n\n\n\t{\n\t\t// Test intrusive_hash_map\n\n\t\tconst size_t kBucketCount = 37;\n\t\ttypedef intrusive_hash_map<int, MapWidget, kBucketCount> IHM_MW;\n\n\t\tconst size_t kArraySize = 100;\n\t\tMapWidget mwArray[kArraySize];\n\n\t\tint nExpectedKeySum = 0; // We use this as a checksum in order to do validity checks below.\n\n\t\tfor(size_t i = 0; i < kArraySize; i++)\n\t\t{\n\t\t\tmwArray[i].mKey  = (int)i;\n\t\t\tmwArray[i].mX    = (int)i;\n\t\t\tnExpectedKeySum += (int)i;\n\t\t}\n\n\n\t\t// intrusive_hashtable(const Hash&, const Equal&);\n\t\t// void swap(this_type& x);\n\t\t// size_type size() const;\n\t\t// bool empty() const;\n\t\t// size_type bucket_count() const;\n\t\t// size_type bucket_size(size_type n) const;\n\t\t// float load_factor() const;\n\t\t// void clear();\n\t\t// bool validate() const;\n\n\t\tIHM_MW ihmMW1;\n\t\tIHM_MW ihmMW2;\n\n\t\tVERIFY(ihmMW1.size() == 0);\n\t\tVERIFY(ihmMW1.empty());\n\t\tVERIFY(ihmMW1.validate());\n\t\tVERIFY(ihmMW2.validate());\n\n\t\tihmMW1.swap(ihmMW2);\n\n\t\tVERIFY(ihmMW1.validate());\n\t\tVERIFY(ihmMW2.validate());\n\t\tVERIFY(ihmMW2.bucket_count() == kBucketCount);\n\t\tVERIFY(ihmMW2.bucket_size(0) == 0);\n\t\tVERIFY(ihmMW2.bucket_size(kBucketCount - 1) == 0);\n\t\tVERIFY(ihmMW1.load_factor() == 0.f);\n\t\tVERIFY(ihmMW2.load_factor() == 0.f);\n\n\t\tihmMW1.clear();\n\t\tVERIFY(ihmMW1.validate());\n\t\tVERIFY(ihmMW1.begin() == ihmMW1.end());\n\n\n\t\t// void insert(InputIterator first, InputIterator last);\n\t\t// insert_return_type insert(value_type& value);\n\t\t// void swap(this_type& x);\n\t\t// void clear();\n\n\t\tihmMW1.clear();\n\t\tihmMW1.insert(mwArray, mwArray + (kArraySize - 10));\n\t\tfor(int i = 0; i < 10; i++) // insert the remaining elements via the other insert function.\n\t\t{\n\t\t\tpair<IHM_MW::iterator, bool> result = ihmMW1.insert(mwArray[(kArraySize - 10) + i]);\n\t\t\tVERIFY(result.second == true);\n\t\t}\n\n\t\tVERIFY(ihmMW1.size() == kArraySize);\n\t\tVERIFY(ihmMW1.validate());\n\n\t\tfor(size_t i = 0; i < kArraySize; i++)\n\t\t{\n\t\t\t// Try to re-insert the elements. All insertions should fail.\n\t\t\tpair<IHM_MW::iterator, bool> result = ihmMW1.insert(mwArray[i]);\n\t\t\tVERIFY(result.second == false);\n\t\t}\n\n\t\tVERIFY(ihmMW1.size() == kArraySize);\n\t\tVERIFY(!ihmMW1.empty());\n\t\tVERIFY(ihmMW1.validate());\n\n\t\tihmMW2.clear();\n\t\tihmMW1.swap(ihmMW2);\n\n\n\t\t// size_type size() const;\n\t\t// bool empty() const;\n\t\t// size_type count(const key_type& k) const;\n\t\t// size_type bucket_size(size_type n) const;\n\t\t// float load_factor() const;\n\t\t// size_type bucket(const key_type& k) const\n\n\t\tVERIFY(ihmMW1.validate());\n\t\tVERIFY(ihmMW2.validate());\n\t\tVERIFY(ihmMW1.size() == 0);\n\t\tVERIFY(ihmMW1.empty());\n\t\tVERIFY(ihmMW2.size() == kArraySize);\n\t\tVERIFY(!ihmMW2.empty());\n\t\tVERIFY(ihmMW1.load_factor() == 0.f);\n\t\tVERIFY(ihmMW2.load_factor() > 2.f);\n\t\tVERIFY(ihmMW1.count(0) == 0);\n\t\tVERIFY(ihmMW1.count(999999) == 0);\n\t\tVERIFY(ihmMW2.count(0) == 1);\n\t\tVERIFY(ihmMW2.count(999999) == 0);\n\t\tVERIFY(ihmMW2.bucket_size(0) == 3);     // We just happen to know this should be so based on the distribution.\n\t\tVERIFY(ihmMW2.bucket(13)    == (13    % kBucketCount)); // We know this is so because our hash function simply returns n.\n\t\tVERIFY(ihmMW2.bucket(10000) == (10000 % kBucketCount)); // We know this is so because our hash function simply returns n.\n   \n\n\t\t// iterator begin();\n\t\t// const_iterator begin() const;\n\n\t\tihmMW1.swap(ihmMW2);\n\t\tint nSum = 0; \n\n\t\tfor(IHM_MW::iterator it = ihmMW1.begin(); it != ihmMW1.end(); ++it)\n\t\t{\n\t\t\tIHM_MW::value_type& v = *it;\n\n\t\t\tVERIFY(v.mKey == v.mX); // We intentionally made this so above.\n\t\t\tnSum += v.mKey;\n\n\t\t\tconst int iresult = ihmMW1.validate_iterator(it);\n\t\t\tVERIFY(iresult == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\tIHM_MW::iterator itf = ihmMW1.find(v.mKey);\n\t\t\tVERIFY(itf == it);\n\t\t}\n\n\t\tVERIFY(nSum == nExpectedKeySum);\n\n\n\t\t// iterator end();\n\t\t// const_iterator end() const;\n\n\t\tconst IHM_MW& ihmMW1Const = ihmMW1;\n\n\t\tfor(IHM_MW::const_iterator itc = ihmMW1Const.begin(); itc != ihmMW1Const.end(); ++itc)\n\t\t{\n\t\t\tconst IHM_MW::value_type& v = *itc;\n\n\t\t\tVERIFY(v.mKey == v.mX); // We intentionally made this so above.\n\n\t\t\tIHM_MW::const_iterator itf = ihmMW1Const.find(v.mKey);\n\t\t\tVERIFY(itf == itc);\n\t\t}\n\n\n\t\t// local_iterator begin(size_type n)\n\t\t// local_iterator end(size_type)\n\n\t\tfor(IHM_MW::local_iterator itl = ihmMW1.begin(5); itl != ihmMW1.end(5); ++itl)\n\t\t{\n\t\t\tIHM_MW::value_type& v = *itl;\n\n\t\t\tVERIFY(v.mKey == v.mX); // We intentionally made this so above.\n\t\t}\n\n\n\t\t// const_local_iterator begin(size_type n) const\n\t\t// const_local_iterator end(size_type) const\n\n\t\tfor(IHM_MW::const_local_iterator itlc = ihmMW1Const.begin(5); itlc != ihmMW1Const.end(5); ++itlc)\n\t\t{\n\t\t\tconst IHM_MW::value_type& v = *itlc;\n\n\t\t\tVERIFY(v.mKey == v.mX); // We intentionally made this so above.\n\t\t}\n\n\n\t\t// iterator       find(const key_type& k);\n\t\t// const_iterator find(const key_type& k) const;\n\n\t\tIHM_MW::iterator itf = ihmMW1.find(99999);\n\t\tVERIFY(itf == ihmMW1.end());\n\n\t\tIHM_MW::const_iterator itfc = ihmMW1Const.find(99999);\n\t\tVERIFY(itfc == ihmMW1Const.end());\n\n\n\t\t// iterator       find_as(const U& u);\n\t\t// const_iterator find_as(const U& u) const;\n\t\t\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\titf = ihmMW1.find_as(8);\n\t\tVERIFY(itf->mKey == 8);\n\n\t\titfc = ihmMW1Const.find_as(8);\n\t\tVERIFY(itfc->mKey == 8);\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\t\t// iterator  erase(iterator);\n\t\t// iterator  erase(iterator, iterator);\n\t\t// size_type erase(const key_type&);\n\n\t\teastl_size_t n = ihmMW1.erase(99999);\n\t\tVERIFY(n == 0);\n\n\t\tn = ihmMW1.erase(17);\n\t\tVERIFY(n == 1);\n\n\t\titf = ihmMW1.find(18);\n\t\tVERIFY(itf != ihmMW1.end());\n\t\tVERIFY(ihmMW1.validate_iterator(itf) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmMW1.erase(itf);\n\t\tVERIFY(itf != ihmMW1.end());\n\t\tVERIFY(ihmMW1.validate_iterator(itf) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmMW1.find(18);\n\t\tVERIFY(itf == ihmMW1.end());\n\n\t\titf = ihmMW1.find(19);\n\t\tVERIFY(itf != ihmMW1.end());\n\n\t\tIHM_MW::iterator itf2(itf);\n\t\teastl::advance(itf2, 7);\n\t\tVERIFY(itf2 != ihmMW1.end());\n\t\tVERIFY(ihmMW1.validate_iterator(itf2) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmMW1.erase(itf, itf2);\n\t\tVERIFY(itf != ihmMW1.end());\n\t\tVERIFY(ihmMW1.validate_iterator(itf) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titf = ihmMW1.find(19);\n\t\tVERIFY(itf == ihmMW1.end());\n\n\n\t\t// eastl::pair<iterator, iterator>             equal_range(const key_type& k);\n\t\t// eastl::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;\n\n\t\teastl::pair<IHM_MW::iterator, IHM_MW::iterator> p = ihmMW1.equal_range(1);\n\t\tVERIFY(p.first != ihmMW1.end());\n\t\tVERIFY(p.second != ihmMW1.end());\n\n\t\teastl::pair<IHM_MW::const_iterator, IHM_MW::const_iterator> pc = ihmMW1Const.equal_range(1);\n\t\tVERIFY(pc.first != ihmMW1Const.end());\n\t\tVERIFY(pc.second != ihmMW1Const.end());\n\n\n\t\t// void clear();\n\t\t// bool validate() const;\n\t\t// int validate_iterator(const_iterator i) const;\n\n\t\tIHM_MW::iterator itTest;\n\t\tint iresult = ihmMW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == isf_none);\n\n\t\titTest = ihmMW1.begin();\n\t\tiresult = ihmMW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == (isf_valid | isf_current | isf_can_dereference));\n\n\t\titTest = ihmMW1.end();\n\t\tiresult = ihmMW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == (isf_valid | isf_current));\n\n\t\tihmMW1.clear();\n\t\tihmMW2.clear();\n\t\tVERIFY(ihmMW1.validate());\n\t\tVERIFY(ihmMW2.validate());\n\n\t\titTest = ihmMW1.begin();\n\t\tiresult = ihmMW1.validate_iterator(itTest);\n\t\tVERIFY(iresult == (isf_valid | isf_current));\n\t}\n\n\n\t{\n\t\t// Test case of single bucket.\n\t\teastl::intrusive_hash_set<SetWidget, 1, SWHash> hs;\n\t\tSetWidget node1, node2, node3;\n\t\t \n\t\tnode1.mX = 1;\n\t\tnode2.mX = 2;\n\t\tnode3.mX = 3;\n\t\t \n\t\ths.insert(node1);\n\t\ths.insert(node2);\n\t\ths.insert(node3);\n\n\t\tconst eastl_size_t removeCount = hs.erase(node3);\n\t\tVERIFY(removeCount == 1); \n\t}\n\n\n\t{\n\t\t// Test intrusive_hashtable_iterator(value_type* pNode, value_type** pBucket = NULL)\n\t\teastl::intrusive_hash_set<SetWidget, 37, SWHash> hs;\n\t\tSetWidget node1, node2, node3;\n\t\t \n\t\tnode1.mX = 1;\n\t\tnode2.mX = 2;\n\t\tnode3.mX = 3;\n\n\t\ths.insert(node1);\n\t\ths.insert(node2);\n\t\ths.insert(node3);\n\n\t\tVERIFY(hs.validate());\n\n\t\ths.remove(node1);\n\t\ths.remove(node2);\n\t\ths.remove(node3);\n\t\t\n\t\tVERIFY(hs.validate());\n\n\t\ths.insert(node1);\n\t\ths.insert(node2);\n\t\ths.insert(node3);\n\n\t\tVERIFY(hs.validate());\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestIntrusiveList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/intrusive_list.h>\n#include <EABase/eabase.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdio.h>\n#include <stdarg.h>\n#include <stddef.h>\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <string>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nusing namespace eastl;\n\n\nnamespace\n{\n\n\t/// IntNode\n\t///\n\t/// Test intrusive_list node.\n\t///\n\tstruct IntNode : public eastl::intrusive_list_node\n\t{\n\t\tint mX;\n\n\t\tIntNode(int x = 0)\n\t\t\t: mX(x) { }\n\n\t\toperator int() const\n\t\t\t{ return mX; }\n\t};\n\n\n\t/// ListInit\n\t///\n\t/// Utility class for setting up a list.\n\t///\n\tclass ListInit\n\t{\n\tpublic:\n\t\tListInit(intrusive_list<IntNode>& container, IntNode* pNodeArray)\n\t\t\t: mpContainer(&container), mpNodeArray(pNodeArray)\n\t\t{\n\t\t\tmpContainer->clear();\n\t\t}\n\n\t\tListInit& operator+=(int x)\n\t\t{\n\t\t\tmpNodeArray->mX = x;\n\t\t\tmpContainer->push_back(*mpNodeArray++);\n\t\t\treturn *this;\n\t\t}\n\n\t\tListInit& operator,(int x)\n\t\t{\n\t\t\tmpNodeArray->mX = x;\n\t\t\tmpContainer->push_back(*mpNodeArray++);\n\t\t\treturn *this;\n\t\t}\n\n\tprotected:\n\t\tintrusive_list<IntNode>* mpContainer;\n\t\tIntNode*                 mpNodeArray;\n\t};\n\n} // namespace\n\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::intrusive_list<IntNode>;\n\n\n\nint TestIntrusiveList()\n{\n\tint nErrorCount = 0;\n\tint i;\n\n\t{\n\t\t// Verify that intrusive_list_node is a POD, at least when EASTL_VALIDATE_INTRUSIVE_LIST is disabled.\n\t\t#if !EASTL_VALIDATE_INTRUSIVE_LIST\n\t\t\t// is_pod doesn't currently detect structs as PODs, even though it should.\n\t\t\t// This is due to limitations in C++.\n\t\t\t// VERIFY(eastl::is_pod<eastl::intrusive_list_node>::value);\n\n\t\t\tconst size_t offset = offsetof(intrusive_list_node, mpPrev);\n\t\t\tVERIFY(offset == sizeof(intrusive_list_node*));\n\t\t#endif\n\t}\n\n\t{\n\t\tIntNode nodes[20];\n\n\t\tintrusive_list<IntNode> ilist;\n\n\t\t// Enforce that the intrusive_list copy ctor is visible. If it is not, \n\t\t// then the class is not a POD type as it is supposed to be.\n\t\tdelete new intrusive_list<IntNode>(ilist);\n\n\t\t#ifndef __GNUC__ // GCC warns on this, though strictly specaking it is allowed to.\n\t\t\t// Enforce that offsetof() can be used with an intrusive_list in a struct;\n\t\t\t// it requires a POD type. Some compilers will flag warnings or even errors\n\t\t\t// when this is violated.\n\t\t\tstruct Test {\n\t\t\t\tintrusive_list<IntNode> m;\n\t\t\t};\n\t\t\t(void)offsetof(Test, m);\n\t\t#endif\n\n\t\t// begin / end\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"ctor()\", -1));\n\n\n\t\t// push_back\n\t\tListInit(ilist, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"push_back()\", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));\n\n\n\t\t// iterator / begin\n\t\tintrusive_list<IntNode>::iterator it = ilist.begin();\n\t\tVERIFY(it->mX == 0);\n\t\t++it;\n\t\tVERIFY(it->mX == 1);\n\t\t++it;\n\t\tVERIFY(it->mX == 2);\n\t\t++it;\n\t\tVERIFY(it->mX == 3);\n\n\n\t\t// const_iterator / begin\n\t\tconst intrusive_list<IntNode>           cilist;\n\t\tintrusive_list<IntNode>::const_iterator cit;\n\t\tfor(cit = cilist.begin(); cit != cilist.end(); ++cit)\n\t\t\tVERIFY(cit == cilist.end()); // This is guaranteed to be false.\n\n\n\t\t// reverse_iterator / rbegin\n\t\tintrusive_list<IntNode>::reverse_iterator itr = ilist.rbegin();\n\t\tVERIFY(itr->mX == 9);\n\t\t++itr;\n\t\tVERIFY(itr->mX == 8);\n\t\t++itr;\n\t\tVERIFY(itr->mX == 7);\n\t\t++itr;\n\t\tVERIFY(itr->mX == 6);\n\n\n\t\t// iterator++/--\n\t\t{\n\t\t\tintrusive_list<IntNode>::iterator it1(ilist.begin());\n\t\t\tintrusive_list<IntNode>::iterator it2(ilist.begin());\n\n\t\t\t++it1;\n\t\t\t++it2;\n\t\t\tif ((it1 != it2++) || (++it1 != it2))\n\t\t\t\tVERIFY(!\"[iterator::increment] fail\\n\");\n\n\t\t\tif ((it1 != it2--) || (--it1 != it2))\n\t\t\t\tVERIFY(!\"[iterator::decrement] fail\\n\");\n\t\t}\n\n\n\t\t// clear / empty\n\t\tVERIFY(!ilist.empty());\n\n\t\tilist.clear();\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"clear()\", -1));\n\t\tVERIFY(ilist.empty());\n\n\n\t\t// splice\n\t\tListInit(ilist, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;\n\n\t\tilist.splice(++ilist.begin(), ilist, --ilist.end());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"splice(single)\", 0, 9, 1, 2, 3, 4, 5, 6, 7, 8, -1));\n\n\t\tintrusive_list<IntNode> ilist2;\n\t\tListInit(ilist2, nodes+10) += 10, 11, 12, 13, 14, 15, 16, 17, 18, 19;\n\n\t\tilist.splice(++++ilist.begin(), ilist2);\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"splice(whole)\", -1));\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"splice(whole)\", 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 7, 8, -1));\n\n\t\tilist.splice(ilist.begin(), ilist, ++++ilist.begin(), ----ilist.end());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"splice(range)\", 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 0, 9, 7, 8, -1));\n\n\t\tilist.clear();\n\t\tilist.swap(ilist2);\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"swap(empty)\", -1));\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"swap(empty)\", -1));\n\n\t\tilist2.push_back(nodes[0]);\n\t\tilist.splice(ilist.begin(), ilist2);\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"splice(single)\", 0, -1));\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"splice(single)\", -1));\n\n\n\t\t// splice(single) -- evil case (splice at or right after current position)\n\t\tListInit(ilist, nodes) += 0, 1, 2, 3, 4;\n\t\tilist.splice(++++ilist.begin(), *++++ilist.begin());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"splice(single)\", 0, 1, 2, 3, 4, -1));\n\t\tilist.splice(++++++ilist.begin(), *++++ilist.begin());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"splice(single)\", 0, 1, 2, 3, 4, -1));\n\n\n\t\t// splice(range) -- evil case (splice right after current position)\n\t\tListInit(ilist, nodes) += 0, 1, 2, 3, 4;\n\t\tilist.splice(++++ilist.begin(), ilist, ++ilist.begin(), ++++ilist.begin());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"splice(range)\", 0, 1, 2, 3, 4, -1));\n\n\n\t\t// push_front / push_back\n\t\tilist.clear();\n\t\tilist2.clear();\n\t\tfor(i = 4; i >= 0; --i)\n\t\t\tilist.push_front(nodes[i]);\n\t\tfor(i = 5; i < 10; ++i)\n\t\t\tilist2.push_back(nodes[i]);\n\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"push_front()\", 0, 1, 2, 3, 4, -1));\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"push_back()\", 5, 6, 7, 8, 9, -1));\n\n\t\tfor(i = 4; i >= 0; --i)\n\t\t{\n\t\t\tilist.pop_front();\n\t\t\tilist2.pop_back();\n\t\t}\n\n\t\tVERIFY(ilist.empty() && ilist2.empty());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"pop_front()\", -1));\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"pop_back()\", -1));\n\n\n\t\t// contains / locate\n\t\tfor(i = 0; i < 5; ++i)\n\t\t\tilist.push_back(nodes[i]);\n\n\t\tVERIFY( ilist.contains(nodes[2]));\n\t\tVERIFY(!ilist.contains(nodes[7]));\n\n\t\tit = ilist.locate(nodes[3]);\n\t\tVERIFY(it->mX == 3);\n\n\t\tit = ilist.locate(nodes[8]);\n\t\tVERIFY(it == ilist.end());\n\n\n\t\t// reverse\n\t\tilist.reverse();\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"push_front()\", 4, 3, 2, 1, 0, -1));\n\n\n\t\t// validate / validate_iterator\n\t\tVERIFY(ilist.validate());\n\t\tit = ilist.locate(nodes[3]);\n\t\tVERIFY((ilist.validate_iterator(it) & (isf_valid | isf_can_dereference)) != 0);\n\t\tVERIFY( ilist.validate_iterator(intrusive_list<IntNode>::iterator(NULL)) == isf_none);\n\n\n\t\t// swap()\n\t\tilist.swap(ilist2);\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"swap()\", -1));\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"swap()\", 4, 3, 2, 1, 0, -1));\n\n\n\t\t// erase()\n\t\tListInit(ilist2, nodes) += 0, 1, 2, 3, 4;\n\t\tListInit(ilist, nodes+5) += 5, 6, 7, 8, 9;\n\t\tilist.erase(++++ilist.begin());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"erase(single)\", 5, 6, 8, 9, -1));\n\n\t\tilist.erase(ilist.begin(), ilist.end());\n\t\tVERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), \"erase(all)\", -1));\n\n\t\tilist2.erase(++ilist2.begin(), ----ilist2.end());\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"erase(range)\", 0, 3, 4, -1));\n\n\n\t\t// size\n\t\tVERIFY(ilist2.size() == 3);\n\n\n\t\t// pop_front / pop_back\n\t\tilist2.pop_front();\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"pop_front()\", 3, 4, -1));\n\n\t\tilist2.pop_back();\n\t\tVERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), \"pop_back()\", 3, -1));\n\t}\n\n\n\t{\n\t\t// Test copy construction and assignment.\n\t\t// The following *should* not compile.\n\n\t\tintrusive_list<IntNode> ilist1;\n\t\tintrusive_list<IntNode> ilist2(ilist1);\n\t\tilist1 = ilist2;\n\t}\n\n\n\t{\n\t\t// void sort()\n\t\t// void sort(Compare compare)\n\n\t\tconst int kSize = 10;\n\t\tIntNode nodes[kSize];\n\n\t\tintrusive_list<IntNode> listEmpty;\n\t\tlistEmpty.sort();\n\t\tVERIFY(VerifySequence(listEmpty.begin(), listEmpty.end(), int(), \"list::sort\", -1));\n\n\t\tintrusive_list<IntNode> list1;\n\t\tListInit(list1, nodes) += 1;\n\t\tlist1.sort();\n\t\tVERIFY(VerifySequence(list1.begin(), list1.end(), int(), \"list::sort\", 1, -1));\n\t\tlist1.clear();\n\n\t\tintrusive_list<IntNode> list4;\n\t\tListInit(list4, nodes) += 1, 9, 2, 3;\n\t\tlist4.sort();\n\t\tVERIFY(VerifySequence(list4.begin(), list4.end(), int(), \"list::sort\", 1, 2, 3, 9, -1));\n\t\tlist4.clear();\n\n\t\tintrusive_list<IntNode> listA;\n\t\tListInit(listA, nodes) += 1, 9, 2, 3, 5, 7, 4, 6, 8, 0;\n\t\tlistA.sort();\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"list::sort\", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));\n\t\tlistA.clear();\n\n\t\tintrusive_list<IntNode> listB;\n\t\tListInit(listB, nodes) += 1, 9, 2, 3, 5, 7, 4, 6, 8, 0;\n\t\tlistB.sort(eastl::less<int>());\n\t\tVERIFY(VerifySequence(listB.begin(), listB.end(), int(), \"list::sort\", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));\n\t\tlistB.clear();\n\t}\n\n\n\t{\n\t\t// void merge(this_type& x);\n\t\t// void merge(this_type& x, Compare compare);\n\n\t\tconst int kSize = 8;\n\t\tIntNode nodesA[kSize];\n\t\tIntNode nodesB[kSize];\n\n\t\tintrusive_list<IntNode> listA;\n\t\tListInit(listA, nodesA) += 1, 2, 3, 4, 4, 5, 9, 9;\n\n\t\tintrusive_list<IntNode> listB;\n\t\tListInit(listB, nodesB) += 1, 2, 3, 4, 4, 5, 9, 9;\n\n\t\tlistA.merge(listB);\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"list::merge\", 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 9, 9, 9, 9, -1));\n\t\tVERIFY(VerifySequence(listB.begin(), listB.end(), int(), \"list::merge\", -1));\n\t}\n\n\n\t{\n\t\t// void unique();\n\t\t// void unique(BinaryPredicate);\n\n\t\tconst int kSize = 8;\n\t\tIntNode nodesA[kSize];\n\t\tIntNode nodesB[kSize];\n\n\t\tintrusive_list<IntNode> listA;\n\t\tListInit(listA, nodesA) += 1, 2, 3, 4, 4, 5, 9, 9;\n\t\tlistA.unique();\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"list::unique\", 1, 2, 3, 4, 5, 9, -1));\n\n\t\tintrusive_list<IntNode> listB;\n\t\tListInit(listB, nodesB) += 1, 2, 3, 4, 4, 5, 9, 9;\n\t\tlistB.unique(eastl::equal_to<int>());\n\t\tVERIFY(VerifySequence(listA.begin(), listA.end(), int(), \"list::unique\", 1, 2, 3, 4, 5, 9, -1));\n\t}\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestIntrusiveSDList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/bonus/intrusive_sdlist.h>\n#include <EASTL/string.h>\n#include <EABase/eabase.h>\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n\n#include <stdarg.h>\n#include <stdio.h>\n\n#if defined(_MSC_VER)\n\t#pragma warning(pop)\n#endif\n\n\n\nusing namespace eastl;\n\n\nnamespace TestSDListLocal\n{\n\n\tstruct IntNode : public intrusive_sdlist_node\n\t{\n\t\tIntNode() {}\n\t\tIntNode(int x) : mX(x) {}\n\t\toperator int() const { return mX; }\n\n\t\tint mX;\n\t};\n\n\ttypedef intrusive_sdlist<IntNode> IntrusiveSDList;\n\n\ttemplate <class T>\n\teastl::string IntListToString8(const T& cont)\n\t{\n\t\teastl::string s(\"<\");\n\n\t\tconst int kBufferSize = 64;\n\t\tchar buf[kBufferSize];\n\n\t\tfor(typename T::const_iterator it(cont.begin()), itEnd(cont.end()); it != itEnd; ++it)\n\t\t{\n\t\t\tconst int& v = *it;\n\t\t\tEA::StdC::Snprintf(buf, kBufferSize, \" %d\", v);\n\t\t\ts += buf;\n\t\t}\n\n\t\ts += \" >\";\n\t\treturn s;\n\t}\n\n\n\ttemplate <class T>\n\tbool VerifyContainer(const T& cont, const char *testname, ...)\n\t{\n\t\t//if (!cont.validate()) {\n\t\t//    EASTLTest_Printf(\"intrusive_list[%s] container damaged!\\n\", testname);\n\t\t//    return false;\n\t\t//}\n\n\t\ttypename T::const_iterator it(cont.begin()), itEnd(cont.end());\n\t\tva_list val;\n\t\tint index = 0;\n\n\t\tva_start(val, testname);\n\t\twhile(it != itEnd)\n\t\t{\n\t\t\tint next = va_arg(val, int);\n\n\t\t\tif (next == -1 || next != *it)\n\t\t\t{\n\t\t\t\tconst int value = *it;\n\t\t\t\tconst char* const pString = IntListToString8(cont).c_str();\n\t\t\t\tEASTLTest_Printf(\"intrusive_list[%s] Mismatch at index %d: expected %d, found %d; contents: %s\\n\", testname, index, next, value, pString);\n\t\t\t\tva_end(val);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t++it;\n\t\t\t++index;\n\t\t}\n\n\t\tif (va_arg(val, int) != -1)\n\t\t{\n\t\t\tdo {\n\t\t\t\t++index;\n\t\t\t} while(va_arg(val, int) != -1);\n\n\t\t\tconst int countainerSize = (int)cont.size();\n\t\t\tconst char* const pString = IntListToString8(cont).c_str();\n\t\t\tEASTLTest_Printf(\"intrusive_list[%s] Too many elements: expected %d, found %d; contents: %s\\n\", testname, index, countainerSize, pString);\n\t\t\tva_end(val);\n\t\t\treturn false;\n\t\t}\n\n\t\tva_end(val);\n\n\t\t// We silence this by default for a quieter test run.\n\t\t// EASTLTest_Printf(\"intrusive_list[%s] pass\\n\", testname);\n\t\treturn true;\n\t}\n\n\n\tclass ListInit\n\t{\n\tpublic:\n\t\tListInit(intrusive_sdlist<IntNode>& container, IntNode* pNodeArray)\n\t\t\t: mpContainer(&container), mpNodeArray(pNodeArray)\n\t\t{\n\t\t\tmpContainer->clear();\n\t\t}\n\n\t\tListInit& operator+=(int x)\n\t\t{\n\t\t\tmpNodeArray->mX = x;\n\t\t\tmpContainer->push_back(*mpNodeArray++);\n\t\t\treturn *this;\n\t\t}\n\n\t\tListInit& operator,(int x)\n\t\t{\n\t\t\tmpNodeArray->mX = x;\n\t\t\tmpContainer->push_back(*mpNodeArray++);\n\t\t\treturn *this;\n\t\t}\n\n\tprotected:\n\t\tintrusive_sdlist<IntNode>* mpContainer;\n\t\tIntNode*                   mpNodeArray;\n\t};\n\n} // namespace\n\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::intrusive_sdlist<TestSDListLocal::IntNode>;\n\n\n\nint TestIntrusiveSDList()\n{\n\tusing namespace TestSDListLocal;\n\n\tint nErrorCount = 0;\n\n\tIntNode nodes[20];\n\n\tIntrusiveSDList l;\n\n\t// Enforce that the intrusive_list copy ctor is visible. If it is not, then\n\t// the class is not a POD type as it is supposed to.\n\tdelete new IntrusiveSDList(l);\n\n\t// Enforce that offsetof() can be used with an intrusive_list in a struct;\n\t// it requires a POD type. Some compilers will flag warnings or even errors\n\t// when this is violated.\n\tstruct Test { IntrusiveSDList m; };\n\n\t#ifndef __GNUC__ // GCC warns on this, though strictly specaking it is allowed to.\n\t\t(void)offsetof(Test, m);\n\t#endif\n\n\tVERIFY(VerifyContainer(l, \"ctor()\", -1));\n\n\t// push_back\n\tListInit(l, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;\n\tVERIFY(VerifyContainer(l, \"push_back()\", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));\n\n\t// iterator++\n\t{\n\t\tIntrusiveSDList::iterator it1(l.begin());\n\t\tIntrusiveSDList::iterator it2(l.begin());\n\n\t\t++it1;\n\t\t++it2;\n\n\t\tif (it1 != it2++ || ++it1 != it2) {\n\t\t\tVERIFY(!\"[iterator::increment] fail\\n\");\n\t\t}\n\t}\n\n\t// clear()/empty()\n\tVERIFY(!l.empty());\n\n\tl.clear();\n\tVERIFY(VerifyContainer(l, \"clear()\", -1));\n\tVERIFY(l.empty());\n\n\tl.erase(l.begin(), l.end()); // Erase an already empty container.\n\tVERIFY(l.empty());\n\n\tIntrusiveSDList l2;\n\n\t// splice\n\t//ListInit(l, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;\n\t//\n\t//l.splice(++l.begin(), l, --l.end());\n\t//VERIFY(VerifyContainer(l, \"splice(single)\", 0, 9, 1, 2, 3, 4, 5, 6, 7, 8, -1));\n\t//\n\t//ListInit(l2, nodes+10) += 10, 11, 12, 13, 14, 15, 16, 17, 18, 19;\n\t//\n\t//l.splice(++++l.begin(), l2);\n\t//VERIFY(VerifyContainer(l2, \"splice(whole)\", -1));\n\t//VERIFY(VerifyContainer(l, \"splice(whole)\", 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 7, 8, -1));\n\n\t//l.splice(l.begin(), l, ++++l.begin(), ----l.end());\n\t//VERIFY(VerifyContainer(l, \"splice(range)\", 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 0, 9, 7, 8, -1));\n\n\t//l.clear();\n\t//l.swap(l2);\n\t//VERIFY(VerifyContainer(l, \"swap(empty)\", -1));\n\t//VERIFY(VerifyContainer(l2, \"swap(empty)\", -1));\n\n\t//l2.push_back(nodes[0]);\n\t//l.splice(l.begin(), l2);\n\t//VERIFY(VerifyContainer(l, \"splice(single)\", 0, -1));\n\t//VERIFY(VerifyContainer(l2, \"splice(single)\", -1));\n\n\t// splice(single) -- evil case (splice at or right after current position)\n\t//ListInit(l, nodes) += 0, 1, 2, 3, 4;\n\t//l.splice(++++l.begin(), *++++l.begin());\n\t//VERIFY(VerifyContainer(l, \"splice(single)\", 0, 1, 2, 3, 4, -1));\n\t//l.splice(++++++l.begin(), *++++l.begin());\n\t//VERIFY(VerifyContainer(l, \"splice(single)\", 0, 1, 2, 3, 4, -1));\n\n\t// splice(range) -- evil case (splice right after current position)\n\t//ListInit(l, nodes) += 0, 1, 2, 3, 4;\n\t//l.splice(++++l.begin(), l, ++l.begin(), ++++l.begin());\n\t//VERIFY(VerifyContainer(l, \"splice(range)\", 0, 1, 2, 3, 4, -1));\n\n\t// push_front()\n\tl.clear();\n\tl2.clear();\n\tfor(int i=4; i>=0; --i) {\n\t\tl.push_front(nodes[i]);\n\t\tl2.push_front(nodes[i+5]);\n\t}\n\n\tVERIFY(VerifyContainer(l, \"push_front()\", 0, 1, 2, 3, 4, -1));\n\tVERIFY(VerifyContainer(l2, \"push_front()\", 5, 6, 7, 8, 9, -1));\n\n\t// swap()\n\tl.swap(l2);\n\tVERIFY(VerifyContainer(l, \"swap()\", 5, 6, 7, 8, 9, -1));\n\tVERIFY(VerifyContainer(l2, \"swap()\", 0, 1, 2, 3, 4, -1));\n\n\t// erase()\n\tListInit(l2, nodes) += 0, 1, 2, 3, 4;\n\tListInit(l, nodes+5) += 5, 6, 7, 8, 9;\n\tl.erase(++++l.begin());\n\tVERIFY(VerifyContainer(l, \"erase(single)\", 5, 6, 8, 9, -1));\n\n\tl.erase(l.begin(), l.end());\n\tVERIFY(VerifyContainer(l, \"erase(all)\", -1));\n\n\tListInit(l, nodes) += 0, 1, 2;\n\tVERIFY(l2.size() == 3);\n\n\tl2.pop_front();\n\tVERIFY(VerifyContainer(l2, \"pop_front()\", 1, 2, -1));\n\n\tl2.pop_back();\n\tVERIFY(VerifyContainer(l2, \"pop_back()\", 1, -1));\n\n\t// remove\n\tIntNode i1(1), i2(2), i3(3);\n\tl.clear();\n\n\tl.push_front(i1);\n\tIntrusiveSDList::remove(i1);\n\tVERIFY(VerifyContainer(l, \"remove()\", -1));\n\n\tl.push_front(i1);\n\tl.push_front(i2);\n\tIntrusiveSDList::remove(i1);\n\tVERIFY(VerifyContainer(l, \"remove()\", 2, -1));\n\n\tl.push_front(i1);\n\tIntrusiveSDList::remove(i2);\n\tVERIFY(VerifyContainer(l, \"remove()\", 1, -1));\n\n\tl.push_back(i2);\n\tl.push_back(i3);\n\tIntrusiveSDList::remove(i2);\n\tVERIFY(VerifyContainer(l, \"remove()\", 1, 3, -1));\n\n\n\t// const_iterator / begin\n\tconst intrusive_sdlist<IntNode>           cilist;\n\tintrusive_sdlist<IntNode>::const_iterator cit;\n\tfor(cit = cilist.begin(); cit != cilist.end(); ++cit)\n\t\tVERIFY(cit == cilist.end()); // This is guaranteed to be false.\n\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestIntrusiveSList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/bonus/intrusive_slist.h>\n#include <EABase/eabase.h>\n\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\n//template class intrusive_slist<int>;\n\n\n\nint TestIntrusiveSList()\n{\n\tint nErrorCount = 0;\n\n\t// As of this writing, we don't yet have a completed intrusive_slist implementation.\n\t// The interface is in place but the implementation hasn't been done yet.\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestIterator.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/deque.h>\n#include <EASTL/iterator.h>\n#include <EASTL/vector.h>\n#include <EASTL/set.h>\n#include <EASTL/array.h>\n#include <EASTL/numeric.h>\n#include <EASTL/list.h>\n#include <EASTL/slist.h>\n#include <EASTL/string.h>\n#include <EASTL/intrusive_list.h>\n#include <EASTL/memory.h>\n#include <EASTL/unique_ptr.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/internal/generic_iterator.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdio.h>\n#include <string.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\ntemplate <class T>\nusing detect_iterator_traits_reference = typename eastl::iterator_traits<T>::reference;\n\n// This is used below, though is currently disabled as documented below.\nstruct IListNode : public eastl::intrusive_list_node{};\n\nint TestIterator_advance()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\t// void advance(InputIterator& i, Distance n)\n\t\tconst int num_elements = 10;\n\t\tint i;\n\n\t\teastl::vector<int> v;\n\t\tfor(i = 0; i < num_elements; i++)\n\t\t\tv.push_back(i);\n\n\t\t// test forward advancement\n\t\teastl::vector<int>::iterator it = v.begin();\n\t\tfor(i = 0; i < num_elements; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(*it == v[i]);\n\t\t\teastl::advance(it, 1);\n\t\t}\n\n\t\t// test backwards advancement\n\t\teastl::vector<int>::iterator it2 = v.end();\n\t\ti = num_elements - 1;\n\t\tdo\n\t\t{\n\t\t\teastl::advance(it2, -1);\n\t\t\tEATEST_VERIFY(*it2 == v[i]);\n\t\t}\n\t\twhile(i-- != 0);\n\t}\n\n\t{\n\t\t// void advance(InputIterator& i, Distance n)\n\t\teastl::list<int> intList;\n\t\tintList.push_back(0);\n\t\tintList.push_back(1);\n\t\tintList.push_back(42);\n\t\tintList.push_back(2);\n\n\t\teastl::list<int>::iterator it = intList.begin();\n\t\teastl::advance(it, intList.size());\n\t\tEATEST_VERIFY(it == intList.end());\n\n\t\t// Exercise advance with an signed Distance type.\n\t\tit = intList.begin();\n\t\teastl::advance(it, (ssize_t)intList.size());\n\t\tEATEST_VERIFY(it == intList.end());\n\n\n\t\teastl::slist<int> intSlist;\n\t\tintSlist.push_front(0);\n\t\tintSlist.push_front(1);\n\t\tintSlist.push_front(42);\n\t\tintSlist.push_front(2);\n\n\t\teastl::slist<int>::iterator its = intSlist.begin();\n\t\teastl::advance(its, intSlist.size());\n\t\tEATEST_VERIFY(its == intSlist.end());\n\n\t\t// Exercise advance with an signed Distance type.\n\t\tits = intSlist.begin();\n\t\teastl::advance(its, (ssize_t)intSlist.size());\n\t\tEATEST_VERIFY(its == intSlist.end());\n\t}\n\n\t{\n\t\t// void next(InputIterator& i, Distance n)\n\t\teastl::vector<int> v;\n\t\tv.push_back(0);\n\t\tv.push_back(1);\n\t\tv.push_back(42);\n\t\tv.push_back(2);\n\n\t\teastl::vector<int>::iterator it = v.begin();\n\t\tEATEST_VERIFY(*eastl::next(it, 0) == 0);\n\t\tEATEST_VERIFY(*eastl::next(it /*testing the iterator distance default value*/) == 1);\n\t\tEATEST_VERIFY(*eastl::next(it, 2) == 42);\n\t}\n\n\t{\n\t\t// void prev(InputIterator& i, Distance n)\n\t\teastl::vector<int> v;\n\t\tv.push_back(0);\n\t\tv.push_back(1);\n\t\tv.push_back(42);\n\t\tv.push_back(2);\n\n\t\teastl::vector<int>::iterator it = v.end();\n\t\tEATEST_VERIFY(*eastl::prev(it, 2) == 42);\n\t\tEATEST_VERIFY(*eastl::prev(it /*testing the iterator distance default value*/) == 2);\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestIterator_moveIterator()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\teastl::vector<int> v = {0, 1, 42, 2};\n\t\tconst auto constBeginMoveIter = eastl::make_move_iterator(v.begin());\n\n\t\t// operator++(int)\n\t\tauto moveIter = constBeginMoveIter;\n\t\tmoveIter++; // the result of the expression is the incremented value, we need this test to read the existing state of the iterator.\n\t\tEATEST_VERIFY(*moveIter != *constBeginMoveIter);\n\n\t\t// operator--(int)\n\t\tmoveIter = constBeginMoveIter + 2; // points to '42'\n\t\tmoveIter--; // the result of the expression is the incremented value, we need this test to read the existing state of the iterator.\n\t\tEATEST_VERIFY(*moveIter != *(constBeginMoveIter + 2));\n\t}\n\n\t{\n\t\t// Ensure that move_iterator indeed move yielded value whenever possible.\n\t\tauto x = eastl::make_unique<int>(42);\n\t\tauto* pX = &x;\n\t\tauto moveIter = eastl::make_move_iterator(pX);\n\n\t\tconstexpr bool isCorrectReferenceType = eastl::is_same_v<decltype(moveIter)::reference, eastl::unique_ptr<int>&&>;\n\t\tconstexpr bool isCorrectReturnType = eastl::is_same_v<decltype(*moveIter), eastl::unique_ptr<int>&&>;\n\n\t\tstatic_assert(isCorrectReferenceType, \"move_iterator::reference has wrong type.\");\n\t\tstatic_assert(isCorrectReturnType, \"move_iterator::operator*() has wrong return type.\");\n\t\tEATEST_VERIFY(isCorrectReferenceType);\n\t\tEATEST_VERIFY(isCorrectReturnType);\n\n\t\tauto pMoveX = *moveIter;\n\t\tEATEST_VERIFY(*pMoveX == 42);\n\t}\n\n\t// Bellow are regression tests that ensure we are covering the defect LWG 2106: http://cplusplus.github.io/LWG/lwg-defects.html#2106\n\t{\n\t\t// Check that we support iterators yielding const references.\n\t\tconst int x = 42;\n\t\tconst int* pX = &x;\n\t\tauto moveIter = eastl::make_move_iterator(pX);\n\n\t\tconstexpr bool isCorrectReferenceType = eastl::is_same_v<decltype(moveIter)::reference, const int&&>;\n\t\tconstexpr bool isCorrectReturnType = eastl::is_same_v<decltype(*moveIter), const int&&>;\n\n\t\tstatic_assert(isCorrectReferenceType, \"move_iterator::reference has wrong type.\");\n\t\tstatic_assert(isCorrectReturnType, \"move_iterator::operator*() has wrong return type.\");\n\t\tEATEST_VERIFY(isCorrectReferenceType);\n\t\tEATEST_VERIFY(isCorrectReturnType);\n\n\t\tauto pCopiedX = *moveIter;\n\t\tEATEST_VERIFY(pCopiedX == 42);\n\t}\n\n\t{\n\t\t// Check that we support iterators yielding plain value (typically a proxy-iterator).\n\t\tstruct FakeProxyIterator\n\t\t{\n\t\t\tusing iterator_category = eastl::forward_iterator_tag;\n\t\t\tusing difference_type   = ptrdiff_t;\n\t\t\tusing value_type        = int;\n\t\t\tusing pointer           = int;  // Note that we are yielding by value.\n\t\t\tusing reference         = int;  // Note that we are yielding by value.\n\n\t\t\treference operator*() const { return 42; }\n\t\t\tpointer operator->() { return 42; }\n\t\t\tFakeProxyIterator& operator++() { return *this; }\n\t\t\tFakeProxyIterator operator++(int) { return {}; }\n\n\t\t\tbool operator==(const FakeProxyIterator&) { return true; };\n\t\t\tbool operator!=(const FakeProxyIterator&) { return false; };\n\t\t};\n\n\t\tFakeProxyIterator it = {};\n\t\tauto moveIter = eastl::make_move_iterator(it);\n\n\t\tconstexpr bool isCorrectReferenceType = eastl::is_same_v<decltype(moveIter)::reference, int>;\n\t\tconstexpr bool isCorrectReturnType = eastl::is_same_v<decltype(*moveIter), int>;\n\n\t\tstatic_assert(isCorrectReferenceType, \"move_iterator::reference has wrong type.\");\n\t\tstatic_assert(isCorrectReturnType, \"move_iterator::operator*() has wrong return type.\");\n\t\tEATEST_VERIFY(isCorrectReferenceType);\n\t\tEATEST_VERIFY(isCorrectReturnType);\n\n\t\tauto pCopiedX = *moveIter;\n\t\tEATEST_VERIFY(pCopiedX == 42);\n\t}\n\n\t{\n\t\t// test move_iterator usable in algorithms\n\n\t\tMoveOnlyType moveableArray[] = {MoveOnlyType{1}, MoveOnlyType{2}, MoveOnlyType{3}};\n\t\tMoveOnlyType destArray[] = {MoveOnlyType{0}, MoveOnlyType{0}, MoveOnlyType{0}};\n\n\t\teastl::copy(eastl::make_move_iterator(moveableArray), eastl::make_move_iterator(moveableArray + 3), destArray);\n\t\tEATEST_VERIFY(VerifySequence(destArray, destArray + 3, {MoveOnlyType{1}, MoveOnlyType{2}, MoveOnlyType{3}},\n\t\t                             \"copy(move_iterator(...))\"));\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestIterator\n//\nint TestIterator()\n{\n\tint nErrorCount = 0;\n\tnErrorCount += TestIterator_advance();\n\tnErrorCount += TestIterator_moveIterator();\n\n\t{\n\t\t// reverse_iterator\n\t\t// reverse_iterator<Iterator> make_reverse_iterator(Iterator mi)\n\t\t{\n\t\t\teastl::vector<int> src;\n\t\t\tfor(int i = 0; i < 10; i++)\n\t\t\t\tsrc.push_back(i); // src should become {0,1,2,3,4,5,6,7,8,9}\n\n\t\t\tauto itr = eastl::make_reverse_iterator(src.end());\n\t\t\tEATEST_VERIFY(*itr == 9); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 8); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 7); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 6); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 5); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 4); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 3); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 2); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 1); ++itr;\n\t\t\tEATEST_VERIFY(*itr == 0); ++itr;\n\t\t\tEATEST_VERIFY( itr == src.rend());\n\t\t\tEATEST_VERIFY( itr == eastl::make_reverse_iterator(src.begin()));\n\t\t}\n\t}\n\n\t{\n\t\t// Regression bug with assign/insert combined with reverse iterator.\n\t\teastl::vector<int> a;\n\t\tfor (int i = 0; i < 10; ++i) {\n\t\t\ta.push_back(i);\n\t\t}\n\n\t\teastl::deque<int> d;\n\t\td.assign(a.rbegin(), a.rend());\n\t\tfor (int i = 0; i < 10; ++i) {\n\t\t\tEATEST_VERIFY(a[i] == d[a.size() - i - 1]);\n\t\t}\n\t\td.insert(d.end(), a.rbegin(), a.rend());\n\t\tfor (int i = 0; i < 10; ++i) {\n\t\t\tEATEST_VERIFY(a[i] == d[d.size() - i - 1]);\n\t\t}\n\n\t\teastl::vector<int> b;\n\t\tb.assign(a.rbegin(), a.rend());\n\t\tfor (int i = 0; i < 10; ++i) {\n\t\t\tEATEST_VERIFY(a[i] == b[a.size() - i - 1]);\n\t\t}\n\t\tb.insert(b.end(), a.rbegin(), a.rend());\n\t\tfor (int i = 0; i < 10; ++i) {\n\t\t\tEATEST_VERIFY(a[i] == b[b.size() - i - 1]);\n\t\t}\n\t}\n\n\t{\n\t\t// move_iterator\n\t\t// move_iterator<Iterator> make_move_iterator(Iterator mi)\n\t\ttypedef eastl::vector<eastl::string> StringArray;\n\n\t\tStringArray src;\n\t\tfor(eastl_size_t i = 0; i < 4; i++)\n\t\t\tsrc.push_back(eastl::string(1, (char8_t)('0' + i))); // v should become {\"0\", \"1\", \"2\", \"3\"};\n\n\t\t// Moves the values out of the string array and into the result.\n\t\tStringArray dst(eastl::make_move_iterator(src.begin()), eastl::make_move_iterator(src.end()));\n\n\t\tEATEST_VERIFY((src.size() == 4) && (src[0] ==  \"\") && (src[3] ==  \"\"));\n\t\tEATEST_VERIFY((dst.size() == 4) && (dst[0] == \"0\") && (dst[3] == \"3\"));\n\t}\n\n\t{\n\t\t// back_insert_iterator\n\t\t// back_inserter\n\t\tEA_CPP14_CONSTEXPR int n = 3;\n\t\teastl::vector<TestObject> v1, v2, v3;\n\t\tv1.resize(n); v2.reserve(n); v3.reserve(n);\n\t\t{\n\t\t\tint64_t copyCtorCount0 = TestObject::sTOCopyCtorCount, moveCtorCount0 = TestObject::sTOMoveCtorCount;\n\t\t\teastl::copy(v1.begin(), v1.end(), eastl::back_inserter(v2));\n\t\t\tEATEST_VERIFY(v1.size() == v2.size() && TestObject::sTOCopyCtorCount == (copyCtorCount0 + n) &&\n\t\t\t\tTestObject::sTOMoveCtorCount == moveCtorCount0);\n\t\t}\n\t\t{\n\t\t\tint64_t copyCtorCount0 = TestObject::sTOCopyCtorCount, moveCtorCount0 = TestObject::sTOMoveCtorCount;\n\t\t\teastl::move(v1.begin(), v1.end(), eastl::back_inserter(v3));\n\t\t\tEATEST_VERIFY(v1.size() == v3.size() && TestObject::sTOCopyCtorCount == copyCtorCount0 &&\n\t\t\t\tTestObject::sTOMoveCtorCount == (moveCtorCount0 + n));\n\t\t}\n\t}\n\n\t{\n\t\t// front_insert_iterator\n\t\t// front_inserter\n\t\t// To do.\n\t}\n\n\t{\n\t\t// insert_iterator\n\t\t// inserter\n\t\t// To do.\n\t}\n\n\t{\n\t\t// difference_type distance(InputIterator first, InputIterator last)\n\t\teastl::vector<int> intVector = {0, 1, 2, 3, 4, 5, 6, 7};\n\t\tEATEST_VERIFY(eastl::distance(intVector.begin(), intVector.end()) == 8);\n    }\n\n\n\t{\n\t\t#if EASTL_BEGIN_END_ENABLED\n\t\t\t// begin / end\n\t\t\t// auto inline begin(Container& container) -> decltype(container.begin())\n\t\t\t// auto inline end(Container& container) -> decltype(container.end())\n\n\t\t\teastl::vector<int> intVector;\n\t\t\teastl::vector<int>::iterator intVectorIterator = eastl::begin(intVector);\n\t\t\tEATEST_VERIFY(intVectorIterator == eastl::end(intVector));\n\n\t\t\teastl::list<int> intList;\n\t\t\teastl::list<int>::iterator intListIterator = eastl::begin(intList);\n\t\t\tEATEST_VERIFY(intListIterator == eastl::end(intList));\n\n\t\t\teastl::set<int> intSet;\n\t\t\teastl::set<int>::iterator intSetIterator = eastl::begin(intSet);\n\t\t\tEATEST_VERIFY(intSetIterator == eastl::end(intSet));\n\n\t\t\teastl::array<int, 0> intArray;\n\t\t\teastl::array<int, 0>::iterator intArrayIterator = eastl::begin(intArray);\n\t\t\tEATEST_VERIFY(intArrayIterator == eastl::end(intArray));\n\n\t\t\teastl::intrusive_list<IListNode> intIList;\n\t\t\teastl::intrusive_list<IListNode>::iterator intIListIterator = eastl::begin(intIList);\n\t\t\tEATEST_VERIFY(intIListIterator == eastl::end(intIList));\n\n\t\t\teastl::string8 str8;\n\t\t\teastl::string8::iterator string8Iterator = eastl::begin(str8);\n\t\t\tEATEST_VERIFY(string8Iterator == eastl::end(str8));\n\t\t#endif\n\t}\n\n\t// eastl::data\n\t{\n\t\teastl::array<int, 0> intArray;\n\t\tint* pIntArrayData = eastl::data(intArray);\n\t\tEATEST_VERIFY(pIntArrayData == intArray.data());\n\n\t\teastl::vector<int> intVector;\n\t\tint* pIntVectorData = eastl::data(intVector);\n\t\tEATEST_VERIFY(pIntVectorData == intVector.data());\n\n\t\tint intCArray[34];\n\t\tint* pIntCArray = eastl::data(intCArray);\n\t\tEATEST_VERIFY(pIntCArray == intCArray);\n\n\t\tstd::initializer_list<int> intInitList;\n\t\tconst int* pIntInitList = eastl::data(intInitList);\n\t\tEATEST_VERIFY(pIntInitList == intInitList.begin());\n\t}\n\n\t// eastl::size\n\t{\n\t\teastl::vector<int> intVector;\n\t\tintVector.push_back();\n\t\tintVector.push_back();\n\t\tintVector.push_back();\n\t\tEATEST_VERIFY(eastl::size(intVector) == 3);\n\n\t\tint intCArray[34];\n\t\tEATEST_VERIFY(eastl::size(intCArray) == 34);\n\t\tstatic_assert(eastl::size(intCArray) == 34, \"eastl::size failure\");\n\t}\n\n\t// eastl::ssize\n\t{\n\t\teastl::vector<int> intVector;\n\t\tintVector.push_back();\n\t\tintVector.push_back();\n\t\tintVector.push_back();\n\t\tEATEST_VERIFY(eastl::ssize(intVector) == (signed)3);\n\n\t\tint intCArray[34];\n\t\tEATEST_VERIFY(eastl::ssize(intCArray) == (signed)34);\n\t\tstatic_assert(eastl::ssize(intCArray) == 34, \"eastl::ssize failure\");\n\t}\n\n\t// eastl::empty\n\t{\n\t\teastl::vector<int> intVector;\n\t\tEATEST_VERIFY(eastl::empty(intVector));\n\t\tintVector.push_back();\n\t\tEATEST_VERIFY(!eastl::empty(intVector));\n\n\t\tstd::initializer_list<int> intInitListEmpty;\n\t\tEATEST_VERIFY(eastl::empty(intInitListEmpty));\n\t\tEATEST_VERIFY(!eastl::empty({1, 2, 3, 4, 5, 6}));\n\t}\n\n\t// Range-based for loops\n\t{\n\t\t{\n\t\t\teastl::vector<int> v;\n\t\t\tint I = 0;\n\n\t\t\tv.push_back(0);\n\t\t\tv.push_back(1);\n\n\t\t\tfor(int i : v)\n\t\t\t\tEATEST_VERIFY(i == I++);\n\t\t}\n\n\t\t{\n\t\t\teastl::string s8;\n\t\t\tchar C = 'a';\n\n\t\t\ts8.push_back('a');\n\t\t\ts8.push_back('b');\n\n\t\t\tfor(char c : s8)\n\t\t\t\tEATEST_VERIFY(c == C++);\n\t\t}\n\t}\n\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // '*': was declared deprecated\n\t{\n\t\t// is_iterator_wrapper\n\t\tstatic_assert((eastl::is_iterator_wrapper<void>::value\t\t\t\t\t\t\t\t\t\t\t\t\t== false),  \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<int>::value\t\t\t\t\t\t\t\t\t\t\t\t\t== false),  \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<int*>::value\t\t\t\t\t\t\t\t\t\t\t\t\t== false),  \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::array<int, 2>::iterator>::value\t\t\t\t\t\t\t== false),   \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::array<char, 2>*>::value\t\t\t\t\t\t\t\t\t== false),  \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::vector<char> >::value\t\t\t\t\t\t\t\t\t== false),  \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::generic_iterator<int*> >::value\t\t\t\t\t\t== true),   \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::move_iterator<eastl::array<int, 2>::iterator> >::value\t== true),   \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::reverse_iterator<eastl::array<int, 2>::iterator> >::value == false),  \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::reverse_iterator<int*> >::value\t\t\t\t\t\t== false),  \"is_iterator_wrapper failure\");\n\t\tstatic_assert((eastl::is_iterator_wrapper<eastl::reverse_iterator<eastl::move_iterator<int*>> >::value  == true),   \"is_iterator_wrapper failure\");\n\t}\n\n\n\t{\n\t\t// unwrap_iterator\n\t\tint intArray[2];\n\t\tint* pInt = eastl::unwrap_iterator(&intArray[0]);\n\t\tintArray[0] = 17;\n\t\tEATEST_VERIFY(*pInt == 17);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(&intArray[0])), int*>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::generic_iterator<int*> giIntArray(intArray);\n\t\tpInt = eastl::unwrap_iterator(giIntArray);\n\t\tintArray[0] = 18;\n\t\tEATEST_VERIFY(*pInt == 18);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(giIntArray)), int*>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::vector<int> intVector(4, 19);\n\t\teastl::vector<int>::iterator itVector = eastl::unwrap_iterator(intVector.begin());\n\t\tEATEST_VERIFY(*itVector == 19);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(intVector.begin())), eastl::vector<int>::iterator>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::move_iterator<eastl::vector<int>::iterator> miIntVector(intVector.begin());\n\t\titVector = eastl::unwrap_iterator(miIntVector);\n\t\tintVector[0] = 20;\n\t\tEATEST_VERIFY(*itVector == 20);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(miIntVector)), eastl::vector<int>::iterator>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::reverse_iterator<eastl::vector<int>::iterator> riIntVector = intVector.rbegin();\n\t\teastl::reverse_iterator<eastl::vector<int>::iterator> riUnwrapped = eastl::unwrap_iterator(riIntVector);\n\t\tEATEST_VERIFY(*riUnwrapped == 19);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(riIntVector)), eastl::reverse_iterator<eastl::vector<int>::iterator>>::value == true), \"unwrap_iterator failure\");\n\n\t\teastl::reverse_iterator<eastl::move_iterator<eastl::vector<int>::iterator>> rimiIntVec(miIntVector);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(rimiIntVec)), eastl::reverse_iterator<eastl::vector<int>::iterator>>::value == true), \"unwrap_iterator failure\");\n\n\t\teastl::reverse_iterator<eastl::generic_iterator<int*>> rigiIntArray(giIntArray);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(rigiIntArray)), eastl::reverse_iterator<int*>>::value == true), \"unwrap_iterator failure\");\n\n\t\teastl::deque<int> intDeque(3);\n\t\teastl::deque<int>::iterator begin = intDeque.begin();\n\t\teastl::generic_iterator<eastl::deque<int>::iterator> giWrappedBegin(begin);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_iterator(giWrappedBegin)), eastl::deque<int>::iterator>::value == true), \"unwrap_iterator failure\");\n\n\t\teastl::deque<int>::iterator unwrappedBegin = eastl::unwrap_iterator(giWrappedBegin);\n\t\tEATEST_VERIFY(begin == unwrappedBegin);\n\t}\n\n\t{\n\t\t// unwrap_generic_iterator\n\t\tint intArray[2] = {0, 1};\n\t\teastl::generic_iterator<int*> giIntArray(intArray);\n\t\tint* pInt = eastl::unwrap_generic_iterator(giIntArray);\n\t\tEATEST_VERIFY(*pInt == 0);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_generic_iterator(giIntArray)), int*>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::move_iterator<int*> miIntArray(intArray);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_generic_iterator(miIntArray)), eastl::move_iterator<int*>>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::vector<int> intVector(1, 1);\n\t\teastl::generic_iterator<eastl::vector<int>::iterator> giVectorInt(intVector.begin());\n\t\teastl::vector<int>::iterator it = unwrap_generic_iterator(giVectorInt);\n\t\tEATEST_VERIFY(*it == 1);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_generic_iterator(giVectorInt)), eastl::vector<int>::iterator>::value == true),  \"unwrap_iterator failure\");\n\t}\n\n\t{\n\t\t// unwrap_move_iterator\n\t\tint intArray[2] = {0, 1};\n\t\teastl::move_iterator<int*> miIntArray(intArray);\n\t\tint* pInt = eastl::unwrap_move_iterator(miIntArray);\n\t\tEATEST_VERIFY(*pInt == 0);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_move_iterator(miIntArray)), int*>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::generic_iterator<int*> giIntArray(intArray);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_move_iterator(giIntArray)), eastl::generic_iterator<int*>>::value == true),  \"unwrap_iterator failure\");\n\n\t\teastl::vector<int> intVector(1, 1);\n\t\teastl::move_iterator<eastl::vector<int>::iterator> miVectorInt(intVector.begin());\n\t\teastl::vector<int>::iterator it = unwrap_move_iterator(miVectorInt);\n\t\tEATEST_VERIFY(*it == 1);\n\t\tstatic_assert((eastl::is_same<decltype(eastl::unwrap_move_iterator(miVectorInt)), eastl::vector<int>::iterator>::value == true),  \"unwrap_iterator failure\");\n    }\n    EASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\t{\n\t\t// array cbegin - cend\n\t\tint arr[3]{ 1, 2, 3 };\n\t\tauto b = eastl::cbegin(arr);\n\t\tauto e = eastl::cend(arr);\n\t\tEATEST_VERIFY(*b == 1);\n\n\t\tauto dist = eastl::distance(b,e);\n\t\tEATEST_VERIFY(dist == 3);\n\t}\n\n\t{\n\t\t// Regression test that ensure N3844 is working correctly.\n\t\tstatic_assert(!eastl::is_detected<detect_iterator_traits_reference, int>::value, \"detecting iterator_traits<int> should SFINAE gracefully.\");\n\t}\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/list.h>\n#include <EASTL/sort.h>\n#include <EASTL/fixed_allocator.h>\n\nusing namespace eastl;\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::list<bool>;\ntemplate class eastl::list<int>;\ntemplate class eastl::list<Align64>;\ntemplate class eastl::list<TestObject>;\n// template class eastl::list<eastl::unique_ptr<int>>;\n\n\nint TestList()\n{\n\tint nErrorCount = 0;\n\n\t// list();\n\t{\n\t\teastl::list<int> l;\n\t\tVERIFY(l.size() == 0);\n\t\tVERIFY(l.empty());\n\t\tVERIFY(l.validate());\n\t\tVERIFY(l.begin() == l.end());\n\t}\n\n\t// list(const allocator_type& allocator);\n\t{\n\t\tMallocAllocator::reset_all();\n\t\tMallocAllocator mallocator;\n\t\t{\n\t\t\teastl::list<int, MallocAllocator> l(mallocator);\n\t\t\tVERIFY(l.get_allocator() == mallocator);\n\t\t\tl.push_front(42);\n\t\t\tVERIFY(MallocAllocator::mAllocCountAll != 0);\n\t\t}\n\t\tVERIFY(MallocAllocator::mAllocCountAll == MallocAllocator::mFreeCountAll);\n\t}\n\n\t// explicit list(size_type n, const allocator_type& allocator = EASTL_LIST_DEFAULT_ALLOCATOR);\n\t{\n\t\tconst int test_size = 42;\n\t\teastl::list<int> l(test_size);\n\t\tVERIFY(!l.empty());\n\t\tVERIFY(l.size() == test_size);\n\t\tVERIFY(l.validate());\n\n\t\tVERIFY(eastl::all_of(l.begin(), l.end(), [](int e)\n\t\t                     { return e == 0; }));\n\t}\n\n\t// list(size_type n, const value_type& value, const allocator_type& allocator = EASTL_LIST_DEFAULT_ALLOCATOR);\n\t{\n\t\tconst int test_size = 42;\n\t\tconst int test_val = 435;\n\n\t\teastl::list<int> l(42, test_val);\n\t\tVERIFY(!l.empty());\n\t\tVERIFY(l.size() == test_size);\n\t\tVERIFY(l.validate());\n\n\t\tVERIFY(eastl::all_of(l.begin(), l.end(), [=](int e)\n\t\t                     { return e == test_val; }));\n\t}\n\n\t// list(const this_type& x);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> b(a); \n\t\tVERIFY(a == b);\n\t\tVERIFY(a.validate());\n\t\tVERIFY(a.size() == b.size());\n\t\tVERIFY(b.validate());\n\t}\n\n\t// list(const this_type& x, const allocator_type& allocator);\n\t{\n\t\tMallocAllocator mallocator;\n\t\teastl::list<int, MallocAllocator> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int, MallocAllocator> b(a, mallocator);\n\t\tVERIFY(a == b);\n\t\tVERIFY(a.validate());\n\t\tVERIFY(a.size() == b.size());\n\t\tVERIFY(b.validate());\n\t\tVERIFY(a.get_allocator() == b.get_allocator());\n\t}\n\n\t// list(this_type&& x);\n\t// list(this_type&&, const allocator_type&);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\tVERIFY(!a.empty());\n\t\tVERIFY(a.size() == 10);\n\t\tVERIFY(a.validate());\n\n\t\teastl::list<int> b(eastl::move(a)); \n\t\tVERIFY(a.empty());\n\t\tVERIFY(!b.empty());\n\t\tVERIFY(a.size() == 0);\n\t\tVERIFY(b.size() == 10);\n\n\t\tVERIFY(a != b);\n\t\tVERIFY(a.size() != b.size());\n\t\tVERIFY(a.validate());\n\t\tVERIFY(b.validate());\n\t}\n\n\t// list(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_LIST_DEFAULT_ALLOCATOR);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::for_each(a.begin(), a.end(), [&](int e)\n\t\t                {\n\t\t\t                static int inc = 0;\n\t\t\t                VERIFY(inc++ == e);\n\t\t\t            });\n\t}\n\n\t// list(InputIterator first, InputIterator last); \n\t{\n\t\teastl::list<int> ref = {3, 4, 5, 6, 7};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto start = a.begin();\n\t\teastl::advance(start, 3);\n\n\t\tauto end = start;\n\t\teastl::advance(end, 5);\n\n\t\teastl::list<int> b(start, end); \n\n\t\tVERIFY(b == ref);\n\t\tVERIFY(a.validate());\n\t\tVERIFY(b.validate());\n\n\t\tVERIFY(a.size() == 10);\n\t\tVERIFY(b.size() == 5);\t\t\n\n\t\tVERIFY(!b.empty());\n\t\tVERIFY(!a.empty());\n\t}\n\n\t// this_type& operator=(const this_type& x);\n\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t// this_type& operator=(this_type&& x);\n\t{\n\t\tconst eastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> b = a;\n\t\tVERIFY(a.validate());\n\t\tVERIFY(b.validate());\n\t\tVERIFY(a.size() == 10);\n\t\tVERIFY(b.size() == 10);\t\t\n\t\tVERIFY(!a.empty());\n\t\tVERIFY(!b.empty());\n\t\tVERIFY(b == a);\n\n\t\teastl::list<int> c = eastl::move(b);\n\t\tVERIFY(b.empty());\n\n\t\tVERIFY(c == a);\n\t\tVERIFY(c.size() == 10);\n\t\tVERIFY(c.validate());\n\t}\n\n\t// void swap(this_type& x);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> b = {};\n\n\t\tVERIFY(a.validate());\n\t\tVERIFY(b.validate());\n\t\tVERIFY(!a.empty());\n\t\tVERIFY(b.empty());\n\n\t\tb.swap(a);\n\n\t\tVERIFY(a.validate());\n\t\tVERIFY(b.validate());\n\t\tVERIFY(a.empty());\n\t\tVERIFY(!b.empty());\n\t}\n\n\t// void assign(size_type n, const value_type& value);\n\t{\n\t\teastl::list<int> ref = {42, 42, 42, 42};\n\t\teastl::list<int> a = {0, 1, 2, 3};\n\t\ta.assign(4, 42);\n\t\tVERIFY(a == ref);\n\t\tVERIFY(a.validate());\n\t\tVERIFY(!a.empty());\n\t\tVERIFY(a.size() == 4);\n\t}\n\n\t// void assign(InputIterator first, InputIterator last);  \n\t{\n\t\teastl::list<int> ref = eastl::list<int>{3, 4, 5, 6, 7};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> b;\n\n\t\tauto start = a.begin();\n\t\teastl::advance(start, 3);\n\n\t\tauto end = start;\n\t\teastl::advance(end, 5);\n\n\t\tb.assign(start, end); \n\n\t\tVERIFY(b == ref);\n\t\tVERIFY(a.validate());\n\t\tVERIFY(b.validate());\n\n\t\tVERIFY(a.size() == 10);\n\t\tVERIFY(b.size() == 5);\t\t\n\n\t\tVERIFY(!b.empty());\n\t\tVERIFY(!a.empty());\n\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t// void assign(std::initializer_list<value_type> ilist);\n\t{\n\t\teastl::list<int> ref = eastl::list<int>{3, 4, 5, 6, 7};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> b;\n\n\t\tauto start = a.begin();\n\t\teastl::advance(start, 3);\n\n\t\tauto end = start;\n\t\teastl::advance(end, 5);\n\n\t\tb.assign(start, end); \n\n\t\tVERIFY(b == ref);\n\t\tVERIFY(a.validate());\n\t\tVERIFY(b.validate());\n\n\t\tVERIFY(a.size() == 10);\n\t\tVERIFY(b.size() == 5);\t\t\n\n\t\tVERIFY(!b.empty());\n\t\tVERIFY(!a.empty());\n\t}\n\n\t// iterator       begin() \n\t// const_iterator begin() const \n\t// const_iterator cbegin() const \n\t// iterator       end() \n\t// const_iterator end() const \n\t// const_iterator cend() const \n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t{\n\t\t\tstatic int inc = 0;\n\t\t\tauto iter = a.begin();\n\t\t\twhile(iter != a.end())\n\t\t\t{\n\t\t\t\tVERIFY(*iter++ == inc++);\t\t\t\t\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tstatic int inc = 0;\n\t\t\tauto iter = a.cbegin();\n\t\t\twhile(iter != a.cend())\n\t\t\t{\n\t\t\t\tVERIFY(*iter++ == inc++);\n\t\t\t}\n\t\t}\n\t}\n\n\t// reverse_iterator       rbegin()\n\t// const_reverse_iterator rbegin() const\n\t// const_reverse_iterator crbegin() const\n\t// reverse_iterator       rend()\n\t// const_reverse_iterator rend() const\n\t// const_reverse_iterator crend() const \n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t{\n\t\t\tstatic int inc = 9;\n\t\t\tauto iter = a.rbegin();\n\t\t\twhile(iter != a.rend())\n\t\t\t{\n\t\t\t\tVERIFY(*iter == inc--);\n\t\t\t\titer++;\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tstatic int inc = 9;\n\t\t\tauto iter = a.crbegin();\n\t\t\twhile(iter != a.crend())\n\t\t\t{\n\t\t\t\tVERIFY(*iter == inc--);\n\t\t\t\titer++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// bool empty() const \n\t{\n\t\t{\n\t\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tVERIFY(!a.empty());\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a = {};\n\t\t\tVERIFY(a.empty());\n\t\t}\n\t}\n\n\t// size_type size() const\n\t{\n\t\t{\n\t\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tVERIFY(a.size() == 10);\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a = {0, 1, 2, 3, 4};\n\t\t\tVERIFY(a.size() == 5);\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a = {0, 1};\n\t\t\tVERIFY(a.size() == 2);\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a = {};\n\t\t\tVERIFY(a.size() == 0);\n\t\t}\n\t}\n\n\t// void resize(size_type n, const value_type& value);\n\t// void resize(size_type n);\n\t{\n\t\t{\n\t\t\teastl::list<int> a;\n\t\t\ta.resize(10);\n\t\t\tVERIFY(a.size() == 10);\n\t\t\tVERIFY(!a.empty());\n\t\t\tVERIFY(eastl::all_of(a.begin(), a.end(), [](int i)\n\t\t\t                     { return i == 0; }));\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a;\n\t\t\ta.resize(10, 42);\n\t\t\tVERIFY(a.size() == 10);\n\t\t\tVERIFY(!a.empty());\n\t\t\tVERIFY(eastl::all_of(a.begin(), a.end(), [](int i)\n\t\t\t                     { return i == 42; }));\n\t\t}\n\t}\n\n\t// reference       front();\n\t// const_reference front() const;\n\t{\n\t\t{\n\t\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tVERIFY(a.front() == 0);\n\n\t\t\ta.front() = 42;\n\t\t\tVERIFY(a.front() == 42);\n\t\t}\n\n\t\t{\n\t\t\tconst eastl::list<int> a = {5, 6, 7, 8, 9};\n\t\t\tVERIFY(a.front() == 5);\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a = {9};\n\t\t\tVERIFY(a.front() == 9);\n\n\t\t\ta.front() = 42;\n\t\t\tVERIFY(a.front() == 42);\n\t\t}\n\t}\n\n\t// reference       back();\n\t// const_reference back() const;\n\t{\n\t\t{\n\t\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tVERIFY(a.back() == 9);\n\n\t\t\ta.back() = 42;\n\t\t\tVERIFY(a.back() == 42);\n\t\t}\n\n\t\t{\n\t\t\tconst eastl::list<int> a = {5, 6, 7, 8, 9};\n\t\t\tVERIFY(a.back() == 9);\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a = {9};\n\t\t\tVERIFY(a.back() == 9);\n\n\t\t\ta.back() = 42;\n\t\t\tVERIFY(a.back() == 42);\n\t\t}\n\t}\n\n\t// template <typename... Args>\n\t// reference emplace_front(Args&&... args);\n\t{\n\t\teastl::list<int> ref = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};\n\t\teastl::list<int> a;\n\n\t\tfor(int i = 0; i < 10; i++)\n\t\t\tVERIFY(a.emplace_front(i) == i);\n\n\t\tVERIFY(a == ref);\n\t}\n\n\t// template <typename... Args>\n\t// reference emplace_back(Args&&... args);\n\t{\n\t\t{\n\t\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\teastl::list<int> a;\n\n\t\t\tfor(int i = 0; i < 10; i++)\n\t\t\t\tVERIFY(a.emplace_back(i) == i);\n\n\t\t\tVERIFY(a == ref);\n\t\t}\n\n\t\t{\n\t\t\tstruct A\n\t\t\t{\n\t\t\t\tA() : mValue(0) {}\n\t\t\t\tA(int in) : mValue(in) {}\n\t\t\t\tint mValue;\n\t\t\t\tbool operator==(const A& other) const { return mValue == other.mValue; }\n\t\t\t};\n\n\t\t\t{\n\t\t\t\teastl::list<A> ref = {{1}, {2}, {3}};\n\t\t\t\teastl::list<A> a;\n\n\t\t\t\tVERIFY(a.emplace_back(1) == A{1});\n\t\t\t\tVERIFY(a.emplace_back(2) == A{2});\n\t\t\t\tVERIFY(a.emplace_back(3) == A{3});\n\n\t\t\t\tVERIFY(a == ref);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\teastl::list<A> ref = {{1}, {2}, {3}};\n\t\t\t\teastl::list<A> a;\n\n\t\t\t\tVERIFY(a.emplace_back(A(1)) == A{1});\n\t\t\t\tVERIFY(a.emplace_back(A(2)) == A{2});\n\t\t\t\tVERIFY(a.emplace_back(A(3)) == A{3});\n\n\t\t\t\tVERIFY(a == ref);\n\t\t\t}\n\n\n\t\t\t{\n\t\t\t\teastl::list<A> ref = {{1}, {2}, {3}};\n\t\t\t\teastl::list<A> a;\n\n\t\t\t\tA a1(1);\n\t\t\t\tA a2(2);\n\t\t\t\tA a3(3);\n\n\t\t\t\tVERIFY(a.emplace_back(a1) == A{1});\n\t\t\t\tVERIFY(a.emplace_back(a2) == A{2});\n\t\t\t\tVERIFY(a.emplace_back(a3) == A{3});\n\n\t\t\t\tVERIFY(a == ref);\n\t\t\t}\n\t\t}\n\t}\n\n\t// void push_front(const value_type& value);\n\t// void push_front(value_type&& x);\n\t// reference push_front();\n\t{\n\t\t{\n\t\t\teastl::list<int> ref = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};\n\t\t\teastl::list<int> a;\n\n\t\t\tfor(int i = 0; i < 10; i++)\n\t\t\t\ta.push_front(i);\n\n\t\t\tVERIFY(a == ref);\n\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> a;\n\t\t\tauto& front_ref = a.push_front(); // value initialized.\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT) // value initialization is not guaranteed before this.\n\t\t\tVERIFY(a.front() == 0);\n#endif\n\t\t\tfront_ref = 42;\n\t\t\tVERIFY(a.front() == 42);\n\t\t}\n\t}\n\n\t// void* push_front_uninitialized();\n\t{\n\t\teastl::list<int> a;\n\t\tfor (unsigned i = 0; i < 100; i++)\n\t\t{\n\t\t\tVERIFY(a.push_front_uninitialized() != nullptr);\n\t\t\tVERIFY(a.size() == (i + 1));\n\t\t}\n\t}\n\n\t// void push_back(const value_type& value);\n\t// void push_back(value_type&& x);\n\t{\n\t\t{\n\t\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\teastl::list<int> a;\n\n\t\t\tfor(int i = 0; i < 10; i++)\n\t\t\t\ta.push_back(i);\n\n\t\t\tVERIFY(a == ref);\n\t\t}\n\n\t\t{\n\t\t\tstruct A { int mValue; };\n\t\t\teastl::list<A> a;\n\t\t\ta.push_back(A{42});\n\t\t\tVERIFY(a.back().mValue == 42);\n\t\t}\n\t}\n\n\t// reference push_back();\n\t{\n\t\teastl::list<int> a;\n\t\tauto& back_ref = a.push_back(); // value initialized.\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT) // value initialization is not guaranteed before this.\n\t\tVERIFY(a.back() == 0);\n#endif\n\t\tback_ref = 42;\n\t\tVERIFY(a.back() == 42);\n\t}\n\n\t// void* push_back_uninitialized();\n\t{\n\t\teastl::list<int> a;\n\t\tfor (unsigned int i = 0; i < 100; i++)\n\t\t{\n\t\t\tVERIFY(a.push_back_uninitialized() != nullptr);\n\t\t\tVERIFY(a.size() == (i + 1));\n\t\t}\n\t}\n\n\t// void pop_front();\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\tfor(unsigned i = 0; i < 10; i++)\n\t\t{\n\t\t\tVERIFY(unsigned(a.front()) == i);\n\t\t\ta.pop_front();\n\t\t}\n\t}\n\n\t// void pop_back();\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\tfor(unsigned i = 0; i < 10; i++)\n\t\t{\n\t\t\tVERIFY(unsigned(a.back()) == (9 - i));\n\t\t\ta.pop_back();\n\t\t}\n\t}\n\n\t// iterator emplace(const_iterator position, Args&&... args);\n\t// iterator emplace(const_iterator position, value_type&& value);\n\t// iterator emplace(const_iterator position, const value_type& value);\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto insert_pos = a.begin();\n\t\teastl::advance(insert_pos, 5);\n\n\t\ta.emplace(insert_pos, 42);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// iterator insert(const_iterator position);\n\t// iterator insert(const_iterator position, const value_type& value);\n\t// iterator insert(const_iterator position, value_type&& x);\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto insert_pos = a.begin();\n\t\teastl::advance(insert_pos, 5);\n\n\t\ta.insert(insert_pos, 42);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void insert(const_iterator position, size_type n, const value_type& value);\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 42, 42, 42, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto insert_pos = a.begin();\n\t\teastl::advance(insert_pos, 5);\n\n\t\tauto result = a.insert(insert_pos, 4, 42);\n\t\tVERIFY(a == ref);\n\t\tVERIFY(*result == 42);\n\t\tVERIFY(*(--result) == 4);\n\t}\n\n\t// void insert(const_iterator position, InputIterator first, InputIterator last);\n\t{\n\t\teastl::list<int> to_insert = {42, 42, 42, 42};\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 42, 42, 42, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto insert_pos = a.begin();\n\t\teastl::advance(insert_pos, 5);\n\n\t\tauto result = a.insert(insert_pos, to_insert.begin(), to_insert.end());\n\t\tVERIFY(a == ref);\n\t\tVERIFY(*result == 42);\n\t\tVERIFY(*(--result) == 4);\n\t}\n\n\t// iterator insert(const_iterator position, std::initializer_list<value_type> ilist);\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 42, 42, 42, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto insert_pos = a.begin();\n\t\teastl::advance(insert_pos, 5);\n\n\t\ta.insert(insert_pos, {42, 42, 42, 42});\n\t\tVERIFY(a == ref);\n\t}\n\n\t// iterator erase(const_iterator position);\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 42, 5, 6, 7, 8, 9};\n\n\t\tauto erase_pos = a.begin();\n\t\teastl::advance(erase_pos, 5);\n\n\t\tauto iter_after_removed = a.erase(erase_pos);\n\t\tVERIFY(*iter_after_removed == 5);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// iterator erase(const_iterator first, const_iterator last);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 42, 42, 42, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto erase_begin = a.begin();\n\t\teastl::advance(erase_begin, 5);\n\n\t\tauto erase_end = erase_begin;\n\t\teastl::advance(erase_end, 4);\n\n\t\ta.erase(erase_begin, erase_end);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// reverse_iterator erase(const_reverse_iterator position);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto erase_rbegin = a.rbegin();\n\t\teastl::advance(erase_rbegin, 5);\n\n\t\tauto iter_after_remove = a.erase(erase_rbegin);\n\t\tVERIFY(*iter_after_remove == 4);\n\t\tVERIFY(a == ref);\n\n\t}\n\n\t// reverse_iterator erase(const_reverse_iterator first, const_reverse_iterator last);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 42, 42, 42, 42, 5, 6, 7, 8, 9};\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\tauto erase_crbegin = a.crbegin();\n\t\tauto erase_crend = a.crbegin();\n\t\teastl::advance(erase_crbegin, 4);\n\t\teastl::advance(erase_crend, 8);\n\n\t\tauto iter_after_removed = a.erase(erase_crbegin, erase_crend);\n\t\tVERIFY(*iter_after_removed == 4);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void clear()\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\ta.clear();\n\t\tVERIFY(a.empty());\n\t\tVERIFY(a.size() == 0);\n\t}\n\n\t// void reset_lose_memory()    \n\t{\n\t\ttypedef eastl::list<int, fixed_allocator> IntList;\n\t\ttypedef IntList::node_type                IntListNode;\n\t\tconst size_t  kBufferCount = 10;\n\t\tIntListNode   buffer1[kBufferCount];\n\t\tIntList       intList1;\n\t\tconst size_t  kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);\n\t\tintList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);\n\n\t\tintList1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\tVERIFY(!intList1.empty());\n\t\tVERIFY(intList1.size() == 10);\n\t\tintList1.reset_lose_memory();\n\t\tVERIFY(intList1.empty());\n\t\tVERIFY(intList1.size() == 0);\n\t}\n\n\t// void remove(const T& x);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> ref = {0, 1, 2, 3, 5, 6, 7, 8, 9};\n\t\ta.remove(4);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void remove_if(Predicate);\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> ref = {0, 1, 2, 3, 5, 6, 7, 8, 9};\n\t\ta.remove_if([](int e) { return e == 4; });\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void reverse()\n\t{\n\t\teastl::list<int> a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> ref = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};\n\t\ta.reverse();\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void splice(const_iterator position, this_type& x);\n\t{\n\t\tconst eastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a1 = {0, 1, 2, 3, 4};\n\t\teastl::list<int> a2 = {5, 6, 7, 8, 9};\n\n\t\teastl::list<int> a;\n\t\ta.splice(a.begin(), a2);\n\t\ta.splice(a.begin(), a1);\n\n\t\tVERIFY(a == ref);\n\t\tVERIFY(a1.empty());\n\t\tVERIFY(a2.empty());\n\t}\n\n\t// void splice(const_iterator position, this_type& x, const_iterator i);\n\t{\n\t\tconst eastl::list<int> ref = {0, 5};\n\t\teastl::list<int> a1 = {-1, -1, 0};\n\t\teastl::list<int> a2 = {-1, -1, 5};\n\n\t\tauto a1_begin = a1.begin();\n\t\tauto a2_begin = a2.begin();\n\n\t\teastl::advance(a1_begin, 2);\n\t\teastl::advance(a2_begin, 2);\n\n\t\teastl::list<int> a;\n\t\ta.splice(a.begin(), a2, a2_begin);\n\t\ta.splice(a.begin(), a1, a1_begin);\n\n\t\tVERIFY(a == ref);\n\t\tVERIFY(!a1.empty());\n\t\tVERIFY(!a2.empty());\n\t}\n\n\t// void splice(const_iterator position, this_type& x, const_iterator first, const_iterator last);\n\t{\n\t\tconst eastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a1 = {-1, -1, 0, 1, 2, 3, 4, -1, -1};\n\t\teastl::list<int> a2 = {-1, -1, 5, 6, 7, 8, 9, -1, -1};\n\n\t\tauto a1_begin = a1.begin();\n\t\tauto a2_begin = a2.begin();\n\t\tauto a1_end = a1.end();\n\t\tauto a2_end = a2.end();\n\n\t\teastl::advance(a1_begin, 2);\n\t\teastl::advance(a2_begin, 2);\n\t\teastl::advance(a1_end, -2);\n\t\teastl::advance(a2_end, -2);\n\n\t\teastl::list<int> a;\n\t\ta.splice(a.begin(), a2, a2_begin, a2_end);\n\t\ta.splice(a.begin(), a1, a1_begin, a1_end);\n\n\t\tconst eastl::list<int> rref = {-1, -1, -1, -1};  // post splice reference list\n\t\tVERIFY(a == ref);\n\t\tVERIFY(a1 == rref);\n\t\tVERIFY(a2 == rref);\n\t}\n\n\t// void splice(const_iterator position, this_type&& x);\n\t{\n\t\tconst eastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a1 = {0, 1, 2, 3, 4};\n\t\teastl::list<int> a2 = {5, 6, 7, 8, 9};\n\n\t\teastl::list<int> a;\n\t\ta.splice(a.begin(), eastl::move(a2));\n\t\ta.splice(a.begin(), eastl::move(a1));\n\n\t\tVERIFY(a == ref);\n\t\tVERIFY(a1.empty());\n\t\tVERIFY(a2.empty());\n\t}\n\n\t// void splice(const_iterator position, this_type&& x, const_iterator i);\n\t{\n\t\tconst eastl::list<int> ref = {0, 5};\n\t\teastl::list<int> a1 = {-1, -1, 0};\n\t\teastl::list<int> a2 = {-1, -1, 5};\n\n\t\tauto a1_begin = a1.begin();\n\t\tauto a2_begin = a2.begin();\n\n\t\teastl::advance(a1_begin, 2);\n\t\teastl::advance(a2_begin, 2);\n\n\t\teastl::list<int> a;\n\t\ta.splice(a.begin(), eastl::move(a2), a2_begin);\n\t\ta.splice(a.begin(), eastl::move(a1), a1_begin);\n\n\t\tVERIFY(a == ref);\n\t\tVERIFY(!a1.empty());\n\t\tVERIFY(!a2.empty());\n\t}\n\n\t// void splice(const_iterator position, this_type&& x, const_iterator first, const_iterator last);\n\t{\n\t\tconst eastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a1 = {-1, -1, 0, 1, 2, 3, 4, -1, -1};\n\t\teastl::list<int> a2 = {-1, -1, 5, 6, 7, 8, 9, -1, -1};\n\n\t\tauto a1_begin = a1.begin();\n\t\tauto a2_begin = a2.begin();\n\t\tauto a1_end = a1.end();\n\t\tauto a2_end = a2.end();\n\n\t\teastl::advance(a1_begin, 2);\n\t\teastl::advance(a2_begin, 2);\n\t\teastl::advance(a1_end, -2);\n\t\teastl::advance(a2_end, -2);\n\n\t\teastl::list<int> a;\n\t\ta.splice(a.begin(), eastl::move(a2), a2_begin, a2_end);\n\t\ta.splice(a.begin(), eastl::move(a1), a1_begin, a1_end);\n\n\t\tconst eastl::list<int> rref = {-1, -1, -1, -1};  // post splice reference list\n\t\tVERIFY(a == ref);\n\t\tVERIFY(a1 == rref);\n\t\tVERIFY(a2 == rref);\n\t}\n\n\n\t// void merge(this_type& x);\n\t// void merge(this_type&& x);\n\t// void merge(this_type& x, Compare compare);\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a1 = {0, 1, 2, 3, 4};\n\t\teastl::list<int> a2 = {5, 6, 7, 8, 9};\n\t\ta1.merge(a2);\n\t\tVERIFY(a1 == ref);\n\t}\n\n\t// void merge(this_type&& x, Compare compare);\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a1 = {0, 1, 2, 3, 4};\n\t\teastl::list<int> a2 = {5, 6, 7, 8, 9};\n\t\ta1.merge(a2, [](int lhs, int rhs) { return lhs < rhs; });\n\t\tVERIFY(a1 == ref);\n\t}\n\n\t// size_type unique();\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3,\n\t\t                      4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9};\n\t\tVERIFY(a.unique() == 34);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// size_type unique(BinaryPredicate);\n\t{\n\t\tstatic bool bBreakComparison;\n\t\tstruct A\n\t\t{\n\t\t\tint mValue;\n\t\t\tbool operator==(const A& other) const { return bBreakComparison ? false : mValue == other.mValue; }\n\t\t};\n\n\t\teastl::list<A> ref = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}};\n\t\teastl::list<A> a = {{0}, {0}, {0}, {0}, {0}, {0}, {1}, {2}, {2}, {2}, {2}, {3}, {4}, {5},\n\t\t                    {5}, {5}, {5}, {5}, {6}, {7}, {7}, {7}, {7}, {8}, {9}, {9}, {9}};\n\n\t\tbBreakComparison = true;\n\t\tVERIFY(a.unique() == 0); // noop because broken comparison operator\n\t\tVERIFY(a != ref);  \n\n\t\tVERIFY(a.unique([](const A& lhs, const A& rhs) { return lhs.mValue == rhs.mValue; }) == 17);\n\n\t\tbBreakComparison = false;\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void sort();\n\t{\n\t\teastl::list<int> ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\teastl::list<int> a =   {9, 4, 5, 3, 1, 0, 6, 2, 7, 8};\n\n\t\ta.sort();\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void sort(Compare compare);\n\t{\n\t\tstruct A\n\t\t{\n\t\t\tint mValue;\n\t\t\tbool operator==(const A& other) const { return mValue == other.mValue; }\n\t\t};\n\n\t\teastl::list<A> ref = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}};\n\t\teastl::list<A> a = {{1}, {0}, {2}, {9}, {4}, {5}, {6}, {7}, {3}, {8}};\n\n\t\ta.sort([](const A& lhs, const A& rhs) { return lhs.mValue < rhs.mValue; });\n\t\tVERIFY(a == ref);\n\t}\n\n\t{ // Test empty base-class optimization\n\t\tstruct UnemptyDummyAllocator : eastl::dummy_allocator\n\t\t{\n\t\t\tint foo;\n\t\t};\n\n\t\ttypedef eastl::list<int, eastl::dummy_allocator> list1;\n\t\ttypedef eastl::list<int, UnemptyDummyAllocator> list2;\n\n\t\tEATEST_VERIFY(sizeof(list1) < sizeof(list2));\n\t}\n\n\t{ // Test erase / erase_if\n\t\t{\n\t\t\teastl::list<int> l = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t\tauto numErased = eastl::erase(l, 3);\n\t\t    VERIFY(numErased == 1);\n\t\t\tnumErased = eastl::erase(l, 5);\n\t\t    VERIFY(numErased == 1);\n\t\t\tnumErased = eastl::erase(l, 7);\n\t\t    VERIFY(numErased == 1);\n\n\t\t\tVERIFY((l == eastl::list<int>{1, 2, 4, 6, 8, 9}));\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> l = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tauto numErased = eastl::erase_if(l, [](auto i) { return i % 2 == 0; });\n\t\t\tVERIFY((l == eastl::list<int>{1, 3, 5, 7, 9}));\n\t\t    VERIFY(numErased == 4);\n\t\t}\n\t}\n\n\t{ // Test global operators\n\t    {\n\t\t    eastl::list<int> list1 = {0, 1, 2, 3, 4, 5};\n\t\t    eastl::list<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t    eastl::list<int> list3 = {5, 6, 7, 8};\n\n\t\t\tVERIFY(list1 == list1);\n\t\t    VERIFY(!(list1 != list1));\n\n\t\t\tVERIFY(list1 != list2);\n\t\t    VERIFY(list2 != list3);\n\t\t    VERIFY(list1 != list3);\n\n\t\t\tVERIFY(list1 < list2);\n\t\t    VERIFY(list1 <= list2);\n\n\t\t\tVERIFY(list2 > list1);\n\t\t    VERIFY(list2 >= list1);\n\t\t\t\n\t\t\tVERIFY(list3 > list1);\n\t\t    VERIFY(list3 > list2);\n\t\t}\n\n\t\t// three way comparison operator\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\t{\n\t\t\teastl::list<int> list1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\teastl::list<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t\t// Verify equality between list1 and list2\n\t\t\tVERIFY((list1 <=> list2) == 0);\n\t\t\tVERIFY(!((list1 <=> list2) != 0));\n\t\t\tVERIFY((list1 <=> list2) <= 0);\n\t\t\tVERIFY((list1 <=> list2) >= 0);\n\t\t\tVERIFY(!((list1 <=> list2) < 0));\n\t\t\tVERIFY(!((list1 <=> list2) > 0));\n\n\t\t\tlist1.push_back(100); // Make list1 less than list2.\n\t\t\tlist2.push_back(101);\n\n\t\t\t// Verify list1 < list2\n\t\t\tVERIFY(!((list1 <=> list2) == 0));\n\t\t\tVERIFY((list1 <=> list2) != 0);\n\t\t\tVERIFY((list1 <=> list2) <= 0);\n\t\t\tVERIFY(!((list1 <=> list2) >= 0));\n\t\t\tVERIFY(((list1 <=> list2) < 0));\n\t\t\tVERIFY(!((list1 <=> list2) > 0));\n\n\t\t\tfor (int i = 0; i < 3; i++) // Make the length of list2 less than list1\n\t\t\t\tlist2.pop_back();\n\n\t\t\t// Verify list2.size() < list1.size() and list2 is a subset of list1\n\t\t\tVERIFY(!((list1 <=> list2) == 0));\n\t\t\tVERIFY((list1 <=> list2) != 0);\n\t\t\tVERIFY((list1 <=> list2) >= 0);\n\t\t\tVERIFY(!((list1 <=> list2) <= 0));\n\t\t\tVERIFY(((list1 <=> list2) > 0));\n\t\t\tVERIFY(!((list1 <=> list2) < 0));\n\t\t}\n\n\t\t{\n\t\t\teastl::list<int> list1 = {1, 2, 3, 4, 5, 6, 7};\n\t\t\teastl::list<int> list2 = {7, 6, 5, 4, 3, 2, 1};\n\t\t\teastl::list<int> list3 = {1, 2, 3, 4};\n\n\t\t\tstruct weak_ordering_list\n\t\t\t{\n\t\t\t\teastl::list<int> list;\n\t\t\t\tinline std::weak_ordering operator<=>(const weak_ordering_list& b) const { return list <=> b.list; }\n\t\t\t};\n\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_list{list1}, weak_ordering_list{list2}) == std::weak_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_list{list3}, weak_ordering_list{list1}) == std::weak_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_list{list2}, weak_ordering_list{list1}) == std::weak_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_list{list2}, weak_ordering_list{list3}) == std::weak_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_list{list1}, weak_ordering_list{list1}) == std::weak_ordering::equivalent);\n\n\t\t\tstruct strong_ordering_list\n\t\t\t{\n\t\t\t\teastl::list<int> list;\n\t\t\t\tinline std::strong_ordering operator<=>(const strong_ordering_list& b) const { return list <=> b.list; }\n\t\t\t};\n\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_list{list1}, strong_ordering_list{list2}) == std::strong_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_list{list3}, strong_ordering_list{list1}) == std::strong_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_list{list2}, strong_ordering_list{list1}) == std::strong_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_list{list2}, strong_ordering_list{list3}) == std::strong_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_list{list1}, strong_ordering_list{list1}) == std::strong_ordering::equal);\n\t\t}\n#endif\n\t}\n\treturn nErrorCount;\n}\n\n\n"
  },
  {
    "path": "test/source/TestListMap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/utility.h>\n#include <EASTL/bonus/list_map.h>\n\n\n#ifdef _MSC_VER\n\t#pragma warning(push, 0)\n#endif\n\n#include <stdio.h>\n\n#if defined(_MSC_VER)\n\t#pragma warning(pop)\n#endif\n\n\n\n// We would like to use the generic EASTLTest VerifySequence function, but it's not currently ready to deal\n// with non-POD types. That can probably be solved, but in the meantime we implement a custom function here.\ntemplate <typename T1, typename T2>\nbool VerifyListMapSequence(const char* pName, \n\t\t\t\t\t\t\teastl::list_map<T1, T2>& listMap, \n\t\t\t\t\t\t\tT1 t1End,   T2, \n\t\t\t\t\t\t\tT1 t10 = 0, T2 t20 = 0, \n\t\t\t\t\t\t\tT1 t11 = 0, T2 t21 = 0, \n\t\t\t\t\t\t\tT1 t12 = 0, T2 t22 = 0, \n\t\t\t\t\t\t\tT1 t13 = 0, T2 t23 = 0, \n\t\t\t\t\t\t\tT1 t14 = 0, T2 t24 = 0, \n\t\t\t\t\t\t\tT1 t15 = 0, T2 t25 = 0)\n{\n\ttypename eastl::list_map<T1, T2>::iterator it = listMap.begin();\n\n\tif(t10 == t1End)\n\t\treturn (it == listMap.end());\n\tif(it->first != t10 || it->second != t20)\n\t\t{ EASTLTest_Printf(\"[%s] Mismatch at index %d\\n\", pName, 0); return false; }\n\t++it;\n\n\tif(t11 == t1End)\n\t\treturn (it == listMap.end());\n\tif(it->first != t11 || it->second != t21)\n\t\t{ EASTLTest_Printf(\"[%s] Mismatch at index %d\\n\", pName, 1); return false; }\n\t++it;\n\n\tif(t12 == t1End)\n\t\treturn (it == listMap.end());\n\tif(it->first != t12 || it->second != t22)\n\t\t{ EASTLTest_Printf(\"[%s] Mismatch at index %d\\n\", pName, 2); return false; }\n\t++it;\n\n\tif(t13 == t1End)\n\t\treturn (it == listMap.end());\n\tif(it->first != t13 || it->second != t23)\n\t\t{ EASTLTest_Printf(\"[%s] Mismatch at index %d\\n\", pName, 3); return false; }\n\t++it;\n\n\tif(t14 == t1End)\n\t\treturn (it == listMap.end());\n\tif(it->first != t14 || it->second != t24)\n\t\t{ EASTLTest_Printf(\"[%s] Mismatch at index %d\\n\", pName, 4); return false; }\n\t++it;\n\n\tif(t15 == t1End)\n\t\treturn (it == listMap.end());\n\tif(it->first != t15 || it->second != t25)\n\t\t{ EASTLTest_Printf(\"[%s] Mismatch at index %d\\n\", pName, 5); return false; }\n\t++it;\n\n\treturn true;\n}\n\n\nint TestListMap()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\ttypedef eastl::list_map<uint32_t, uint64_t> TestMapType;\n\t\ttypedef eastl::pair<uint32_t, uint64_t>     ValueType;      // We currently can't use TestMapType::value_type because its 'first' is const.\n\n\t\tTestMapType                         testMap;\n\t\tTestMapType::iterator               iter;\n\t\tTestMapType::const_iterator         c_iter;\n\t\tTestMapType::reverse_iterator       rIter;\n\t\tTestMapType::const_reverse_iterator c_rIter;\n\t\tTestMapType::iterator               tempIter;\n\n\t\tEATEST_VERIFY(testMap.empty());\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_front(ValueType(3, 1003));\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_back(ValueType(4, 1004));\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_back(ValueType(2, 1002));\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_front(ValueType(6, 1006));\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\tEATEST_VERIFY(!testMap.empty());\n\t\tEATEST_VERIFY(testMap.size() == 4);\n\t\n\t\tEATEST_VERIFY(testMap.find(3) != testMap.end());\n\t\tEATEST_VERIFY(testMap.find(5) == testMap.end());\n\t\tEATEST_VERIFY((VerifyListMapSequence<uint32_t, uint64_t>(\"list_map::push_back\", testMap, UINT32_MAX, 0,  6, 1006,  3, 1003,  4, 1004,  2, 1002,  UINT32_MAX, 0)));\n\n\t\titer = testMap.find(3);\n\t\tEATEST_VERIFY((iter->first == 3) && ((++iter)->first == 4) && ((++iter)->first == 2));\n\n\t\trIter = testMap.rbegin();\n\t\tEATEST_VERIFY((rIter->first == 2) && ((++rIter)->first == 4) && ((++rIter)->first == 3) && ((++rIter)->first == 6));\n\n\t\tTestMapType::const_reference rFront = testMap.front();\n\t\tEATEST_VERIFY(rFront.first == 6);\n\n\t\tTestMapType::reference rBack = testMap.back();\n\t\tEATEST_VERIFY(rBack.first == 2);\n\n\t\ttestMap.clear();\n\t\tEATEST_VERIFY(testMap.empty());\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\titer = testMap.begin();\n\t\tEATEST_VERIFY(iter == testMap.end());\n\n\t\ttestMap.push_back(ValueType(10, 1010));\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_front(ValueType(8, 1008));\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_back(7, 1007);\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_front(9, 1009);\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.push_back(11, 1011LL);\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\tEATEST_VERIFY((VerifyListMapSequence<uint32_t, uint64_t>(\"list_map::push_back\", testMap, UINT32_MAX, 0,  9, 1009,  8, 1008,  10, 1010,  7, 1007,  11, 1011,  UINT32_MAX, 0)));\n\n\t\ttestMap.pop_front();\n\t\tEATEST_VERIFY(testMap.validate());\n\t\tEATEST_VERIFY((VerifyListMapSequence<uint32_t, uint64_t>(\"list_map::push_back\", testMap, UINT32_MAX, 0,  8, 1008,  10, 1010,  7, 1007,  11, 1011,  UINT32_MAX, 0)));\n\n\t\trIter = testMap.rbegin();\n\t\tEATEST_VERIFY((rIter->first == 11 && ((++rIter)->first == 7) && ((++rIter)->first == 10) && ((++rIter)->first == 8)));\n\n\t\ttestMap.pop_back();\n\t\tEATEST_VERIFY(testMap.validate());\n\t\tEATEST_VERIFY((VerifyListMapSequence<uint32_t, uint64_t>(\"list_map::push_back\", testMap, UINT32_MAX, 0,  8, 1008,  10, 1010,  7, 1007,  UINT32_MAX, 0)));\n\n\t\trIter = testMap.rbegin();\n\t\tEATEST_VERIFY(((rIter)->first == 7) && ((++rIter)->first == 10) && ((++rIter)->first == 8));\n\n\t\ttempIter = testMap.find(10);\n\t\tEATEST_VERIFY(tempIter != testMap.end());\n\n\t\ttestMap.erase(10);\n\t\tEATEST_VERIFY(testMap.validate());\n\t\tEATEST_VERIFY((VerifyListMapSequence<uint32_t, uint64_t>(\"list_map::push_back\", testMap, UINT32_MAX, 0,  8, 1008,  7, 1007,  UINT32_MAX, 0)));\n\n\t\tEATEST_VERIFY(testMap.validate_iterator(testMap.find(8)) == (eastl::isf_valid | eastl::isf_current | eastl::isf_can_dereference));\n\t\tEATEST_VERIFY(testMap.validate_iterator(testMap.find(30)) == (eastl::isf_valid | eastl::isf_current));\n\t\tEATEST_VERIFY(testMap.validate_iterator(tempIter) == eastl::isf_none);\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.erase(20);  // erasing an index not in use should still be safe\n\t\tEATEST_VERIFY(testMap.validate());\n\t\tEATEST_VERIFY((VerifyListMapSequence<uint32_t, uint64_t>(\"list_map::push_back\", testMap, UINT32_MAX, 0,  8, 1008,  7, 1007,  UINT32_MAX, 0)));\n\n\t\tEATEST_VERIFY(testMap.count(7) == 1);\n\t\tEATEST_VERIFY(testMap.count(10) == 0);\n\t\tEATEST_VERIFY(testMap.validate());\n\n\t\ttestMap.erase(testMap.find(8));\n\t\tEATEST_VERIFY(testMap.validate());\n\t\tEATEST_VERIFY((VerifyListMapSequence<uint32_t, uint64_t>(\"list_map::push_back\", testMap, UINT32_MAX, 0,  7, 1007,  UINT32_MAX, 0)));\n\n\t\ttestMap.erase(testMap.rbegin());\n\t\tEATEST_VERIFY(testMap.empty());\n\t\tEATEST_VERIFY(testMap.validate());\n\t}\n\n\t{\n\t\ttypedef eastl::list_map<eastl::string, uint32_t> TestStringMapType;\n\t\tTestStringMapType           testStringMap;\n\t\tTestStringMapType::iterator strIter;\n\n\t\ttestStringMap.push_back(eastl::string(\"hello\"), 750);\n\t\tEATEST_VERIFY(testStringMap.size() == 1);\n\n\t\tstrIter = testStringMap.find_as(\"hello\", eastl::less<>());\n\t\tEATEST_VERIFY(strIter != testStringMap.end());\n\t\tEATEST_VERIFY(strIter->first == \"hello\");\n\t\tEATEST_VERIFY(strIter->second == 750);\n\n\t\tstrIter = testStringMap.find_as(\"fake_string\", eastl::less<>());\n\t\tEATEST_VERIFY(strIter == testStringMap.end());\n\t\tEATEST_VERIFY(testStringMap.validate());\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestLruCache.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/bonus/lru_cache.h>\n#include <EASTL/unique_ptr.h>\n#include <EASTL/map.h>\n// #include <EASTL/deque.h>\n\nnamespace TestLruCacheInternal\n{\n\tstruct Foo\n\t{\n\t\tstatic int count;\n\n\t\tFoo()\n\t\t\t: a(count++)\n\t\t\t, b(count++)\n\t\t{ }\n\n\t\tFoo(int x, int y) : a(x), b(y) {}\n\n\t\tint a;\n\t\tint b;\n\n\t\tbool operator==(const Foo &other) const\n\t\t{\n\t\t\treturn this->a == other.a && this->b == other.b;\n\t\t}\n\t};\n\n\tint Foo::count = 0;\n\n\tclass FooCreator\n\t{\n\tpublic:\n\t\tFooCreator() : mFooCreatedCount(0) {}\n\n\t\tFoo\t*Create()\n\t\t{\n\t\t\tmFooCreatedCount++;\n\t\t\treturn new Foo();\n\t\t}\n\n\t\tvoid Destroy(Foo *f)\n\t\t{\n\t\t\tdelete f;\n\t\t\tmFooCreatedCount--;\n\t\t}\n\n\t\tint mFooCreatedCount;\n\t};\n}\n\n\ntemplate<template<typename, typename> typename LruCache>\nint TestLruCacheOfType()\n{\n\tint nErrorCount = 0;\n\n\t// Test simple situation\n\t{\n\t\tusing namespace TestLruCacheInternal;\n\n\t\tFoo::count = 0;\n\n\t\tLruCache<int, Foo> lruCache(3);\n\n\t\t// Empty state\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.size() == 0);\n\t\tEATEST_VERIFY(lruCache.empty() == true);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\t\tEATEST_VERIFY(lruCache.at(1).has_value() == false);\n\n\t\t// Auto create with get call\n\t\tEATEST_VERIFY(lruCache[0].a == 0);\n\t\tEATEST_VERIFY(lruCache[0].b == 1);\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.contains(0) == true);\n\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\n\t\t// Fill structure up to 2 more entries to fill out, also test at()\n\t\tlruCache.insert(1, Foo(2, 3));\n\t\tEATEST_VERIFY(lruCache.at(1).value().a == 2);\n\t\tEATEST_VERIFY(lruCache.at(1).value().b == 3);\n\t\tEATEST_VERIFY(lruCache.contains(0) == true);\n\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\tEATEST_VERIFY(lruCache.contains(3) == false);\n\t\tEATEST_VERIFY(lruCache.size() == 2);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\n\t\tlruCache.insert(2, Foo(4, 5));\n\t\tEATEST_VERIFY(lruCache[2].a == 4);\n\t\tEATEST_VERIFY(lruCache[2].b == 5);\n\t\tEATEST_VERIFY(lruCache.contains(0) == true);\n\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\tEATEST_VERIFY(lruCache.contains(2) == true);\n\t\tEATEST_VERIFY(lruCache.contains(3) == false);\n\t\tEATEST_VERIFY(lruCache.size() == 3);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\n\t\t// Add another entry, at this point 0 is the oldest, so it should be pulled\n\t\tlruCache.insert(3, Foo(6, 7));\n\t\tEATEST_VERIFY(lruCache[3].a == 6);\n\t\tEATEST_VERIFY(lruCache[3].b == 7);\n\t\tEATEST_VERIFY(lruCache.contains(0) == false);\n\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\tEATEST_VERIFY(lruCache.contains(2) == true);\n\t\tEATEST_VERIFY(lruCache.contains(3) == true);\n\t\tEATEST_VERIFY(lruCache.size() == 3);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\n\t\t// Touch the now oldest 1 key\n\t\tEATEST_VERIFY(lruCache.touch(1) == true);\n\n\t\t// Add another entry, this will be #4 but since 1 was touched, 2 is now the oldest\n\t\tlruCache.insert(4, Foo(8, 9));\n\t\tEATEST_VERIFY(lruCache[4].a == 8);\n\t\tEATEST_VERIFY(lruCache[4].b == 9);\n\t\tEATEST_VERIFY(lruCache.contains(0) == false);\n\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\tEATEST_VERIFY(lruCache.contains(3) == true);\n\t\tEATEST_VERIFY(lruCache.contains(4) == true);\n\t\tEATEST_VERIFY(lruCache.size() == 3);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\n\t\t// Test resize down\n\t\tEATEST_VERIFY(lruCache.touch(3) == true);\t// Let's make some key in the middle the most recent\n\t\tlruCache.resize(1);\t// Resize down to 1 entry in the cache\n\t\tEATEST_VERIFY(lruCache.contains(0) == false);\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\tEATEST_VERIFY(lruCache.contains(3) == true);\n\t\tEATEST_VERIFY(lruCache.contains(4) == false);\n\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 1);\n\n\t\t// Let's resize up to a size of 5 now\n\t\tlruCache.resize(5);\n\t\tEATEST_VERIFY(lruCache.contains(0) == false);\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\tEATEST_VERIFY(lruCache.contains(3) == true);\n\t\tEATEST_VERIFY(lruCache.contains(4) == false);\n\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 5);\n\n\t\t// Let's try updating\n\t\tlruCache.assign(3, Foo(0, 0));\n\t\tEATEST_VERIFY(lruCache[3] == Foo(0, 0));\n\t\tEATEST_VERIFY(lruCache.contains(0) == false);\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\tEATEST_VERIFY(lruCache.contains(3) == true);\n\t\tEATEST_VERIFY(lruCache.contains(4) == false);\n\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 5);\n\n\t\t// add or update existing\n\t\tlruCache.insert_or_assign(3, Foo(1, 1));\n\t\tEATEST_VERIFY(lruCache[3] == Foo(1, 1));\n\t\tEATEST_VERIFY(lruCache.contains(0) == false);\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\tEATEST_VERIFY(lruCache.contains(3) == true);\n\t\tEATEST_VERIFY(lruCache.contains(4) == false);\n\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 5);\n\t\t\n\t\t// Add or update a new entry\n\t\tlruCache.insert_or_assign(25, Foo(2, 2));\n\t\tEATEST_VERIFY(lruCache[3] == Foo(1, 1));\n\t\tEATEST_VERIFY(lruCache[25] == Foo(2, 2));\n\t\tEATEST_VERIFY(lruCache.contains(0) == false);\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\tEATEST_VERIFY(lruCache.contains(3) == true);\n\t\tEATEST_VERIFY(lruCache.contains(4) == false);\n\t\tEATEST_VERIFY(lruCache.contains(25) == true);\n\t\tEATEST_VERIFY(lruCache.size() == 2);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 5);\n\n\t\t// clear everything\n\t\tlruCache.clear();\n\t\tEATEST_VERIFY(lruCache.size() == 0);\n\t\tEATEST_VERIFY(lruCache.empty() == true);\n\t\tEATEST_VERIFY(lruCache.capacity() == 5);\n\t\tEATEST_VERIFY(lruCache.contains(3) == false);\n\n\t\t// test unilateral reset\n\t\tlruCache[1] = Foo(1, 2);\n\t\tlruCache.reset_lose_memory();\n\t\tEATEST_VERIFY(lruCache.size() == 0);\n\t}\n\n\t// Test more advanced creation / deletion via callbacks\n\t{\n\t\tusing namespace TestLruCacheInternal;\n\n\t\tFooCreator fooCreator;\n\n\t\tauto createCallback = [&fooCreator](int) { return fooCreator.Create(); };\n\t\tauto deleteCallback = [&fooCreator](Foo *f) { fooCreator.Destroy(f); };\n\n\t\tLruCache<int, Foo*> lruCache(3, EASTLAllocatorType(\"eastl lru_cache\"), createCallback, deleteCallback);\n\n\t\tlruCache[1];\n\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 1);\n\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\n\t\tlruCache[2];\n\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 2);\n\t\tEATEST_VERIFY(lruCache.size() == 2);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\tEATEST_VERIFY(lruCache.contains(2) == true);\n\n\t\t// Update 2, which should delete the existing entry\n\t\t{\n\t\t\tauto f = fooCreator.Create();\n\t\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 3);\n\t\t\tf->a = 20;\n\t\t\tf->b = 21;\n\t\t\tlruCache.assign(2, f);\n\t\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 2);\n\t\t\tEATEST_VERIFY(lruCache.size() == 2);\n\t\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\t\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\t\tEATEST_VERIFY(lruCache.contains(2) == true);\n\t\t\tEATEST_VERIFY(lruCache[2]->a == 20);\n\t\t\tEATEST_VERIFY(lruCache[2]->b == 21);\n\t\t}\n\n\t\tlruCache.erase(2);\n\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 1);\n\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\t\tEATEST_VERIFY(lruCache.contains(1) == true);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\n\t\tlruCache.erase(1);\n\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 0);\n\t\tEATEST_VERIFY(lruCache.size() == 0);\n\t\tEATEST_VERIFY(lruCache.empty() == true);\n\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\n\t\t// Test insert_or_assign\n\t\t{\n\t\t\tauto f = fooCreator.Create();\n\t\t\tf->a = 22;\n\t\t\tf->b = 30;\n\t\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 1);\n\n\t\t\tlruCache.insert_or_assign(7, f);\n\t\t\tEATEST_VERIFY(lruCache.size() == 1);\n\t\t\tEATEST_VERIFY(lruCache.empty() == false);\n\t\t\tEATEST_VERIFY(lruCache.capacity() == 3);\n\t\t\tEATEST_VERIFY(lruCache.contains(1) == false);\n\t\t\tEATEST_VERIFY(lruCache.contains(2) == false);\n\t\t\tEATEST_VERIFY(lruCache.contains(7) == true);\n\t\t\tEATEST_VERIFY(lruCache.erase(7) == true);\n\t\t\tEATEST_VERIFY(fooCreator.mFooCreatedCount == 0);\n\t\t}\n\t}\n\n\t// Test iteration\n\t{\n\t\tLruCache<int, int> lc(5);\n\t\tlc.insert_or_assign(0,10);\n\t\tlc.insert_or_assign(1,11);\n\t\tlc.insert_or_assign(2,12);\n\t\tlc.insert_or_assign(3,13);\n\t\tlc.insert_or_assign(4,14);\n\n\t\t{ // test manual for-loop\n\t\t\tint i = 0;\n\t\t\tfor (auto b = lc.begin(), e = lc.end(); b != e; b++)\n\t\t\t{\n\t\t\t\tauto &p = *b;\n\t\t\t\tVERIFY(i == p.first);\n\t\t\t\tVERIFY(i + 10 == p.second.first);\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\n\t\t{ // test pairs \n\t\t\tint i = 0;\n\t\t\tfor(auto& p : lc)\n\t\t\t{\n\t\t\t\tVERIFY(i == p.first);\n\t\t\t\tVERIFY(i + 10 == p.second.first);\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\n\t\t{ // test structured bindings\n\t\t\tint i = 0;\n\t\t\tfor(auto& [key, value] : lc)\n\t\t\t{\n\t\t\t\tVERIFY(i == key);\n\t\t\t\tVERIFY(i + 10 == value.first);\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// test initializer_list\n\t{\n\t\tLruCache<int, int> lc = {{0, 10}, {1, 11}, {2, 12}, {3, 13}, {4, 14}, {5, 15}};\n\n\t\tint i = 0;\n\t\tfor(auto& p : lc)\n\t\t{\n\t\t\tVERIFY(i == p.first);\n\t\t\tVERIFY(i + 10 == p.second.first);\n\t\t\ti++;\n\t\t}\n\t}\n\n\t// emplace\n\t{\n\t\teastl::lru_cache<int, TestObject> lc = { {0, TestObject{ 1, 2, 3 }}, {1, TestObject{ 4, 5, 6 }} };\n\n\t\tVERIFY((lc.at(0) == TestObject{1, 2, 3}));\n\t\tVERIFY((lc.at(1) == TestObject{ 4, 5, 6 }));\n\n\t\tVERIFY((lc.emplace(0, 3, 2, 1).first->second.first == TestObject{ 3, 2, 1 }));\n\t\tVERIFY((lc.emplace(1, 6, 5, 4).first->second.first == TestObject{ 6, 5, 4 }));\n\n\t\t// fail to emplace: key 0 already exists.\n\t\tauto [ it, did_emplace ] = lc.emplace(0, 9, 9, 9);\n\t\tVERIFY(!did_emplace);\n\t\tVERIFY((it->second.first == TestObject{ 3, 2, 1 }));\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate<typename K, typename V>\nusing LruCache = eastl::lru_cache<K, V, EASTLAllocatorType, eastl::list<K>, eastl::unordered_map<K, eastl::pair<V, typename eastl::list<K>::iterator>>>;\n\ntemplate<typename K, typename V>\nusing LruCacheMap = eastl::lru_cache<K, V, EASTLAllocatorType, eastl::list<K>, eastl::map<K, eastl::pair<V, typename eastl::list<K>::iterator>>>;\n\n// template<typename K, typename V>\n// using LruCacheDequeMap = eastl::lru_cache<K, V, EASTLAllocatorType, eastl::deque<K>, eastl::map<K, eastl::pair<V, typename eastl::deque<K>::iterator>>>;\n\nint TestLruCache()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestLruCacheOfType<LruCache>();\n\tnErrorCount += TestLruCacheOfType<LruCacheMap>();\n\t// could use a deque instead of a list, except that lru_cache requires the container have a reset_lose_memory() function.\n\t// nErrorCount += TestLruCacheOfType<LruCacheDequeMap>();\n\n\treturn nErrorCount;\n}"
  },
  {
    "path": "test/source/TestMap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"TestMap.h\"\n#include \"EASTLTest.h\"\n#include <EASTL/map.h>\n#include <EASTL/string.h>\n#include <EASTL/vector.h>\n#include \"TestAssociativeContainers.h\"\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <map>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::map<int, int>;\ntemplate class eastl::multimap<int, int>;\ntemplate class eastl::map<TestObject, TestObject>;\ntemplate class eastl::multimap<TestObject, TestObject>;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// typedefs\n//\ntypedef eastl::map<int, int> VM1;\ntypedef eastl::map<TestObject, TestObject> VM4;\ntypedef eastl::map<Align64, Align64> VM7;\ntypedef eastl::multimap<int, int> VMM1;\ntypedef eastl::multimap<TestObject, TestObject> VMM4;\ntypedef eastl::multimap<Align64, Align64> VMM7;\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\ttypedef std::map<int, int> VM3;\n\ttypedef std::map<TestObject, TestObject> VM6;\n\ttypedef std::map<Align64, Align64> VM9;\n\ttypedef std::multimap<int, int> VMM3;\n\ttypedef std::multimap<TestObject, TestObject> VMM6;\n\ttypedef std::multimap<Align64, Align64> VMM9;\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\nint TestMap()\n{\n\tint nErrorCount = 0;\n\n\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t{   // Test construction\n\t\t\tnErrorCount += TestMapConstruction<VM1, VM3, false>();\n\t\t\tnErrorCount += TestMapConstruction<VM4, VM6, false>();\n\t\t\tnErrorCount += TestMapConstruction<eastl::map<int, int, eastl::less<void>>, std::map<int, int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestMapConstruction<VMM1, VMM3, true>();\n\t\t\tnErrorCount += TestMapConstruction<VMM4, VMM6, true>();\n\t\t\tnErrorCount += TestMapConstruction<eastl::multimap<int, int, eastl::less<void>>, std::multimap<int, int, std::less<void>>, true>();\n\t\t}\n\n\n\t\t{   // Test mutating functionality.\n\t\t\tnErrorCount += TestMapMutation<VM1, VM3, false>();\n\t\t\tnErrorCount += TestMapMutation<VM4, VM6, false>();\n\t\t\tnErrorCount += TestMapMutation<eastl::map<int, int, eastl::less<void>>, std::map<int, int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestMapMutation<VMM1, VMM3, true>();\n\t\t\tnErrorCount += TestMapMutation<VMM4, VMM6, true>();\n\t\t\tnErrorCount += TestMapMutation<eastl::multimap<int, int, eastl::less<void>>, std::multimap<int, int, std::less<void>>, true>();\n\t\t}\n\n\t\t// Note: some std:: libraries throw UBSAN errors with Align64.\n\t\t// So we only run these tests when UBSAN is not enabled to\n\t\t// keep our UBSAN builds clean.\n\t\t#if !EA_UBSAN_ENABLED\n\t\t\t{\n\t\t\t\t// Construction\n\t\t\t\tnErrorCount += TestMapConstruction<VM7, VM9, false>();\n\t\t\t\tnErrorCount += TestMapConstruction<VMM7, VMM9, true>();\n\t\t\t\tnErrorCount += TestMapConstruction<eastl::map<int, int, eastl::less<void>>, std::map<int, int, std::less<void>>, false>();\n\t\t\t\tnErrorCount += TestMapConstruction<eastl::multimap<int, int, eastl::less<void>>, std::multimap<int, int, std::less<void>>, true>();\n\n\t\t\t\t// Mutation\n\t\t\t\tnErrorCount += TestMapMutation<VMM7, VMM9, true>();\n\t\t\t\tnErrorCount += TestMapMutation<VM7, VM9, false>();\n\t\t\t\tnErrorCount += TestMapMutation<eastl::map<int, int, eastl::less<void>>, std::map<int, int, std::less<void>>, false>();\n\t\t\t\tnErrorCount += TestMapMutation<eastl::multimap<int, int, eastl::less<void>>, std::multimap<int, int, std::less<void>>, true>();\n\t\t\t}\n\t\t#endif // !EA_UBSAN_ENABLED\n\n\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n\t{   // Test searching functionality.\n\t\tnErrorCount += TestMapSearch<VM1, false>();\n\t\tnErrorCount += TestMapSearch<VM4, false>();\n\t\tnErrorCount += TestMapSearch<VM7, false>();\n\t\tnErrorCount += TestMapSearch<eastl::map<int, int, eastl::less<void>>, false>();\n\n\t\tnErrorCount += TestMapSearch<VMM1, true>();\n\t\tnErrorCount += TestMapSearch<VMM4, true>();\n\t\tnErrorCount += TestMapSearch<VMM7, true>();\n\t\tnErrorCount += TestMapSearch<eastl::multimap<int, int, eastl::less<void>>, true>();\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestMapCpp11<eastl::map<int, TestObject>>();\n\t\tnErrorCount += TestMapCpp11<eastl::map<int, TestObject, eastl::less<void>>>();\n\t\tnErrorCount += TestMultimapCpp11<eastl::multimap<int, TestObject>>();\n\t\tnErrorCount += TestMultimapCpp11<eastl::multimap<int, TestObject, eastl::less<void>>>();\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::map<int, NonCopyable>>();\n\t\tnErrorCount += TestMapCpp11NonCopyable<eastl::map<int, NonCopyable, eastl::less<void>>>();\n\t}\n\n\t{\n\t\t// C++17 try_emplace and related functionality\n\t\tnErrorCount += TestMapCpp17<eastl::map<int, TestObject>>();\n\t\tnErrorCount += TestMapCpp17<eastl::map<int, TestObject, eastl::less<void>>>();\n\t}\n\n\t{\n\t\t// Tests for element access: operator[] and at()\n\t\tnErrorCount += TestMapAccess<VM1>();\n\t\tnErrorCount += TestMapAccess<VM4>();\n\t\tnErrorCount += TestMapAccess<VM7>();\n\t\tnErrorCount += TestMapAccess<eastl::map<int, int, eastl::less<void>>>();\n\t}\n\n\n\t{ // Misc tests\n\n\t\t// const key_compare& key_comp() const;\n\t\t// key_compare&       key_comp();\n\t\tVM1       vm;\n\t\tconst VM1 vmc;\n\n\t\tconst VM1::key_compare& kc = vmc.key_comp();\n\t\tvm.key_comp() = kc;\n\t}\n\n\n\t// Regressions against user bug reports.\n\t{\n\t\t// User reports that the following doesn't compile on GCC 4.1.1 due to unrecognized lower_bound.\n\t\teastl::map<int, int> m;\n\t\tm[1] = 1;\n\t\tEATEST_VERIFY(m.size() == 1);\n\t\tm.erase(1);\n\t\tEATEST_VERIFY(m.empty());\n\t}\n\n\t{\n\t\t// User reports that EASTL_VALIDATE_COMPARE_ENABLED / EASTL_COMPARE_VALIDATE isn't compiling for this case.\n\t\teastl::map<eastl::u8string, int> m; \n\t\tm.find_as(EA_CHAR8(\"some string\"), eastl::equal_to<>()); \n\t}\n\n\t{\n\t\teastl::map<int*, int> m;\n\t\tint* ip = (int*)(uintptr_t)0xDEADC0DE;\n\n\t\tm[ip] = 0;\n\n\t\tauto it = m.find_as(ip, eastl::less<>{});\n\t\tEATEST_VERIFY(it != m.end());\n\n\t\tit = m.find_as((int*)(uintptr_t)0xDEADC0DE, eastl::less<>{});\n\t\tEATEST_VERIFY(it != m.end());\n\t}\n\n\t{\n\t\t// User reports that vector<map<enum,enum>> is crashing after the recent changes to add rvalue move and emplace support to rbtree.\n\t\ttypedef eastl::map<int, int>     IntIntMap;\n\t\ttypedef eastl::vector<IntIntMap> IntIntMapArray;\n\n\t\tIntIntMapArray v;\n\t\tv.push_back(IntIntMap());           // This was calling the rbtree move constructor, which had a bug.\n\t\tv[0][16] = 0;                       // The rbtree was in a bad internal state and so this line resulted in a crash.\n\t\tEATEST_VERIFY(v[0].validate());\n\t\tEATEST_VERIFY(v.validate());\n\t}\n\n\t// User regression test\n\t{\n\t#if !EASTL_RBTREE_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR\n\t\ttypedef eastl::map<int, MoveOnlyTypeDefaultCtor> IntMOMap;\n\n\t\tIntMOMap m1, m2;\n\t\tm2[0] = MoveOnlyTypeDefaultCtor(0);\n\t\tm2[1] = MoveOnlyTypeDefaultCtor(1);\n\n\t\tEATEST_VERIFY( m1.empty());\n\t\tEATEST_VERIFY(!m2.empty());\n\n\t\tm1.swap(m2);\n\n\t\tEATEST_VERIFY(!m1.empty());\n\t\tEATEST_VERIFY( m2.empty());\n\t#endif\n\t}\n\n//    todo:  create a test case for this.\n//    {\t\n//      // User reports that an incorrectly wrapped pair key used to insert into an eastl map compiles when it should fire a compiler error about unconvertible types.\n//\t\ttypedef eastl::pair<eastl::string, eastl::string> PairStringKey;\n//        typedef eastl::map<PairStringKey, eastl::string> PairStringMap;\n//\n//        PairStringMap p1, p2;\t\t\n//\n//        p1.insert(PairStringMap::value_type(PairStringKey(\"key1\", \"key2\"), \"data\")).first->second = \"other_data\";\n//\n//        PairStringKey key(\"key1\", \"key2\");\n//\t\tPairStringMap::value_type insert_me(key, \"data\");\n//        p2.insert(insert_me).first->second = \"other_data\";\n//\n//\t\tfor(auto& e : p1)\n//\t\t\tprintf(\"%s,%s = %s\\n\", e.first.first.c_str(), e.first.second.c_str(), e.second.c_str());\n//\n//\t\tfor(auto& e : p2)\n//\t\t\tprintf(\"%s,%s = %s\\n\", e.first.first.c_str(), e.first.second.c_str(), e.second.c_str());\n//\n//        EATEST_VERIFY(p1 == p2); \n//    }\n\n\t{ // Test empty base-class optimization\n\t\tstruct UnemptyLess : eastl::less<int>\n\t\t{\n\t\t\tint foo;\n\t\t};\n\n\t\ttypedef eastl::map<int, int, eastl::less<int>> VM1;\n\t\ttypedef eastl::map<int, int, UnemptyLess> VM2;\n\n\t\tEATEST_VERIFY(sizeof(VM1) < sizeof(VM2));\n\t}\n\n\t{ // Test erase_if\n\t\teastl::map<int, int> m = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};\n\t\tauto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });\n\t\tVERIFY((m == eastl::map<int, int>{{1, 1},{3, 3}}));\n\t\tVERIFY(numErased == 3);\n\t}\n\n\t{ // Test erase_if\n\t\teastl::multimap<int, int> m = {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {4, 4}, {4, 4}};\n\t\tauto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });\n\t\tVERIFY((m == eastl::multimap<int, int>{{1, 1}, {1, 1}, {3, 3}}));;\n\t\tVERIFY(numErased == 7);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{ // Test map <=>\n\t\teastl::map<int, int> m1 = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};\n\t\teastl::map<int, int> m2 = {{4, 4}, {3, 3}, {2, 2}, {1, 1}, {0, 0}};\n\t\teastl::map<int, int> m3 = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}};\n\t\teastl::map<int, int> m4 = {{1, 0}, {3, 2}, {5, 4}, {7, 6}, {9, 8}};\n\t\teastl::map<int, int> m5 = {{0, 1}, {2, 3}, {4, 5}};\n\n\t\tVERIFY(m1 == m2);\n\t\tVERIFY(m1 != m3);\n\t\tVERIFY(m3 != m4);\n\t\tVERIFY(m3 < m4);\n\t\tVERIFY(m5 < m4);\n\t\tVERIFY(m5 < m3);\n\n\n\t\tVERIFY((m1 <=> m2) == 0);\n\t\tVERIFY((m1 <=> m3) != 0);\n\t\tVERIFY((m3 <=> m4) != 0);\n\t\tVERIFY((m3 <=> m4) < 0);\n\t\tVERIFY((m5 <=> m4) < 0);\n\t\tVERIFY((m5 <=> m3) < 0);\n\t}\n\n\t{ // Test multimap <=>\n\t\teastl::multimap<int, int> m1 = {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {2, 2}, {3, 3}, {3, 3}, {4, 4}, {4, 4}};\n\t\teastl::multimap<int, int> m2 = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {0, 0}};\n\t\teastl::multimap<int, int> m3 = {{0, 1}, {2, 3}, {4, 5}, {0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}};\n\t\teastl::multimap<int, int> m4 = {{1, 0}, {3, 2}, {5, 4}, {1, 0}, {3, 2}, {5, 4}, {7, 6}, {9, 8}};\n\t\teastl::multimap<int, int> m5 = {{10, 11}, {10, 11}};\n\n\t\tVERIFY(m1 == m2);\n\t\tVERIFY(m1 != m3);\n\t\tVERIFY(m3 != m4);\n\t\tVERIFY(m3 < m4);\n\t\tVERIFY(m5 > m4);\n\t\tVERIFY(m5 > m3);\n\n\t\tVERIFY((m1 <=> m2) == 0);\n\t\tVERIFY((m1 <=> m3) != 0);\n\t\tVERIFY((m3 <=> m4) != 0);\n\t\tVERIFY((m3 <=> m4) < 0);\n\t\tVERIFY((m5 <=> m4) > 0);\n\t\tVERIFY((m5 <=> m3) > 0);\n\t}\n#endif\n\n\t{ // heterogenous functions - map\n\t\teastl::map<ExplicitString, int, eastl::less<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestMapHeterogeneousInsertion<decltype(m)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\t{ // heterogenous functions - multimap\n\t\teastl::multimap<ExplicitString, int, eastl::less<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(m);\n\n\t\tVERIFY(m.equal_range_small(\"not found\") == eastl::make_pair(m.lower_bound(\"not found\"), m.upper_bound(\"not found\")));\n\t\tVERIFY(m.equal_range_small(\"found\") == eastl::make_pair(m.lower_bound(\"found\"), m.upper_bound(\"found\")));\n\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestMap.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/vector.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/scoped_ptr.h>\n#include <EASTL/random.h>\n#include <EASTL/tuple.h>\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\tEA_DISABLE_ALL_VC_WARNINGS()\n\t#include <algorithm>\n\tEA_RESTORE_ALL_VC_WARNINGS()\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMapConstruction\n//\n// This test compares eastl::map/multimap to std::map/multimap. It could possibly\n// work for comparing eastl::hash_map to C++11 std::unordered_map, but we would \n// rather move towards making this test be independent of any std comparisons.\n//\n// Requires a container that can hold at least 1000 items.\n//\ntemplate <typename T1, typename T2, bool bMultimap>\nint TestMapConstruction()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{\n\t\t// We use new because fixed-size versions these objects might be too big for declaration on a stack.\n\t\teastl::scoped_ptr<T1> pt1A(new T1);\n\t\teastl::scoped_ptr<T2> pt2A(new T2);\n\t\tT1& t1A = *pt1A;\n\t\tT2& t2A = *pt2A;\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map ctor\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\tEATEST_VERIFY(t1A.validate());\n\n\n\t\teastl::scoped_ptr<T1> pt1B(new T1);\n\t\teastl::scoped_ptr<T2> pt2B(new T2);\n\t\tT1& t1B = *pt1B;\n\t\tT2& t2B = *pt2B;\n\t\tnErrorCount += CompareContainers(t1B, t2B, \"Map ctor\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\teastl::scoped_ptr<T1> pt1C(new T1);\n\t\teastl::scoped_ptr<T2> pt2C(new T2);\n\t\tT1& t1C = *pt1C;\n\t\tT2& t2C = *pt2C;\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t{\n\t\t\tt1C.insert(typename T1::value_type(typename T1::key_type(i), typename T1::mapped_type(i)));\n\t\t\tt2C.insert(typename T2::value_type(typename T2::key_type(i), typename T2::mapped_type(i)));\n\t\t\tEATEST_VERIFY(t1C.validate());\n\t\t\tnErrorCount += CompareContainers(t1C, t2C, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\t}\n\n\n\t\teastl::scoped_ptr<T1> pt1D(new T1);\n\t\teastl::scoped_ptr<T2> pt2D(new T2);\n\t\tT1& t1D = *pt1D;\n\t\tT2& t2D = *pt2D;\n\t\tnErrorCount += CompareContainers(t1D, t2D, \"Map ctor\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\teastl::scoped_ptr<T1> pt1E(new T1(t1C));\n\t\teastl::scoped_ptr<T2> pt2E(new T2(t2C));\n\t\tT1& t1E = *pt1E;\n\t\tT2& t2E = *pt2E;\n\t\tEATEST_VERIFY(t1E.validate());\n\t\tnErrorCount += CompareContainers(t1E, t2E, \"Map ctor\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\teastl::scoped_ptr<T1> pt1F(new T1(t1C.begin(), t1C.end()));\n\t\teastl::scoped_ptr<T2> pt2F(new T2(t2C.begin(), t2C.end()));\n\t\tT1& t1F = *pt1F;\n\t\tT2& t2F = *pt2F;\n\t\tEATEST_VERIFY(t1F.validate());\n\t\tnErrorCount += CompareContainers(t1F, t2F, \"Map ctor\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t// operator=(const map&)\n\t\tt1E = t1D;\n\t\tt2E = t2D;\n\t\tnErrorCount += CompareContainers(t1D, t2D, \"Map operator=\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\tnErrorCount += CompareContainers(t1E, t2E, \"Map operator=\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t// operator=(map&&)\n\t\t// We test just the EASTL container here.\n\t\teastl::scoped_ptr<T1> pT1P(new T1);\n\t\teastl::scoped_ptr<T1> pT1Q(new T1);\n\t\tT1& t1P = *pT1P;\n\t\tT1& t1Q = *pT1Q;\n\n\t\ttypename T1::key_type k10(0);\n\t\ttypename T1::key_type k11(1);\n\t\ttypename T1::key_type k12(2);\n\t\ttypename T1::key_type k13(3);\n\t\ttypename T1::key_type k14(4);\n\t\ttypename T1::key_type k15(5);\n\n\t\ttypename T1::value_type v10(k10, typename T1::mapped_type(0));\n\t\ttypename T1::value_type v11(k11, typename T1::mapped_type(1));\n\t\ttypename T1::value_type v12(k12, typename T1::mapped_type(2));\n\t\ttypename T1::value_type v13(k13, typename T1::mapped_type(3));\n\t\ttypename T1::value_type v14(k14, typename T1::mapped_type(4));\n\t\ttypename T1::value_type v15(k15, typename T1::mapped_type(5));\n\n\t\tt1P.insert(v10);\n\t\tt1P.insert(v11);\n\t\tt1P.insert(v12);\n\n\t\tt1Q.insert(v13);\n\t\tt1Q.insert(v14);\n\t\tt1Q.insert(v15);\n\n\t\tt1Q = eastl::move(t1P); // We are effectively requesting to swap t1A with t1B.\n\t  //EATEST_VERIFY((t1P.size() == 3) && (t1P.find(k13) != t1P.end()) && (t1P.find(k14) != t1P.end()) && (t1P.find(k15) != t1P.end()));  // Currently operator=(this_type&& x) clears x instead of swapping with it.\n\t\tEATEST_VERIFY((t1Q.size() == 3) && (t1Q.find(k10) != t1Q.end()) && (t1Q.find(k11) != t1Q.end()) && (t1Q.find(k12) != t1Q.end()));\n\n\n\t\t// swap\n\t\tt1E.swap(t1D);\n\t\tt2E.swap(t2D);\n\t\tEATEST_VERIFY(t1D.validate());\n\t\tEATEST_VERIFY(t1E.validate());\n\t\tnErrorCount += CompareContainers(t1D, t2D, \"Map swap\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\tnErrorCount += CompareContainers(t1E, t2E, \"Map swap\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t// clear\n\t\tt1A.clear();\n\t\tt2A.clear();\n\t\tEATEST_VERIFY(t1A.validate());\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map clear\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\t\tt1B.clear();\n\t\tt2B.clear();\n\t\tEATEST_VERIFY(t1B.validate());\n\t\tnErrorCount += CompareContainers(t1B, t2B, \"Map clear\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t// global operators (==, !=, <, etc.)\n\t\tt1A.clear();\n\t\tt1B.clear();\n\t\t\t\t\t\t\t   // Make t1A equal to t1B\n\t\tt1A.insert(typename T1::value_type(typename T1::key_type(0), typename T1::mapped_type(0)));\n\t\tt1A.insert(typename T1::value_type(typename T1::key_type(1), typename T1::mapped_type(1)));\n\t\tt1A.insert(typename T1::value_type(typename T1::key_type(2), typename T1::mapped_type(2)));\n\n\t\tt1B.insert(typename T1::value_type(typename T1::key_type(0), typename T1::mapped_type(0)));\n\t\tt1B.insert(typename T1::value_type(typename T1::key_type(1), typename T1::mapped_type(1)));\n\t\tt1B.insert(typename T1::value_type(typename T1::key_type(2), typename T1::mapped_type(2)));\n\n\t\tEATEST_VERIFY( (t1A == t1B));\n\t\tEATEST_VERIFY(!(t1A != t1B));\n\t\tEATEST_VERIFY( (t1A <= t1B));\n\t\tEATEST_VERIFY( (t1A >= t1B));\n\t\tEATEST_VERIFY(!(t1A  < t1B));\n\t\tEATEST_VERIFY(!(t1A  > t1B));\n\t\t\t\t\t\t\t   // Make t1A less than t1B\n\t\tt1A.insert(typename T1::value_type(typename T1::key_type(3), typename T1::mapped_type(3)));\n\t\tt1B.insert(typename T1::value_type(typename T1::key_type(4), typename T1::mapped_type(4)));\n\n\t\tEATEST_VERIFY(!(t1A == t1B));\n\t\tEATEST_VERIFY( (t1A != t1B));\n\t\tEATEST_VERIFY( (t1A <= t1B));\n\t\tEATEST_VERIFY(!(t1A >= t1B));\n\t\tEATEST_VERIFY( (t1A  < t1B));\n\t\tEATEST_VERIFY(!(t1A  > t1B));\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMapMutation\n//\n// Requires a container that can hold at least 1000 items.\n//\ntemplate <typename T1, typename T2, bool bMultimap>\nint TestMapMutation()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{\n\t\teastl::scoped_ptr<T1> pt1A(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\teastl::scoped_ptr<T2> pt2A(new T2);\n\t\tT1&                   t1A = *pt1A;\n\t\tT2&                   t2A = *pt2A;\n\t\tint                   i, iEnd, p;\n\n\t\t// Set up an array of values to randomize / permute.\n\t\teastl::vector<typename T1::key_type> valueArrayInsert;\n\n\t\tif(gEASTL_TestLevel >= kEASTL_TestLevelLow)\n\t\t{\n\t\t\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\t\tvalueArrayInsert.clear();\n\n\t\t\tfor(i = 0; i < 1000; i++)\n\t\t\t{\n\t\t\t\tvalueArrayInsert.push_back(typename T1::key_type(i));\n\n\t\t\t\t// Occasionally attempt to duplicate an element, both for map and multimap.\n\t\t\t\tif(((i + 1) < 1000) && (rng.RandLimit(4) == 0))\n\t\t\t\t{\n\t\t\t\t\tvalueArrayInsert.push_back(typename T1::key_type(i));\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor(p = 0; p < gEASTL_TestLevel * 100; p++) // For each permutation...\n\t\t\t{\n\t\t\t\teastl::random_shuffle(valueArrayInsert.begin(), valueArrayInsert.end(), rng);\n\n\t\t\t\t// insert\n\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t{\n\t\t\t\t\ttypename T1::key_type& k = valueArrayInsert[i];\n\n\t\t\t\t\tt1A.insert(typename T1::value_type(k, k)); // We expect that both arguments are the same.\n\t\t\t\t\tt2A.insert(typename T2::value_type(k, k));\n\n\t\t\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\t\t\t}\n\n\n\t\t\t\t// reverse iteration\n\t\t\t\ttypename T1::reverse_iterator r1 = t1A.rbegin();\n\t\t\t\ttypename T2::reverse_iterator r2 = t2A.rbegin();\n\n\t\t\t\twhile(r1 != t1A.rend())\n\t\t\t\t{\n\t\t\t\t\ttypename T1::key_type k1 = (*r1).first;\n\t\t\t\t\ttypename T2::key_type k2 = (*r2).first;\n\t\t\t\t\tEATEST_VERIFY(k1 == k2);\n\t\t\t\t}\n\n\n\t\t\t\t// erase\n\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t{\n\t\t\t\t\ttypename T1::key_type& k = valueArrayInsert[i];\n\n\t\t\t\t\ttypename T1::size_type n1 = t1A.erase(k);\n\t\t\t\t\ttypename T2::size_type n2 = t2A.erase(k);\n\n\t\t\t\t\tEATEST_VERIFY(n1 == n2);\n\t\t\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map erase\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\t\t\t}\n\n\t\t\t\tEATEST_VERIFY((TestObject::sTOCount == 0) || (TestObject::sTOCount == (int64_t)valueArrayInsert.size())); // This test will only have meaning when T1 contains TestObject.\n\t\t\t}\n\t\t}\n\n\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\n\n\t\t// Possibly do extended testing.\n\t\tif(gEASTL_TestLevel > 6)\n\t\t{\n\t\t\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\t\t\t\tvalueArrayInsert.clear();\n\n\t\t\t\tfor(i = 0; i < 9; i++) // Much more than this count would take too long to test all permutations.\n\t\t\t\t\tvalueArrayInsert.push_back(typename T1::key_type(i));\n\n\t\t\t\t// Insert these values into the map in every existing permutation.\n\t\t\t\tfor(p = 0; std::next_permutation(valueArrayInsert.begin(), valueArrayInsert.end()); p++) // For each permutation...\n\t\t\t\t{\n\t\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\ttypename T1::key_type& k = valueArrayInsert[i];\n\n\t\t\t\t\t\tt1A.insert(typename T1::value_type(k, k)); // We expect that both arguments are the same.\n\t\t\t\t\t\tt2A.insert(typename T2::value_type(k, k));\n\n\t\t\t\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\t\t\t\t}\n\n\t\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\ttypename T1::key_type& k = valueArrayInsert[i];\n\n\t\t\t\t\t\tt1A.erase(k);\n\t\t\t\t\t\tt2A.erase(k);\n\n\t\t\t\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map erase\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\t\t\t\t\t}\n\n\t\t\t\t\tEATEST_VERIFY((TestObject::sTOCount == 0) || (TestObject::sTOCount == (int64_t)valueArrayInsert.size())); // This test will only have meaning when T1 contains TestObject.\n\n\t\t\t\t}\n\n\t\t\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t}\n\t}\n\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\n\t{  // Other insert and erase operations\n\n\t\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t\teastl::scoped_ptr<T1> pt1A(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\t\teastl::scoped_ptr<T2> pt2A(new T2);\n\t\t\tT1& t1A = *pt1A;\n\t\t\tT2& t2A = *pt2A;\n\t\t\tint i;\n\n\t\t\t// Set up an array of values to randomize / permute.\n\t\t\teastl::vector<eastl::pair<typename T1::key_type, typename T1::mapped_type> > valueArrayInsert1;\n\t\t\teastl::vector<  std::pair<typename T2::key_type, typename T2::mapped_type> > valueArrayInsert2;\n\n\t\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\t\tfor(i = 0; i < 100; i++)\n\t\t\t{\n\t\t\t\tvalueArrayInsert1.push_back(typename T1::value_type(typename T1::key_type(i), typename T1::mapped_type(i)));\n\t\t\t\tvalueArrayInsert2.push_back(typename T2::value_type(typename T2::key_type(i), typename T2::mapped_type(i)));\n\n\t\t\t\tif(rng.RandLimit(3) == 0)\n\t\t\t\t{\n\t\t\t\t\tvalueArrayInsert1.push_back(typename T1::value_type(typename T1::key_type(i), typename T1::mapped_type(i)));\n\t\t\t\t\tvalueArrayInsert2.push_back(typename T2::value_type(typename T2::key_type(i), typename T2::mapped_type(i)));\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\t// insert(InputIterator first, InputIterator last)\n\t\t\tt1A.insert(valueArrayInsert1.begin(), valueArrayInsert1.end());\n\t\t\tt2A.insert(valueArrayInsert2.begin(), valueArrayInsert2.end());\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t\t// insert_return_type insert(const Key& key);\n\t\t\tt1A.insert(typename T1::key_type(8888));\n\t\t\tt2A.insert(typename T2::value_type(typename T2::key_type(8888), typename T2::mapped_type(0)));\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t\t// iterator insert(iterator position, const value_type& value);\n\t\t\t//\n\t\t\t// If bMultimap == true, then the insertions below should fail due to the \n\t\t\t// item being present. But they should return the correct iterator value.\n\t\t\ttypename T1::iterator it1 = t1A.insert(t1A.find(typename T1::key_type(2)), typename T1::value_type(typename T1::key_type(1), typename T1::mapped_type(1)));\n\t\t\ttypename T2::iterator it2 = t2A.insert(t2A.find(typename T2::key_type(2)), typename T2::value_type(typename T2::key_type(1), typename T2::mapped_type(1)));\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tEATEST_VERIFY(it1->first == typename T1::key_type(1));\n\t\t\tEATEST_VERIFY(it2->first == typename T2::key_type(1));\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\t\t\tit1 = t1A.insert(t1A.end(), typename T1::value_type(typename T1::key_type(5), typename T1::mapped_type(5)));\n\t\t\tit2 = t2A.insert(t2A.end(), typename T2::value_type(typename T2::key_type(5), typename T2::mapped_type(5)));\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tEATEST_VERIFY(it1->first == typename T1::key_type(5));\n\t\t\tEATEST_VERIFY(it2->first == typename T2::key_type(5));\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\t\t\t// Now we remove these items so that the insertions above can succeed.\n\t\t\tt1A.erase(t1A.find(typename T1::key_type(1)));\n\t\t\tt2A.erase(t2A.find(typename T2::key_type(1)));\n\t\t\tit1 = t1A.insert(t1A.find(typename T1::key_type(2)), typename T1::value_type(typename T1::key_type(1), typename T1::mapped_type(1)));\n\t\t\tit2 = t2A.insert(t2A.find(typename T2::key_type(2)), typename T2::value_type(typename T2::key_type(1), typename T2::mapped_type(1)));\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tEATEST_VERIFY(it1->first == typename T1::key_type(1));\n\t\t\tEATEST_VERIFY(it2->first == typename T2::key_type(1));\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\t\t\tt1A.erase(t1A.find(typename T1::key_type(5)));\n\t\t\tt2A.erase(t2A.find(typename T2::key_type(5)));\n\t\t\tit1 = t1A.insert(t1A.end(), typename T1::value_type(typename T1::key_type(5), typename T1::mapped_type(5)));\n\t\t\tit2 = t2A.insert(t2A.end(), typename T2::value_type(typename T2::key_type(5), typename T2::mapped_type(5)));\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tEATEST_VERIFY(it1->first == typename T1::key_type(5));\n\t\t\tEATEST_VERIFY(it2->first == typename T2::key_type(5));\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map insert\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t\t// iterator erase(iterator first, iterator last);\n\t\t\ttypename T1::iterator it11 = t1A.find(typename T1::key_type(17));\n\t\t\ttypename T1::iterator it12 = t1A.find(typename T2::key_type(37));\n\t\t\tt1A.erase(it11, it12);\n\n\t\t\ttypename T2::iterator it21 = t2A.find(typename T1::key_type(17));\n\t\t\ttypename T2::iterator it22 = t2A.find(typename T2::key_type(37));\n\t\t\tt2A.erase(it21, it22);\n\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map erase(first, last)\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t\t// iterator erase(iterator position);\n\t\t\tt1A.erase(t1A.find(typename T1::key_type(60)));\n\t\t\tt2A.erase(t2A.find(typename T1::key_type(60)));\n\t\t\tEATEST_VERIFY(t1A.validate());\n\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Map erase(first, last)\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\n\t\t\t// Disabled because this function isn't exposed outside the rbtree yet.\n\t\t\t// void erase(const key_type* first, const key_type* last);\n\t\t\t//typename T1::key_type keyArray1[3] = { typename T1::key_type(70), typename T1::key_type(71), typename T1::key_type(72) };\n\t\t\t//typename T2::key_type keyArray2[3] = { typename T2::key_type(70), typename T2::key_type(71), typename T2::key_type(72) };\n\t\t\t//t1A.erase(keyArray1 + 0, keyArray1 + 3);\n\t\t\t//t2A.erase(keyArray2 + 0, keyArray2 + 3);\n\t\t\t//EATEST_VERIFY(t1A.validate());\n\t\t\t//nErrorCount += CompareContainers(t1A, t2A, \"Map erase(first, last)\", eastl::use_first<typename T1::value_type>(), eastl::use_first<typename T2::value_type>());\n\n\t\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t}\n\n\t{\n\t\t// map(std::initializer_list<value_type> ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);\n\t\t// this_type& operator=(std::initializer_list<T> ilist);\n\t\t// void insert(std::initializer_list<value_type> ilist);\n\n\t\t// VS2013 has a known issue when dealing with std::initializer_lists\n\t\t// https://connect.microsoft.com/VisualStudio/feedback/details/792355/compiler-confused-about-whether-to-use-a-initializer-list-assignment-operator\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS) && !(defined(_MSC_VER) && _MSC_VER == 1800)\n\t\t\tT1 myMap = { {typename T1::key_type(10),typename T1::mapped_type(0)}, {typename T1::key_type(11),typename T1::mapped_type(1)} };\n\t\t\tEATEST_VERIFY(myMap.size() == 2);\n\t\t\tEATEST_VERIFY(myMap.begin()->first == typename T1::key_type(10));\n\t\t\ttypename T1::iterator it = myMap.rbegin().base();\n\t\t\tEATEST_VERIFY((--it)->first == typename T1::key_type(11));\n\n\t\t\tmyMap = { {typename T1::key_type(20),typename T1::mapped_type(0)}, {typename T1::key_type(21),typename T1::mapped_type(1)} };\n\t\t\tEATEST_VERIFY(myMap.size() == 2);\n\t\t\tEATEST_VERIFY(myMap.begin()->first == typename T1::key_type(20));\n\t\t\tit = myMap.rbegin().base();\n\t\t\tEATEST_VERIFY((--it)->first == typename T1::key_type(21));\n\n\t\t\tmyMap.insert({ {typename T1::key_type(40),typename T1::mapped_type(0)}, {typename T1::key_type(41),typename T1::mapped_type(1)} });\n\t\t\tEATEST_VERIFY(myMap.size() == 4);\n\t\t\tit = myMap.rbegin().base();\n\t\t\tEATEST_VERIFY((--it)->first == typename T1::key_type(41));\n\t\t#endif\n\t}\n\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n\n\n\ntemplate <typename T1>\nint TestMapSpecific(T1& t1A, eastl::false_type) // false_type means this is a map and not a multimap.\n{\n\tint nErrorCount = 0;\n\n\t// operator[] (map only)\n\ttypename T1::mapped_type m = t1A[typename T1::key_type(0)];\n\tEATEST_VERIFY(m == typename T1::mapped_type(0));\n\n\tm = t1A[typename T1::key_type(999)];\n\tEATEST_VERIFY(m == typename T1::mapped_type(999));\n\n\tm = t1A[typename T1::key_type(10000000)]; // Test the creation of an element that isn't present.\n\tEATEST_VERIFY(m == typename T1::mapped_type(0)); // Test for 0 because the default ctor for our test objects assigns 0 to the object.\n\n\treturn nErrorCount;\n}\n\n\ntemplate <typename T1>\nint TestMapSpecific(T1& t1A, eastl::true_type) // true_type means this is a multimap and not a map.\n{\n\tint nErrorCount = 0;\n\n\t// equal_range_small (multimap only)\n\teastl::pair<typename T1::iterator, typename T1::iterator> er = t1A.equal_range_small(typename T1::key_type(499));\n\tEATEST_VERIFY(er.first->first  == typename T1::key_type(499));\n\tEATEST_VERIFY(er.second->first == typename T1::key_type(501));\n\n\ter = t1A.equal_range_small(typename T1::key_type(-1));\n\tEATEST_VERIFY(er.first == er.second);\n\tEATEST_VERIFY(er.first == t1A.begin());\n\n\treturn nErrorCount;\n}\n\n\n// Just for the purposes of the map::find_as test below, we declare the following.\n// The map::find_as function searches a container of X for a type Y, where the user \n// defines the equality of X to Y. The purpose of TMapComparable is to be a generic type Y\n// that can be used for any X. We need to make this generic because the whole TestMapSearch\n// function below is templated on type T1 and so we don't know what T1 is ahead of time.\n\ntemplate <typename T>\nstruct TMapComparable\n{\n\tT b;\n\n\tTMapComparable() : b() { }\n\tTMapComparable(const T& a) : b(a){ }\n\tconst TMapComparable& operator=(const T& a) { b = a; return *this; }\n\tconst TMapComparable& operator=(const TMapComparable& x) { b = x.b; return *this; }\n\toperator const T&() const { return b; }\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMapSearch\n//\n// This function is designed to work with map, fixed_map (and not hash containers).\n// Requires a container that can hold at least 1000 items.\n//\ntemplate <typename T1, bool bMultimap>\nint TestMapSearch()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{  // Test find, lower_bound, upper_bound, etc..\n\t\teastl::scoped_ptr<T1> pt1A(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\tT1& t1A = *pt1A;\n\t\tint i, iEnd;\n\t\ttypename T1::iterator it;\n\n\t\t// Set up an array of values to randomize / permute.\n\t\teastl::vector<typename T1::key_type> valueArrayInsert;\n\n\t\tfor(i = 0; i < 1000; i++)\n\t\t\tvalueArrayInsert.push_back(typename T1::key_type(i));\n\n\t\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\t\teastl::random_shuffle(valueArrayInsert.begin(), valueArrayInsert.end(), rng);\n\n\n\t\t// insert\n\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t{\n\t\t\ttypename T1::key_type k(i);\n\t\t\tt1A.insert(typename T1::value_type(k, k));\n\n\t\t\tit = t1A.find(k);\n\t\t\tEATEST_VERIFY(it != t1A.end());\n\t\t}\n\n\n\t\t// find\n\t\tfor(i = 0; i < 1000; i++)\n\t\t{\n\t\t\ttypename T1::key_type k(i);\n\t\t\tit = t1A.find(k);\n\n\t\t\tEATEST_VERIFY(it != t1A.end());\n\t\t\tEATEST_VERIFY(it->first  == k);\n\t\t\tEATEST_VERIFY(it->second == k);\n\t\t}\n\n\t\tit = t1A.find(typename T1::key_type(-1));\n\t\tEATEST_VERIFY(it == t1A.end());\n\n\t\tit = t1A.find(typename T1::key_type(1001));\n\t\tEATEST_VERIFY(it == t1A.end());\n\n\n\t\t// find_as\n\t\ttypedef TMapComparable<typename T1::key_type> TC;\n\n\t\t// Normally we use find_as to find via a different type, but we can test it here like this.\n\t\tfor(i = 0; i < 1000; i++)\n\t\t{\n\t\t\tTC k = typename T1::key_type(i);\n\t\t\tit = t1A.find_as(k, eastl::less<>());\n\n\t\t\tEATEST_VERIFY(it != t1A.end());\n\t\t\tEATEST_VERIFY(it->first  == k);\n\t\t\tEATEST_VERIFY(it->second == k);\n\t\t}\n\n\t\tit = t1A.find_as(TC(typename T1::key_type(-1)), eastl::less<>());\n\t\tEATEST_VERIFY(it == t1A.end());\n\n\t\tit = t1A.find_as(TC(typename T1::key_type(1001)), eastl::less<>());\n\t\tEATEST_VERIFY(it == t1A.end());\n\n\n\t\t// lower_bound\n\t\tit = t1A.lower_bound(typename T1::key_type(0));\n\t\tEATEST_VERIFY(it == t1A.begin());\n\n\t\tit = t1A.lower_bound(typename T1::key_type(-1));\n\t\tEATEST_VERIFY(it == t1A.begin());\n\n\t\tit = t1A.lower_bound(typename T1::key_type(1001));\n\t\tEATEST_VERIFY(it == t1A.end());\n\n\t\tt1A.erase(typename T1::key_type(500));\n\t\tit = t1A.lower_bound(typename T1::key_type(500));\n\t\tEATEST_VERIFY(it->first  == typename T1::key_type(501));\n\n\n\t\t// upper_bound\n\t\tit = t1A.upper_bound(typename T1::key_type(-1));\n\t\tEATEST_VERIFY(it == t1A.begin());\n\n\t\tit = t1A.upper_bound(typename T1::key_type(499));\n\t\tEATEST_VERIFY(it->first  == typename T1::key_type(501));\n\n\t\tit = t1A.upper_bound(typename T1::key_type(-1));\n\t\tEATEST_VERIFY(it->first  == typename T1::key_type(0));\n\n\t\tit = t1A.upper_bound(typename T1::key_type(1000));\n\t\tEATEST_VERIFY(it == t1A.end());\n\n\n\t\t// count\n\t\ttypename T1::size_type n = t1A.count(typename T1::key_type(-1));\n\t\tEATEST_VERIFY(n == 0);\n\n\t\tn = t1A.count(typename T1::key_type(0));\n\t\tEATEST_VERIFY(n == 1);\n\n\t\tn = t1A.count(typename T1::key_type(500)); // We removed 500 above.\n\t\tEATEST_VERIFY(n == 0);\n\n\t\tn = t1A.count(typename T1::key_type(1001));\n\t\tEATEST_VERIFY(n == 0);\n\n\n\t\t// equal_range\n\t\teastl::pair<typename T1::iterator, typename T1::iterator> er = t1A.equal_range(typename T1::key_type(200));\n\t\tEATEST_VERIFY(er.first->first == typename T1::key_type(200));\n\t\tEATEST_VERIFY(er.first->second == typename T1::key_type(200));\n\n\t\ter = t1A.equal_range(typename T1::key_type(499));\n\t\tEATEST_VERIFY(er.first->first == typename T1::key_type(499));\n\t\tEATEST_VERIFY(er.second->first == typename T1::key_type(501));\n\n\t\ter = t1A.equal_range(typename T1::key_type(-1));\n\t\tEATEST_VERIFY(er.first == er.second);\n\t\tEATEST_VERIFY(er.first == t1A.begin());\n\n\n\t\t// Some tests need to be differently between map and multimap.\n\t\tnErrorCount += TestMapSpecific(t1A, eastl::integral_constant<bool, bMultimap>());\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMapCpp11\n//\n// This function is designed to work with map, fixed_map, hash_map, fixed_hash_map.\n//\ntemplate <typename T1>\nint TestMapCpp11()\n{\n\tint nErrorCount = 0;\n\n\t// template <class... Args>\n\t// insert_return_type emplace(Args&&... args);\n\t//\n\t// template <class... Args> \n\t// iterator emplace_hint(const_iterator position, Args&&... args);\n\t//\n\t// insert_return_type insert(value_type&& value);\n\t// iterator insert(const_iterator position, value_type&& value);\n\t// void insert(std::initializer_list<value_type> ilist);\n\tTestObject::Reset();\n\n\ttypedef T1 TOMap;\n\ttypedef typename TOMap::value_type value_type;\n\ttypename TOMap::insert_return_type toMapInsertResult;\n\ttypename TOMap::iterator toMapIterator;\n\n\tTOMap      toMap;\n\tTestObject to0(0);\n\tTestObject to1(1);\n\n\ttoMapInsertResult = toMap.emplace(value_type(0, to0));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\t//EATEST_VERIFY((TestObject::sTOCopyCtorCount == 2) && (TestObject::sTOMoveCtorCount == 1));  // Disabled until we can guarantee its behavior and deal with how it's different between compilers of differing C++11 support.\n\n\ttoMapInsertResult = toMap.emplace(value_type(1, eastl::move(to1)));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\n\t// insert_return_type t1A.emplace(value_type&& value);\n\tTestObject to4(4);\n\tvalue_type value40(4, to4);\n\tEATEST_VERIFY(toMap.find(4) == toMap.end());\n\tEATEST_VERIFY(value40.second.mX == 4); // It should change to 0 below during the move swap.\n\ttoMapInsertResult = toMap.emplace(eastl::move(value40));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(4) != toMap.end());\n\tEATEST_VERIFY(value40.second.mX == 0);\n\n\tvalue_type value41(4, TestObject(41));\n\ttoMapInsertResult = toMap.emplace(eastl::move(value41));\n\tEATEST_VERIFY(toMapInsertResult.second == false);\n\tEATEST_VERIFY(toMapInsertResult.first->second.mX == 4);\n\tEATEST_VERIFY(toMap.find(4) != toMap.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, value_type&& value);\n\tTestObject to5(5);\n\tvalue_type value50(5, to5);\n\tEATEST_VERIFY(toMap.find(5) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(eastl::move(value50));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(5) != toMap.end());\n\n\tvalue_type value51(5, TestObject(51));\n\ttoMapIterator = toMap.emplace_hint(toMapInsertResult.first, eastl::move(value51));\n\tEATEST_VERIFY(toMapIterator->first == 5);\n\tEATEST_VERIFY(toMapIterator->second.mX == 5);\n\tEATEST_VERIFY(toMap.find(5) != toMap.end());\n\n\tTestObject to6(6);\n\tvalue_type value6(6, to6);\n\tEATEST_VERIFY(toMap.find(6) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), eastl::move(value6)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 6);\n\tEATEST_VERIFY(toMap.find(6) != toMap.end());\n\t\t\n\tTestObject to2(2);\n\tEATEST_VERIFY(toMap.find(2) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(value_type(2, to2));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(2) != toMap.end());\n\ttoMapInsertResult = toMap.emplace(value_type(2, to2));\n\tEATEST_VERIFY(toMapInsertResult.second == false);\n\tEATEST_VERIFY(toMap.find(2) != toMap.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, const value_type& value);\n\tTestObject to7(7);\n\tvalue_type value70(7, to7);\n\tEATEST_VERIFY(toMap.find(7) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(value70);\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(7) != toMap.end());\n\n\tvalue_type value71(7, TestObject(71));\n\ttoMapIterator = toMap.emplace_hint(toMapInsertResult.first, value71);\n\tEATEST_VERIFY(toMapIterator->first == 7);\n\tEATEST_VERIFY(toMapIterator->second.mX == 7);\n\tEATEST_VERIFY(toMap.find(7) != toMap.end());\n\n\tTestObject to8(8);\n\tvalue_type value8(8, to8);\n\tEATEST_VERIFY(toMap.find(8) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), value8); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 8);\n\tEATEST_VERIFY(toMap.find(8) != toMap.end());\n\n\t// insert_return_type t1A.insert(value_type&& value);\n\tTestObject to3(3);\n\tEATEST_VERIFY(toMap.find(3) == toMap.end());\n\ttoMapInsertResult = toMap.insert(value_type(3, to3));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(3) != toMap.end());\n\ttoMapInsertResult = toMap.insert(value_type(3, to3));\n\tEATEST_VERIFY(toMapInsertResult.second == false);\n\tEATEST_VERIFY(toMap.find(3) != toMap.end());\n\n\n\t// iterator t1A.insert(const_iterator position, value_type&& value);\n\tTestObject to9(9);\n\tvalue_type value90(9, to9);\n\tEATEST_VERIFY(toMap.find(9) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(eastl::move(value90));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(9) != toMap.end());\n\n\tvalue_type value91(9, TestObject(91));\n\ttoMapIterator = toMap.insert(toMapInsertResult.first, eastl::move(value91));\n\tEATEST_VERIFY(toMapIterator->first == 9);\n\tEATEST_VERIFY(toMapIterator->second.mX == 9);\n\tEATEST_VERIFY(toMap.find(9) != toMap.end());\n\n\tTestObject to10(10);\n\tvalue_type value10(10, to10);\n\tEATEST_VERIFY(toMap.find(10) == toMap.end());\n\ttoMapIterator = toMap.insert(toMap.begin(), eastl::move(value10)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 10);\n\tEATEST_VERIFY(toMap.find(10) != toMap.end());\n\n\t// insert_return_type t1A.emplace(Args&&... args);\n\tTestObject to11(11);\n\tEATEST_VERIFY(toMap.find(11) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(11, to11);\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMapInsertResult.first->first == 11);\n\tEATEST_VERIFY(toMap.find(11) != toMap.end());\n\n\tTestObject to111(111);\n\ttoMapInsertResult = toMap.emplace(11, to111);\n\tEATEST_VERIFY(toMapInsertResult.second == false);\n\tEATEST_VERIFY(toMapInsertResult.first->first == 11);\n\tEATEST_VERIFY(toMapInsertResult.first->second.mX == 11);\n\tEATEST_VERIFY(toMap.find(11) != toMap.end());\n\n\tTestObject to12(12);\n\tEATEST_VERIFY(toMap.find(12) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(12, eastl::move(to12));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMapInsertResult.first->first == 12);\n\tEATEST_VERIFY(toMap.find(12) != toMap.end());\n\n\tTestObject to121(121);\n\ttoMapInsertResult = toMap.emplace(12, eastl::move(to121));\n\tEATEST_VERIFY(toMapInsertResult.second == false);\n\tEATEST_VERIFY(toMapInsertResult.first->first == 12);\n\tEATEST_VERIFY(toMapInsertResult.first->second.mX == 12);\n\tEATEST_VERIFY(toMap.find(12) != toMap.end());\n\n\tEATEST_VERIFY(toMap.find(13) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(eastl::piecewise_construct, eastl::make_tuple(13), eastl::make_tuple(1, 2, 10)); // 1 + 2 + 10 = 13\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMapInsertResult.first->first == 13);\n\tEATEST_VERIFY(toMap.find(13) != toMap.end());\n\n\ttoMapInsertResult = toMap.emplace(eastl::piecewise_construct, eastl::make_tuple(13), eastl::make_tuple(1, 30, 100)); // 1 + 30 + 100 = 131\n\tEATEST_VERIFY(toMapInsertResult.second == false);\n\tEATEST_VERIFY(toMapInsertResult.first->first == 13);\n\tEATEST_VERIFY(toMapInsertResult.first->second.mX == 13);\n\tEATEST_VERIFY(toMap.find(13) != toMap.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, Args&&... args);\n\tTestObject to14(14);\n\tEATEST_VERIFY(toMap.find(14) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(14, to14);\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(14) != toMap.end());\n\n\tTestObject to141(141);\n\ttoMapIterator = toMap.emplace_hint(toMapInsertResult.first, 14, to141);\n\tEATEST_VERIFY(toMapIterator->first == 14);\n\tEATEST_VERIFY(toMapIterator->second.mX == 14);\n\tEATEST_VERIFY(toMap.find(14) != toMap.end());\n\n\tTestObject to15(15);\n\tEATEST_VERIFY(toMap.find(15) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), 15, to15); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 15);\n\tEATEST_VERIFY(toMap.find(15) != toMap.end());\n\n\tTestObject to16(16);\n\tEATEST_VERIFY(toMap.find(16) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(16, eastl::move(to16));\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(16) != toMap.end());\n\n\tTestObject to161(161);\n\ttoMapIterator = toMap.emplace_hint(toMapInsertResult.first, 16, eastl::move(to161));\n\tEATEST_VERIFY(toMapIterator->first == 16);\n\tEATEST_VERIFY(toMapIterator->second.mX == 16);\n\tEATEST_VERIFY(toMap.find(16) != toMap.end());\n\n\tTestObject to17(17);\n\tEATEST_VERIFY(toMap.find(17) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), 17, eastl::move(to17)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 17);\n\tEATEST_VERIFY(toMap.find(17) != toMap.end());\n\n\tEATEST_VERIFY(toMap.find(18) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(eastl::piecewise_construct, eastl::make_tuple(18), eastl::make_tuple(3, 5, 10)); // 3 + 5 + 10 = 18\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(18) != toMap.end());\n\n\ttoMapIterator = toMap.emplace_hint(toMapInsertResult.first, eastl::piecewise_construct, eastl::make_tuple(18), eastl::make_tuple(1, 80, 100)); // 1 + 80 + 100 = 181\n\tEATEST_VERIFY(toMapIterator->first == 18);\n\tEATEST_VERIFY(toMapIterator->second.mX == 18);\n\tEATEST_VERIFY(toMap.find(18) != toMap.end());\n\n\tEATEST_VERIFY(toMap.find(19) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), eastl::piecewise_construct, eastl::make_tuple(19), eastl::make_tuple(4, 5, 10)); // 4 + 5 + 10 = 19 // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 19);\n\tEATEST_VERIFY(toMap.find(19) != toMap.end());\n\n\t// iterator t1A.insert(const_iterator position, const value_type& value);\n\tTestObject to20(20);\n\tvalue_type value20(20, to20);\n\tEATEST_VERIFY(toMap.find(20) == toMap.end());\n\ttoMapInsertResult = toMap.emplace(value20);\n\tEATEST_VERIFY(toMapInsertResult.second == true);\n\tEATEST_VERIFY(toMap.find(20) != toMap.end());\n\n\tvalue_type value201(20, TestObject(201));\n\ttoMapIterator = toMap.insert(toMapInsertResult.first, value201);\n\tEATEST_VERIFY(toMapIterator->first == 20);\n\tEATEST_VERIFY(toMapIterator->second.mX == 20);\n\tEATEST_VERIFY(toMap.find(20) != toMap.end());\n\n\tTestObject to21(21);\n\tvalue_type value21(21, to21);\n\tEATEST_VERIFY(toMap.find(21) == toMap.end());\n\ttoMapIterator = toMap.insert(toMap.begin(), value21); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 21);\n\tEATEST_VERIFY(toMap.find(21) != toMap.end());\n\n\t// void insert(std::initializer_list<value_type> ilist);\n\ttoMap.insert({ value_type(22, TestObject(22)), value_type(23, TestObject(23)), value_type(24, TestObject(24)) });\n\tEATEST_VERIFY(toMap.find(22) != toMap.end());\n\tEATEST_VERIFY(toMap.find(23) != toMap.end());\n\tEATEST_VERIFY(toMap.find(24) != toMap.end());\n\n\treturn nErrorCount;\n}\n\nstruct NonCopyable\n{\n\tNonCopyable() : mX(0) {}\n\tNonCopyable(int x) : mX(x) {}\n\n\tint mX;\n\n\tEA_NON_COPYABLE(NonCopyable)\n};\n\ninline bool operator<(const NonCopyable& a, const NonCopyable& b) { return a.mX < b.mX; }\n\ntemplate <typename T>\nint TestMapCpp11NonCopyable()\n{\n\tint nErrorCount = 0;\n\n\t// Verify that operator[]() can be called for a type that is default constructible but not copy constructible. C++11\n\t// relaxed the requirements on operator[]() and so this should compile.\n\tT ncMap;\n\tncMap[1].mX = 1;\n\tEATEST_VERIFY(ncMap[1].mX == 1);\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMultimapCpp11\n//\n// This function is designed to work with multimap, fixed_multimap, hash_multimap, fixed_hash_multimap\n//\n// This is similar to the TestSetCpp11 function, with some differences related\n// to handling of duplicate entries.\n//\ntemplate <typename T1>\nint TestMultimapCpp11()\n{\n\tint nErrorCount = 0;\n\n\t// template <class... Args>\n\t// insert_return_type emplace(Args&&... args);\n\t//\n\t// template <class... Args> \n\t// iterator emplace_hint(const_iterator position, Args&&... args);\n\t//\n\t// insert_return_type insert(value_type&& value);\n\t// iterator insert(const_iterator position, value_type&& value);\n\t// void insert(std::initializer_list<value_type> ilist);\n\tTestObject::Reset();\n\n\ttypedef T1 TOMap;\n\ttypedef typename TOMap::value_type value_type;\n\ttypename TOMap::iterator toMapIterator;\n\n\tTOMap      toMap;\n\tTestObject to0(0);\n\tTestObject to1(1);\n\n\ttoMapIterator = toMap.emplace(value_type(0, to0));\n\tEATEST_VERIFY(toMapIterator->first == 0);\n\t//EATEST_VERIFY((TestObject::sTOCopyCtorCount == 2) && (TestObject::sTOMoveCtorCount == 1));  // Disabled until we can guarantee its behavior and deal with how it's different between compilers of differing C++11 support.\n\n\ttoMapIterator = toMap.emplace(value_type(1, eastl::move(to1)));\n\tEATEST_VERIFY(toMapIterator->first == 1);\n\n\t// insert_return_type t1A.emplace(value_type&& value);\n\tTestObject to4(4);\n\tvalue_type value40(4, to4);\n\tEATEST_VERIFY(toMap.find(4) == toMap.end());\n\tEATEST_VERIFY(value40.second.mX == 4); // It should change to 0 below during the move swap.\n\ttoMapIterator = toMap.emplace(eastl::move(value40));\n\tEATEST_VERIFY(toMapIterator->first == 4);\n\tEATEST_VERIFY(toMap.find(4) != toMap.end());\n\tEATEST_VERIFY(value40.second.mX == 0);\n\n\tvalue_type value41(4, TestObject(41));\n\ttoMapIterator = toMap.emplace(eastl::move(value41));\n\tEATEST_VERIFY(toMapIterator->first == 4);\n\tEATEST_VERIFY(toMapIterator->second.mX == 41);\n\tEATEST_VERIFY(toMap.count(4) == 2);\n\n\t// iterator t1A.emplace_hint(const_iterator position, value_type&& value);\n\tTestObject to5(5);\n\tvalue_type value50(5, to5);\n\tEATEST_VERIFY(toMap.find(5) == toMap.end());\n\ttoMapIterator = toMap.emplace(eastl::move(value50));\n\tEATEST_VERIFY(toMapIterator->first == 5);\n\tEATEST_VERIFY(toMap.find(5) != toMap.end());\n\n\tvalue_type value51(5, TestObject(51));\n\ttoMapIterator = toMap.emplace_hint(toMapIterator, eastl::move(value51));\n\tEATEST_VERIFY(toMapIterator->first == 5);\n\tEATEST_VERIFY(toMapIterator->second.mX == 51);\n\tEATEST_VERIFY(toMap.count(5) == 2);\n\n\tTestObject to6(6);\n\tvalue_type value6(6, to6);\n\tEATEST_VERIFY(toMap.find(6) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), eastl::move(value6)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 6);\n\tEATEST_VERIFY(toMap.find(6) != toMap.end());\n\t\t\n\tTestObject to2(2);\n\tEATEST_VERIFY(toMap.find(2) == toMap.end());\n\ttoMapIterator = toMap.emplace(value_type(2, to2));\n\tEATEST_VERIFY(toMapIterator->first == 2);\n\tEATEST_VERIFY(toMap.find(2) != toMap.end());\n\ttoMapIterator = toMap.emplace(value_type(2, to2));\n\tEATEST_VERIFY(toMapIterator->first == 2);\n\tEATEST_VERIFY(toMap.find(2) != toMap.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, const value_type& value);\n\tTestObject to7(7);\n\tvalue_type value70(7, to7);\n\tEATEST_VERIFY(toMap.find(7) == toMap.end());\n\ttoMapIterator = toMap.emplace(value70);\n\tEATEST_VERIFY(toMapIterator->first == 7);\n\tEATEST_VERIFY(toMap.find(7) != toMap.end());\n\n\tvalue_type value71(7, TestObject(71));\n\ttoMapIterator = toMap.emplace_hint(toMapIterator, value71);\n\tEATEST_VERIFY(toMapIterator->first == 7);\n\tEATEST_VERIFY(toMapIterator->second.mX == 71);\n\tEATEST_VERIFY(toMap.count(7) == 2);\n\n\tTestObject to8(8);\n\tvalue_type value8(8, to8);\n\tEATEST_VERIFY(toMap.find(8) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), value8); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 8);\n\tEATEST_VERIFY(toMap.find(8) != toMap.end());\n\n\t// insert_return_type t1A.insert(value_type&& value);\n\tTestObject to3(3);\n\tEATEST_VERIFY(toMap.find(3) == toMap.end());\n\ttoMapIterator = toMap.insert(value_type(3, to3));\n\tEATEST_VERIFY(toMapIterator->first == 3);\n\tEATEST_VERIFY(toMap.find(3) != toMap.end());\n\ttoMapIterator = toMap.insert(value_type(3, to3));\n\tEATEST_VERIFY(toMapIterator->first == 3);\n\tEATEST_VERIFY(toMap.find(3) != toMap.end());\n\n\n\t// iterator t1A.insert(const_iterator position, value_type&& value);\n\tTestObject to9(9);\n\tvalue_type value90(9, to9);\n\tEATEST_VERIFY(toMap.find(9) == toMap.end());\n\ttoMapIterator = toMap.emplace(eastl::move(value90));\n\tEATEST_VERIFY(toMapIterator->first == 9);\n\tEATEST_VERIFY(toMap.find(9) != toMap.end());\n\n\tvalue_type value91(9, TestObject(91));\n\ttoMapIterator = toMap.insert(toMapIterator, eastl::move(value91));\n\tEATEST_VERIFY(toMapIterator->first == 9);\n\tEATEST_VERIFY(toMapIterator->second.mX == 91);\n\tEATEST_VERIFY(toMap.count(9) == 2);\n\n\tTestObject to10(10);\n\tvalue_type value10(10, to10);\n\tEATEST_VERIFY(toMap.find(10) == toMap.end());\n\ttoMapIterator = toMap.insert(toMap.begin(), eastl::move(value10)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 10);\n\tEATEST_VERIFY(toMap.find(10) != toMap.end());\n\n\t// iterator t1A.emplace(Args&&... args);\n\tTestObject to11(11);\n\tEATEST_VERIFY(toMap.find(11) == toMap.end());\n\ttoMapIterator = toMap.emplace(11, to11);\n\tEATEST_VERIFY(toMapIterator->first == 11);\n\tEATEST_VERIFY(toMap.find(11) != toMap.end());\n\n\tTestObject to111(111);\n\ttoMapIterator = toMap.emplace(11, to111);\n\tEATEST_VERIFY(toMapIterator->first == 11);\n\tEATEST_VERIFY(toMapIterator->second.mX == 111);\n\tEATEST_VERIFY(toMap.count(11) == 2);\n\n\tTestObject to12(12);\n\tEATEST_VERIFY(toMap.find(12) == toMap.end());\n\ttoMapIterator = toMap.emplace(12, eastl::move(to12));\n\tEATEST_VERIFY(toMapIterator->first == 12);\n\tEATEST_VERIFY(toMap.find(12) != toMap.end());\n\n\tTestObject to121(121);\n\ttoMapIterator = toMap.emplace(12, eastl::move(to121));\n\tEATEST_VERIFY(toMapIterator->first == 12);\n\tEATEST_VERIFY(toMapIterator->second.mX == 121);\n\tEATEST_VERIFY(toMap.count(12) == 2);\n\n\tEATEST_VERIFY(toMap.find(13) == toMap.end());\n\ttoMapIterator = toMap.emplace(eastl::piecewise_construct, eastl::make_tuple(13), eastl::make_tuple(1, 2, 10)); // 1 + 2 + 10 = 13\n\tEATEST_VERIFY(toMapIterator->first == 13);\n\tEATEST_VERIFY(toMap.find(13) != toMap.end());\n\n\ttoMapIterator = toMap.emplace(eastl::piecewise_construct, eastl::make_tuple(13), eastl::make_tuple(1, 30, 100)); // 1 + 30 + 100 = 131\n\tEATEST_VERIFY(toMapIterator->first == 13);\n\tEATEST_VERIFY(toMapIterator->second.mX == 131);\n\tEATEST_VERIFY(toMap.count(13) == 2);\n\n\t// iterator t1A.emplace_hint(const_iterator position, Args&&... args);\n\tTestObject to14(14);\n\tEATEST_VERIFY(toMap.find(14) == toMap.end());\n\ttoMapIterator = toMap.emplace(14, to14);\n\tEATEST_VERIFY(toMap.find(14) != toMap.end());\n\n\tTestObject to141(141);\n\ttoMapIterator = toMap.emplace_hint(toMapIterator, 14, to141);\n\tEATEST_VERIFY(toMapIterator->first == 14);\n\tEATEST_VERIFY(toMapIterator->second.mX == 141);\n\tEATEST_VERIFY(toMap.count(14) == 2);\n\n\tTestObject to15(15);\n\tEATEST_VERIFY(toMap.find(15) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), 15, to15); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 15);\n\tEATEST_VERIFY(toMap.find(15) != toMap.end());\n\n\tTestObject to16(16);\n\tEATEST_VERIFY(toMap.find(16) == toMap.end());\n\ttoMapIterator = toMap.emplace(16, eastl::move(to16));\n\tEATEST_VERIFY(toMap.find(16) != toMap.end());\n\n\tTestObject to161(161);\n\ttoMapIterator = toMap.emplace_hint(toMapIterator, 16, eastl::move(to161));\n\tEATEST_VERIFY(toMapIterator->first == 16);\n\tEATEST_VERIFY(toMapIterator->second.mX == 161);\n\tEATEST_VERIFY(toMap.count(16) == 2);\n\n\tTestObject to17(17);\n\tEATEST_VERIFY(toMap.find(17) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), 17, eastl::move(to17)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 17);\n\tEATEST_VERIFY(toMap.find(17) != toMap.end());\n\n\tEATEST_VERIFY(toMap.find(18) == toMap.end());\n\ttoMapIterator = toMap.emplace(eastl::piecewise_construct, eastl::make_tuple(18), eastl::make_tuple(3, 5, 10)); // 3 + 5 + 10 = 18\n\tEATEST_VERIFY(toMap.find(18) != toMap.end());\n\n\ttoMapIterator = toMap.emplace_hint(toMapIterator, eastl::piecewise_construct, eastl::make_tuple(18), eastl::make_tuple(1, 80, 100)); // 1 + 80 + 100 = 181\n\tEATEST_VERIFY(toMapIterator->first == 18);\n\tEATEST_VERIFY(toMapIterator->second.mX == 181);\n\tEATEST_VERIFY(toMap.count(18) == 2);\n\n\tEATEST_VERIFY(toMap.find(19) == toMap.end());\n\ttoMapIterator = toMap.emplace_hint(toMap.begin(), eastl::piecewise_construct, eastl::make_tuple(19), eastl::make_tuple(4, 5, 10)); // 4 + 5 + 10 = 19 // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 19);\n\tEATEST_VERIFY(toMap.find(19) != toMap.end());\n\n\t// iterator t1A.insert(const_iterator position, const value_type& value);\n\tTestObject to20(20);\n\tvalue_type value20(20, to20);\n\tEATEST_VERIFY(toMap.find(20) == toMap.end());\n\ttoMapIterator = toMap.emplace(value20);\n\tEATEST_VERIFY(toMap.find(20) != toMap.end());\n\n\tvalue_type value201(20, TestObject(201));\n\ttoMapIterator = toMap.insert(toMapIterator, value201);\n\tEATEST_VERIFY(toMapIterator->first == 20);\n\tEATEST_VERIFY(toMapIterator->second.mX == 201);\n\tEATEST_VERIFY(toMap.count(20) == 2);\n\n\tTestObject to21(21);\n\tvalue_type value21(21, to21);\n\tEATEST_VERIFY(toMap.find(21) == toMap.end());\n\ttoMapIterator = toMap.insert(toMap.begin(), value21); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(toMapIterator->first == 21);\n\tEATEST_VERIFY(toMap.find(21) != toMap.end());\n\n\t// void insert(std::initializer_list<value_type> ilist);\n\ttoMap.insert({ value_type(22, TestObject(22)), value_type(23, TestObject(23)), value_type(24, TestObject(24)), value_type(24, TestObject(241)) });\n\tEATEST_VERIFY(toMap.find(22) != toMap.end());\n\tEATEST_VERIFY(toMap.find(23) != toMap.end());\n\tEATEST_VERIFY(toMap.count(24) == 2);\n\n\treturn nErrorCount;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMapCpp17\n//\n// This function is designed to work with map, fixed_map, hash_map, fixed_hash_map, unordered_map.\n//\ntemplate <typename T1>\nint TestMapCpp17()\n{\n\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\ttypedef T1 TOMap;\n\ttypedef typename TOMap::mapped_type mapped_type;\n\ttypename TOMap::iterator toMapIterator;\n\n\n\t{\n\t\t// pair<iterator, bool> try_emplace (const key_type& k, Args&&... args);\n\t\t// pair<iterator, bool> try_emplace (key_type&& k, Args&&... args);\n\t\t// iterator             try_emplace (const_iterator hint, const key_type& k, Args&&... args);\n\t\t// iterator             try_emplace (const_iterator hint, key_type&& k, Args&&... args);\n\n\t\tTOMap toMap;\n\n\t\t{ // do initial insert\n\t\t\tauto result = toMap.try_emplace(7, 7); // test fwding to conversion-ctor\n\t\t\tVERIFY(result.second);\n\t\t\tVERIFY(result.first->second == mapped_type(7));\n\t\t\tVERIFY(toMap.size() == 1);\n\t\t}\n\n\t\tauto ctorCount = TestObject::sTOCtorCount;\n\n\t\t{ // verify duplicate not inserted\n\t\t\tauto result = toMap.try_emplace(7, mapped_type(7)); // test fwding to copy-ctor\n\t\t\tVERIFY(!result.second);\n\t\t\tVERIFY(result.first->second == mapped_type(7));\n\t\t\tVERIFY(toMap.size() == 1);\n\n\t\t\t// we explicitly constructed an element for the parameter\n\t\t\t// and one for the VERIFY check\n\t\t\tctorCount += 2;\n\t\t\tVERIFY(ctorCount == TestObject::sTOCtorCount);\n\t\t}\n\n\t\t{ // verify duplicate not inserted\n\t\t\tauto hint = toMap.find(7);\n\t\t\tauto result = toMap.try_emplace(hint, 7, 7); // test fwding to conversion-ctor\n\t\t\tVERIFY(result->first == 7);\n\t\t\tVERIFY(result->second == mapped_type(7));\n\t\t\tVERIFY(toMap.size() == 1);\n\t\t\t// we explicitly constructed an element for the VERIFY check\n\t\t\t++ctorCount;\n\t\t\tVERIFY(ctorCount == TestObject::sTOCtorCount);\n\t\t}\n\n\t\t{ // verify duplicate not inserted\n\t\t\tauto hint = toMap.find(7);\n\t\t\tauto result = toMap.try_emplace(hint, 7, mapped_type(7)); // test fwding to copy-ctor\n\t\t\tVERIFY(result->first == 7);\n\t\t\tVERIFY(result->second == mapped_type(7));\n\t\t\tVERIFY(toMap.size() == 1);\n\n\t\t\t// we explicitly constructed an element for the parameter\n\t\t\t// and one for the VERIFY check\n\t\t\tctorCount += 2;\n\t\t\tVERIFY(ctorCount == TestObject::sTOCtorCount);\n\t\t}\n\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = toMap.try_emplace(8, 8);\n\t\t\t\t// emplacing a new value should call exactly one constructor,\n\t\t\t\t// when the value is constructed in place inside the container.\n\t\t\t\t++ctorCount;\n\t\t\t\tVERIFY(result.second);\n\t\t\t\tVERIFY(result.first->second == mapped_type(8));\n\t\t\t\t// One more constructor for the temporary in the VERIFY\n\t\t\t\t++ctorCount;\n\t\t\t\tVERIFY(toMap.size() == 2);\n\t\t\t\tVERIFY(ctorCount == TestObject::sTOCtorCount);\n\t\t\t}\n\t\t\t{\n\t\t\t\tauto result = toMap.try_emplace(9, mapped_type(9));\n\t\t\t\tVERIFY(result.second);\n\t\t\t\tVERIFY(result.first->second == mapped_type(9));\n\t\t\t\tVERIFY(toMap.size() == 3);\n\t\t\t\t// one more constructor for the temporary argument,\n\t\t\t\t// one for moving it to the container, and one for the VERIFY\n\t\t\t\tctorCount += 3;\n\t\t\t\tVERIFY(ctorCount == TestObject::sTOCtorCount);\n\n\t\t\t}\n\t\t}\n\t}\n\n\t{\n\t\t// eastl::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);\n\t\t// eastl::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);\n\t\t// iterator                    insert_or_assign(const_iterator hint, const key_type& k, M&& obj);\n\t\t// iterator                    insert_or_assign(const_iterator hint, key_type&& k, M&& obj);\n\n\t\tTOMap toMap;\n\n\t\t{\n\t\t\t// initial rvalue insert\n\t\t\tauto result = toMap.insert_or_assign(3, mapped_type(3));\n\t\t\tVERIFY(result.second);\n\t\t\tVERIFY(toMap.size() == 1);\n\t\t\tVERIFY(result.first->first == 3);\n\t\t\tVERIFY(result.first->second == mapped_type(3));\n\n\t\t\t// verify rvalue assign occurred\n\t\t\tresult = toMap.insert_or_assign(3, mapped_type(9));\n\t\t\tVERIFY(!result.second);\n\t\t\tVERIFY(toMap.size() == 1);\n\t\t\tVERIFY(result.first->first == 3);\n\t\t\tVERIFY(result.first->second == mapped_type(9));\n\t\t}\n\n\t\t{\n\t\t\tmapped_type mt5(5);\n\t\t\tmapped_type mt6(6);\n\t\t\tmapped_type mt7(7);\n\n\t\t\t{\n\t\t\t\t// initial lvalue insert\n\t\t\t\tauto result = toMap.insert_or_assign(5, mt5);\n\t\t\t\tVERIFY(result.second);\n\t\t\t\tVERIFY(toMap.size() == 2);\n\t\t\t\tVERIFY(result.first->first == 5);\n\t\t\t\tVERIFY(result.first->second == mt5);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t// verify lvalue assign occurred\n\t\t\t\tauto result = toMap.insert_or_assign(5, mt7);\n\t\t\t\tVERIFY(!result.second);\n\t\t\t\tVERIFY(toMap.size() == 2);\n\t\t\t\tVERIFY(result.first->first == 5);\n\t\t\t\tVERIFY(result.first->second == mt7);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t// verify lvalue hints\n\t\t\t\tauto hint = toMap.find(5);\n\t\t\t\tauto result = toMap.insert_or_assign(hint, 6, mt6);\n\t\t\t\tVERIFY(result != toMap.end());\n\t\t\t\tVERIFY(toMap.size() == 3);\n\t\t\t\tVERIFY(result->first == 6);\n\t\t\t\tVERIFY(result->second == mt6);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t// verify rvalue hints\n\t\t\t\tauto hint = toMap.find(6);\n\t\t\t\tauto result = toMap.insert_or_assign(hint, 7, mapped_type(7));\n\t\t\t\tVERIFY(result != toMap.end());\n\t\t\t\tVERIFY(toMap.size() == 4);\n\t\t\t\tVERIFY(result->first == 7);\n\t\t\t\tVERIFY(result->second == mapped_type(7));\n\t\t\t}\n\t\t}\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMapAccess\n//\n// This function is designed to work with map, fixed_map, hash_map, fixed_hash_map, unordered_map.\n//\n// Tests for element access: operator[] and at()\ntemplate <typename T1>\nint TestMapAccess()\n{\n\tint nErrorCount = 0;\n\n\ttypedef T1 TOMap;\n\ttypedef typename TOMap::key_type key_type;\n\ttypedef typename TOMap::mapped_type mapped_type;\n\n\tTOMap map1;\n\tmap1[key_type(1)] = mapped_type(1);\n\tmap1[key_type(3)] = mapped_type(3);\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEATEST_VERIFY_THROW(map1.at(key_type(0)));\n\tEATEST_VERIFY_THROW(map1.at(key_type(2)));\n\tEATEST_VERIFY_THROW(map1.at(key_type(4)));\n#endif\n\tmap1[key_type(0)] = mapped_type(1);\n#if EASTL_EXCEPTIONS_ENABLED\n\tEATEST_VERIFY_NOTHROW(map1.at(key_type(0)));\n\tEATEST_VERIFY_NOTHROW(map1.at(key_type(1)));\n\tEATEST_VERIFY_NOTHROW(map1.at(key_type(3)));\n#endif\n\tEATEST_VERIFY(map1.at(key_type(0)) == mapped_type(1));\n\tEATEST_VERIFY(map1.at(key_type(1)) == mapped_type(1));\n\tEATEST_VERIFY(map1.at(key_type(3)) == mapped_type(3));\n\n\tconst TOMap map2;\n\tconst TOMap map3(map1);\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tEATEST_VERIFY_THROW(map2.at(key_type(0)));\n\tEATEST_VERIFY_NOTHROW(map3.at(key_type(0)));\n#endif\n\tEATEST_VERIFY(map3.at(key_type(0)) == mapped_type(1));\n\n\treturn nErrorCount;\n}\n\n\ntemplate<typename HashContainer>\nstruct HashContainerReserveTest\n{\n\tint operator()()\n\t{\n\t\tint nErrorCount = 0;\n\n\t\tHashContainer hashContainer;\n\n\t\tconst typename HashContainer::size_type reserve_sizes[] = {16, 128, 4096, 32768};\n\t\tfor (auto& reserve_size : reserve_sizes)\n\t\t{\n\t\t\thashContainer.reserve(reserve_size);\n\n\t\t\t// verify bucket count and hashtable load_factor requirements\n\t\t\tVERIFY(hashContainer.bucket_count() >= reserve_size);\n\t\t\tVERIFY(hashContainer.load_factor() <= ceilf(reserve_size / hashContainer.get_max_load_factor()));\n\t\t}\n\n\t\treturn nErrorCount;\n\t}\n};\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestMemory.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/memory.h>\n#include <EASTL/utility.h>\n#include <EASTL/vector.h>\n#include <EAStdC/EAMemory.h>\n#include <EAStdC/EAAlignment.h>\n\n\n// Regression for user reported operator new problem (12/8/2009):\nclass AssetHandler\n{\npublic:\n\tinline static void* operator new(size_t size, const char* /*text*/, unsigned int /*flags*/)\n\t{\n\t\treturn ::operator new(size);\n\t}\n\tinline static void operator delete(void* p)\n\t{\n\t\treturn ::operator delete(p);\n\t}\n};\ntypedef eastl::vector<AssetHandler> AssetHandlerArray;\n\n// Regression test for a default memory fill optimization that defers to memset instead of explicitly\n// value-initialization each element in a vector individually.  This test ensures that the value of the memset is\n// consistent with an explicitly value-initialized element (namely when the container holds a scalar value that is\n// memset to zero).\ntemplate <typename T>\nint TestValueInitOptimization()\n{\n\tint nErrorCount = 0;\n\tconst int ELEM_COUNT = 100;\n\n\t{\n\t\teastl::vector<T> v1;\n\t\teastl::vector<ValueInitOf<T>> v2;\n\n\t\tv1.resize(ELEM_COUNT);\n\t\tv2.resize(ELEM_COUNT);\n\n\t\tfor (int i = 0; i < ELEM_COUNT; i++)\n\t\t\t{ EATEST_VERIFY(v1[i] == v2[i].get()); }\n\t}\n\n\t{\n\t\teastl::vector<T> v1(ELEM_COUNT);\n\t\teastl::vector<ValueInitOf<T>> v2(ELEM_COUNT);\n\n\t\tfor (int i = 0; i < ELEM_COUNT; i++)\n\t\t\t{ EATEST_VERIFY(v1[i] == v2[i].get()); }\n\t}\n\n\tEATEST_VERIFY(nErrorCount == 0);\n\treturn nErrorCount;\n}\n\n\n// LCTestObject\n//\n// Helps test the late_constructed utility.\n// Has an unusual alignment so we can test that aspect of late_constructed.\n//\nstruct EA_ALIGN(64) LCTestObject\n{\n\tint             mX;                  // \n\tstatic int64_t  sTOCount;            // Count of all current existing objects.\n\tstatic int64_t  sTOCtorCount;        // Count of times any ctor was called.\n\tstatic int64_t  sTODtorCount;        // Count of times dtor was called.\n\n\texplicit LCTestObject(int x = 0)\n\t\t: mX(x)\n\t{\n\t\t++sTOCount;\n\t\t++sTOCtorCount;\n\t}\n\n\tLCTestObject(int x0, int x1, int x2)\n\t\t: mX(x0 + x1 + x2)\n\t{\n\t\t++sTOCount;\n\t\t++sTOCtorCount;\n\t}\n\n\tLCTestObject(const LCTestObject& testObject)\n\t\t: mX(testObject.mX)\n\t{\n\t\t++sTOCount;\n\t\t++sTOCtorCount;\n\t}\n\n\t#if !defined(EA_COMPILER_NO_RVALUE_REFERENCES)\n\t\tLCTestObject(TestObject&& testObject)\n\t\t\t: mX(testObject.mX)\n\t\t{\n\t\t\t++sTOCount;\n\t\t\t++sTOCtorCount;\n\t\t}\n\t#endif\n\n\tLCTestObject& operator=(const LCTestObject& testObject)\n\t{\n\t\tmX = testObject.mX;\n\t\treturn *this;\n\t}\n\n\t#if !defined(EA_COMPILER_NO_RVALUE_REFERENCES)\n\t\tLCTestObject& operator=(LCTestObject&& testObject)\n\t\t{\n\t\t\teastl::swap(mX, testObject.mX);\n\t\t\treturn *this;\n\t\t}\n\t#endif\n\n\t~LCTestObject()\n\t{\n\t\t--sTOCount;\n\t\t++sTODtorCount;\n\t}\n};\n\nint64_t LCTestObject::sTOCount     = 0;\nint64_t LCTestObject::sTOCtorCount = 0;\nint64_t LCTestObject::sTODtorCount = 0;\n\n\neastl::late_constructed<LCTestObject, true, true>  gLCTestObjectTrueTrue;\neastl::late_constructed<LCTestObject, false, true> gLCTestObjectFalseTrue;\neastl::late_constructed<LCTestObject, false, false> gLCTestObjectFalseFalse;\neastl::late_constructed<LCTestObject, true, false> gLCTestObjectTrueFalse;\n\nstruct TypeWithPointerTraits {};\n\nnamespace eastl\n{\n\ttemplate <>\n\tstruct pointer_traits<TypeWithPointerTraits>\n\t{\n\t\t// Note: only parts of the traits we are interested to test are defined here.\n\t\tstatic const int* to_address(TypeWithPointerTraits)\n\t\t{\n\t\t\treturn &a;\n\t\t}\n\n\t\tinline static constexpr int a = 42;\n\t};\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMemory\n//\nint TestMemory()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\n\t{\n\t\tLCTestObject* pLCTO;\n\n\t\tLCTestObject::sTOCount     = 0;\n\t\tLCTestObject::sTOCtorCount = 0;\n\t\tLCTestObject::sTODtorCount = 0;\n\n\t\t// Verify alignment requirements.\n\t\t// We don't verify that gLCTestObjectTrueTrue.get() is aligned for all platforms because some platforms can't do that with global memory.\n\t\tstatic_assert(eastl::alignment_of<typename late_constructed<LCTestObject>::value_type>::value == 64, \"late_constructed alignment failure.\");\n\t\tstatic_assert(eastl::alignment_of<typename late_constructed<LCTestObject>::storage_type>::value == 64, \"late_constructed alignment failure.\");\n\t\tstatic_assert(eastl::alignment_of<late_constructed<LCTestObject> >::value >= 64, \"late_constructed alignment failure.\");\n\n\n\t\t// late_constructed / gLCTestObjectTrueTrue \n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));\n\t\tEATEST_VERIFY(!gLCTestObjectTrueTrue.is_constructed());\n\n\t\tpLCTO = gLCTestObjectTrueTrue.get(); // This will auto-construct LCTestObject.\n\t\tEATEST_VERIFY(pLCTO != NULL);\n\t\tEATEST_VERIFY(gLCTestObjectTrueTrue.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectTrueTrue->mX = 17;\n\t\tEATEST_VERIFY(gLCTestObjectTrueTrue->mX == 17);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectTrueTrue.destruct();\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 1));\n\t\tEATEST_VERIFY(!gLCTestObjectTrueTrue.is_constructed());\n\n\t\tgLCTestObjectTrueTrue->mX = 18;\n\t\tEATEST_VERIFY(gLCTestObjectTrueTrue->mX == 18);\n\t\tEATEST_VERIFY(gLCTestObjectTrueTrue.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 2) && (LCTestObject::sTODtorCount == 1));\n\n\t\tgLCTestObjectTrueTrue.destruct();\n\t\t(*gLCTestObjectTrueTrue).mX = 19;\n\t\tEATEST_VERIFY(gLCTestObjectTrueTrue->mX == 19);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 3) && (LCTestObject::sTODtorCount == 2));\n\n\t\tgLCTestObjectTrueTrue.destruct();\n\t\tLCTestObject::sTOCount     = 0;\n\t\tLCTestObject::sTOCtorCount = 0;\n\t\tLCTestObject::sTODtorCount = 0;\n\n\t\t// late_constructed / gLCTestObjectFalseTrue \n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));\n\t\tEATEST_VERIFY(!gLCTestObjectFalseTrue.is_constructed());\n\n\t\tpLCTO = gLCTestObjectFalseTrue.get(); // This will not auto-construct LCTestObject.\n\t\tEATEST_VERIFY(pLCTO == NULL);\n\t\tEATEST_VERIFY(!gLCTestObjectFalseTrue.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectFalseTrue.construct();\n\t\tpLCTO = gLCTestObjectFalseTrue.get();\n\t\tEATEST_VERIFY(pLCTO != NULL);\n\t\tEATEST_VERIFY(gLCTestObjectFalseTrue.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectFalseTrue->mX = 17;\n\t\tEATEST_VERIFY(gLCTestObjectFalseTrue->mX == 17);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectFalseTrue.destruct();\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 1));\n\t\tEATEST_VERIFY(!gLCTestObjectFalseTrue.is_constructed());\n\n\t\tgLCTestObjectFalseTrue.construct(14);\n\t\tEATEST_VERIFY(gLCTestObjectFalseTrue->mX == 14);\n\t\tgLCTestObjectFalseTrue->mX = 18;\n\t\tEATEST_VERIFY(gLCTestObjectFalseTrue->mX == 18);\n\t\tEATEST_VERIFY(gLCTestObjectFalseTrue.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 2) && (LCTestObject::sTODtorCount == 1));\n\n\t\tgLCTestObjectFalseTrue.destruct();\n\t\tgLCTestObjectFalseTrue.construct(10, 20, 30);\n\t\tEATEST_VERIFY(gLCTestObjectFalseTrue->mX == 10+20+30);\n\t\t(*gLCTestObjectFalseTrue).mX = 19;\n\t\tEATEST_VERIFY(gLCTestObjectFalseTrue->mX == 19);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 3) && (LCTestObject::sTODtorCount == 2));\n\n\t\tgLCTestObjectFalseTrue.destruct();\n\t}\n\n\t{\n\t\tLCTestObject* pLCTO;\n\n\t\tLCTestObject::sTOCount     = 0;\n\t\tLCTestObject::sTOCtorCount = 0;\n\t\tLCTestObject::sTODtorCount = 0;\n\n\t\t// Verify alignment requirements.\n\t\t// We don't verify that gLCTestObjectTrueTrue.get() is aligned for all platforms because some platforms can't do that with global memory.\n\t\tstatic_assert(eastl::alignment_of<typename late_constructed<LCTestObject>::value_type>::value == 64, \"late_constructed alignment failure.\");\n\t\tstatic_assert(eastl::alignment_of<typename late_constructed<LCTestObject>::storage_type>::value == 64, \"late_constructed alignment failure.\");\n\t\tstatic_assert(eastl::alignment_of<late_constructed<LCTestObject> >::value >= 64, \"late_constructed alignment failure.\");\n\n\n\t\t// late_constructed / gLCTestObjectTrueFalse\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));\n\t\tEATEST_VERIFY(!gLCTestObjectTrueFalse.is_constructed());\n\n\t\tpLCTO = gLCTestObjectTrueFalse.get(); // This will auto-construct LCTestObject.\n\t\tEATEST_VERIFY(pLCTO != NULL);\n\t\tEATEST_VERIFY(gLCTestObjectTrueFalse.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectTrueFalse->mX = 17;\n\t\tEATEST_VERIFY(gLCTestObjectTrueFalse->mX == 17);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectTrueFalse.destruct();\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 1));\n\t\tEATEST_VERIFY(!gLCTestObjectTrueFalse.is_constructed());\n\n\t\tgLCTestObjectTrueFalse->mX = 18;\n\t\tEATEST_VERIFY(gLCTestObjectTrueFalse->mX == 18);\n\t\tEATEST_VERIFY(gLCTestObjectTrueFalse.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 2) && (LCTestObject::sTODtorCount == 1));\n\n\t\tgLCTestObjectTrueFalse.destruct();\n\t\t(*gLCTestObjectTrueFalse).mX = 19;\n\t\tEATEST_VERIFY(gLCTestObjectTrueFalse->mX == 19);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 3) && (LCTestObject::sTODtorCount == 2));\n\n\t\tgLCTestObjectTrueFalse.destruct();\n\t\tLCTestObject::sTOCount     = 0;\n\t\tLCTestObject::sTOCtorCount = 0;\n\t\tLCTestObject::sTODtorCount = 0;\n\n\t\t// late_constructed / gLCTestObjectFalseFalse\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));\n\t\tEATEST_VERIFY(!gLCTestObjectFalseFalse.is_constructed());\n\n\t\tpLCTO = gLCTestObjectFalseFalse.get(); // This will not auto-construct LCTestObject.\n\t\tEATEST_VERIFY(pLCTO == NULL);\n\t\tEATEST_VERIFY(!gLCTestObjectFalseFalse.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 0) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectFalseFalse.construct();\n\t\tpLCTO = gLCTestObjectFalseFalse.get();\n\t\tEATEST_VERIFY(pLCTO != NULL);\n\t\tEATEST_VERIFY(gLCTestObjectFalseFalse.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectFalseFalse->mX = 17;\n\t\tEATEST_VERIFY(gLCTestObjectFalseFalse->mX == 17);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\t\tgLCTestObjectFalseFalse.destruct();\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 0) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 1));\n\t\tEATEST_VERIFY(!gLCTestObjectFalseFalse.is_constructed());\n\n\t\tgLCTestObjectFalseFalse.construct(14);\n\t\tEATEST_VERIFY(gLCTestObjectFalseFalse->mX == 14);\n\t\tgLCTestObjectFalseFalse->mX = 18;\n\t\tEATEST_VERIFY(gLCTestObjectFalseFalse->mX == 18);\n\t\tEATEST_VERIFY(gLCTestObjectFalseFalse.is_constructed());\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 2) && (LCTestObject::sTODtorCount == 1));\n\n\t\tgLCTestObjectFalseFalse.destruct();\n\t\tgLCTestObjectFalseFalse.construct(10, 20, 30);\n\t\tEATEST_VERIFY(gLCTestObjectFalseFalse->mX == 10+20+30);\n\t\t(*gLCTestObjectFalseFalse).mX = 19;\n\t\tEATEST_VERIFY(gLCTestObjectFalseFalse->mX == 19);\n\t\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 3) && (LCTestObject::sTODtorCount == 2));\n\n\t\tgLCTestObjectFalseFalse.destruct();\n\t}\n\n\tLCTestObject::sTOCount     = 0;\n\tLCTestObject::sTOCtorCount = 0;\n\tLCTestObject::sTODtorCount = 0;\n\t{\n\t\teastl::late_constructed<LCTestObject, true, false> lc;\n\t\tlc.construct();\n\t}\n\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\tLCTestObject::sTOCount     = 0;\n\tLCTestObject::sTOCtorCount = 0;\n\tLCTestObject::sTODtorCount = 0;\n\t{\n\t\teastl::late_constructed<LCTestObject, false, false> lc;\n\t\tlc.construct();\n\t}\n\tEATEST_VERIFY((LCTestObject::sTOCount == 1) && (LCTestObject::sTOCtorCount == 1) && (LCTestObject::sTODtorCount == 0));\n\n\n\t// We use the vector container to supply a RandomAccessIterator.\n\t// We use the list container to supply a BidirectionalIterator.\n\t// We use the slist container to supply a ForwardIterator.\n\t// We use our generic_input_iterator adapter to supply an InputIterator.\n\n\t// eastl::vector<int>  intVector;\n\t// eastl::list<int>    intList;\n\t// eastl::slist<int>   intSlist;\n\n\tint* pEnd;\n\n\t{\n\t\t// template <typename InputIterator, typename ForwardIterator>\n\t\t// ForwardIterator uninitialized_copy(InputIterator sourceFirst, InputIterator sourceLast, ForwardIterator destination);\n\n\t\tpEnd = eastl::uninitialized_copy<int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);\n\t\tEATEST_VERIFY(pEnd == NULL);\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 1, 2, 3, 4, 5, 6 };\n\n\t\tuninitialized_copy(intArray2, intArray2 + 6, intArray1);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"uninitialized_copy\", 1, 2, 3, 4, 5, 6, -1));\n\n\t\tuninitialized_copy(eastl::move_iterator{ intArray2 }, eastl::move_iterator{ intArray2 + 6 }, intArray1);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"uninitialized_copy\", 1, 2, 3, 4, 5, 6, -1));\n\t}\n\n\t{\n\t\t// uninitialized_copy_n\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 1, 2, 3, 4, 5, 6 };\n\t\tuninitialized_copy_n(intArray2, 6, intArray1);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"uninitialized_copy_n\", 1, 2, 3, 4, 5, 6, -1));\n\t}\n\n\n\t// template <typename First, typename Last, typename Result>\n\t// Result uninitialized_copy_ptr(First first, Last last, Result result)\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // '*': was declared deprecated\n\tpEnd = eastl::uninitialized_copy_ptr<int*, int*, int*>((int*)NULL, (int*)NULL, (int*)NULL);\n\tEATEST_VERIFY(pEnd == NULL);\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\t{\n\t\t// template <typename ForwardIterator, typename T>\n\t\t// void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value)\n\n\t\teastl::uninitialized_fill<int*, int>((int*)NULL, (int*)NULL, (int)0);\n\n\t\tint intArray[] = { 3, 2, 6, 5, 4, 1 };\n\t\tuninitialized_fill(intArray, intArray + 6, 4);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"uninitialized_fill\", 4, 4, 4, 4, 4, 4, -1));\n\t}\n\n\n\t// template <typename T>\n\t// void uninitialized_fill_ptr(T* first, T* last, const T& value)\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // '*': was declared deprecated\n\teastl::uninitialized_fill_ptr<int>((int*)NULL, (int*)NULL, (int)0);\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\t{\n\t\t// template <typename ForwardIterator, typename Count, typename T>\n\t\t// void uninitialized_fill_n(ForwardIterator first, Count n, const T& value)\n\n\t\teastl::uninitialized_fill_n<int*, int, int>((int*)NULL, (int)0, (int)0);\n\n\t\tint intArray[] = { 3, 2, 6, 5, 4, 1 };\n\t\tuninitialized_fill_n(intArray, 6, 5);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"uninitialized_fill_n\", 5, 5, 5, 5, 5, 5, -1));\n\t}\n\n\n\t// template <typename T, typename Count>\n\t// void uninitialized_fill_n_ptr(T* first, Count n, const T& value)\n\n\tEASTL_INTERNAL_DISABLE_DEPRECATED() // '*': was declared deprecated\n\teastl::uninitialized_fill_n_ptr<int, int>((int*)NULL, (int)0, (int)0);\n\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\n\n\n\t// template <typename InputIterator, typename ForwardIterator, typename T>\n\t// void uninitialized_copy_fill(InputIterator first1, InputIterator last1,\n\t//                                 ForwardIterator first2, ForwardIterator last2, const T& value)\n\n\teastl::uninitialized_copy_fill<int*, int*, int>((int*)NULL, (int*)NULL, (int*)NULL, (int*)NULL, (int)0);\n\n\n\n\t// template <typename ForwardIterator, typename T, typename InputIterator>\n\t// ForwardIterator uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)\n\n\teastl::uninitialized_fill_copy<int*, int, int*>((int*)NULL, (int*)NULL, (int)0, (int*)NULL, (int*)NULL);\n\n\n\n\t// template <typename InputIterator1, typename InputIterator2, typename ForwardIterator>\n\t// ForwardIterator uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,\n\t//                                         InputIterator2 first2, InputIterator2 last2,\n\t//                                         ForwardIterator result)\n\n\teastl::uninitialized_copy_copy<int*, int*, int*>((int*)NULL, (int*)NULL, (int*)NULL, (int*)NULL, (int*)NULL);\n\n\t// uninitialized_default_construct\n\t{\n\t\tTestObject::Reset();\n\t\tchar testCharArray[sizeof(TestObject) * 10];\n\t\tTestObject* pTestMemory = (TestObject*)(testCharArray);\n\n\t\teastl::uninitialized_default_construct(pTestMemory, pTestMemory + 10);\n\t\tEATEST_VERIFY(TestObject::sTODefaultCtorCount == 10);\n\t}\n\n\t// uninitialized_default_construct_n\n\t{\n\t\tTestObject::Reset();\n\t\tchar testCharArray[sizeof(TestObject) * 10];\n\t\tTestObject* pTestMemory = (TestObject*)(testCharArray);\n\n\t\tauto endIter = eastl::uninitialized_default_construct_n(pTestMemory, 5);\n\t\tEATEST_VERIFY(TestObject::sTODefaultCtorCount == 5);\n\t\tEATEST_VERIFY(endIter == (pTestMemory + 5));\n\t}\n\n\t// uninitialized_value_construct\n\t{\n\t\tTestObject::Reset();\n\t\tchar testCharArray[sizeof(TestObject) * 10];\n\t\tTestObject* pTestMemory = (TestObject*)(testCharArray);\n\n\t\teastl::uninitialized_value_construct(pTestMemory, pTestMemory + 10);\n\t\tEATEST_VERIFY(TestObject::sTODefaultCtorCount == 10);\n\n\t\tint intArray[] = { 3, 2, 6, 5, 4, 1 };\n\t\tuninitialized_value_construct(intArray, intArray + 6);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"uninitialized_value_construct\", 0, 0, 0, 0, 0, 0, -1));\n\t}\n\n\t// uninitialized_value_construct_n\n\t{\n\t\tTestObject::Reset();\n\t\tchar testCharArray[sizeof(TestObject) * 10];\n\t\tTestObject* pTestMemory = (TestObject*)(testCharArray);\n\n\t\tauto endIter = eastl::uninitialized_value_construct_n(pTestMemory, 5);\n\t\tEATEST_VERIFY(TestObject::sTODefaultCtorCount == 5);\n\t\tEATEST_VERIFY(endIter == (pTestMemory + 5));\n\n\t\tint intArray[] = { 3, 2, 6, 5, 4, 1 };\n\t\tuninitialized_value_construct_n(intArray, 6);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"uninitialized_value_construct_n\", 0, 0, 0, 0, 0, 0, -1));\n\t}\n\n\t// Verify that uninitialized_value_construct does not do any additional initialization besides zero-initialization.\n\t//\n\t/// Value-Initialization:\n\t//   If T is a class, the object is default-initialized (after being zero-initialized if T's default \n\t//   constructor is not user-provided/deleted); otherwise, the object is zero-initialized.\n\t{\n\t\tstruct foo\n\t\t{\n\t\t\t// foo() = default; // intentionally removed to force zero-initialization behavior \n\t\t\tchar mV;\n\t\t};\n\n\t\tstatic const int ARRAY_SIZE_IN_BYTES = sizeof(foo) * 10;\n\n\t\tchar testCharArray[ARRAY_SIZE_IN_BYTES];\n\t\tEA::StdC::Memfill8(testCharArray, 42, ARRAY_SIZE_IN_BYTES);\n\t\tfoo* pTestMemory = (foo*)testCharArray;\n\n\t\teastl::uninitialized_value_construct(pTestMemory, pTestMemory + 10);\n\n\t\tfor (int i = 0; i < 10; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(pTestMemory[i].mV == 0); // verify that memory is zero-initialized\n\t\t}\n\t}\n\n\t// Verify that uninitialized_default_construct does not do any additional initialization besides the calling of a empty\n\t// constructor.\n\t//\n\t// Default-initialization:\n\t//  If T is a class, the default constructor is called; otherwise, no initialization is done, resulting in\n\t//  indeterminate values.\n\t{\n\t\tstruct foo\n\t\t{\n\t\t\tfoo() {}  // default ctor intentionally a no-op\n\t\t\tchar mV;\n\t\t};\n\n\t\tstatic const int ARRAY_SIZE_IN_BYTES = sizeof(foo) * 10;\n\n\t\tchar testCharArray[ARRAY_SIZE_IN_BYTES];\n\t\tEA::StdC::Memfill8(testCharArray, 42, ARRAY_SIZE_IN_BYTES);\n\t\tfoo* pTestMemory = (foo*)testCharArray;\n\n\t\teastl::uninitialized_default_construct(pTestMemory, pTestMemory + 10);\n\n\t\tfor (int i = 0; i < 10; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(pTestMemory[i].mV == 42); // verify original memset value is intact \n\t\t}\n\t}\n\n\t{\n\t\t// uninitialized_move\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 1, 2, 3, 4, 5, 6 };\n\n\t\tuninitialized_move(intArray2, intArray2 + 6, intArray1);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"uninitialized_move\", 1, 2, 3, 4, 5, 6, -1));\n\t}\n\n\t{\n\t\t// uninitialized_move_n\n\n\t\tint intArray1[] = { 3, 2, 6, 5, 4, 1 };\n\t\tint intArray2[] = { 1, 2, 3, 4, 5, 6 };\n\n\t\tuninitialized_move_n(intArray2, 6, intArray1);\n\t\tEATEST_VERIFY(VerifySequence(intArray1, intArray1 + 6, int(), \"uninitialized_move_n\", 1, 2, 3, 4, 5, 6, -1));\n\t}\n\n\t// template <typename T>\n\t// void destruct(T* p)\n\t{\n\t\tTestObject::Reset();\n\t\tuint64_t testObjectMemory[((sizeof(TestObject) / sizeof(uint64_t)) + 1) * 2];\n\n\t\tTestObject* pTestObject = new(testObjectMemory) TestObject;\n\t\tdestruct(pTestObject);\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t}\n\n\t// template <typename T>\n\t// void destroy_at(T* p)\n\t{\n\t\tTestObject::Reset();\n\t\tuint64_t testObjectMemory[((sizeof(TestObject) / sizeof(uint64_t)) + 1) * 2];\n\t\tTestObject* pTestObject = new(testObjectMemory) TestObject;\n\t\tdestroy_at(pTestObject);\n\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t}\n\n\n\t// template <typename ForwardIterator>\n\t// void destruct(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tTestObject::Reset();\n\t\tchar testObjectMemory[sizeof(TestObject) * 3];\n\t\tTestObject* pTestObject = new(testObjectMemory) TestObject[2];\n\t\tdestruct(pTestObject, pTestObject + 2);\n\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t}\n\n\t// template <typename ForwardIterator>\n\t// void destroy(ForwardIterator first, ForwardIterator last)\n\t{\n\t\tTestObject::Reset();\n\t\tchar testObjectMemory[sizeof(TestObject) * 3];\n\t\tTestObject* pTestObject = new(testObjectMemory) TestObject[2];\n\t\tdestroy(pTestObject, pTestObject + 2);\n\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t}\n\n\t// template <typename ForwardIterator, typename Size>\n\t// void destroy_n(ForwardIterator first, Size n)\n\t{\n\t\tTestObject::Reset();\n\t\tchar testObjectMemory[sizeof(TestObject) * 3];\n\t\tTestObject* pTestObject = new (testObjectMemory) TestObject[2];\n\n\t\tdestroy_n(pTestObject, 1);     // destroy TestObject[0]\n\t\tdestroy_n(pTestObject + 1, 1); // destroy TestObject[1]\n\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t}\n\n\n\t{\n\t\t// Regression for user reported operator new problem (12/8/2009):\n\t\teastl::vector<AssetHandler> ahArray;\n\t\tahArray.push_back(AssetHandler());\n\t}\n\n\n\t// void* align(size_t alignment, size_t size, void*& ptr, size_t& space);\n\t// void* align_advance(size_t alignment, size_t size, void*& ptr, size_t& space);\n\t{\n\t\tconst  size_t kBufferSize = 256;\n\t\tchar   buffer[kBufferSize * 2];\n\t\tsize_t space = sizeof(buffer);\n\t\tvoid*  ptr = buffer;\n\t\tvoid*  ptrSaved;\n\t\tvoid*  ptrAligned;\n\t\tsize_t i;\n\n\t\t// First get 256 bytes of space aligned to 256.\n\t\t// It's a coincidence that we are using eastl::align to set up a buffer for testing eastl::align below.\n\t\tptrSaved = eastl::align(256, 256, ptr, space);\n\n\t\t// At this point we have 256 bytes of memory aligned on 256 bytes, within buffer.\n\t\t// We test allocating multiple blocks from this space at various alignments values.\n\t\t// We also test that the function sets ptr to the next available location after the \n\t\t// returned allocated block.\n\t\tEA::StdC::Memset8(buffer, 0x00, sizeof(buffer));\n\t\tEATEST_VERIFY(EA::StdC::IsAligned(ptr, 256));\n\n\t\t// align test\n\t\t// Try a number of allocation sizes.\n\t\tfor(size_t a = 1; a < 64; a *= 2)\n\t\t{\n\t\t\t// Do multiple sequental allocations from the storage.\n\t\t\tfor(i = 0, space = 256, ptr = ptrSaved; i < kBufferSize; i += a)\n\t\t\t{\n\t\t\t\tptrAligned = eastl::align(a, a, ptr, space);\n\n\t\t\t\tEATEST_VERIFY((uintptr_t)ptrAligned == ((uintptr_t)ptrSaved + i));\n\t\t\t\tEATEST_VERIFY(ptr                   == ptrAligned);\n\t\t\t\tEATEST_VERIFY(space                 == (kBufferSize - i));\n\t\t\t\tEATEST_VERIFY(EA::StdC::IsAligned(ptrAligned, a));\n\t\t\t\tEATEST_VERIFY(EA::StdC::Memcheck8(ptrAligned, 0x00, a) == NULL);\n\n\t\t\t\tptr    = (char*)ptr + a;\n\t\t\t\tspace -= a;\n\t\t\t\tmemset(ptrAligned, 0xff, a); // Do this so that next time around we can verify this memory isn't returned.\n\t\t\t}\n\n\t\t\tEA::StdC::Memset8(buffer, 0x00, sizeof(buffer));\n\t\t}\n\n\t\t// align_advance test (similar to but not identical to the align test)\n\t\t// Try a number of allocation sizes.\n\t\tfor(size_t a = 1; a < 64; a *= 2)\n\t\t{\n\t\t\t// Do multiple sequental allocations from the storage.\n\t\t\tfor(i = 0, space = 256, ptr = ptrSaved; i < kBufferSize; i += a)\n\t\t\t{\n\t\t\t\tptrAligned = eastl::align_advance(a, a, ptr, space, &ptr, &space);\n\n\t\t\t\tEATEST_VERIFY((uintptr_t)ptrAligned == ((uintptr_t)ptrSaved + i));\n\t\t\t\tEATEST_VERIFY((uintptr_t)ptr        == (uintptr_t)ptrAligned + a);\n\t\t\t\tEATEST_VERIFY(space                 == (kBufferSize - i) - a);\n\t\t\t\tEATEST_VERIFY(EA::StdC::IsAligned(ptrAligned, a));\n\t\t\t\tEATEST_VERIFY(EA::StdC::Memcheck8(ptrAligned, 0x00, a) == NULL);\n\n\t\t\t\tmemset(ptrAligned, 0xff, a); // Do this so that next time around we can verify this memory isn't returned.\n\t\t\t}\n\n\t\t\tEA::StdC::Memset8(buffer, 0x00, sizeof(buffer));\n\t\t}\n\t}\n\n\t// to_address\n\t{\n\t\t// Normal pointers.\n\t\tint a;\n\t\tint* ptrA = &a;\n\t\tEATEST_VERIFY(ptrA == to_address(ptrA));\n\n\t\t// Smart pointer.\n\t\tstruct MockSmartPointer\n\t\t{\n\t\t\tconst int* operator->() const\n\t\t\t{\n\t\t\t\treturn &a;\n\t\t\t}\n\n\t\t\tint a = 42;\n\t\t};\n\n\t\tMockSmartPointer sp;\n\t\tEATEST_VERIFY(&sp.a == to_address(sp));\n\n\t\t// Type with specialized pointer_traits.\n\t\tTypeWithPointerTraits t;\n\t\tconst int* result = to_address(t);\n\t\tEATEST_VERIFY(result != nullptr && *result == 42);\n\t}\n\n\t{\n\t\t// Test that align handles integral overflow correctly and returns NULL.\n\t\tvoid*  ptr;\n\t\tvoid*  ptrSaved;\n\t\tsize_t space;\n\t\tvoid*  pResult;\n\n\t\tspace    = 64;\n\t\tptr      = 0;\n\t\tptr      = (void*)((uintptr_t)ptr - (uintptr_t)space);\n\t\tptrSaved = ptr;\n\t\tpResult  = eastl::align(1, space + 1, ptr, space);             // Possible alignment, impossible size due to wraparound.\n\t\tEATEST_VERIFY((pResult == NULL) && (ptr == ptrSaved));\n\n\t\tspace    = 64;\n\t\tptr      = 0;\n\t\tptr      = (void*)((uintptr_t)ptr - (uintptr_t)space);\n\t\tptrSaved = ptr;\n\t\tpResult  = eastl::align(space * 2, 32, ptr, space);            // Impossible alignment due to wraparound, possible size.\n\t\tEATEST_VERIFY((pResult == NULL) && (ptr == ptrSaved));\n\t}\n\n\t{\n\t\tnErrorCount += TestValueInitOptimization<int>();\n\t\tnErrorCount += TestValueInitOptimization<char>();\n\t\tnErrorCount += TestValueInitOptimization<short>();\n\t\tnErrorCount += TestValueInitOptimization<float>();\n\t\tnErrorCount += TestValueInitOptimization<double>();\n\t\tnErrorCount += TestValueInitOptimization<void*>();\n\t}\n\n\tEATEST_VERIFY(nErrorCount == 0);\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestMeta.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n\n#ifdef EA_COMPILER_CPP14_ENABLED\n#include \"ConceptImpls.h\"\n#include <EASTL/meta.h>\n\n\nint TestGetTypeIndex()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tstatic_assert(meta::get_type_index_v<short, short, char, int> == 0, \"error\");\n\tstatic_assert(meta::get_type_index_v<char, short, char, int> == 1, \"error\");\n\tstatic_assert(meta::get_type_index_v<int, short, char, int> == 2, \"error\");\n\tstatic_assert(meta::get_type_index_v<int, int, int, int> == 0, \"error\");\n\n\treturn nErrorCount;\n}\n\nint TestGetType()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tstatic_assert(is_same_v<meta::get_type_at_t<2, short, short, char, int>, char>, \"error\");\n\tstatic_assert(is_same_v<meta::get_type_at_t<3, char, short, char, int>, int>, \"error\");\n\t// static_assert(is_same_v<meta::get_type_at_t<4, int, short, char, int>, int>, \"error\");\n\tstatic_assert(is_same_v<meta::get_type_at_t<1, int, int, int, int>, int>, \"error\");\n\n\treturn nErrorCount;\n}\n\nint TestTypeCount()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tstatic_assert(meta::type_count_v<short, short, char, int> == 1, \"error\");\n\tstatic_assert(meta::type_count_v<char, short, char, int> == 1, \"error\");\n\tstatic_assert(meta::type_count_v<int, short, char, int> == 1, \"error\");\n\tstatic_assert(meta::type_count_v<int, int, int, int> == 3, \"error\");\n\tstatic_assert(meta::type_count_v<int, int, int, int, int, int, int, int, int> == 8, \"error\");\n\tstatic_assert(meta::type_count_v<int, int, int, int, char, int, int, int, int> == 7, \"error\");\n\tstatic_assert(meta::type_count_v<int, int, char, int, char, int, int, int, int> == 6, \"error\");\n\tstatic_assert(meta::type_count_v<int, int, char, int, char, int, int, int, char> == 5, \"error\");\n\tstatic_assert(meta::type_count_v<int, int, char, int, char, int, const int, int, char> == 4, \"error\");\n\tstatic_assert(meta::type_count_v<int, volatile int, char, int, char, int, const int, const volatile int, char> == 2, \"error\");\n\n\treturn nErrorCount;\n}\n\nint TestDuplicateTypeCheck()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tstatic_assert( meta::duplicate_type_check_v<short, short, char, int>, \"error\");\n\tstatic_assert( meta::duplicate_type_check_v<short, short, char, int, long, unsigned, long long>, \"error\");\n\tstatic_assert( meta::duplicate_type_check_v<int, const int, volatile int, const volatile int, int>, \"error\");\n\tstatic_assert(!meta::duplicate_type_check_v<short, short, char, int, long, unsigned, short, long long>, \"error\");\n\n\treturn nErrorCount;\n}\n\nint TestOverloadResolution()\n{\n\tusing namespace eastl;\n\tusing namespace eastl::meta;\n\n\tint nErrorCount = 0;\n\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<int>>, int>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<short>>, short>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<long>>, long>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<short, overload_set<int>>, int>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<int, short, long>>, int>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<short, int, long, float>>, int>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<short, long, int, float, char>>, int>, \"error\");\n\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<int>>, int>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<int, short>>, int>, \"error\");\n\tstatic_assert(is_same_v<overload_resolution_t<int, overload_set<int, short, long>>, int>, \"error\");\n\n\treturn nErrorCount;\n}\n\n\nint TestMeta()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestGetTypeIndex();\n\tnErrorCount += TestGetType();\n\tnErrorCount += TestTypeCount();\n\tnErrorCount += TestDuplicateTypeCheck();\n\tnErrorCount += TestOverloadResolution();\n\n\treturn nErrorCount;\n}\n\n#endif // EA_COMPILER_CPP14_ENABLED\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestNumericLimits.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/numeric_limits.h>\n#include <EASTL/numeric.h>\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestNumericLimits\n//\nint TestNumericLimits()\n{\n\tint nErrorCount = 0;\n\n\t// To consider: Some day when we get more time, make a big table-driven set of \n\t// expected results to all member variables and function calls.\n\n\t// Test bool in all const-volatile variants.\n\tEATEST_VERIFY(eastl::numeric_limits<bool>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<bool>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<const bool>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<const bool>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<volatile bool>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<volatile bool>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<const volatile bool>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<const volatile bool>::max() != 0);\n\n\t// Do basic tests of the remaining types.\n\tEATEST_VERIFY(eastl::numeric_limits<char>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<char>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned char>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned char>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<signed char>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<signed char>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<wchar_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<wchar_t>::max() != 0);\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\tEATEST_VERIFY(eastl::numeric_limits<char8_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<char8_t>::max() != 0);\n\t#endif\n\n\tEATEST_VERIFY(eastl::numeric_limits<char16_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<char16_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<char32_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<char32_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned short>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned short>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<signed short>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<signed short>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned int>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned int>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<signed int>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<signed int>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned long>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned long>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<signed long>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<signed long>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned long long>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<unsigned long long>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<signed long long>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<signed long long>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<float>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<float>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<double>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<double>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<long double>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<long double>::max() != 0);\n\n\t// We don't yet have a generic global way to identify what the name of the supported 128 bit type is. \n\t// We just happen to know that for gcc/clang it is __int128.\n\t#if (EA_COMPILER_INTMAX_SIZE >= 16) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) // If __int128_t/__uint128_t is supported...\n\t\tEATEST_VERIFY(eastl::numeric_limits<__uint128_t>::is_bounded);\n\t\tEATEST_VERIFY(eastl::numeric_limits<__uint128_t>::max() != 0);\n\n\t\tEATEST_VERIFY(eastl::numeric_limits<__int128_t>::is_bounded);\n\t\tEATEST_VERIFY(eastl::numeric_limits<__int128_t>::max() != 0);\n\t#endif\n\n\t// Test sized types.\n\tEATEST_VERIFY(eastl::numeric_limits<uint8_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<uint8_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<int8_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<int8_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<uint16_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<uint16_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<int16_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<int16_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<uint32_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<uint32_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<int32_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<int32_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<uint64_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<uint64_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::numeric_limits<int64_t>::is_bounded);\n\tEATEST_VERIFY(eastl::numeric_limits<int64_t>::max() != 0);\n\n\tEATEST_VERIFY(eastl::isnan(eastl::numeric_limits<float>::quiet_NaN()));\n\tEATEST_VERIFY(eastl::isnan(eastl::numeric_limits<float>::signaling_NaN()));\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestOptional.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/type_traits.h>\n#include <EASTL/sort.h>\n#include <EASTL/vector.h>\n#include <EASTL/string.h>\n#include <EASTL/optional.h>\n#include <EASTL/unique_ptr.h>\n\n/////////////////////////////////////////////////////////////////////////////\nstruct IntStruct\n{\n\tIntStruct(int in) : data(in) {}\n\tint data;\n};\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\nauto operator<=>(const IntStruct& lhs, const IntStruct& rhs) { return lhs.data <=> rhs.data; }\n#else\nbool operator<(const IntStruct& lhs, const IntStruct& rhs)\n\t{ return lhs.data < rhs.data; }\n#endif\nbool operator==(const IntStruct& lhs, const IntStruct& rhs)\n\t{ return lhs.data == rhs.data; }\n\n\n\n/////////////////////////////////////////////////////////////////////////////\nstruct destructor_test\n{\n\t~destructor_test() { destructor_ran = true; }\n\tstatic bool destructor_ran;\n\tstatic void reset() { destructor_ran = false; }\n};\nbool destructor_test::destructor_ran = false;\n\n/////////////////////////////////////////////////////////////////////////////\nstruct copy_test\n{\n\tcopy_test() = default;\n\n\tcopy_test(const copy_test& ct)\n\t{\n\t\twas_copied = true;\n\t\tvalue = ct.value;\n\t}\n\n\tcopy_test& operator=(const copy_test& ct)\n\t{\n\t\twas_copied = true;\n\t\tvalue = ct.value;\n\n\t\treturn *this;\n\t}\n\n\t// issue a compiler error if container tries to move\n\tcopy_test(copy_test const&&) = delete;\n\tcopy_test& operator=(const copy_test&&) = delete;\n\n\tstatic bool was_copied;\n\n\tint value;\n};\n\nbool copy_test::was_copied = false;\n\n/////////////////////////////////////////////////////////////////////////////\nstruct move_test\n{\n\tmove_test() = default;\n\n\tmove_test(move_test&& mt)\n\t{\n\t\twas_moved = true;\n\t\tvalue = mt.value;\n\t}\n\n\tmove_test& operator=(move_test&& mt)\n\t{\n\t\twas_moved = true;\n\t\tvalue = mt.value;\n\n\t\treturn *this;\n\t}\n\n\t// issue a compiler error if container tries to copy\n\tmove_test(move_test const&) = delete;\n\tmove_test& operator=(const move_test&) = delete;\n\n\tstatic bool was_moved;\n\n\tint value;\n};\n\nbool move_test::was_moved = false;\n\n/////////////////////////////////////////////////////////////////////////////\ntemplate <typename T>\nclass forwarding_test\n{\n\teastl::optional<T> m_optional;\n\npublic:\n\tforwarding_test() : m_optional() {}\n\tforwarding_test(T&& t) : m_optional(t) {}\n\t~forwarding_test() { m_optional.reset(); }\n\n\ttemplate <typename U>\n\tT GetValueOrDefault(U&& def) const\n\t{\n\t\treturn m_optional.value_or(eastl::forward<U>(def));\n\t}\n};\n\n/////////////////////////////////////////////////////////////////////////////\nstruct assignment_test\n{\n\tassignment_test()                                  { ++num_objects_inited; }\n\tassignment_test(assignment_test&&)                 { ++num_objects_inited; }\n\tassignment_test(const assignment_test&)            { ++num_objects_inited; }\n\tassignment_test& operator=(assignment_test&&)      { return *this; }\n\tassignment_test& operator=(const assignment_test&) { return *this; }\n\t~assignment_test()                                 { --num_objects_inited; }\n\n\tstatic int num_objects_inited;\n};\n\nint assignment_test::num_objects_inited = 0;\n\nstatic int TestOptional_MonadicOperations()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n#if defined(EASTL_OPTIONAL_ENABLED) && EASTL_OPTIONAL_ENABLED\n\t// and_then l-value ref\n\t{\n\t\t{\n\t\t\toptional<int> o{42};\n\t\t\tauto result = o.and_then(\n\t\t\t\t[](int& x)\n\t\t\t\t{\n\t\t\t\t\tconst int old_x = eastl::exchange(x, 1337);\n\t\t\t\t\treturn make_optional(to_string(old_x));\n\t\t\t\t});\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(*o == 1337);\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\toptional<int> o;\n\t\t\tauto result = o.and_then(\n\t\t\t\t[&called](int& x)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn make_optional(to_string(x));\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o{42};\n\t\t\tauto result = o.and_then(\n\t\t\t\t[](int& x) -> optional<string>\n\t\t\t\t{\n\t\t\t\t\tx = 1337;\n\t\t\t\t\treturn nullopt;\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(*o == 1337);\n\t\t}\n\t}\n\n\t// and_then const l-value ref\n\t{\n\t\t{\n\t\t\tconst optional<int> o{42};\n\t\t\tauto result = o.and_then([](const int& x) { return make_optional(to_string(x)); });\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(*o == 42);\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\tconst optional<int> o;\n\t\t\tauto result = o.and_then(\n\t\t\t\t[&called](const int& x)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn make_optional(to_string(x));\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\tconst optional<int> o{42};\n\t\t\tauto result = o.and_then([](const int&) -> optional<string> { return nullopt; });\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(*o == 42);\n\t\t}\n\t}\n\n\t// and_then r-value ref\n\t{\n\t\t{\n\t\t\toptional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).and_then([](auto ptr) { return make_optional(to_string(*ptr)); });\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(o.value() == nullptr); // o should be moved-from.\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\toptional<unique_ptr<int>> o;\n\t\t\tauto result = eastl::move(o).and_then(\n\t\t\t\t[&called](auto ptr)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn make_optional(to_string(*ptr));\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\toptional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).and_then([](auto ptr) -> optional<string> { return nullopt; });\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(o.value() == nullptr); // o should be moved-from.\n\t\t}\n\t}\n\n\t// and_then const r-value ref\n\t{\n\t\t{\n\t\t\tconst optional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result =\n\t\t\t\teastl::move(o).and_then([](const unique_ptr<int>&& ptr) { return make_optional(to_string(*ptr)); });\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(o.value() != nullptr);\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\tconst optional<unique_ptr<int>> o;\n\t\t\tauto result = eastl::move(o).and_then(\n\t\t\t\t[&called](const unique_ptr<int>&& ptr)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn make_optional(to_string(*ptr));\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\tconst optional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result =\n\t\t\t\teastl::move(o).and_then([](const unique_ptr<int>&&) -> optional<string> { return nullopt; });\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(o.value() != nullptr);\n\t\t}\n\t}\n\n\t// transform l-value ref\n\t{\n\t\t{\n\t\t\toptional<int> o{42};\n\t\t\tauto result = o.transform(\n\t\t\t\t[](int& x)\n\t\t\t\t{\n\t\t\t\t\tconst int old_x = eastl::exchange(x, 1337);\n\t\t\t\t\treturn to_string(old_x);\n\t\t\t\t});\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(*o == 1337);\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\toptional<int> o;\n\t\t\tauto result = o.transform(\n\t\t\t\t[&called](int& x)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn to_string(x);\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\t// Check that the return type of the callable gets remove_cvref_t.\n\t\t\teastl::string externalString = \"Jean Guegant was here\";\n\n\t\t\toptional<int> o{42};\n\t\t\tauto result = o.transform([&externalString](int&) -> const eastl::string& { return externalString; });\n\n\t\t\tstatic_assert(eastl::is_same_v<decltype(result), optional<eastl::string>>,\n\t\t\t\t\t\t  \"Wrong return type for transform.\");\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == externalString);\n\t\t}\n\t}\n\n\t// transform const l-value ref\n\t{\n\t\t{\n\t\t\tconst optional<int> o{42};\n\t\t\tauto result = o.transform([](const int& x) { return to_string(x); });\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\tconst optional<int> o;\n\t\t\tauto result = o.transform(\n\t\t\t\t[&called](const int& x)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn to_string(x);\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\t// Check that the return type of the callable gets remove_cvref_t.\n\t\t\teastl::string externalString = \"Jean Guegant was here\";\n\n\t\t\tconst optional<int> o{42};\n\t\t\tauto result =\n\t\t\t\to.transform([&externalString](const int&) -> const eastl::string& { return externalString; });\n\n\t\t\tstatic_assert(eastl::is_same_v<decltype(result), optional<eastl::string>>,\n\t\t\t\t\t\t  \"Wrong return type for transform.\");\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == externalString);\n\t\t}\n\t}\n\n\t// transform r-value ref\n\t{\n\t\t{\n\t\t\toptional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).transform([](auto ptr) { return to_string(*ptr); });\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(*o == nullptr); // o should be moved-from.\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\toptional<unique_ptr<int>> o;\n\t\t\tauto result = eastl::move(o).transform(\n\t\t\t\t[&called](auto ptr)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn to_string(*ptr);\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\t// Check that the return type of the callable gets remove_cvref_t.\n\t\t\teastl::string externalString = \"Jean Guegant was here\";\n\n\t\t\toptional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).transform([&externalString](auto ptr) -> const eastl::string&\n\t\t\t\t\t\t\t\t\t\t\t\t   { return externalString; });\n\n\t\t\tstatic_assert(eastl::is_same_v<decltype(result), optional<eastl::string>>,\n\t\t\t\t\t\t  \"Wrong return type for transform.\");\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == externalString);\n\t\t}\n\t}\n\n\t// transform const r-value ref\n\t{\n\t\t{\n\t\t\tconst optional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).transform([](const unique_ptr<int>&& ptr) { return to_string(*ptr); });\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == string_view(\"42\"));\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(*o != nullptr);\n\t\t}\n\n\t\t{\n\t\t\t// Ensuring that the callable is not called when optional is empty.\n\t\t\tbool called = false;\n\t\t\tconst optional<unique_ptr<int>> o;\n\t\t\tauto result = eastl::move(o).transform(\n\t\t\t\t[&called](const unique_ptr<int>&& ptr)\n\t\t\t\t{\n\t\t\t\t\tcalled = true;\n\t\t\t\t\treturn to_string(*ptr);\n\t\t\t\t});\n\t\t\tVERIFY(!result.has_value());\n\t\t\tVERIFY(!o.has_value());\n\t\t\tVERIFY(!called);\n\t\t}\n\n\t\t{\n\t\t\t// Check that the return type of the callable gets remove_cvref_t.\n\t\t\teastl::string externalString = \"Jean Guegant was here\";\n\n\t\t\tconst optional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).transform(\n\t\t\t\t[&externalString](const unique_ptr<int>&&) -> const eastl::string& { return externalString; });\n\n\t\t\tstatic_assert(eastl::is_same_v<decltype(result), optional<eastl::string>>,\n\t\t\t\t\t\t  \"Wrong return type for transform.\");\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result == externalString);\n\t\t}\n\t}\n\n\t// or_else const l-value ref\n\t{\n\t\t{\n\t\t\tconst optional<int> o{42};\n\t\t\tauto result = o.or_else([]() { return eastl::make_optional(1337); });\n\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(result.value() == 42);\n\t\t}\n\n\t\t{\n\t\t\tconst optional<int> o;\n\t\t\tauto result = o.or_else([]() { return eastl::make_optional(1337); });\n\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(result.value() == 1337);\n\t\t}\n\n\t\t{\n\t\t\t// Ensure that we can return refs from the callable that get copied.\n\t\t\teastl::optional<int> externalOptional{1337};\n\n\t\t\tconst optional<int> o;\n\t\t\tauto result = o.or_else([&externalOptional]() -> const eastl::optional<int>& { return externalOptional; });\n\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(result.value() == 1337);\n\t\t}\n\t}\n\n\t// or_else const l-value ref\n\t{\n\t\t{\n\t\t\toptional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).or_else([]() { return eastl::make_optional(eastl::make_unique<int>(1337)); });\n\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(o.value() == nullptr); // o should be moved-from.\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result.value() == 42);\n\t\t}\n\n\t\t{\n\t\t\toptional<unique_ptr<int>> o;\n\t\t\tauto result = eastl::move(o).or_else([]() { return eastl::make_optional(eastl::make_unique<int>(1337)); });\n\n\t\t\tVERIFY(result.has_value());\n\t\t\tVERIFY(*result.value() == 1337);\n\t\t}\n\t}\n#endif\n\t\n\treturn nErrorCount;\n}\n\t\t\n\n\n/////////////////////////////////////////////////////////////////////////////\n// TestOptional\n//\nint TestOptional()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\t#if defined(EASTL_OPTIONAL_ENABLED) && EASTL_OPTIONAL_ENABLED\n\t{\n\t\t{\n\t\t\tVERIFY( (is_same<optional<int>::value_type, int>::value));\n\t\t\tVERIFY( (is_same<optional<short>::value_type, short>::value));\n\t\t\tVERIFY(!(is_same<optional<short>::value_type, long>::value));\n\t\t\tVERIFY( (is_same<optional<const short>::value_type, const short>::value));\n\t\t\tVERIFY( (is_same<optional<volatile short>::value_type, volatile short>::value));\n\t\t\tVERIFY( (is_same<optional<const volatile short>::value_type, const volatile short>::value));\n\n\t\t\tVERIFY(is_empty<nullopt_t>::value);\n\n\t\t\t#if EASTL_TYPE_TRAIT_is_trivially_destructible_CONFORMANCE\n\t\t\t\tVERIFY(is_trivially_destructible<int>::value);\n\t\t\t\tVERIFY(is_trivially_destructible<Internal::optional_storage<int>>::value);\n\t\t\t\tVERIFY(is_trivially_destructible<optional<int>>::value);\n\t\t\t\tVERIFY(is_trivially_destructible<optional<int>>::value == is_trivially_destructible<int>::value);\n\t\t\t#endif\n\n\t\t\t{\n\t\t\t\tstruct NotTrivialDestructible { ~NotTrivialDestructible() {} };\n\t\t\t\tVERIFY(!is_trivially_destructible<NotTrivialDestructible>::value);\n\t\t\t\tVERIFY(!is_trivially_destructible<optional<NotTrivialDestructible>>::value);\n\t\t\t\tVERIFY(!is_trivially_destructible<Internal::optional_storage<NotTrivialDestructible>>::value);\n\t\t\t\tVERIFY(is_trivially_destructible<optional<NotTrivialDestructible>>::value == is_trivially_destructible<NotTrivialDestructible>::value);\n\t\t\t}\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\t// test special member functions are enabled/disabled based on the contained type.\n\t\t\t{\n\t\t\t\t// copy / move constructor & assignment are deleted for this type.\n\t\t\t\tstatic_assert(!is_copy_constructible_v<optional<NoCopyMove>>, \"!copy constructible\");\n\t\t\t\tstatic_assert(!is_copy_assignable_v<optional<NoCopyMove>>, \"!copy assignable\");\n\t\t\t\tstatic_assert(!is_move_constructible_v<optional<NoCopyMove>>, \"!move constructible\");\n\t\t\t\tstatic_assert(!is_move_assignable_v<optional<NoCopyMove>>, \"!move assignable\");\n\n\t\t\t\t// copy constructor is enabled and trivial if T is copy constructible.\n\t\t\t\tstatic_assert(is_copy_constructible_v<optional<TriviallyCopyableWithCopyCtor>>, \"copy constructible\");\n\t\t\t\tstatic_assert(is_trivially_copy_constructible_v<optional<TriviallyCopyableWithCopyCtor>>, \"trivially copy constructible\");\n\t\t\t\tstatic_assert(!is_copy_assignable_v<optional<TriviallyCopyableWithCopyCtor>>, \"!copy assignable\");\n\t\t\t\tstatic_assert(is_move_constructible_v<optional<TriviallyCopyableWithCopyCtor>>, \"move constructible\"); // invokes copy constructor. therefore true.\n\t\t\t\tstatic_assert(is_trivially_move_constructible_v<optional<TriviallyCopyableWithCopyCtor>>, \"trivially move constructible\"); // invokes copy constructor. therefore true.\n\t\t\t\tstatic_assert(!is_move_assignable_v<optional<TriviallyCopyableWithCopyCtor>>, \"!move assignable\");\n\n\t\t\t\t// copy assignment is not enabled unless T is both copy constructible and assignable.\n\t\t\t\tstatic_assert(!is_copy_constructible_v<optional<TriviallyCopyableWithCopyAssign>>, \"!copy constructible\");\n\t\t\t\tstatic_assert(!is_copy_assignable_v<optional<TriviallyCopyableWithCopyAssign>>, \"!copy assignable\");\n\t\t\t\tstatic_assert(!is_move_constructible_v<optional<TriviallyCopyableWithCopyAssign>>, \"!move constructible\");\n\t\t\t\tstatic_assert(!is_move_assignable_v<optional<TriviallyCopyableWithCopyAssign>>, \"!move assignable\");\n\n\t\t\t\t// move constructor is enabled and trivial if T is move constructible.\n\t\t\t\tstatic_assert(!is_copy_constructible_v<optional<TriviallyCopyableWithMoveCtor>>, \"!copy constructible\");\n\t\t\t\tstatic_assert(!is_copy_assignable_v<optional<TriviallyCopyableWithMoveCtor>>, \"!copy assignable\");\n\t\t\t\tstatic_assert(is_move_constructible_v<optional<TriviallyCopyableWithMoveCtor>>, \"move constructible\");\n\t\t\t\tstatic_assert(is_trivially_move_constructible_v<optional<TriviallyCopyableWithMoveCtor>>, \"trivially move constructible\");\n\t\t\t\tstatic_assert(!is_move_assignable_v<optional<TriviallyCopyableWithMoveCtor>>, \"!move assignable\");\n\n\t\t\t\t// move assignment is not enabled unless T is both move constructible and assignable.\n\t\t\t\tstatic_assert(!is_copy_constructible_v<optional<TriviallyCopyableWithMoveAssign>>, \"!copy constructible\");\n\t\t\t\tstatic_assert(!is_copy_assignable_v<optional<TriviallyCopyableWithMoveAssign>>, \"!copy assignable\");\n\t\t\t\tstatic_assert(!is_move_constructible_v<optional<TriviallyCopyableWithMoveAssign>>, \"!move constructible\");\n\t\t\t\tstatic_assert(!is_move_assignable_v<optional<TriviallyCopyableWithMoveAssign>>, \"!move assignable\");\n\n\t\t\t\t// copy / move constructor & assignment are all defined for this type, but non-trivial.\n\t\t\t\tstatic_assert(is_copy_constructible_v<optional<NonTriviallyCopyable>>, \"copy constructible\");\n\t\t\t\tstatic_assert(!is_trivially_copy_constructible_v<optional<NonTriviallyCopyable>>, \"!trivially copy constructible\");\n\t\t\t\tstatic_assert(is_copy_assignable_v<optional<NonTriviallyCopyable>>, \"copy assignable\");\n\t\t\t\tstatic_assert(!is_trivially_copy_assignable_v<optional<NonTriviallyCopyable>>, \"!trivially copy assignable\");\n\t\t\t\tstatic_assert(is_move_constructible_v<optional<NonTriviallyCopyable>>, \"move constructible\"); // invokes copy constructor. therefore true.\n\t\t\t\tstatic_assert(!is_trivially_move_constructible_v<optional<NonTriviallyCopyable>>, \"!trivially move constructible\");\n\t\t\t\tstatic_assert(is_move_assignable_v<optional<NonTriviallyCopyable>>, \"move assignable\"); // invokes copy assignment. therefore true.\n\t\t\t\tstatic_assert(!is_trivially_move_assignable_v<optional<NonTriviallyCopyable>>, \"!trivially move assignable\");\n\n\t\t\t\t// move constructor & assignment are all defined for this type, but non-trivial.\n\t\t\t\tstatic_assert(!is_copy_constructible_v<optional<MoveOnlyType>>, \"copy constructible\");\n\t\t\t\tstatic_assert(!is_copy_assignable_v<optional<MoveOnlyType>>, \"copy assignable\");\n\t\t\t\tstatic_assert(is_move_constructible_v<optional<MoveOnlyType>>, \"move constructible\");\n\t\t\t\tstatic_assert(!is_trivially_move_constructible_v<optional<MoveOnlyType>>, \"!trivially move constructible\");\n\t\t\t\tstatic_assert(is_move_assignable_v<optional<MoveOnlyType>>, \"move assignable\");\n\t\t\t\tstatic_assert(!is_trivially_move_assignable_v<optional<MoveOnlyType>>, \"!trivially move assignable\");\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tstatic_assert(is_convertible_v<optional<uint32_t>, optional<int32_t>>, \"convertible\");\n\t\t\t\tstatic_assert(is_convertible_v<optional<char*>, optional<void*>>, \"convertible\");\n\t\t\t\tstatic_assert(!is_convertible_v<optional<void*>, optional<char*>>, \"!convertible\");\n\t\t\t}\n#endif\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o;  \n\t\t\tVERIFY(!o);\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == (int)0x8BADF00D);\n\t\t\to = 1024;\n\t\t\tVERIFY(static_cast<bool>(o));\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == 1024);\n\t\t\tVERIFY(o.value() == 1024);\n\t\t\t\n\t\t\t// Test reset\n\t\t\to.reset();\n\t\t\tVERIFY(!o);\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == (int)0x8BADF00D);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o(nullopt);  \n\t\t\tVERIFY(!o);\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == (int)0x8BADF00D);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o = {};  \n\t\t\tVERIFY(!o);\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == (int)0x8BADF00D);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o(42);  \n\t\t\tVERIFY(bool(o));\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == 42);\n\t\t\to = nullopt;\n\t\t\tVERIFY(!o);\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == (int)0x8BADF00D);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o(42);\n\t\t\tVERIFY(static_cast<bool>(o));\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == 42);\n\t\t\tVERIFY(o.value() == 42);\n\t\t}\n\n\t\t{\n\t\t\tauto o = make_optional(42);\n\t\t\tVERIFY((is_same<decltype(o), optional<int>>::value));\n\t\t\tVERIFY(static_cast<bool>(o));\n\t\t\tVERIFY(o.value_or(0x8BADF00D) == 42);\n\t\t\tVERIFY(o.value() == 42);\n\t\t}\n\n\t\t{\n\t\t\t// value_or with this a r-value ref and engaged.\n\t\t\toptional<unique_ptr<int>> o = eastl::make_unique<int>(42);\n\t\t\tauto result = eastl::move(o).value_or(eastl::make_unique<int>(1337));\n\t\t\tVERIFY(result != nullptr);\n\t\t\tVERIFY(*result == 42);\n\t\t\tVERIFY(o.has_value());\n\t\t\tVERIFY(o.value() == nullptr); // o has been moved-from.\n\t\t}\n\n\t\t{\n\t\t\t// value_or with this a r-value ref and not engaged.\n\t\t\toptional<unique_ptr<int>> o;\n\t\t\tauto result = eastl::move(o).value_or(eastl::make_unique<int>(1337));\n\t\t\tVERIFY(result != nullptr);\n\t\t\tVERIFY(*result == 1337);\n\t\t\tVERIFY(!o.has_value());\n\t\t}\n\t\t\n\t\t{\n\t\t\tint a = 42;\n\t\t\tauto o = make_optional(a);\n\t\t\tVERIFY((is_same<decltype(o)::value_type, int>::value));\n\t\t\tVERIFY(o.value() == 42);\n\t\t}\n\n\t\t{\n\t\t\t// test make_optional stripping refs/cv-qualifers\n\t\t\tint a = 42;\n\t\t\tconst volatile int& intRef = a;\n\t\t\tauto o = make_optional(intRef);\n\t\t\tVERIFY((is_same<decltype(o)::value_type, int>::value));\n\t\t\tVERIFY(o.value() == 42);\n\t\t}\n\n\t\t{\n\t\t\tint a = 10;\n\t\t\tconst volatile int& aRef = a;\n\t\t\tauto o = eastl::make_optional(aRef);\n\t\t\tVERIFY(o.value() == 10);\n\t\t}\n\n\t\t{\n\t\t\t{\n\t\t\t\tstruct local\n\t\t\t\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\t\t\t/* implicit */ local(int p) : payload1(p) {}\n#endif\n\t\t\t\t\tint payload1;\n\t\t\t\t};\n\t\t\t\tauto o = eastl::make_optional<local>(42);\n\t\t\t\tVERIFY(o.value().payload1 == 42);\n\t\t\t}\n\t\t\t{\n\t\t\t\tstruct local\n\t\t\t\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\t\t\t\t/* implicit */ local(int p1, int p2) : payload1(p1), payload2(p2) {}\n#endif\n\t\t\t\t\tint payload1;\n\t\t\t\t\tint payload2;\n\t\t\t\t};\n\t\t\t\tauto o = eastl::make_optional<local>(42, 43);\n\t\t\t\tVERIFY(o.value().payload1 == 42);\n\t\t\t\tVERIFY(o.value().payload2 == 43);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tstruct local\n\t\t\t\t{\n\t\t\t\t\tlocal(std::initializer_list<int> ilist)\n\t\t\t\t\t{\n\t\t\t\t\t\tpayload1 = ilist.begin()[0];\n\t\t\t\t\t\tpayload2 = ilist.begin()[1];\n\t\t\t\t\t}\n\n\t\t\t\t\tint payload1;\n\t\t\t\t\tint payload2;\n\t\t\t\t};\n\n\t\t\t\tauto o = eastl::make_optional<local>({42, 43});\n\t\t\t\tVERIFY(o.value().payload1 == 42);\n\t\t\t\tVERIFY(o.value().payload2 == 43);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o1(42), o2(24);\n\t\t\tVERIFY(o1.value() == 42);\n\t\t\tVERIFY(o2.value() == 24);\n\t\t\tVERIFY(*o1 == 42);\n\t\t\tVERIFY(*o2 == 24);\n\t\t\to1 = eastl::move(o2);\n\t\t\tVERIFY(*o2 == 24);\n\t\t\tVERIFY(*o1 == 24);\n\t\t\tVERIFY(o2.value() == 24);\n\t\t\tVERIFY(o1.value() == 24);\n\t\t\tVERIFY(bool(o1));\n\t\t\tVERIFY(bool(o2));\n\t\t}\n\n\t\t{\n\t\t\tstruct local { int payload; };\n\t\t\toptional<local> o = local{ 42 }; \n\t\t\tVERIFY(o->payload == 42);\n\t\t}\n\n\t\t{\n\t\t\tstruct local\n\t\t\t{\n\t\t\t\tint test() const { return 42; }\n\t\t\t};\n\n\t\t\t{\n\t\t\t\tconst optional<local> o = local{};\n\t\t\t\tVERIFY(o->test() == 42);\n\t\t\t\tVERIFY((*o).test() == 42);\n\t\t\t\tVERIFY(o.value().test() == 42);\n\t\t\t\tVERIFY(bool(o));\n\t\t\t}\n\n\t\t\t{\n\t\t\t\toptional<local> o = local{};\n\t\t\t\tVERIFY(bool(o));\n\t\t\t\to = nullopt;\n\t\t\t\tVERIFY(!bool(o));\n\n\t\t\t\tVERIFY(o.value_or(local{}).test() == 42);\n\t\t\t\tVERIFY(!bool(o));\n\t\t\t}\n\t\t}\n\t}\n\n\t{\n\t\tcopy_test c;\n\t\tc.value = 42;\n\n\t\toptional<copy_test> o1(c);\n\t\tVERIFY(copy_test::was_copied);\n\n\t\tcopy_test::was_copied = false;\n\n\t\tstatic_assert(is_copy_constructible_v<copy_test>, \"copy\");\n\t\toptional<copy_test> o2(o1);\n\t\tVERIFY(copy_test::was_copied);\n\t\tVERIFY(o2->value == 42);\n\t}\n\n\t{\n\t\tmove_test t;\n\t\tt.value = 42;\n\n\t\toptional<move_test> o1(eastl::move(t));\n\t\tVERIFY(move_test::was_moved);\n\n\t\tmove_test::was_moved = false;\n\n\t\toptional<move_test> o2(eastl::move(o1));\n\t\tVERIFY(move_test::was_moved);\n\t\tVERIFY(o2->value == 42);\n\t}\n\n\t{\n\t\tforwarding_test<float>ft(1.f);\n\t\tfloat val = ft.GetValueOrDefault(0.f);\n\t\tVERIFY(val == 1.f);\n\t}\n\n\t{\n\t\tassignment_test::num_objects_inited = 0;\n\t\t{\n\t\t\toptional<assignment_test> o1;\n\t\t\toptional<assignment_test> o2 = assignment_test();\n\t\t\toptional<assignment_test> o3(o2);\n\t\t\tVERIFY(assignment_test::num_objects_inited == 2);\n\t\t\to1 = nullopt;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 2);\n\t\t\to1 = o2;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 3);\n\t\t\to1 = o2;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 3);\n\t\t\to1 = nullopt;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 2);\n\t\t\to2 = o1;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 1);\n\t\t\to1 = o2;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 1);\n\t\t}\n\t\tVERIFY(assignment_test::num_objects_inited == 0);\n\n\t\t{\n\t\t\toptional<assignment_test> o1;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 0);\n\t\t\to1 = nullopt;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 0);\n\t\t\to1 = optional<assignment_test>(assignment_test());\n\t\t\tVERIFY(assignment_test::num_objects_inited == 1);\n\t\t\to1 = optional<assignment_test>(assignment_test());\n\t\t\tVERIFY(assignment_test::num_objects_inited == 1);\n\t\t\toptional<assignment_test> o2(eastl::move(o1));\n\t\t\tVERIFY(assignment_test::num_objects_inited == 2);\n\t\t\to1 = nullopt;\n\t\t\tVERIFY(assignment_test::num_objects_inited == 1);\n\t\t}\n\t\tVERIFY(assignment_test::num_objects_inited == 0);\n\t}\n\n\t#if EASTL_VARIADIC_TEMPLATES_ENABLED \n\t{\n\t\tstruct vec3\n\t\t{\n\t\t\tvec3(std::initializer_list<float> ilist) { auto* p = ilist.begin();  x = *p++; y = *p++; z = *p++; }\n\t\t\tvec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}  // testing variadic template constructor overload \n\t\t\tfloat x = 0, y = 0, z = 0;\n\t\t};\n\n\t\t{\n\t\t\toptional<vec3> o{ in_place, 4.f, 5.f, 6.f };\n\t\t\tVERIFY(o->x == 4 && o->y == 5 && o->z == 6);\n\t\t}\n\n\t\t{\n\t\t\toptional<vec3> o{ in_place, {4.f, 5.f, 6.f} };\n\t\t\tVERIFY(o->x == 4 && o->y == 5 && o->z == 6);\n\t\t}\n\n\t\t{\n\t\t\toptional<string> o(in_place, {'a', 'b', 'c'});\n\t\t\tVERIFY(o == string(\"abc\"));\n\t\t}\n\n\t\t// http://en.cppreference.com/w/cpp/utility/optional/emplace\n\t\t{\n\t\t\toptional<vec3> o;\n\t\t\tvec3& v = o.emplace(42.f, 42.f, 42.f);\n\t\t\tVERIFY(o->x == 42.f && o->y == 42.f && o->z == 42.f);\n\t\t\tVERIFY(v.x == 42.f && v.y == 42.f && v.z == 42.f);\n\t\t\tv.x = 10.f;\n\t\t\tVERIFY(o->x == 10.f && o->y == 42.f && o->z == 42.f);\n\t\t}\n\n\t\t{\n\t\t\toptional<vec3> o;\n\t\t\tvec3& v = o.emplace({42.f, 42.f, 42.f});\n\t\t\tVERIFY(o->x == 42.f && o->y == 42.f && o->z == 42.f);\n\t\t\tVERIFY(v.x == 42.f && v.y == 42.f && v.z == 42.f);\n\t\t\tv.x = 10.f;\n\t\t\tVERIFY(o->x == 10.f && o->y == 42.f && o->z == 42.f);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o;\n\t\t\tint& i = o.emplace(42);\n\t\t\tVERIFY(*o == 42);\n\t\t\tVERIFY(i == 42);\n\t\t\ti = 10;\n\t\t\tVERIFY(*o == 10);\n\t\t}\n\n\t\tstruct nonCopyableNonMovable\n\t\t{\n\t\t\tnonCopyableNonMovable(int v) : val(v) {}\n\n\t\t\tnonCopyableNonMovable(const nonCopyableNonMovable&) = delete;\n\t\t\tnonCopyableNonMovable(nonCopyableNonMovable&&) = delete;\n\t\t\tnonCopyableNonMovable& operator=(const nonCopyableNonMovable&) = delete;\n\n\t\t\tint val = 0;\n\t\t};\n\n\t\t{\n\t\t\toptional<nonCopyableNonMovable> o;\n\t\t\to.emplace(42);\n\t\t\tVERIFY(o->val == 42);\n\t\t}\n\n\t\t{\n\t\t\t// Verify emplace will destruct object if it has been engaged.\n\t\t\tdestructor_test::reset();\n\t\t\toptional<destructor_test> o;\n\t\t\to.emplace();\n\t\t\tVERIFY(!destructor_test::destructor_ran);\n\n\t\t\tdestructor_test::reset();\n\t\t\to.emplace();\n\t\t\tVERIFY(destructor_test::destructor_ran);\n\t\t}\n\t}\n\t#endif\n\n\n\t// swap\n\t{\n\t\t{\n\t\t\toptional<int> o1 = 42, o2 = 24;\n\t\t\tVERIFY(*o1 == 42);\n\t\t\tVERIFY(*o2 == 24);\n\t\t\to1.swap(o2);\n\t\t\tVERIFY(*o1 == 24);\n\t\t\tVERIFY(*o2 == 42);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o1 = 42, o2 = 24;\n\t\t\tVERIFY(*o1 == 42);\n\t\t\tVERIFY(*o2 == 24);\n\t\t\tswap(o1, o2);\n\t\t\tVERIFY(*o1 == 24);\n\t\t\tVERIFY(*o2 == 42);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o1 = 42, o2;\n\t\t\tVERIFY(*o1 == 42);\n\t\t\tVERIFY(o2.has_value() == false);\n\t\t\tswap(o1, o2);\n\t\t\tVERIFY(o1.has_value() == false);\n\t\t\tVERIFY(*o2 == 42);\n\t\t}\n\n\t\t{\n\t\t\toptional<int> o1 = nullopt, o2 = 42;\n\t\t\tVERIFY(o1.has_value() == false);\n\t\t\tVERIFY(*o2 == 42);\n\t\t\tswap(o1, o2);\n\t\t\tVERIFY(*o1 == 42);\n\t\t\tVERIFY(o2.has_value() == false);\n\t\t}\n\t}\n\n\t{\n\t\toptional<IntStruct> o(in_place, 10);\n\t\toptional<IntStruct> e;\n\n\t\tVERIFY(o < IntStruct(42));\n\t\tVERIFY(!(o < IntStruct(2)));\n\t\tVERIFY(!(o < IntStruct(10)));\n\t\tVERIFY(e < o);\n\t\tVERIFY(e < IntStruct(10));\n\n\t\tVERIFY(o > IntStruct(4));\n\t\tVERIFY(!(o > IntStruct(42)));\n\n\t\tVERIFY(o >= IntStruct(4));\n\t\tVERIFY(o >= IntStruct(10));\n\t\tVERIFY(IntStruct(4) <= o);\n\t\tVERIFY(IntStruct(10) <= o);\n\n\t\tVERIFY(o == IntStruct(10));\n\t\tVERIFY(o->data == IntStruct(10).data);\n\n\t\tVERIFY(o != IntStruct(11));\n\t\tVERIFY(o->data != IntStruct(11).data);\n\t\t\n\t\tVERIFY(e == nullopt);\n\t\tVERIFY(nullopt == e);\n\n\t\tVERIFY(o != nullopt);\n\t\tVERIFY(nullopt != o);\n\t\tVERIFY(nullopt < o);\n\t\tVERIFY(o > nullopt);\n\t\tVERIFY(!(nullopt > o));\n\t\tVERIFY(!(o < nullopt));\n\t\tVERIFY(nullopt <= o);\n\t\tVERIFY(o >= nullopt);\n\n\t\to = 90; // perfect-forwarded assignment.\n\t\tVERIFY(o == IntStruct(90));\n\t}\n\n\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{\n\t\toptional<IntStruct> o(in_place, 10);\n\t\toptional<IntStruct> e;\n\n\t\tVERIFY((o <=> IntStruct(42)) < 0);\n\t\tVERIFY((o <=> IntStruct(2)) >= 0);\n\t\tVERIFY((o <=> IntStruct(10)) >= 0);\n\t\tVERIFY((e <=> o) < 0);\n\t\tVERIFY((e <=> IntStruct(10)) < 0);\n\n\t\tVERIFY((o <=> IntStruct(4)) > 0);\n\t\tVERIFY(o <=> IntStruct(42) <= 0);\n\n\t\tVERIFY((o <=> IntStruct(4)) >= 0);\n\t\tVERIFY((o <=> IntStruct(10)) >= 0);\n\t\tVERIFY((IntStruct(4) <=> o) <= 0);\n\t\tVERIFY((IntStruct(10) <=> o) <= 0);\n\n\t\tVERIFY((o <=> IntStruct(10)) == 0);\n\t\tVERIFY((o->data <=> IntStruct(10).data) == 0);\n\n\t\tVERIFY((o <=> IntStruct(11)) != 0);\n\t\tVERIFY((o->data <=> IntStruct(11).data) != 0);\n\n\t\tVERIFY((e <=> nullopt) == 0);\n\t\tVERIFY((nullopt <=> e) == 0);\n\n\t\tVERIFY((o <=> nullopt) != 0);\n\t\tVERIFY((nullopt <=> o) != 0);\n\t\tVERIFY((nullopt <=> o) < 0);\n\t\tVERIFY((o <=> nullopt) > 0);\n\t\tVERIFY((nullopt <=> o) <= 0);\n\t\tVERIFY((o <=> nullopt) >= 0);\n\t}\n\t#endif\n\n\t// hash \n\t{\n\t\t{\n\t\t\t// verify that the hash an empty eastl::optional object is zero.\n\t\t\ttypedef hash<optional<int>> hash_optional_t;\n\t\t\toptional<int> e;\n\t\t\tVERIFY(hash_optional_t{}(e) == 0);\n\t\t}\n\n\t\t{\n\t\t\t// verify that the hash is the same as the hash of the underlying type\n\t\t\tconst char* const pMessage = \"Electronic Arts Canada\";\n\t\t\ttypedef hash<optional<string>> hash_optional_t;\n\t\t\toptional<string> o = string(pMessage);\n\t\t\tVERIFY(hash_optional_t{}(o) == hash<string>{}(pMessage));\n\t\t}\n\t}\n\n\t// sorting\n\t{\n\t\tvector<optional<int>> v = {{122}, {115}, nullopt, {223}}; \n\t\tsort(begin(v), end(v));\n\t\tvector<optional<int>> sorted = {nullopt, 115, 122, 223};\n\n\t\tVERIFY(v == sorted);\n\t}\n\n\t// test destructors being called.\n\t{\n\t\tdestructor_test::reset();\n\t\t{\n\t\t\toptional<destructor_test> o = destructor_test{};\n\t\t}\n\t\tVERIFY(destructor_test::destructor_ran);\n\n\t\tdestructor_test::reset();\n\t\t{\n\t\t\toptional<destructor_test> o;\n\t\t} \n\t\t// destructor shouldn't be called as object wasn't constructed.\n\t\tVERIFY(!destructor_test::destructor_ran);\n\n\n\t\tdestructor_test::reset();\n\t\t{\n\t\t\toptional<destructor_test> o = {};\n\t\t} \n\t\t// destructor shouldn't be called as object wasn't constructed.\n\t\tVERIFY(!destructor_test::destructor_ran);\n\n\t\tdestructor_test::reset();\n\t\t{\n\t\t\toptional<destructor_test> o = nullopt; \n\t\t} \n\t\t// destructor shouldn't be called as object wasn't constructed.\n\t\tVERIFY(!destructor_test::destructor_ran);\n\t}\n\n\t// optional rvalue tests\n\t{\n\t\tVERIFY(*optional<uint32_t>(1u)\t\t\t\t\t\t== 1u);\n\t\tVERIFY(optional<uint32_t>(1u).value()\t\t\t\t== 1u);\n\t\tVERIFY(optional<uint32_t>(1u).value_or(0xdeadf00d)\t== 1u);\n\t\tVERIFY(optional<uint32_t>().value_or(0xdeadf00d)\t== 0xdeadf00d);\n\t\tVERIFY(optional<uint32_t>(1u).has_value() == true);\n\t\tVERIFY(optional<uint32_t>().has_value() == false);\n\t\tVERIFY( optional<IntStruct>(in_place, 10)->data\t\t== 10);\n\n\t}\n\n\t// alignment type tests\n\t{\n\t\tstatic_assert(alignof(optional<Align16>) == alignof(Align16), \"optional alignment failure\");\n\t\tstatic_assert(alignof(optional<Align32>) == alignof(Align32), \"optional alignment failure\");\n\t\tstatic_assert(alignof(optional<Align64>) == alignof(Align64), \"optional alignment failure\");\n\t}\n\n\t{\n\t\t// user reported regression that failed to compile\n\t\tstruct local_struct\n\t\t{\n\t\t\tlocal_struct() {}\n\t\t\t~local_struct() {}\n\t\t};\n\t\tstatic_assert(!eastl::is_trivially_destructible_v<local_struct>, \"\");\n\n\t\t{\n\t\t\tlocal_struct ls;\n\t\t\teastl::optional<local_struct> o{ls};\n\t\t}\n\t\t{\n\t\t\tconst local_struct ls;\n\t\t\teastl::optional<local_struct> o{ls};\n\t\t}\n\t}\n\n\t{\n\t\t{\n\t\t\t// user regression\n\t\t\teastl::optional<eastl::string> o = eastl::string(\"Hello World\");\n\t\t\teastl::optional<eastl::string> co;\n\n\t\t\tco = o; // force copy-assignment\n\n\t\t\tVERIFY( o.value().data() != co.value().data());\n\t\t\tVERIFY( o.value().data() == eastl::string(\"Hello World\"));\n\t\t\tVERIFY(co.value().data() == eastl::string(\"Hello World\"));\n\t\t}\n\t\t{\n\t\t\t// user regression\n\t\t\tEA_DISABLE_VC_WARNING(4625 4626) // copy/assignment operator constructor was implicitly defined as deleted\n\t\t\tstruct local\n\t\t\t{\n\t\t\t\teastl::unique_ptr<int> ptr;\n\t\t\t};\n\t\t\tEA_RESTORE_VC_WARNING()\n\n\t\t\teastl::optional<local> o1 = local{eastl::make_unique<int>(42)};\n\t\t\teastl::optional<local> o2;\n\n\t\t\to2 = eastl::move(o1);\n\n\t\t\tVERIFY(!!o1 == true);\n\t\t\tVERIFY(!!o2 == true);\n\t\t\tVERIFY(!!o1->ptr == false);\n\t\t\tVERIFY(!!o2->ptr == true);\n\t\t\tVERIFY(o2->ptr.get() != nullptr);\n\t\t\tVERIFY(o1.has_value());\n\t\t}\n\t\t{\n\t\t\t// user regression\n\t\t\tstatic bool copyCtorCalledWithUninitializedValue;\n\t\t\tstatic bool moveCtorCalledWithUninitializedValue;\n\t\t\tcopyCtorCalledWithUninitializedValue = moveCtorCalledWithUninitializedValue = false;\n\t\t\tstruct local\n\t\t\t{\n\t\t\t\tuint32_t val;\n\t\t\t\tlocal()\n\t\t\t\t\t: val(0xabcdabcd)\n\t\t\t\t{}\n\t\t\t\tlocal(const local& other)\n\t\t\t\t\t: val(other.val)\n\t\t\t\t{\n\t\t\t\t\tif (other.val != 0xabcdabcd)\n\t\t\t\t\t\tcopyCtorCalledWithUninitializedValue = true;\n\t\t\t\t}\n\t\t\t\tlocal(local&& other)\n\t\t\t\t\t: val(eastl::move(other.val))\n\t\t\t\t{\n\t\t\t\t\tif (other.val != 0xabcdabcd)\n\t\t\t\t\t\tmoveCtorCalledWithUninitializedValue = true;\n\t\t\t\t}\n\t\t\t\tlocal& operator=(const local&) = delete;\n\t\t\t};\n\t\t\teastl::optional<local> n;\n\t\t\teastl::optional<local> o1(n);\n\t\t\tVERIFY(!copyCtorCalledWithUninitializedValue);\n\t\t\teastl::optional<local> o2(eastl::move(n));\n\t\t\tVERIFY(!moveCtorCalledWithUninitializedValue);\n\t\t}\n\t}\n\n\t{\n\t\tauto testFn = []() -> optional<int>\n\t\t{\n\t\t\treturn eastl::nullopt;\n\t\t};\n\n\t\tauto o = testFn();\n\t\tVERIFY(!!o == false);\n\t}\n\n\t{\n\t\tstruct convert_to_bool\n\t\t{\n\t\t\tconvert_to_bool() = default;\n\n\t\t\tconstexpr explicit operator bool() const noexcept { return true; }\n\t\t};\n\n\t\toptional<bool> x{ convert_to_bool{} }; // optional<bool>(convert_to_bool), which converts to bool.\n\t\tVERIFY(x.has_value());\n\t\tVERIFY(x.value());\n\t}\n\n\t// enable/disable constructors & assignment based on bool type\n\t{\n\t\toptional<int> x{ 3 };\n\t\toptional<bool> y{ x };\n\t\tVERIFY(y.has_value());\n\t\tVERIFY(y.value());\n\n\t\toptional<bool> z{ move(y) };\n\t\tVERIFY(z.has_value());\n\t\tVERIFY(z.value());\n\n\t\tbool a = true;\n\t\toptional<bool> b{ a };\n\t\toptional<bool> c{ move(a) };\n\t}\n\n\t// enable/disable constructor appropriately\n\t{\n\t\tstatic constexpr int sentinel_value = 8;\n\n\t\tstruct construct_from_optional\n\t\t{\n\t\t\tconstruct_from_optional() = default;\n\t\t\tconstruct_from_optional(optional<int>) : m_value(sentinel_value) {}\n\n\t\t\tint m_value{ 0 };\n\t\t};\n\n\t\t// optional<construct_from_optional>(construct_from_optional) which calls construct_from_optional(optional<int>), don't call converting copy constructor optional<construct_from_optional>(optional<int>). \n\t\toptional<int> x;\n\t\toptional<construct_from_optional> y{ x };\n\t\tVERIFY(y.has_value());\n\t\tVERIFY(y.value().m_value == sentinel_value);\n\t}\n\n\t#endif // EASTL_OPTIONAL_ENABLED\n\n\tnErrorCount += TestOptional_MonadicOperations();\n\t\n\treturn nErrorCount;\n}\n\n"
  },
  {
    "path": "test/source/TestRandom.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#if defined(_MSC_VER)\n\t//#pragma warning(disable: 4267)  // 'argument' : conversion from 'size_t' to 'uint32_t', possible loss of data.\n#endif\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/numeric_limits.h>\n#include <EASTL/set.h>\n#include <EASTL/random.h>\n\n\nstruct GeneratorUint8\n{\n\tuint8_t mValue;\n\tGeneratorUint8() : mValue(0) {}\n\tuint8_t operator()(){ return mValue++; } // This is a pretty bad random number generator, but works for our tests.\n};\n\nstruct GeneratorUint16\n{\n\tuint16_t mValue;\n\tGeneratorUint16() : mValue(0) {}\n\tuint16_t operator()(){ return mValue++; }\n};\n\nstruct GeneratorUint32\n{\n\tuint32_t mValue;\n\tGeneratorUint32() : mValue(0) {}\n\tuint32_t operator()(){ return mValue++; }\n};\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestRandom\n//\nint TestRandom()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\t// template<class IntType = int>\n\t\t// class uniform_int_distribution\n\n\t\t// The C++11 Standard defines a number of formal Generators, such as std::mersenne_twister_engine, \n\t\t// linear_congruential_engine, discard_block_engine, etc.\n\n\t\tusing namespace eastl;\n\n\t\t{\n\t\t\teastl::uniform_int_distribution<uint8_t> uid(1, 6);\n\t\t\tGeneratorUint8 g;\n \n\t\t\tfor(uint32_t i = 0; i < UINT8_MAX; i += 1)\n\t\t\t{\n\t\t\t\tuint8_t value = uid(g);\n\t\t\t\tEATEST_VERIFY((value >= 1) && (value <= 6));\n\t\t\t\t// To do: Validate the randomness of the value.\n\t\t\t}\n\n\t\t\teastl::uniform_int_distribution<uint8_t> uid2(1, 6);\n\t\t\tEATEST_VERIFY(uid == uid2);\n\t\t}\n\n\t\t{\n\t\t\teastl::uniform_int_distribution<uint16_t> uid(1, 6);\n\t\t\tGeneratorUint16 g;\n \n\t\t\tfor(uint32_t i = 0; i < (UINT16_MAX - (UINT16_MAX / 50)); i += (UINT16_MAX / 50))\n\t\t\t{\n\t\t\t\tuint16_t value = uid(g);\n\t\t\t\tEATEST_VERIFY((value >= 1) && (value <= 6));\n\t\t\t\t// To do: Validate the randomness of the value.\n\t\t\t}\n\n\t\t\teastl::uniform_int_distribution<uint16_t> uid2(1, 6);\n\t\t\tEATEST_VERIFY(uid == uid2);\n\t\t}\n\n\t\t{\n\t\t\teastl::uniform_int_distribution<uint32_t> uid(1, 6);\n\t\t\tGeneratorUint32 g;\n \n\t\t\tfor(uint32_t i = 0; i < (UINT32_MAX - (UINT32_MAX / 500)); i += (UINT32_MAX / 500))\n\t\t\t{\n\t\t\t\tuint32_t value = uid(g);\n\t\t\t\tEATEST_VERIFY((value >= 1) && (value <= 6));\n\t\t\t\t// To do: Validate the randomness of the value.\n\t\t\t}\n\n\t\t\teastl::uniform_int_distribution<uint32_t> uid2(1, 6);\n\t\t\tEATEST_VERIFY(uid == uid2);\n\t\t}\n\t}\n\n\n\n\t/// Example usage:\n\t///     eastl_size_t Rand(eastl_size_t n) { return (eastl_size_t)(rand() % n); } // Note: The C rand function is poor and slow.\n\t///     pointer_to_unary_function<eastl_size_t, eastl_size_t> randInstance(Rand);\n\t///     random_shuffle(pArrayBegin, pArrayEnd, randInstance);\n\t///\n\t/// Example usage:\n\t///     struct Rand{ eastl_size_t operator()(eastl_size_t n) { return (eastl_size_t)(rand() % n); } }; // Note: The C rand function is poor and slow.\n\t///     Rand randInstance;\n\t///     random_shuffle(pArrayBegin, pArrayEnd, randInstance);\n\n\n\t{\n\t\t// void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rng)\n\t\tusing namespace eastl;\n\n\t\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\t\tint intArray[] = { 3, 2, 6, 5, 4, 1 };\n\n\t\trandom_shuffle(intArray, intArray + 0, rng);\n\t\tEATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), \"random_shuffle\", 3, 2, 6, 5, 4, 1, -1));\n\n\t\trandom_shuffle(intArray, intArray + (sizeof(intArray) / sizeof(intArray[0])), rng);\n\t\tbool changed = false;\n\t\tfor(int i = 0; (i < 5) && !changed; i++)\n\t\t{\n\t\t\tchanged = (intArray[0] != 3) || (intArray[1] != 2) || (intArray[2] != 6) || \n\t\t\t\t\t  (intArray[3] != 5) || (intArray[4] != 4) || (intArray[5] != 1);\n\t\t}\n\t\tEATEST_VERIFY(changed);\n\n\t\t// Test of possible bug report by user John Chin.\n\t\t// The report is that shuffling an ordered array 0, 1, 2, 3, 4 ... results in duplicates, such as 5, 2, 2, 4 ...\n\t\teastl::vector<eastl_size_t> rngArray;\n\n\t\tfor(eastl_size_t i = 0; i < 200; ++i)\n\t\t\trngArray.push_back(i);\n\n\t\trandom_shuffle(rngArray.begin(), rngArray.end(), rng);\n\t\tEATEST_VERIFY(rngArray.validate());\n\n\t\teastl::set<eastl_size_t> intSet;\n\n\t\tfor(eastl_size_t s = 0, sEnd = rngArray.size(); s < sEnd; ++s)\n\t\t\tintSet.insert(rngArray[s]);\n\n\t\t// If the shuffled array is unique, then a set of its values should be the same size as the array.\n\t\tEATEST_VERIFY(intSet.size() == rngArray.size());\n\t}\n\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestRatio.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EABase/eabase.h>\n#include <EASTL/ratio.h>\n\n\nint TestRatio()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\t{\n\t\tusing namespace eastl::Internal;\n\n\t\t// lcm (least common multiple)\n\t\tstatic_assert(lcm<0,0>::value == 0, \"lcm failure\");\n\t\tstatic_assert(lcm<10,6>::value == 30, \"lcm failure\");\n\t\tstatic_assert(lcm<21,6>::value == 42, \"lcm failure\");\n\t\tstatic_assert(lcm<21,6>::value == lcm<6,21>::value, \"lcm failure\");\n\t\n\t\t// gcd (greatest common divisor)\n\t\tstatic_assert(gcd<6, 4>::value == 2, \"gcd failure\");\n\t\tstatic_assert(gcd<54, 24>::value == 6, \"gcd failure\");\n\t\tstatic_assert(gcd<42, 56>::value == 14, \"gcd failure\");\n\t\tstatic_assert(gcd<48, 18>::value == 6, \"gcd failure\");\n\t\tstatic_assert(gcd<50, 40>::value == 10, \"gcd failure\");\n\t\tstatic_assert(gcd<6, 4>::value != 9, \"gcd failure\");\n\t\tstatic_assert(gcd<0, 0>::value == 1, \"gcd failure\");\n\t\tstatic_assert(gcd<1, 0>::value == 1, \"gcd failure\");\n\t\tstatic_assert(gcd<0, 1>::value == 1, \"gcd failure\");\n\t\tstatic_assert(gcd<34,7>::value == gcd<7, 34>::value, \"gcd failure\");\n\t\tstatic_assert(gcd<9223372036854775807, 9223372036854775807>::value == 9223372036854775807, \"gcd failure\");\n\t\n\t\t// simplify\n\t\ttypedef ct_simplify<ratio<50, 40>>::ratio_type smp_rt;\n\t\ttypedef ct_simplify<ratio<50, 40>>::this_type smp_tt;\n\t\tstatic_assert(smp_rt::num == 5 && smp_rt::den == 4, \"simplify failure\");\n\t\tstatic_assert(smp_tt::divisor == 10, \"simplify failure0\");\n\t\tstatic_assert(smp_rt::num == 5, \"simplify failure1\");\n\t\tstatic_assert(smp_rt::den == 4, \"simplify failure2\");\n\t}\n\n\t{\n\t\t// ratio_add\n\t\ttypedef ratio_add<ratio<2, 3>, ratio<1, 6>> sum;\n\t\tstatic_assert(sum::num == 5 && sum::den == 6, \"ratio_add failure\");\n\t\ttypedef ratio_add<ratio<3,4>, ratio<5,10>> sum2;\n\t\tstatic_assert(sum2::num == 5 && sum2::den == 4, \"ratio_add failure\");\n\n\t\t// ratio_subtract\n\t\ttypedef ratio_subtract<ratio<10,10>, ratio<1,2>> sum3;\n\t\tstatic_assert(sum3::num == 1 && sum3::den == 2, \"ratio_subtract failure\");\n\n\t\t// ratio_multiply\n\t\ttypedef ratio_multiply<ratio<10,10>, ratio<1,2>> sum4;\n\t\tstatic_assert(sum4::num == 1 && sum4::den == 2, \"ratio_multiply failure\");\n\t\ttypedef ratio_multiply<ratio<2,5>, ratio<1,2>> sum5;\n\t\tstatic_assert(sum5::num == 1 && sum5::den == 5, \"ratio_multiply failure\");\n\t\ttypedef ratio_multiply<ratio<1,3>, ratio<9,16>> sum6;\n\t\tstatic_assert(sum6::num == 3 && sum6::den == 16, \"ratio_multiply failure\");\n\n\t\t// ratio_divide\n\t\ttypedef ratio_divide<ratio<1,8>, ratio<1,4>> sum8;\n\t\tstatic_assert(sum8::num == 1 && sum8::den == 2, \"ratio_divide failure\");\n\t\ttypedef ratio_divide<ratio<2,3>, ratio<5>> sum9;\n\t\tstatic_assert(sum9::num == 2 && sum9::den == 15, \"ratio_divide failure\");\n\n\t\t// ratio_equal\n\t\tstatic_assert(ratio_equal<ratio<1>, ratio<1>>::value, \"ratio_equal failure\");\n\t\tstatic_assert(ratio_equal<ratio<1,1>, ratio<4,4>>::value, \"ratio_equal failure\");\n\t\tstatic_assert(ratio_equal<ratio<5,10>, ratio<1,2>>::value, \"ratio_equal failure\");\n\t\tstatic_assert(ratio_equal<ratio<2,3>, ratio<4,6>>::value, \"ratio_equal failure\");\n\n\t\t// ratio_not_equal\n\t\tstatic_assert(!ratio_not_equal<ratio<5,10>, ratio<1,2>>::value, \"ratio_not_equal failure\");\n\n\t\t// ratio_less\n\t\tstatic_assert(ratio_less<ratio<2,10>, ratio<1,2>>::value, \"ratio_less failure\");\n\t\tstatic_assert(ratio_less<ratio<23,37>, ratio<57,90>>::value, \"ratio_less failure\");\n\n\t\t// ratio_less_equal\n\t\tstatic_assert(ratio_less_equal<ratio<2,10>, ratio<1,2>>::value, \"ratio_less_equal failure\");\n\t\tstatic_assert(ratio_less_equal<ratio<2,10>, ratio<1,5>>::value, \"ratio_less_equal failure\");\n\t\tstatic_assert(ratio_less_equal<ratio<1,100>, ratio<1,5>>::value, \"ratio_less_equal failure\");\n\n\t\t// ratio_greater \n\t\tstatic_assert(ratio_greater<ratio<1,2>, ratio<1,4>>::value, \"ratio_greater failure\");\n\n\t\t// ratio_greater_equal\n\t\tstatic_assert(ratio_greater_equal<ratio<3,4>, ratio<1,2>>::value, \"ratio_greater_equal failure\");\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestRingBuffer.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EAStdC/EASprintf.h>\n#include <EASTL/bonus/ring_buffer.h>\n#include <EASTL/bonus/fixed_ring_buffer.h>\n#include <EASTL/vector.h>\n#include <EASTL/deque.h>\n#include <EASTL/string.h>\n#include <EASTL/list.h>\n#include <EASTL/fixed_vector.h>\n#include <EASTL/fixed_string.h>\n\n\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::ring_buffer< int,        eastl::vector<int>        >;\ntemplate class eastl::ring_buffer< Align64,    eastl::vector<Align64>    >;\ntemplate class eastl::ring_buffer< TestObject, eastl::vector<TestObject> >;\n\ntemplate class eastl::ring_buffer< int,        eastl::deque<int>        >;\ntemplate class eastl::ring_buffer< Align64,    eastl::deque<Align64>    >;\ntemplate class eastl::ring_buffer< TestObject, eastl::deque<TestObject> >;\n\ntemplate class eastl::ring_buffer< int,        eastl::list<int>        >;\ntemplate class eastl::ring_buffer< Align64,    eastl::list<Align64>    >;\ntemplate class eastl::ring_buffer< TestObject, eastl::list<TestObject> >;\n\n// TODO(rparolin):  To consider adding support for eastl::array. \n// template class eastl::ring_buffer< int, eastl::array<int, 64>>;\n\ntypedef eastl::fixed_string<char, 256, false>          RBFixedString;\ntypedef eastl::fixed_vector<RBFixedString, 100, false> RBFixedStringVector;\ntypedef RBFixedStringVector::overflow_allocator_type   RBFixedStringVectorOverflowAllocator;\ntemplate class eastl::ring_buffer<RBFixedString, RBFixedStringVector, RBFixedStringVectorOverflowAllocator>;\n\ntypedef eastl::fixed_vector<int, 100, false> RBFixedIntVector;\ntemplate class eastl::ring_buffer<int, RBFixedIntVector, RBFixedIntVector::overflow_allocator_type>;\n// template class eastl::ring_buffer<int, RBFixedIntVector>;  // currently fails to compile\n\ntypedef eastl::fixed_vector<int, 100> RBFixedIntVectorWithOverFlow;\ntemplate class eastl::ring_buffer<int, RBFixedIntVectorWithOverFlow, RBFixedIntVectorWithOverFlow::overflow_allocator_type>; \n// template class eastl::ring_buffer<int, RBFixedIntVectorWithOverFlow>; // currently fails to compile\n\n\n\nint TestRingBuffer()\n{\n\tint nErrorCount = 0;\n\n\t// GCC prior to 4.1 has a fatal code generation bug in string arrays, which we use below.\n\t#if !defined(EA_DEBUG) && defined(__GNUC__) && !defined(__EDG__) && (((__GNUC__ * 100) + __GNUC_MINOR__) < 401)\n\t\treturn nErrorCount;\n\t#endif\n\n\t{ // regression for bug in the capacity() function for the case of capacity == 0.\n\n\t\tvector<int> emptyIntArray;\n\t\tring_buffer<int, vector<int> > intRingBuffer(emptyIntArray);\n\n\t\tEATEST_VERIFY(intRingBuffer.validate());\n\t\tEATEST_VERIFY(intRingBuffer.capacity() == 0);\n\n\t\tintRingBuffer.resize(0);\n\t\tEATEST_VERIFY(intRingBuffer.validate());\n\t\tEATEST_VERIFY(intRingBuffer.size() == 0);\n\n\t\tintRingBuffer.resize(1);\n\t\tEATEST_VERIFY(intRingBuffer.validate());\n\t\tEATEST_VERIFY(intRingBuffer.size() == 1);\n\t}\n\n\t{\n\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\ttypedef ring_buffer< string, vector<string> > RBVectorString;\n\n\t\tint  counter = 0;\n\t\tconst int kBufferSize = 32;\n\t\tchar counterBuffer[kBufferSize];\n\n\t\t// explicit ring_buffer(size_type size = 0);\n\t\tconst int kOriginalCapacity = 50;\n\t\tRBVectorString rbVectorString(50);\n\n\t\t// bool empty() const;\n\t\t// size_type size() const;\n\t\t// bool validate() const;\n\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\tEATEST_VERIFY(rbVectorString.empty());\n\t\tEATEST_VERIFY(rbVectorString.size() == 0);\n\t\tEATEST_VERIFY(rbVectorString.capacity() == 50);\n\n\t\t// void clear();\n\t\trbVectorString.clear();\n\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\tEATEST_VERIFY(rbVectorString.empty());\n\t\tEATEST_VERIFY(rbVectorString.size() == 0);\n\t\tEATEST_VERIFY(rbVectorString.capacity() == 50);\n\n\t\t// container_type& get_container();\n\t\tRBVectorString::container_type& c = rbVectorString.get_container();\n\t\tEATEST_VERIFY(c.size() == (kOriginalCapacity + 1)); // We need to add one because the ring_buffer mEnd is necessarily an unused element.\n\n\t\t// iterator begin();\n\t\t// iterator end();\n\t\t// int validate_iterator(const_iterator i) const;\n\t\tRBVectorString::iterator it = rbVectorString.begin();\n\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));\n\n\t\twhile(it != rbVectorString.end()) // This loop should do nothing.\n\t\t{\n\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t++it;\n\t\t}\n\n\t\t// void push_back(const value_type& value);\n\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\t\trbVectorString.push_back(string(counterBuffer));\n\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\tEATEST_VERIFY(!rbVectorString.empty());\n\t\tEATEST_VERIFY(rbVectorString.size() == 1);\n\t\tEATEST_VERIFY(rbVectorString.capacity() == 50);\n\n\t\tit = rbVectorString.begin();\n\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\tEATEST_VERIFY(*it == \"0\");\n\n\t\t// reference front();\n\t\t// reference back();              \n\t\tstring& sFront = rbVectorString.front();\n\t\tstring& sBack  = rbVectorString.back();\n\t\tEATEST_VERIFY(&sFront == &sBack);\n\n\t\t// void push_back();\n\t\tstring& ref = rbVectorString.push_back();\n\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\tEATEST_VERIFY(rbVectorString.size() == 2);\n\t\tEATEST_VERIFY(rbVectorString.capacity() == 50);\n\t\tEATEST_VERIFY(&ref == &rbVectorString.back());\n\n\t\tit = rbVectorString.begin();\n\t\t++it;\n\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\tEATEST_VERIFY(it->empty());\n\n\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\t\t*it = counterBuffer;\n\t\tEATEST_VERIFY(*it == \"1\");\n\n\t\t++it;\n\t\tEATEST_VERIFY(it == rbVectorString.end());\n\n\t\tit = rbVectorString.begin();\n\t\twhile(it != rbVectorString.end())\n\t\t{\n\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\t\t++it;\n\t\t}\n\n\t\t// reference operator[](size_type n);\n\t\tstring& s0 = rbVectorString[0];\n\t\tEATEST_VERIFY(s0 == \"0\");\n\n\t\tstring& s1 = rbVectorString[1];\n\t\tEATEST_VERIFY(s1 == \"1\");\n\n\t\t// Now we start hammering the ring buffer with push_back.\n\t\tfor(eastl_size_t i = 0, iEnd = rbVectorString.capacity() * 5; i != iEnd; i++)\n\t\t{\n\t\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\t\t\trbVectorString.push_back(string(counterBuffer));\n\t\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\t}\n\n\t\tint  counterCheck = counter - 1;\n\t\tchar counterCheckBuffer[kBufferSize];\n\t\tEA::StdC::Snprintf(counterCheckBuffer, kBufferSize, \"%d\", counterCheck);\n\t\tEATEST_VERIFY(rbVectorString.back() == counterCheckBuffer);\n\n\t\t// reverse_iterator rbegin();\n\t\t// reverse_iterator rend();\n\t\tfor(RBVectorString::reverse_iterator ri = rbVectorString.rbegin(); ri != rbVectorString.rend(); ++ri)\n\t\t{\n\t\t\tEA::StdC::Snprintf(counterCheckBuffer, kBufferSize, \"%d\", counterCheck--);\n\t\t\tEATEST_VERIFY(*ri == counterCheckBuffer);\n\t\t}\n\n\t\t++counterCheck;\n\n\t\t// iterator begin();\n\t\t// iterator end();\n\t\tfor(RBVectorString::iterator i = rbVectorString.begin(); i != rbVectorString.end(); ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(i) == (isf_valid | isf_current | isf_can_dereference));\n\t\t\tEATEST_VERIFY(*i == counterCheckBuffer);\n\t\t\tEA::StdC::Snprintf(counterCheckBuffer, kBufferSize, \"%d\", ++counterCheck);\n\t\t}\n\n\t\t// void clear();\n\t\trbVectorString.clear();\n\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\tEATEST_VERIFY(rbVectorString.empty());\n\t\tEATEST_VERIFY(rbVectorString.size() == 0);\n\t\tEATEST_VERIFY(rbVectorString.capacity() == 50);\n\n\t\t// Random operations\n\t\t// Not easy to test the expected values without some tedium.\n\t\tfor(int j = 0; j < 10000 + (gEASTL_TestLevel * 10000); j++)\n\t\t{\n\t\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\n\t\t\tconst eastl_size_t op = rng.RandLimit(12);\n\t\t\tconst eastl_size_t s  = rbVectorString.size();\n\n\t\t\tif(op == 0)\n\t\t\t{\n\t\t\t\t// void push_back(const value_type& value);\n\n\t\t\t\trbVectorString.push_back(string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 1)\n\t\t\t{\n\t\t\t\t// void push_back();\n\n\t\t\t\tstring& ref2 = rbVectorString.push_back();\n\t\t\t\trbVectorString.back() = string(counterBuffer);\n\t\t\t\tEATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));\n\t\t\t\tEATEST_VERIFY(&ref2 == &rbVectorString.back());\n\t\t\t}\n\t\t\telse if(op == 2)\n\t\t\t{\n\t\t\t\t// void pop_back();\n\n\t\t\t\tif(!rbVectorString.empty())\n\t\t\t\t{\n\t\t\t\t\trbVectorString.pop_back();\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.size() == (s - 1));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 3)\n\t\t\t{\n\t\t\t\t// void push_front(const value_type& value);\n\n\t\t\t\trbVectorString.push_front(string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 4)\n\t\t\t{\n\t\t\t\t// void push_front();\n\n\t\t\t\tstring& ref2 = rbVectorString.push_front();\n\t\t\t\trbVectorString.front() = string(counterBuffer);\n\t\t\t\tEATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));\n\t\t\t\tEATEST_VERIFY(&ref2 == &rbVectorString.front());\n\t\t\t}\n\t\t\telse if(op == 5)\n\t\t\t{\n\t\t\t\t// void pop_front();\n\n\t\t\t\tif(!rbVectorString.empty())\n\t\t\t\t{\n\t\t\t\t\trbVectorString.pop_front();\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.size() == (s - 1));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 6)\n\t\t\t{\n\t\t\t\t// iterator insert(iterator position, const value_type& value);\n\n\t\t\t\tit = rbVectorString.begin();\n\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);\n\t\t\t\teastl::advance(it, dist);\n\n\t\t\t\tif(it == rbVectorString.end())\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\trbVectorString.insert(it, string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbVectorString.size() == eastl::min(s + 1, rbVectorString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 7)\n\t\t\t{\n\t\t\t\t// void insert(iterator position, size_type n, const value_type& value);\n\n\t\t\t\tit = rbVectorString.begin();\n\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);\n\t\t\t\teastl::advance(it, dist);\n\n\t\t\t\tif(it == rbVectorString.end())\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\tconst eastl_size_t count = (eastl_size_t)rng.RandLimit(10);\n\n\t\t\t\trbVectorString.insert(it, count, string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbVectorString.size() == eastl::min(s + count, rbVectorString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 8)\n\t\t\t{\n\t\t\t\t// template <typename InputIterator>\n\t\t\t\t// void insert(iterator position, InputIterator first, InputIterator last);\n\n\t\t\t\tstring stringArray[10];\n\n\t\t\t\tit = rbVectorString.begin();\n\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);\n\t\t\t\teastl::advance(it, dist);\n\n\t\t\t\tif(it == rbVectorString.end())\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\tconst eastl_size_t count = (eastl_size_t)rng.RandLimit(10);\n\n\t\t\t\trbVectorString.insert(it, stringArray, stringArray + count);\n\t\t\t\tEATEST_VERIFY(rbVectorString.size() == eastl::min(s + count, rbVectorString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 9)\n\t\t\t{\n\t\t\t\t// iterator erase(iterator position);\n\n\t\t\t\tif(!rbVectorString.empty())\n\t\t\t\t{\n\t\t\t\t\tit = rbVectorString.begin();\n\t\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s);\n\t\t\t\t\teastl::advance(it, dist);\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\t\t\t\trbVectorString.erase(it);\n\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.size() == (s  - 1));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 10)\n\t\t\t{\n\t\t\t\t// iterator erase(iterator first, iterator last);\n\n\t\t\t\tif(!rbVectorString.empty())\n\t\t\t\t{\n\t\t\t\t\tRBVectorString::iterator it1 = rbVectorString.begin();\n\t\t\t\t\tconst eastl_size_t pos = rng.RandLimit((uint32_t)s / 4);\n\t\t\t\t\teastl::advance(it1, pos);\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it1) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\t\tRBVectorString::iterator it2 = it1;\n\t\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s / 4);\n\t\t\t\t\teastl::advance(it2, dist);\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(it2) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\t\tEATEST_VERIFY(s > (pos + dist));\n\t\t\t\t\trbVectorString.erase(it1, it2);\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.size() == (s - dist));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 11)\n\t\t\t{\n\t\t\t\t// void resize(size_type n);\n\t\t\t\tconst eastl_size_t nSubOp = rng.RandLimit(100);\n\n\t\t\t\tif(nSubOp == 1)\n\t\t\t\t{\n\t\t\t\t\trbVectorString.resize(kOriginalCapacity);\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.size() == (RBVectorString::size_type)kOriginalCapacity);\n\t\t\t\t}\n\t\t\t\telse if(nSubOp == 2)\n\t\t\t\t{\n\t\t\t\t\tconst eastl_size_t newSize = rng.RandLimit((uint32_t)s * 2) + 2;\n\n\t\t\t\t\trbVectorString.resize(newSize);\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.size() == newSize);\n\t\t\t\t}\n\t\t\t\telse if(nSubOp == 3)\n\t\t\t\t{\n\t\t\t\t\trbVectorString.clear();\n\t\t\t\t\tEATEST_VERIFY(rbVectorString.size() == 0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\t}\n\n\t\t// We make sure that after the above we still have some contents.\n\t\tif(rbVectorString.size() < 8)\n\t\t\trbVectorString.resize(8);\n\n\t\tEATEST_VERIFY(rbVectorString.validate());\n\n\t\t// Test const functions\n\t\t// const_iterator begin() const;\n\t\t// const_iterator end() const;\n\t\t// const_reverse_iterator rbegin() const;\n\t\t// const_reverse_iterator rend() const;\n\t\t// const_reference front() const;\n\t\t// const_reference back() const;\n\t\t// const_reference operator[](size_type n) const;\n\t\t// const container_type& get_container() const;\n\t\tconst RBVectorString& rbVSConst = rbVectorString;\n\n\t\tfor(RBVectorString::const_iterator ic = rbVSConst.begin(); ic != rbVSConst.end(); ++ic)\n\t\t{\n\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(ic) == (isf_valid | isf_current | isf_can_dereference));\n\t\t}\n\n\t\tfor(RBVectorString::const_reverse_iterator ric = rbVSConst.rbegin(); ric != rbVSConst.rend(); ++ric)\n\t\t{\n\t\t\tif(ric == rbVSConst.rbegin())\n\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(ric.base()) == (isf_valid | isf_current));\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(rbVectorString.validate_iterator(ric.base()) == (isf_valid | isf_current | isf_can_dereference));\n\t\t}\n\n\t\tEATEST_VERIFY(rbVSConst.front() == rbVectorString.front());\n\t\tEATEST_VERIFY(rbVSConst.back() == rbVectorString.back());\n\t\tEATEST_VERIFY(rbVSConst[0] == rbVectorString[0]);\n\t\tEATEST_VERIFY(&rbVSConst.get_container() == &rbVectorString.get_container());\n\n\n\t\t// Test additional constructors.\n\t\t// ring_buffer(const this_type& x);\n\t\t// explicit ring_buffer(const Container& x);\n\t\t// this_type& operator=(const this_type& x);\n\t\t// void swap(this_type& x);\n\t\tRBVectorString rbVectorString2(rbVectorString);\n\t\tRBVectorString rbVectorString3(rbVectorString.get_container());\n\t\tRBVectorString rbVectorString4(rbVectorString.capacity() / 2);\n\t\tRBVectorString rbVectorString5(rbVectorString.capacity() * 2);\n\n\t\tEATEST_VERIFY(rbVectorString.validate());\n\t\tEATEST_VERIFY(rbVectorString2.validate());\n\t\tEATEST_VERIFY(rbVectorString3.validate());\n\t\tEATEST_VERIFY(rbVectorString4.validate());\n\t\tEATEST_VERIFY(rbVectorString5.validate());\n\n\t\tEATEST_VERIFY(rbVectorString == rbVectorString2);\n\t\tEATEST_VERIFY(rbVectorString3.get_container() == rbVectorString2.get_container());\n\n\t\trbVectorString3 = rbVectorString4;\n\t\tEATEST_VERIFY(rbVectorString3.validate());\n\n\t\teastl::swap(rbVectorString2, rbVectorString4);\n\t\tEATEST_VERIFY(rbVectorString2.validate());\n\t\tEATEST_VERIFY(rbVectorString3.validate());\n\t\tEATEST_VERIFY(rbVectorString4.validate());\n\t\tEATEST_VERIFY(rbVectorString == rbVectorString4);\n\t\tEATEST_VERIFY(rbVectorString2 == rbVectorString3);\n\n\t\t// void ring_buffer<T, Container>::reserve(size_type n)\n\t\teastl_size_t cap = rbVectorString2.capacity();\n\t\trbVectorString2.reserve(cap += 2);\n\t\tEATEST_VERIFY(rbVectorString2.validate());\n\t\tEATEST_VERIFY(rbVectorString2.capacity() == cap);\n\t\trbVectorString2.reserve(cap -= 4); // This should act as a no-op if we are following convention.\n\t\tEATEST_VERIFY(rbVectorString2.validate());\n\n\t\t// void ring_buffer<T, Container>::set_capacity(size_type n)\n\t\tcap = rbVectorString2.capacity();\n\t\trbVectorString2.resize(cap);\n\t\tEATEST_VERIFY(rbVectorString2.size() == cap);\n\t\trbVectorString2.set_capacity(cap += 2);\n\t\tEATEST_VERIFY(rbVectorString2.validate());\n\t\tEATEST_VERIFY(rbVectorString2.capacity() == cap);\n\t\trbVectorString2.set_capacity(cap -= 4);\n\t\tEATEST_VERIFY(rbVectorString2.capacity() == cap);\n\t\tEATEST_VERIFY(rbVectorString2.validate());\n\n\t\t// template <typename InputIterator>\n\t\t// void assign(InputIterator first, InputIterator last);\n\t\tstring stringArray[10];\n\t\tfor(int q = 0; q < 10; q++)\n\t\t\tstringArray[q] = (char)('0' + (char)q);\n\n\t\trbVectorString5.assign(stringArray, stringArray + 10);\n\t\tEATEST_VERIFY(rbVectorString5.validate());\n\t\tEATEST_VERIFY(rbVectorString5.size() == 10);\n\t\tEATEST_VERIFY(rbVectorString5.front() == \"0\");\n\t\tEATEST_VERIFY(rbVectorString5.back() == \"9\");\n\t}\n\n\n\t{\n\t\t// Additional testing\n\t\ttypedef ring_buffer< int, vector<int> > RBVectorInt;\n\n\t\tRBVectorInt rbVectorInt(6);\n\n\t\trbVectorInt.push_back(0);\n\t\trbVectorInt.push_back(1);\n\t\trbVectorInt.push_back(2);\n\t\trbVectorInt.push_back(3);\n\t\trbVectorInt.push_back(4);\n\t\trbVectorInt.push_back(5);\n\t\tEATEST_VERIFY(rbVectorInt[0] == 0);\n\t\tEATEST_VERIFY(rbVectorInt[5] == 5);\n\n\t\t// iterator insert(iterator position, const value_type& value);\n\t\trbVectorInt.insert(rbVectorInt.begin(), 999);\n\t\tEATEST_VERIFY(rbVectorInt[0] == 999);\n\t\tEATEST_VERIFY(rbVectorInt[1] == 0);\n\t\tEATEST_VERIFY(rbVectorInt[5] == 4);\n\n\t\trbVectorInt.clear();\n\t\trbVectorInt.push_back(0);\n\t\trbVectorInt.push_back(1);\n\t\trbVectorInt.push_back(2);\n\t\trbVectorInt.push_back(3);\n\t\trbVectorInt.push_back(4);\n\n\t\t// iterator insert(iterator position, const value_type& value);\n\t\trbVectorInt.insert(rbVectorInt.begin(), 999);\n\t\tEATEST_VERIFY(rbVectorInt[0] == 999);\n\t\tEATEST_VERIFY(rbVectorInt[1] == 0);\n\t\tEATEST_VERIFY(rbVectorInt[5] == 4);\n\n\t\trbVectorInt.clear();\n\t\trbVectorInt.push_back(0);\n\t\trbVectorInt.push_back(1);\n\t\trbVectorInt.push_back(2);\n\t\trbVectorInt.push_back(3);\n\t\trbVectorInt.push_back(4);\n\t\trbVectorInt.push_back(5);\n\t\trbVectorInt.push_back(6);\n\t\tEATEST_VERIFY(rbVectorInt[0] == 1);\n\t\tEATEST_VERIFY(rbVectorInt[5] == 6);\n\n\t\t// iterator insert(iterator position, const value_type& value);\n\t\trbVectorInt.insert(rbVectorInt.begin(), 999);\n\t\tEATEST_VERIFY(rbVectorInt[0] == 999);\n\t\tEATEST_VERIFY(rbVectorInt[1] == 1);\n\t\tEATEST_VERIFY(rbVectorInt[5] == 5);\n\n\t\t// iterator insert(iterator position, const value_type& value);\n\t\tRBVectorInt::iterator it = rbVectorInt.begin();\n\t\teastl::advance(it, 3);\n\t\trbVectorInt.insert(it, 888);\n\t\tEATEST_VERIFY(rbVectorInt[0] == 999);\n\t\tEATEST_VERIFY(rbVectorInt[1] == 1);\n\t\tEATEST_VERIFY(rbVectorInt[2] == 2);\n\t\tEATEST_VERIFY(rbVectorInt[3] == 888);\n\t\tEATEST_VERIFY(rbVectorInt[4] == 3);\n\t\tEATEST_VERIFY(rbVectorInt[5] == 4);\n\t}\n\n\t{\n\t\t// Comparation operator ==, operator <\n\t\t// Fix bug mentioned in https://github.com/electronicarts/EASTL/issues/511\n\t\ttypedef ring_buffer<int, vector<int>> RBVectorInt;\n\n\t\tRBVectorInt rbVectorInt(3);\n\n\t\trbVectorInt.push_back(0);\n\t\trbVectorInt.push_back(1);\n\t\trbVectorInt.push_back(2);\n\t\trbVectorInt.push_back(3);\n\t\trbVectorInt.push_back(4);\n\n\t\tEATEST_VERIFY(rbVectorInt[0] == 2);\n\t\tEATEST_VERIFY(rbVectorInt[1] == 3);\n\t\tEATEST_VERIFY(rbVectorInt[2] == 4);\n\n\t\tRBVectorInt rbVectorInt2({3, 4, 2});\n\t\tRBVectorInt rbVectorInt3({2, 3, 4});\n\t\tRBVectorInt rbVectorInt4({3, 4, 5});\n\n\t\tEATEST_VERIFY(rbVectorInt != rbVectorInt2);\n\t\tEATEST_VERIFY(rbVectorInt == rbVectorInt3);\n\t\tEATEST_VERIFY(rbVectorInt < rbVectorInt4);\n\n\t\t// Different size\n\t\tRBVectorInt rbVectorInt5({1, 2});\n\t\tEATEST_VERIFY(rbVectorInt != rbVectorInt5);\n\t\tEATEST_VERIFY(rbVectorInt > rbVectorInt5);\n\n\t\tRBVectorInt rbVectorInt6({2, 3});\n\t\tEATEST_VERIFY(rbVectorInt != rbVectorInt6);\n\t\tEATEST_VERIFY(rbVectorInt > rbVectorInt6);\n\n\t\tRBVectorInt rbVectorInt7({3, 4});\n\t\tEATEST_VERIFY(rbVectorInt != rbVectorInt7);\n\t\tEATEST_VERIFY(rbVectorInt < rbVectorInt7);\n\n\t\tRBVectorInt rbVectorInt8({1, 2, 3, 4});\n\t\tEATEST_VERIFY(rbVectorInt != rbVectorInt8);\n\t\tEATEST_VERIFY(rbVectorInt > rbVectorInt8);\n\n\t\tRBVectorInt rbVectorInt9({2, 3, 4, 5});\n\t\tEATEST_VERIFY(rbVectorInt != rbVectorInt9);\n\t\tEATEST_VERIFY(rbVectorInt < rbVectorInt9);\n\n\t\tRBVectorInt rbVectorInt10({3, 4, 5, 6});\n\t\tEATEST_VERIFY(rbVectorInt != rbVectorInt10);\n\t\tEATEST_VERIFY(rbVectorInt < rbVectorInt10);\n\t}\n\n\t{\n\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\ttypedef ring_buffer< string, list<string> > RBListString;\n\n\t\tint  counter = 0;\n\t\tconst int kBufferSize = 32;\n\t\tchar counterBuffer[kBufferSize];\n\n\t\t// explicit ring_buffer(size_type size = 0);\n\t\tconst int kOriginalCapacity = 50;\n\t\tRBListString rbListString(50);\n\n\t\t// bool empty() const;\n\t\t// size_type size() const;\n\t\t// bool validate() const;\n\t\tEATEST_VERIFY(rbListString.validate());\n\t\tEATEST_VERIFY(rbListString.empty());\n\t\tEATEST_VERIFY(rbListString.size() == 0);\n\t\tEATEST_VERIFY(rbListString.capacity() == 50);\n\n\t\t// void clear();\n\t\trbListString.clear();\n\t\tEATEST_VERIFY(rbListString.validate());\n\t\tEATEST_VERIFY(rbListString.empty());\n\t\tEATEST_VERIFY(rbListString.size() == 0);\n\t\tEATEST_VERIFY(rbListString.capacity() == 50);\n\n\t\t// container_type& get_container();\n\t\tRBListString::container_type& c = rbListString.get_container();\n\t\tEATEST_VERIFY(c.size() == (kOriginalCapacity + 1)); // We need to add one because the ring_buffer mEnd is necessarily an unused element.\n\n\t\t// iterator begin();\n\t\t// iterator end();\n\t\t// int validate_iterator(const_iterator i) const;\n\t\tRBListString::iterator it = rbListString.begin();\n\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));\n\n\t\twhile(it != rbListString.end()) // This loop should do nothing.\n\t\t{\n\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t++it;\n\t\t}\n\n\t\t// void push_back(const value_type& value);\n\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\t\trbListString.push_back(string(counterBuffer));\n\t\tEATEST_VERIFY(rbListString.validate());\n\t\tEATEST_VERIFY(!rbListString.empty());\n\t\tEATEST_VERIFY(rbListString.size() == 1);\n\t\tEATEST_VERIFY(rbListString.capacity() == 50);\n\n\t\tit = rbListString.begin();\n\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\tEATEST_VERIFY(*it == \"0\");\n\n\t\t// reference front();\n\t\t// reference back();              \n\t\tstring& sFront = rbListString.front();\n\t\tstring& sBack  = rbListString.back();\n\t\tEATEST_VERIFY(&sFront == &sBack);\n\n\t\t// void push_back();\n\t\tstring& ref = rbListString.push_back();\n\t\tEATEST_VERIFY(rbListString.validate());\n\t\tEATEST_VERIFY(rbListString.size() == 2);\n\t\tEATEST_VERIFY(rbListString.capacity() == 50);\n\t\tEATEST_VERIFY(&ref == &rbListString.back());\n\n\t\tit = rbListString.begin();\n\t\t++it;\n\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\tEATEST_VERIFY(it->empty());\n\n\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\t\t*it = counterBuffer;\n\t\tEATEST_VERIFY(*it == \"1\");\n\n\t\t++it;\n\t\tEATEST_VERIFY(it == rbListString.end());\n\n\t\tit = rbListString.begin();\n\t\twhile(it != rbListString.end())\n\t\t{\n\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\t\t++it;\n\t\t}\n\n\t\t// reference operator[](size_type n);\n\t\tstring& s0 = rbListString[0];\n\t\tEATEST_VERIFY(s0 == \"0\");\n\n\t\tstring& s1 = rbListString[1];\n\t\tEATEST_VERIFY(s1 == \"1\");\n\n\t\t// Now we start hammering the ring buffer with push_back.\n\t\tfor(eastl_size_t i = 0, iEnd = rbListString.capacity() * 5; i != iEnd; i++)\n\t\t{\n\t\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\t\t\trbListString.push_back(string(counterBuffer));\n\t\t\tEATEST_VERIFY(rbListString.validate());\n\t\t}\n\n\t\tint  counterCheck = counter - 1;\n\t\tchar counterCheckBuffer[kBufferSize];\n\t\tEA::StdC::Snprintf(counterCheckBuffer, kBufferSize, \"%d\", counterCheck);\n\t\tEATEST_VERIFY(rbListString.back() == counterCheckBuffer);\n\n\t\t// reverse_iterator rbegin();\n\t\t// reverse_iterator rend();\n\t\tfor(RBListString::reverse_iterator ri = rbListString.rbegin(); ri != rbListString.rend(); ++ri)\n\t\t{\n\t\t\tEA::StdC::Snprintf(counterCheckBuffer, kBufferSize, \"%d\", counterCheck--);\n\t\t\tEATEST_VERIFY(*ri == counterCheckBuffer);\n\t\t}\n\n\t\t++counterCheck;\n\n\t\t// iterator begin();\n\t\t// iterator end();\n\t\tfor(RBListString::iterator i = rbListString.begin(); i != rbListString.end(); ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(rbListString.validate_iterator(i) == (isf_valid | isf_current | isf_can_dereference));\n\t\t\tEATEST_VERIFY(*i == counterCheckBuffer);\n\t\t\tEA::StdC::Snprintf(counterCheckBuffer, kBufferSize, \"%d\", ++counterCheck);\n\t\t}\n\n\t\t// void clear();\n\t\trbListString.clear();\n\t\tEATEST_VERIFY(rbListString.validate());\n\t\tEATEST_VERIFY(rbListString.empty());\n\t\tEATEST_VERIFY(rbListString.size() == 0);\n\t\tEATEST_VERIFY(rbListString.capacity() == 50);\n\n\t\t// Random operations\n\t\t// Not easy to test the expected values without some tedium.\n\t\tfor(int j = 0; j < 10000 + (gEASTL_TestLevel * 10000); j++)\n\t\t{\n\t\t\tEA::StdC::Snprintf(counterBuffer, kBufferSize, \"%d\", counter++);\n\n\t\t\tconst eastl_size_t op = rng.RandLimit(12);\n\t\t\tconst eastl_size_t s  = rbListString.size();\n\n\t\t\tif(op == 0)\n\t\t\t{\n\t\t\t\t// void push_back(const value_type& value);\n\n\t\t\t\trbListString.push_back(string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 1)\n\t\t\t{\n\t\t\t\t// void push_back();\n\n\t\t\t\tstring& ref2 = rbListString.push_back();\n\t\t\t\trbListString.back() = string(counterBuffer);\n\t\t\t\tEATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));\n\t\t\t\tEATEST_VERIFY(&ref2 == &rbListString.back());\n\t\t\t}\n\t\t\telse if(op == 2)\n\t\t\t{\n\t\t\t\t// void pop_back();\n\n\t\t\t\tif(!rbListString.empty())\n\t\t\t\t{\n\t\t\t\t\trbListString.pop_back();\n\t\t\t\t\tEATEST_VERIFY(rbListString.size() == (s - 1));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 3)\n\t\t\t{\n\t\t\t\t// void push_front(const value_type& value);\n\n\t\t\t\trbListString.push_front(string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 4)\n\t\t\t{\n\t\t\t\t// void push_front();\n\n\t\t\t\tstring& ref2 = rbListString.push_front();\n\t\t\t\trbListString.front() = string(counterBuffer);\n\t\t\t\tEATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));\n\t\t\t\tEATEST_VERIFY(&ref2 == &rbListString.front());\n\t\t\t}\n\t\t\telse if(op == 5)\n\t\t\t{\n\t\t\t\t// void pop_front();\n\n\t\t\t\tif(!rbListString.empty())\n\t\t\t\t{\n\t\t\t\t\trbListString.pop_front();\n\t\t\t\t\tEATEST_VERIFY(rbListString.size() == (s - 1));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 6)\n\t\t\t{\n\t\t\t\t// iterator insert(iterator position, const value_type& value);\n\n\t\t\t\tit = rbListString.begin();\n\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);\n\t\t\t\teastl::advance(it, dist);\n\n\t\t\t\tif(it == rbListString.end())\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\trbListString.insert(it, string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbListString.size() == eastl::min(s + 1, rbListString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 7)\n\t\t\t{\n\t\t\t\t// void insert(iterator position, size_type n, const value_type& value);\n\n\t\t\t\tit = rbListString.begin();\n\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);\n\t\t\t\teastl::advance(it, dist);\n\n\t\t\t\tif(it == rbListString.end())\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\tconst eastl_size_t count = (eastl_size_t)rng.RandLimit(10);\n\n\t\t\t\trbListString.insert(it, count, string(counterBuffer));\n\t\t\t\tEATEST_VERIFY(rbListString.size() == eastl::min(s + count, rbListString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 8)\n\t\t\t{\n\t\t\t\t// template <typename InputIterator>\n\t\t\t\t// void insert(iterator position, InputIterator first, InputIterator last);\n\n\t\t\t\tstring stringArray[10];\n\n\t\t\t\tit = rbListString.begin();\n\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s + 1);\n\t\t\t\teastl::advance(it, dist);\n\n\t\t\t\tif(it == rbListString.end())\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\tconst eastl_size_t count = (eastl_size_t)rng.RandLimit(10);\n\n\t\t\t\trbListString.insert(it, stringArray, stringArray + count);\n\t\t\t\tEATEST_VERIFY(rbListString.size() == eastl::min(s + count, rbListString.capacity()));\n\t\t\t}\n\t\t\telse if(op == 9)\n\t\t\t{\n\t\t\t\t// iterator erase(iterator position);\n\n\t\t\t\tif(!rbListString.empty())\n\t\t\t\t{\n\t\t\t\t\tit = rbListString.begin();\n\t\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s);\n\t\t\t\t\teastl::advance(it, dist);\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it) == (isf_valid | isf_current | isf_can_dereference));\n\t\t\t\t\trbListString.erase(it);\n\n\t\t\t\t\tEATEST_VERIFY(rbListString.size() == (s  - 1));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 10)\n\t\t\t{\n\t\t\t\t// iterator erase(iterator first, iterator last);\n\n\t\t\t\tif(!rbListString.empty())\n\t\t\t\t{\n\t\t\t\t\tRBListString::iterator it1 = rbListString.begin();\n\t\t\t\t\tconst eastl_size_t pos = rng.RandLimit((uint32_t)s / 4);\n\t\t\t\t\teastl::advance(it1, pos);\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it1) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\t\tRBListString::iterator it2 = it1;\n\t\t\t\t\tconst eastl_size_t dist = rng.RandLimit((uint32_t)s / 4);\n\t\t\t\t\teastl::advance(it2, dist);\n\t\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(it2) == (isf_valid | isf_current | isf_can_dereference));\n\n\t\t\t\t\tEATEST_VERIFY(s > (pos + dist));\n\t\t\t\t\trbListString.erase(it1, it2);\n\t\t\t\t\tEATEST_VERIFY(rbListString.size() == (s - dist));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(op == 11)\n\t\t\t{\n\t\t\t\t// void resize(size_type n);\n\t\t\t\tconst eastl_size_t nSubOp = rng.RandLimit(100);\n\n\t\t\t\tif(nSubOp == 1)\n\t\t\t\t{\n\t\t\t\t\trbListString.resize(kOriginalCapacity);\n\t\t\t\t\tEATEST_VERIFY(rbListString.size() == (RBListString::size_type)kOriginalCapacity);\n\t\t\t\t}\n\t\t\t\telse if(nSubOp == 2)\n\t\t\t\t{\n\t\t\t\t\tconst eastl_size_t newSize = rng.RandLimit((uint32_t)s * 2) + 2;\n\n\t\t\t\t\trbListString.resize(newSize);\n\t\t\t\t\tEATEST_VERIFY(rbListString.size() == newSize);\n\t\t\t\t}\n\t\t\t\telse if(nSubOp == 3)\n\t\t\t\t{\n\t\t\t\t\trbListString.clear();\n\t\t\t\t\tEATEST_VERIFY(rbListString.size() == 0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(rbListString.validate());\n\t\t}\n\n\t\t// We make sure that after the above we still have some contents.\n\t\tif(rbListString.size() < 8)\n\t\t\trbListString.resize(8);\n\n\t\tEATEST_VERIFY(rbListString.validate());\n\n\t\t// Test const functions\n\t\t// const_iterator begin() const;\n\t\t// const_iterator end() const;\n\t\t// const_reverse_iterator rbegin() const;\n\t\t// const_reverse_iterator rend() const;\n\t\t// const_reference front() const;\n\t\t// const_reference back() const;\n\t\t// const_reference operator[](size_type n) const;\n\t\t// const container_type& get_container() const;\n\t\tconst RBListString& rbVSConst = rbListString;\n\n\t\tfor(RBListString::const_iterator ic = rbVSConst.begin(); ic != rbVSConst.end(); ++ic)\n\t\t{\n\t\t\tEATEST_VERIFY(rbListString.validate_iterator(ic) == (isf_valid | isf_current | isf_can_dereference));\n\t\t}\n\n\t\tfor(RBListString::const_reverse_iterator ric = rbVSConst.rbegin(); ric != rbVSConst.rend(); ++ric)\n\t\t{\n\t\t\tif(ric == rbVSConst.rbegin())\n\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(ric.base()) == (isf_valid | isf_current));\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(rbListString.validate_iterator(ric.base()) == (isf_valid | isf_current | isf_can_dereference));\n\t\t}\n\n\t\tEATEST_VERIFY(rbVSConst.front() == rbListString.front());\n\t\tEATEST_VERIFY(rbVSConst.back() == rbListString.back());\n\t\tEATEST_VERIFY(rbVSConst[0] == rbListString[0]);\n\t\tEATEST_VERIFY(&rbVSConst.get_container() == &rbListString.get_container());\n\n\n\t\t// Test additional constructors.\n\t\t// ring_buffer(const this_type& x);\n\t\t// explicit ring_buffer(const Container& x);\n\t\t// this_type& operator=(const this_type& x);\n\t\t// void swap(this_type& x);\n\t\tRBListString rbListString2(rbListString);\n\t\tRBListString rbListString3(rbListString.get_container());\n\t\tRBListString rbListString4(rbListString.capacity() / 2);\n\t\tRBListString rbListString5(rbListString.capacity() * 2);\n\n\t\tEATEST_VERIFY(rbListString.validate());\n\t\tEATEST_VERIFY(rbListString2.validate());\n\t\tEATEST_VERIFY(rbListString3.validate());\n\t\tEATEST_VERIFY(rbListString4.validate());\n\t\tEATEST_VERIFY(rbListString5.validate());\n\n\t\tEATEST_VERIFY(rbListString == rbListString2);\n\t\tEATEST_VERIFY(rbListString3.get_container() == rbListString2.get_container());\n\n\t\trbListString3 = rbListString4;\n\t\tEATEST_VERIFY(rbListString3.validate());\n\n\t\teastl::swap(rbListString2, rbListString4);\n\t\tEATEST_VERIFY(rbListString2.validate());\n\t\tEATEST_VERIFY(rbListString3.validate());\n\t\tEATEST_VERIFY(rbListString4.validate());\n\t\tEATEST_VERIFY(rbListString == rbListString4);\n\t\tEATEST_VERIFY(rbListString2 == rbListString3);\n\n\t\t// void ring_buffer<T, Container>::reserve(size_type n)\n\t\teastl_size_t cap = rbListString2.capacity();\n\t\trbListString2.reserve(cap += 2);\n\t\tEATEST_VERIFY(rbListString2.validate());\n\t\tEATEST_VERIFY(rbListString2.capacity() == cap);\n\t\trbListString2.reserve(cap -= 4); // This should act as a no-op if we are following convention.\n\t\tEATEST_VERIFY(rbListString2.validate());\n\n\n\t\t// template <typename InputIterator>\n\t\t// void assign(InputIterator first, InputIterator last);\n\t\tstring stringArray[10];\n\t\tfor(int q = 0; q < 10; q++)\n\t\t\tstringArray[q] = '0' + (char)q;\n\n\t\trbListString5.assign(stringArray, stringArray + 10);\n\t\tEATEST_VERIFY(rbListString5.validate());\n\t\tEATEST_VERIFY(rbListString5.size() == 10);\n\t\tEATEST_VERIFY(rbListString5.front() == \"0\");\n\t\tEATEST_VERIFY(rbListString5.back() == \"9\");\n\n\n\t\t// ring_buffer(this_type&& x);\n\t\t// ring_buffer(this_type&& x, const allocator_type& allocator);\n\t\t// this_type& operator=(this_type&& x);\n\n\t\tRBListString rbListStringM1(eastl::move(rbListString5));\n\t\tEATEST_VERIFY(rbListStringM1.validate() && rbListString5.validate());\n\t\tEATEST_VERIFY((rbListStringM1.size() == 10) && (rbListString5.size() == 0));\n\n\t\tRBListString rbListStringM2(eastl::move(rbListStringM1), RBListString::allocator_type());\n\t\tEATEST_VERIFY(rbListStringM2.validate() && rbListStringM1.validate());\n\t\tEATEST_VERIFY((rbListStringM2.size() == 10) && (rbListStringM1.size() == 0));\n\n\t\trbListStringM1 = eastl::move(rbListStringM2);\n\t\tEATEST_VERIFY(rbListStringM1.validate() && rbListStringM2.validate());\n\t\tEATEST_VERIFY((rbListStringM1.size() == 10) && (rbListStringM2.size() == 0));\n\t}\n\n\n\n\t{\n\t\t// ring_buffer(std::initializer_list<value_type> ilist, const allocator_type& allocator = allocator_type());\n\t\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t\t// void     insert(iterator position, std::initializer_list<value_type> ilist);\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\tring_buffer<int> intBuffer = { 0, 1, 2 };\n\t\t\tEATEST_VERIFY(VerifySequence(intBuffer.begin(), intBuffer.end(), int(), \"ring_buffer std::initializer_list\", 0, 1, 2, -1));\n\n\t\t\tintBuffer = { 16, 17, 18 };\n\t\t\tEATEST_VERIFY(VerifySequence(intBuffer.begin(), intBuffer.end(), int(), \"ring_buffer std::initializer_list\", 16, 17, 18, -1));\n\n\t\t\t// We need to increase the capacity in order to insert new items because the ctor above set the capacity to be only enough to hold the initial list.\n\t\t\tintBuffer.reserve(intBuffer.capacity() + 2);\n\t\t\tintBuffer.insert(intBuffer.begin(), { 14, 15 });\n\t\t\tEATEST_VERIFY(VerifySequence(intBuffer.begin(), intBuffer.end(), int(), \"ring_buffer std::initializer_list\", 14, 15, 16, 17, 18, -1));\n\t\t#endif\n\t}\n\n\t{\n\t\t// Regression for user-reported problem.\n\t\ttypedef eastl::fixed_vector<float, 8>                     GamepadData_t;\n\t\ttypedef eastl::ring_buffer<GamepadData_t>                 GamepadDataDelayBuffer_t;\n\t\ttypedef eastl::fixed_vector<GamepadDataDelayBuffer_t, 32> GamepadDataDelayBufferTable_t;\n\n\t\tGamepadDataDelayBufferTable_t mDelayTable;\n\t\tmDelayTable.resize(32);\n\t\tfor(eastl_size_t i = 0; i < mDelayTable.size(); i++)\n\t\t\tmDelayTable[i].reserve(16);\n\t\t\n\t\tGamepadData_t data(8, 1.f);\n\t\tmDelayTable[0].push_back(data);\n\t\tmDelayTable[0].push_back(data);\n\t\tmDelayTable[0].push_back(data);\n\t\tmDelayTable[0].push_back(data);\n\n\t\tEATEST_VERIFY(mDelayTable[0].size() == 4);\n\t\tGamepadData_t dataFront = mDelayTable[0].front();\n\t\tEATEST_VERIFY((dataFront.size() == 8) && (dataFront[0] == 1.f));\n\t\tmDelayTable[0].pop_front();\n\t}\n\n\t{\n\t\t// Regression for bug with iterator subtraction\n\t\ttypedef eastl::ring_buffer<int>\t\tIntBuffer_t;\n\t\tIntBuffer_t intBuffer = { 0, 1, 2, 3, 4, 5, 6, 7 };\n\t\tIntBuffer_t::iterator it = intBuffer.begin();\n\n\t\tEATEST_VERIFY(*it == 0);\n\t\tit += 4;\n\t\tEATEST_VERIFY(*it == 4);\n\t\tit--;\n\t\tEATEST_VERIFY(*it == 3);\n\t\tit -= 2;\n\t\tEATEST_VERIFY(*it == 1);\n\n\t\tintBuffer.push_back(8);\n\t\tintBuffer.push_back(9);\n\t\tintBuffer.push_back(10);\n\t\tintBuffer.push_back(11);\n\n\t\tEATEST_VERIFY(*it == 10);\n\t\tit -= 3;\n\t\tEATEST_VERIFY(*it == 7); // Test looping around the end of the underlying container\n\t\tit -= 5;\n\t\tEATEST_VERIFY(*it == 11); // Test wrapping around begin to end of the ring_buffer\n\t\tit -= 2;\n\t\tEATEST_VERIFY(*it == 9); // It is important to test going back to the beginning of the underlying container.\n\n\t}\n\n\t// fixed_ring_buffer<T,N> tests\n\t// ring_buffer<T, fixed_vector<T,N>> tests\n\t{\n\t\t{\n\t\t\t// (MAX_ELEMENTS - 1) accommodates the ring_buffer sentinel\n\t\t\tconst int MAX_ELEMENTS = 8;\n\t\t\teastl::ring_buffer<int, eastl::fixed_vector<int, MAX_ELEMENTS, false>> rb(MAX_ELEMENTS - 1);  \n\n\t\t\tfor (int i = 0; i < MAX_ELEMENTS - 1; i++)\n\t\t\t\trb.push_back(i);\n\n\t\t\tauto it = rb.begin();\n\t\t\tfor (int i = 0; i < MAX_ELEMENTS - 1; i++)\n\t\t\t\t{ EATEST_VERIFY(*it++ == i); }\n\t\t}\n\n\t\t#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t{\n\t\t\tconst int MAX_ELEMENTS = 25;\n\t\t\teastl::fixed_ring_buffer<int, MAX_ELEMENTS> rb(MAX_ELEMENTS);\n\n\t\t\tfor(int i = 0; i < MAX_ELEMENTS; i++)\n\t\t\t\trb.push_back(i);\n\n\t\t\tauto it = rb.begin();\n\t\t\tfor(int i = 0; i < MAX_ELEMENTS; i++)\n\t\t\t\t{ EATEST_VERIFY(*it++ == i); }\n\t\t}\n\t\t#endif\n\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS) && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)\n\t\t{\n\t\t\tconst int MAX_ELEMENTS = 8;\n\t\t\teastl::fixed_ring_buffer<int, MAX_ELEMENTS> rb = {0, 1, 2, 3, 4, 5, 6, 7};\n\n\t\t\tauto it = rb.begin();\n\t\t\tfor(int i = 0; i < MAX_ELEMENTS; i++)\n\t\t\t\t{ EATEST_VERIFY(*it++ == i); }\n\t\t}\n\n\t\t{\n\t\t\tstruct LocalStruct {};\n\t\t\tfixed_ring_buffer<LocalStruct, 8> rb = {{{}, {}, {}}};\n\t\t\tEATEST_VERIFY(rb.size() == 3);\n\t\t}\n\t\t#endif\n\t}\n\n\t{\n\t\tconst auto MAX_ELEMENTS = EASTL_MAX_STACK_USAGE;\n\n\t\t// create a container simulating LARGE state that exceeds\n\t\t// our maximum stack size macro. This forces our ring_buffer implementation\n\t\t// to allocate the container in the heap instead of holding it on the stack.\n\t\t// This test ensures that allocation is NOT serviced by the default global heap.  \n\t\t// Instead it is serviced by the allocator of the ring_buffers underlying container.\n\t\tstruct PaddedVector : public eastl::vector<int, MallocAllocator>\n\t\t{\n\t\t\tchar mPadding[EASTL_MAX_STACK_USAGE];\n\t\t};\n\n\t\tMallocAllocator::reset_all();\n\t\tCountingAllocator::resetCount();\n\n\t\t{\n\t\t\tCountingAllocator countingAlloc;\n\t\t\tAutoDefaultAllocator _(&countingAlloc);\n\n\t\t\teastl::ring_buffer<int, PaddedVector> intBuffer(1);  \n\t\t\tfor (int i = 0; i < MAX_ELEMENTS; i++)\n\t\t\t\tintBuffer.push_back(i);\n\n\t\t#if !EASTL_OPENSOURCE\n\t\t\tconst auto cacheAllocationCount = gEASTLTest_TotalAllocationCount.load(eastl::memory_order_relaxed);\n\t\t#endif\n\t\t\tconst auto cacheMallocatorCount = MallocAllocator::mAllocCountAll;\n\t\t\tconst auto forceReAllocSize = intBuffer.size() * 2;\n\n\t\t\tintBuffer.resize(forceReAllocSize);\n\n\t\t#if !EASTL_OPENSOURCE\n\t\t\tVERIFY(cacheAllocationCount == gEASTLTest_TotalAllocationCount.load(eastl::memory_order_relaxed));\n\t\t#endif\n\t\t\tVERIFY(cacheMallocatorCount <  MallocAllocator::mAllocCountAll);\n\t\t\tVERIFY(CountingAllocator::neverUsed());\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestSList.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/slist.h>\n#include <EABase/eabase.h>\n#include <EASTL/fixed_allocator.h>\n\nusing namespace eastl;\n\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\nstruct TestObj\n{\n\tTestObj() : mI(0), mMoveCtor(0), mCopyCtor(0) {} \n\texplicit TestObj(int i) : mI(i), mMoveCtor(0), mCopyCtor(0) {}\n\texplicit TestObj(int a, int b, int c, int d) : mI(a+b+c+d), mMoveCtor(0), mCopyCtor(0) {}\n\n\tTestObj(TestObj&& other)\n\t{\n\t\tmI = other.mI;\n\t\tmMoveCtor = other.mMoveCtor;\n\t\tmCopyCtor = other.mCopyCtor;\n\t\tmMoveCtor++;\n\t}\n\n\tTestObj(const TestObj& other)\n\t{\n\t\tmI = other.mI;\n\t\tmMoveCtor = other.mMoveCtor;\n\t\tmCopyCtor = other.mCopyCtor;\n\t\tmCopyCtor++;\n\t}\n\n\tTestObj& operator=(const TestObj& other) \n\t{\n\t\tmI = other.mI;\n\t\tmMoveCtor = other.mMoveCtor;\n\t\tmCopyCtor = other.mCopyCtor;\n\t\treturn *this;\n\t}\n\n\tint mI;\n\tint mMoveCtor;\n\tint mCopyCtor;\n};\n\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// TestSList\nint TestSList()\n{\n\tint nErrorCount = 0;\n\n\t// slist();\n\t{\n\t\tslist<int> list;\n\t\tVERIFY(list.empty());\n\t\tVERIFY(list.size() == 0);\n\t}\n\n\t// slist(const allocator_type& allocator);\n\t{ \n\t\tMallocAllocator::reset_all();\n\n\t\tVERIFY(MallocAllocator::mAllocCountAll == 0);\n\t\tslist<int, MallocAllocator> list;\n\t\tlist.resize(100, 42);\n\t\tVERIFY(MallocAllocator::mAllocCountAll == 100);\n\t}\n\n\t// explicit slist(size_type n, const allocator_type& allocator = EASTL_SLIST_DEFAULT_ALLOCATOR);\n\t{\n\t\tslist<int> list(100);\n\t\tVERIFY(list.size() == 100);\n\t\tVERIFY(!list.empty());\n\t}\n\n\t// slist(size_type n, const value_type& value, const allocator_type& allocator = EASTL_SLIST_DEFAULT_ALLOCATOR);\n\t{\n\t\tslist<int> list(32, 42);\n\t\tVERIFY(list.size() == 32);\n\t\tVERIFY(list.front() == 42);\n\t\tVERIFY(!list.empty());\n\t}\n\n\t// slist(const this_type& x);\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 42);\n\n\t\tVERIFY(!list1.empty());\n\t\tslist<int> list2(list1);\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list1 == list2);\n\t}\n\t\n\t// slist(std::initializer_list<value_type> ilist, const allocator_type& allocator = EASTL_SLIST_DEFAULT_ALLOCATOR);\n\t{\n\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\tslist<int> list1({1,2,3,4,5,6,7,8});\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 8);\n\t#endif\n\t}\n\n\t// slist(this_type&& x);\n\t{\n\t\tslist<int> list1; \n\t\tlist1.resize(100,42);\n\n\t\tslist<int> list2(eastl::move(list1));\n\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list1 != list2);\n\t}\n\t\n\t// slist(this_type&& x, const allocator_type& allocator);\n\t{ } \n\n\t// slist(InputIterator first, InputIterator last); \n\t{\n\t\tslist<int> list1; \n\t\tlist1.resize(100, 42);\n\t\tVERIFY(!list1.empty());\n\n\t\tslist<int> list2(list1.begin(), list1.end());\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list1 == list2);\n\t}\n\n\t// this_type& operator=(const this_type& x);\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 42);\n\t\tVERIFY(!list1.empty());\n\n\t\tslist<int> list2 = list1;\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list1 == list2);\n\t}\n\n\t// this_type& operator=(std::initializer_list<value_type>);\n\t{\n\t\tslist<int> list1 = {1,2,3,4,5,6,7,8};\n\t\tVERIFY(!list1.empty());\n\t}\n\n\t// this_type& operator=(this_type&& x);\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 42);\n\t\tslist<int> list2 = eastl::move(list1);\n\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list1 != list2);\n\t}\n\n\t// void swap(this_type& x);\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(8, 37);\n\n\t\tslist<int> list2; \n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 8);\n\t\tVERIFY(list2.empty());\n\n\t\tlist2.swap(list1);\n\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(!list2.empty());\n\t}\n\n\t// void assign(size_type n, const value_type& value);\n\t{\n\t\tslist<int> list1;\n\t\tlist1.assign(100, 42);\n\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 100);\n\n\t\tfor(auto& e : list1)\n\t\t\tVERIFY(e == 42);\n\t}\n\n\t// void assign(std::initializer_list<value_type> ilist);\n\t{\n\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\tslist<int> list1;\n\t\tlist1.assign({1,2,3,4,5,6,7,8});\n\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 8);\n\n\t\tauto i = eastl::begin(list1);\n\t\tVERIFY(*i == 1); i++;\n\t\tVERIFY(*i == 2); i++;\n\t\tVERIFY(*i == 3); i++;\n\t\tVERIFY(*i == 4); i++;\n\t\tVERIFY(*i == 5); i++;\n\t\tVERIFY(*i == 6); i++;\n\t\tVERIFY(*i == 7); i++;\n\t\tVERIFY(*i == 8); i++;\n\t\tVERIFY(i == eastl::end(list1));\n\t#endif\n\t}\n\n\t// void assign(InputIterator first, InputIterator last);\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 42);\n\t\tVERIFY(!list1.empty());\n\n\t\tslist<int> list2;\n\t\tlist2.assign(list1.begin(), list1.end());\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list1 == list2);\n\t}\n\n\t// iterator       begin() EA_NOEXCEPT;\n\t// const_iterator begin() const EA_NOEXCEPT;\n\t// const_iterator cbegin() const EA_NOEXCEPT;\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 1);\n\t\tVERIFY(!list1.empty());\n\n\t\tconst auto ci = list1.begin();\n\t\tauto i        = list1.begin();\n\t\tauto ci2      = list1.cbegin();\n\n\t\tVERIFY(*i   == 1);\n\t\tVERIFY(*ci  == 1);\n\t\tVERIFY(*ci2 == 1);\n\t}\n\n\t// iterator       end() EA_NOEXCEPT;\n\t// const_iterator end() const EA_NOEXCEPT;\n\t// const_iterator cend() const EA_NOEXCEPT;\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 42);\n\t\tVERIFY(!list1.empty());\n\n\t\tconst auto ci = list1.end();\n\t\tauto i = list1.end();\n\t\tauto ci2 = list1.cend();\n\n\t\tVERIFY(i == eastl::end(list1));\n\t\tVERIFY(ci == eastl::end(list1));\n\t\tVERIFY(ci2 == eastl::end(list1));\n\t}\n\n\t// iterator       before_begin() EA_NOEXCEPT;\n\t// const_iterator before_begin() const EA_NOEXCEPT;\n\t// const_iterator cbefore_begin() const EA_NOEXCEPT;\n\t// iterator        previous(const_iterator position);\n\t// const_iterator  previous(const_iterator position) const;\n\t{\n\t\tslist<int> list1;\n\n\t\tauto b = list1.begin();\n\t\tauto prev = list1.previous(b);\n\n\t\tVERIFY(prev == list1.before_begin());\n\t}\n\n\t// reference       front();\n\t// const_reference front() const;\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 1);\n\n\t\tVERIFY(list1.begin() == eastl::begin(list1));\n\t\tVERIFY(list1.front() == 1);\n\n\t\tconst slist<int> clist1(list1); \n\t\tVERIFY(clist1.front() == 1);\n\t\tVERIFY(list1.validate());\n\t\tVERIFY(clist1.validate());\n\t}\n\n\n\t//     void emplace_front(Args&&... args);\n\t{\n\t\tslist<TestObj> list1;\n\t\tVERIFY(list1.emplace_front(42).mI == 42);\n\t\tVERIFY(list1.front().mI == 42);\n\t\tVERIFY(list1.front().mCopyCtor == 0);\n\t\tVERIFY(list1.front().mMoveCtor == 0);\n\t\tVERIFY(list1.size() == 1);\n\t\tVERIFY(list1.validate());\n\n\t\tVERIFY(list1.emplace_front(1,2,3,4).mI == (1 + 2 + 3 + 4));\n\t\tVERIFY(list1.front().mCopyCtor == 0);\n\t\tVERIFY(list1.front().mMoveCtor == 0);\n\t\tVERIFY(list1.front().mI == (1+2+3+4));\n\t\tVERIFY(list1.size() == 2);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// void      push_front(const value_type& value);\n\t// reference push_front();\n\t// void      push_front(value_type&& value);\n\t{\n\t\tslist<TestObj> list1;\n\t\tlist1.push_front(TestObj(42));\n\t\tVERIFY(list1.front().mI == 42);\n\t\tVERIFY(list1.front().mCopyCtor == 0);\n\t\tVERIFY(list1.front().mMoveCtor == 1);\n\t\tVERIFY(list1.size() == 1);\n\n\t\tlist1.push_front();\n\t\tVERIFY(list1.front().mCopyCtor == 0);\n\t\tVERIFY(list1.front().mMoveCtor == 0);\n\t\tVERIFY(list1.front().mI == 0);\n\t\tVERIFY(list1.size() == 2);\n\n\t\tlist1.push_front().mI = 1492;\n\t\tVERIFY(list1.front().mI == 1492);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// void pop_front();\n\t{\n\t\tslist<int> list1;\n\t\tlist1.push_front(4);\n\t\tlist1.push_front(3);\n\t\tlist1.push_front(2);\n\t\tlist1.push_front(1);\n\n\t\tlist1.pop_front();\n\t\tVERIFY(list1.front() == 2);\n\t\tVERIFY(list1.size()  == 3);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.pop_front();\n\t\tVERIFY(list1.front() == 3);\n\t\tVERIFY(list1.size()  == 2);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.pop_front();\n\t\tVERIFY(list1.front() == 4);\n\t\tVERIFY(list1.size()  == 1);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// bool empty() const EA_NOEXCEPT;\n\t// size_type size() const EA_NOEXCEPT;\n\t{\n\t\tslist<int> list1;\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(list1.size() == 0);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.push_front(42);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 1);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.pop_front();\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(list1.size() == 0);\n\t\tVERIFY(list1.validate());\n\t}\n\n\n\t// void resize(size_type n, const value_type& value);\n\t// void resize(size_type n);\n\t{\n\t\tslist<int> list1;\n\t\tVERIFY(list1.empty());\n\t\tlist1.resize(100, 42);\n\t\tVERIFY(list1.front() == 42);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 100);\n\t\tVERIFY(list1.validate());\n\n\t\tslist<int> list2;\n\t\tVERIFY(list2.empty());\n\t\tlist2.resize(100);\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list2.size() == 100);\n\t\tVERIFY(list2.validate());\n\t}\n\n\t// iterator insert(const_iterator position);\n\t// iterator insert(const_iterator position, const value_type& value);\n\t// void     insert(const_iterator position, size_type n, const value_type& value);\n\t{\n\t\tstatic const int MAGIC_VALUE = 4242;\n\t\tstruct TestVal\n\t\t{\n\t\t\tTestVal() : mV(MAGIC_VALUE) {}\n\t\t\tTestVal(int v) : mV(v) {}\n\t\t\toperator int() { return mV; }\n\t\t\tint mV;\n\t\t};\n\n\t\tslist<TestVal> list1;\n\t\tVERIFY(list1.empty());\n\n\t\tauto insert_iter = eastl::begin(list1);\n\t\tlist1.insert(insert_iter);\n\t\tVERIFY(list1.size() == 1);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.insert(insert_iter, 42);\n\t\tVERIFY(list1.size() == 2);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.front() == MAGIC_VALUE);\n\t\tVERIFY(list1.validate());\n\n\n\t\tlist1.insert(insert_iter, 43);\n\t\tVERIFY(list1.size() == 3);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.front() == MAGIC_VALUE);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// template <typename InputIterator>\n\t// void insert(const_iterator position, InputIterator first, InputIterator last);\n\t{\n\t\tslist<int> list1;\n\t\tVERIFY(list1.empty());\n\t\tlist1.resize(100, 42);\n\t\tVERIFY(list1.size() == 100);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.validate());\n\n\t\tslist<int> list2;\n\t\tlist2.resize(400, 24);\n\t\tVERIFY(list2.size() == 400);\n\t\tVERIFY(!list2.empty());\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.insert(eastl::end(list1), eastl::begin(list2), eastl::end(list2)); // [42,42,42,...,42, | 24,24,24,24...]\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 500);\n\t\tVERIFY(list1.front() == 42);\n\t\tVERIFY(list1.validate());\n\n\t\tauto boundary_iter = list1.begin();\n\t\teastl::advance(boundary_iter, 100); // move to insertation point\n\t\tVERIFY(*boundary_iter == 24);\n\t\tVERIFY(list1.validate());\n\t}\n\n\n\t// Returns an iterator pointing to the last inserted element, or position if insertion count is zero.\n\t// iterator insert_after(const_iterator position);\n\t// iterator insert_after(const_iterator position, const value_type& value);\n\t// iterator insert_after(const_iterator position, size_type n, const value_type& value);\n\t// iterator insert_after(const_iterator position, std::initializer_list<value_type> ilist);\n\t{\n\t\tslist<int> list1;\n\t\tVERIFY(list1.empty());\n\t\tlist1.push_front();\n\n\t\tlist1.insert_after(list1.begin());\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 2);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.insert_after(list1.begin(), 43);\n\t\tVERIFY(list1.size() == 3);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.insert_after(list1.begin(), 10, 42);\n\t\tVERIFY(list1.size() == 13);\n\t\tVERIFY(eastl::count_if(list1.begin(), list1.end(), [](int i) { return i == 42; }) == 10);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.insert_after(list1.begin(), {1,2,3,4,5,6,7,8,9,0});\n\t\tVERIFY(list1.size() == 23);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// iterator insert_after(const_iterator position, value_type&& value);\n\t{\n\t\tslist<TestObj> list1;\n\t\tVERIFY(list1.empty());\n\t\tlist1.push_front();\n\n\t\tauto inserted = list1.insert_after(list1.begin(), TestObj(42));\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY((*inserted).mCopyCtor == 0);\n\t\tVERIFY((*inserted).mMoveCtor == 1);\n\t}\n\n\t// iterator insert_after(const_iterator position, InputIterator first, InputIterator last);\n\t{\n\t\tslist<int> list1 = {0,1,2,3,4};\n\t\tslist<int> list2 = {9,8,7,6,5};\n\t\tlist1.insert_after(list1.begin(), list2.begin(), list2.end());\n\t\tVERIFY(list1 == slist<int>({0,9,8,7,6,5,1,2,3,4}));\n\t}\n\n\t// iterator emplace_after(const_iterator position, Args&&... args);\n\t// iterator emplace_after(const_iterator position, value_type&& value);\n\t// iterator emplace_after(const_iterator position, const value_type& value);\n\t{\n\t\tslist<TestObj> list1;\n\t\tlist1.emplace_after(list1.before_begin(), 42);\n\t\tVERIFY(list1.front().mI == 42);\n\t\tVERIFY(list1.front().mCopyCtor == 0);\n\t\tVERIFY(list1.front().mMoveCtor == 0);\n\t\tVERIFY(list1.size() == 1);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.emplace_after(list1.before_begin(),1,2,3,4);\n\t\tVERIFY(list1.front().mCopyCtor == 0);\n\t\tVERIFY(list1.front().mMoveCtor == 0);\n\t\tVERIFY(list1.front().mI == (1+2+3+4));\n\t\tVERIFY(list1.size() == 2);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// iterator erase(const_iterator position);\n\t// iterator erase(const_iterator first, const_iterator last);\n\t{\n\t\tslist<int> list1 = {0,1,2,3,4,5,6,7};\n\n\t\tauto p = list1.begin();\n\t\tp++; p++; p++;\n\n\t\tlist1.erase(p);\n\t\tVERIFY(list1 == slist<int>({0,1,2,4,5,6,7}));\n\n\t\tlist1.erase(list1.begin(), list1.end());\n\t\tVERIFY(list1 == slist<int>({}));\n\t\tVERIFY(list1.size() == 0);\n\t\tVERIFY(list1.empty());\n\t}\n\n\t// iterator erase_after(const_iterator position);\n\t// iterator erase_after(const_iterator before_first, const_iterator last);\n\t{\n\t\tslist<int> list1 = {0,1,2,3,4,5,6,7};\n\t\tauto p = list1.begin();\n\n\t\tlist1.erase_after(p);\n\t\tVERIFY(list1 == slist<int>({0,2,3,4,5,6,7}));\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.erase_after(p);\n\t\tVERIFY(list1 == slist<int>({0,3,4,5,6,7}));\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.erase_after(p);\n\t\tVERIFY(list1 == slist<int>({0,4,5,6,7}));\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.erase_after(p, list1.end());\n\t\tVERIFY(list1 == slist<int>({0}));\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// void clear();\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 42);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == 100);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.clear();\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(list1.size() == 0);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// void reset_lose_memory();    \n\t{\n\t\ttypedef eastl::slist<int, fixed_allocator> SIntList;\n\t\ttypedef SIntList::node_type                SIntListNode;\n\t\tconst size_t  kBufferCount = 100;\n\t\tSIntListNode  buffer1[kBufferCount];\n\t\tSIntList      list1;\n\t\tconst size_t  kAlignOfSIntListNode = EA_ALIGN_OF(SIntListNode);\n\t\tlist1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(SIntListNode), kAlignOfSIntListNode);\n\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(list1.size() == 0);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.resize(kBufferCount, 42);\n\t\tVERIFY(!list1.empty());\n\t\tVERIFY(list1.size() == kBufferCount);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.reset_lose_memory();\n\t\tVERIFY(list1.empty());\n\t\tVERIFY(list1.size() == 0);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// void remove(const value_type& value);\n\t{\n\t\tslist<int> list1 = {0,1,2,3,4};\n\t\tslist<int> list2 = {0,1,3,4};\n\n\t\tlist1.remove(2);\n\n\t\tVERIFY(list1 == list2);\n\t\tVERIFY(list1.validate());\n\t\tVERIFY(list2.validate());\n\t}\n\n\t// void remove_if(Predicate predicate);\n\t{\n\t\tslist<int> list1;\n\t\tlist1.resize(100, 42);\n\t\tVERIFY(list1.size() == 100);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.remove_if([](int i) { return i == 1234; }); // intentionally remove nothing.\n\t\tVERIFY(list1.size() == 100);\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.remove_if([](int i) { return i == 42; });\n\t\tVERIFY(list1.size() == 0);\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// void reverse() EA_NOEXCEPT;\n\t{\n\t\tslist<int> list1 = {0,1,2,3,4};\n\t\tslist<int> list2 = {4,3,2,1,0};\n\t\tVERIFY(list1 != list2);\n\n\t\tlist1.reverse();\n\t\tVERIFY(list1 == list2);\n\t}\n\n\t// void splice(const_iterator position, this_type& x);\n\t// void splice(const_iterator position, this_type& x, const_iterator i);\n\t// void splice(const_iterator position, this_type& x, const_iterator first, const_iterator last);\n\t{\n\t\tslist<int> valid = {0,1,2,3,4,5,6,7};\t\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\n\t\t\tlist1.splice(list1.end(), list2);\n\n\t\t\tVERIFY(list1 == valid);\n\t\t\tVERIFY(list1.validate());\n\t\t}\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\n\n\t\t\tlist1.splice(list1.begin(), list2, list2.begin());\n\t\t\tVERIFY(list1 == slist<int>({4,0,1,2,3}));\n\t\t\tVERIFY(list2 == slist<int>({5,6,7}));\n\n\t\t\tlist1.splice(list1.begin(), list2, list2.begin());\n\t\t\tVERIFY(list1 == slist<int>({5,4,0,1,2,3}));\n\t\t\tVERIFY(list2 == slist<int>({6,7}));\n\n\t\t\tlist1.splice(list1.begin(), list2, list2.begin());\n\t\t\tVERIFY(list1 == slist<int>({6,5,4,0,1,2,3}));\n\t\t\tVERIFY(list2 == slist<int>({7}));\n\n\t\t\tlist1.splice(list1.begin(), list2, list2.begin());\n\t\t\tVERIFY(list1 == slist<int>({7,6,5,4,0,1,2,3}));\n\t\t\tVERIFY(list2 == slist<int>({}));\n\n\t\t\tVERIFY(list1.validate());\n\t\t\tVERIFY(list2.validate());\n\t\t}\n\t}\n\n\t// void splice(const_iterator position, this_type&& x);\n\t// void splice(const_iterator position, this_type&& x, const_iterator i);\n\t// void splice(const_iterator position, this_type&& x, const_iterator first, const_iterator last);\n\t{\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\t\n\n\t\t\tlist1.splice(list1.begin(), eastl::move(list2));\n\t\t\tVERIFY(list1 == slist<int>({4,5,6,7,0,1,2,3}));\n\t\t}\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\t\n\n\t\t\tlist1.splice(list1.begin(), eastl::move(list2), list2.begin());\n\t\t\tVERIFY(list1 == slist<int>({4,0,1,2,3}));\n\t\t}\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\t\n\n\t\t\tauto b = list2.begin();\n\t\t\tauto e = list2.end();\n\t\t\te = list2.previous(e);\n\t\t\te = list2.previous(e);\n\n\t\t\tlist1.splice(list1.begin(), eastl::move(list2), b, e);\n\t\t\tVERIFY(list1 == slist<int>({4,5,0,1,2,3}));\n\t\t}\n\t}\n\n\t// void splice_after(const_iterator position, this_type& x);\n\t// void splice_after(const_iterator position, this_type& x, const_iterator i);\n\t// void splice_after(const_iterator position, this_type& x, const_iterator first, const_iterator last);\n\t{\n\t\tslist<int> list1 = {0,1,2,3};\t\n\t\tslist<int> list2 = {4,5,6,7};\t\n\n\t\tlist1.splice_after(list1.begin(), list2);\n\t\tVERIFY(list1 == slist<int>({0,4,5,6,7,1,2,3}));\n\t\tVERIFY(list1.validate());\n\t\tVERIFY(list2.validate());\n\t}\n\n\t// void splice_after(const_iterator position, this_type&& x);\n\t// void splice_after(const_iterator position, this_type&& x, const_iterator i);\n\t// void splice_after(const_iterator position, this_type&& x, const_iterator first, const_iterator last);\n\t{\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\t\n\n\t\t\tlist1.splice_after(list1.begin(), eastl::move(list2));\n\t\t\tVERIFY(list1 == slist<int>({0,4,5,6,7,1,2,3}));\n\t\t}\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\t\n\n\t\t\tlist1.splice_after(list1.begin(), eastl::move(list2), list2.begin());\n\t\t\tVERIFY(list1 == slist<int>({0,5,6,7,1,2,3}));\n\t\t}\n\t\t{\n\t\t\tslist<int> list1 = {0,1,2,3};\n\t\t\tslist<int> list2 = {4,5,6,7};\t\n\n\t\t\tauto b = list2.begin();\n\t\t\tauto e = list2.end();\n\t\t\te = list2.previous(e);\n\t\t\te = list2.previous(e);\n\n\t\t\tlist1.splice_after(list1.begin(), eastl::move(list2), b, e);\n\t\t\tVERIFY(list1 == slist<int>({0,5,6,1,2,3}));\n\t\t}\n\t}\n\n\t// size_type unique();\n\t{\n\t\tslist<int> ref = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\t\tslist<int> a = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3,\n\t\t\t\t\t\t\t  4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 };\n\t\tVERIFY(a.unique() == 34);\n\t\tVERIFY(a == ref);\n\t}\n\n\t// size_type unique(BinaryPredicate);\n\t{\n\t\tstatic bool bBreakComparison;\n\t\tstruct A\n\t\t{\n\t\t\tint mValue;\n\t\t\tbool operator==(const A& other) const { return bBreakComparison ? false : mValue == other.mValue; }\n\t\t};\n\n\t\tslist<A> ref = { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9} };\n\t\tslist<A> a = { {0}, {0}, {0}, {0}, {0}, {0}, {1}, {2}, {2}, {2}, {2}, {3}, {4}, {5},\n\t\t\t\t\t\t\t{5}, {5}, {5}, {5}, {6}, {7}, {7}, {7}, {7}, {8}, {9}, {9}, {9} };\n\n\t\tbBreakComparison = true;\n\t\tVERIFY(a.unique() == 0); // noop because broken comparison operator\n\t\tVERIFY(a != ref);\n\n\t\tVERIFY(a.unique([](const A& lhs, const A& rhs) { return lhs.mValue == rhs.mValue; }) == 17);\n\n\t\tbBreakComparison = false;\n\t\tVERIFY(a == ref);\n\t}\n\n\t// void sort();\n\t{\n\t\tslist<int> list1 = {0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2, 1, 0};\n\t\tVERIFY(!eastl::is_sorted(eastl::begin(list1), eastl::end(list1)));\n\t\tVERIFY(list1.validate());\n\n\t\tlist1.sort();\n\n\t\tVERIFY(eastl::is_sorted(eastl::begin(list1), eastl::end(list1)));\n\t\tVERIFY(list1.validate());\n\t}\n\n\t// template <class Compare>\n\t// void sort(Compare compare);\n\t{\n\t\tauto compare = [](int a, int b) { return a > b;};\n\n\t\tslist<int> list1 = {0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2, 1, 0};\n\t\tVERIFY(!eastl::is_sorted(eastl::begin(list1), eastl::end(list1), compare));\n\t\tlist1.sort(compare);\n\t\tVERIFY(eastl::is_sorted(eastl::begin(list1), eastl::end(list1), compare));\n\t}\n\n\t{ // Test empty base-class optimization\n\t\tstruct UnemptyDummyAllocator : eastl::dummy_allocator\n\t\t{\n\t\t\tint foo;\n\t\t};\n\n\t\ttypedef eastl::slist<int, eastl::dummy_allocator> list1;\n\t\ttypedef eastl::slist<int, UnemptyDummyAllocator> list2;\n\n\t\tEATEST_VERIFY(sizeof(list1) < sizeof(list2));\n\t}\n\n\t{ // Test erase / erase_if\n\t\t{\n\t\t\tslist<int> l = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t\tauto numErased = eastl::erase(l, 5);\n\t\t\tVERIFY((l == slist<int>{0, 1, 2, 3, 4, 6, 7, 8, 9}));\n\t\t    VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(l, 7);\n\t\t\tVERIFY((l == slist<int>{0, 1, 2, 3, 4, 6, 8, 9}));\n\t\t    VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(l, 2);\n\t\t\tVERIFY((l == slist<int>{0, 1, 3, 4, 6, 8, 9}));\n\t\t    VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(l, 0);\n\t\t\tVERIFY((l == slist<int>{1, 3, 4, 6, 8, 9}));\n\t\t    VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(l, 4);\n\t\t\tVERIFY((l == slist<int>{1, 3, 6, 8, 9}));\n\t\t    VERIFY(numErased == 1);\n\t\t}\n\n\t\t{\n\t\t\tslist<int> l = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t\tauto numErased = eastl::erase_if(l, [](auto e) { return e % 2 == 0; });\n\t\t\tVERIFY((l == slist<int>{1, 3, 5, 7, 9}));\n\t\t    VERIFY(numErased == 5);\n\n\t\t\tnumErased = eastl::erase_if(l, [](auto e) { return e == 5; });\n\t\t\tVERIFY((l == slist<int>{1, 3, 7, 9}));\n\t\t    VERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase_if(l, [](auto e) { return e % 3 == 0; });\n\t\t\tVERIFY((l == slist<int>{1, 7}));\n\t\t    VERIFY(numErased == 2);\n\t\t}\n\t}\n\n\t{ // Test global operators\n\t\t{\n\t\t\tslist<int> list1 = {0, 1, 2, 3, 4, 5};\n\t\t\tslist<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tslist<int> list3 = {5, 6, 7, 8};\n\n\t\t\tVERIFY(list1 == list1);\n\t\t\tVERIFY(!(list1 != list1));\n\n\t\t\tVERIFY(list1 != list2);\n\t\t\tVERIFY(list2 != list3);\n\t\t\tVERIFY(list1 != list3);\n\n\t\t\tVERIFY(list1 < list2);\n\t\t\tVERIFY(list1 <= list2);\n\n\t\t\tVERIFY(list2 > list1);\n\t\t\tVERIFY(list2 >= list1);\n\n\t\t\tVERIFY(list3 > list1);\n\t\t\tVERIFY(list3 > list2);\n\t\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\t{\n\t\t\tslist<int> list1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tslist<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tslist<int> list3 = {-1, 0, 1, 2, 3, 4, 5};\n\n\t\t\t// Verify equality between list1 and list2\n\t\t\tVERIFY((list1 <=> list2) == 0);\n\t\t\tVERIFY(!((list1 <=> list2) != 0));\n\t\t\tVERIFY((list1 <=> list2) <= 0);\n\t\t\tVERIFY((list1 <=> list2) >= 0);\n\t\t\tVERIFY(!((list1 <=> list2) < 0));\n\t\t\tVERIFY(!((list1 <=> list2) > 0));\n\n\t\t\tlist1.push_front(-2); // Make list1 less than list2.\n\t\t\tlist2.push_front(-1);\n\n\t\t\t// Verify list1 < list2\n\t\t\tVERIFY(!((list1 <=> list2) == 0));\n\t\t\tVERIFY((list1 <=> list2) != 0);\n\t\t\tVERIFY((list1 <=> list2) <= 0);\n\t\t\tVERIFY(!((list1 <=> list2) >= 0));\n\t\t\tVERIFY(((list1 <=> list2) < 0));\n\t\t\tVERIFY(!((list1 <=> list2) > 0));\n\n\n\t\t\t// Verify list3.size() < list2.size() and list3 is a subset of list2\n\t\t\tVERIFY(!((list3 <=> list2) == 0));\n\t\t\tVERIFY((list3 <=> list2) != 0);\n\t\t\tVERIFY((list3 <=> list2) <= 0);\n\t\t\tVERIFY(!((list3 <=> list2) >= 0));\n\t\t\tVERIFY(((list3 <=> list2) < 0));\n\t\t\tVERIFY(!((list3 <=> list2) > 0));\n\t\t}\n\n\t\t{\n\t\t\tslist<int> list1 = {1, 2, 3, 4, 5, 6, 7};\n\t\t\tslist<int> list2 = {7, 6, 5, 4, 3, 2, 1};\n\t\t\tslist<int> list3 = {1, 2, 3, 4};\n\n\t\t\tstruct weak_ordering_slist\n\t\t\t{\n\t\t\t\tslist<int> slist;\n\t\t\t\tinline std::weak_ordering operator<=>(const weak_ordering_slist& b) const { return slist <=> b.slist; }\n\t\t\t};\n\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_slist{list1}, weak_ordering_slist{list2}) == std::weak_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_slist{list3}, weak_ordering_slist{list1}) == std::weak_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_slist{list2}, weak_ordering_slist{list1}) == std::weak_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_slist{list2}, weak_ordering_slist{list3}) == std::weak_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(weak_ordering_slist{list1}, weak_ordering_slist{list1}) == std::weak_ordering::equivalent);\n\n\t\t\tstruct strong_ordering_slist\n\t\t\t{\n\t\t\t\tslist<int> slist;\n\t\t\t\tinline std::strong_ordering operator<=>(const strong_ordering_slist& b) const { return slist <=> b.slist; }\n\t\t\t};\n\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_slist{list1}, strong_ordering_slist{list2}) == std::strong_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_slist{list3}, strong_ordering_slist{list1}) == std::strong_ordering::less);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_slist{list2}, strong_ordering_slist{list1}) == std::strong_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_slist{list2}, strong_ordering_slist{list3}) == std::strong_ordering::greater);\n\t\t\tVERIFY(synth_three_way{}(strong_ordering_slist{list1}, strong_ordering_slist{list1}) == std::strong_ordering::equal);\n\t\t}\n#endif\n\t}\n\n\treturn nErrorCount;\n}\n\n"
  },
  {
    "path": "test/source/TestSegmentedVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/segmented_vector.h>\n#include <EASTL/list.h>\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::segmented_vector<bool, 16>;\ntemplate class eastl::segmented_vector<int, 16>;\ntemplate class eastl::segmented_vector<Align64, 16>;\ntemplate class eastl::segmented_vector<TestObject, 16>;\n\n\nint TestSegmentedVector()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{\n\t\teastl::segmented_vector<int, 8> sv;\n\t\tsv.push_back(0);\n\t\tsv.push_back(1);\n\t\tsv.push_back(2);\n\t\tsv.push_back(3);\n\n\t\t{\n\t\t\tauto i = sv.begin();\n\t\t\tEATEST_VERIFY(*i == 0);\n\t\t\tEATEST_VERIFY(*i++ == 0);\n\t\t\tEATEST_VERIFY(*i++ == 1);\n\t\t\tEATEST_VERIFY(*i++ == 2);\n\t\t\tEATEST_VERIFY(*i++ == 3);\n\t\t}\n\n\t\t{\n\t\t\tauto i = sv.begin();\n\t\t\tEATEST_VERIFY(*i == 0);\n\t\t\tEATEST_VERIFY(*(++i) == 1);\n\t\t\tEATEST_VERIFY(*(++i) == 2);\n\t\t\tEATEST_VERIFY(*(++i) == 3);\n\t\t}\n\n\n\t\t{\n\t\t\tfor (int i = 4; i < 100; ++i)\n\t\t\t{\n\t\t\t\tsv.push_back(i);\n\t\t\t}\n\n\t\t\tEATEST_VERIFY(sv.size() == 100);\n\t\t\t// the capacity is always a multiple of the segment count,\n\t\t\t// in this case it should be the smallest multiple of 8\n\t\t\t// which is >= 100, that number is 104.\n\t\t\tEATEST_VERIFY(sv.capacity() == 104);\n\n\t\t\t// multi-segment iteration.\n\t\t\tint i = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t// pop_back() 25 items.\n\t\t\tfor (int i = 0; i < 25; ++i)\n\t\t\t{\n\t\t\t\tsv.pop_back();\n\t\t\t}\n\n\t\t\t// started with 100 and then popped 25.\n\t\t\tEATEST_VERIFY(sv.size() == 75);\n\n\t\t\tint i = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i);\n\t\t\t}\n\n\t\t\t// capacity is unchanged, this is the same as a normal vector.\n\t\t\tEATEST_VERIFY(sv.capacity() == 104);\n\t\t}\n\n\t\t{\n\t\t\tsv.shrink_to_fit();\n\t\t\t// the smallest multiple of 8 which is  >= 75 is 80.\n\t\t\tEATEST_VERIFY(sv.capacity() == 80);\n\t\t}\n\n\t\t// Copy/move assignment/construction:\n\t\t{\n\t\t\t// copy construction:\n\t\t\teastl::segmented_vector<int, 8> other = sv;\n\n\t\t\t// We'll use this down below.\n\t\t\teastl::segmented_vector<int, 8> other2 = sv;\n\n\t\t\t// check other has the right things in it.\n\t\t\tint i = 0;\n\t\t\tfor (auto it = other.begin(); it != other.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(other.size() == 75);\n\n\t\t\t// check that sv is unchanged\n\t\t\ti = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(sv.size() == 75);\n\n\t\t\t// fill other back to 100\n\t\t\tfor (int j = 75; j < 100; ++j)\n\t\t\t{\n\t\t\t\tother.push_back(j);\n\t\t\t}\n\n\t\t\t// test copy assignment (growing)\n\t\t\tsv = other;\n\t\t\ti = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(sv.size() == 100);\n\n\t\t\t// check other is unchanged.\n\t\t\ti = 0;\n\t\t\tfor (auto it = other.begin(); it != other.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(other.size() == 100);\n\n\t\t\t// make other smaller.\n\t\t\tother.clear();\n\n\t\t\t// fill it with 10 multiples of 10\n\t\t\tfor (int j = 0; j < 10; ++j)\n\t\t\t{\n\t\t\t\tother.push_back(10 * j);\n\t\t\t}\n\n\t\t\t// copy assignment (shrinking)\n\t\t\tsv = other;\n\t\t\ti = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i * 10);\n\t\t\t}\n\t\t\tEATEST_VERIFY(sv.size() == 10);\n\n\n\t\t\t// move assignment (growing)\n\t\t\tsv = eastl::move(other2);\n\t\t\ti = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(sv.size() == 75);\n\n\t\t\t// this behavior need not be set in stone, we could decide\n\t\t\t// the moved from object is in a different state, this is\n\t\t\t// just the current behavior.\n\t\t\tEATEST_VERIFY(other2.empty());\n\n\t\t\t// move assignment (shrinking)\n\t\t\tsv = eastl::move(other);\n\t\t\ti = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i * 10);\n\t\t\t}\n\t\t\tEATEST_VERIFY(sv.size() == 10);\n\n\t\t\t// this behavior need not be set in stone, we could decide\n\t\t\t// the moved from object is in a different state, this is\n\t\t\t// just the current behavior.\n\t\t\tEATEST_VERIFY(other.empty());\n\n\t\t\t// move construct\n\t\t\teastl::segmented_vector<int, 8> other3 = eastl::move(sv);\n\t\t\ti = 0;\n\t\t\tfor (auto it = other3.begin(); it != other3.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(*it == i * 10);\n\t\t\t}\n\t\t\tEATEST_VERIFY(other3.size() == 10);\n\n\t\t\t// this behavior need not be set in stone, we could decide\n\t\t\t// the moved from object is in a different state, this is\n\t\t\t// just the current behavior.\n\t\t\tEATEST_VERIFY(sv.empty());\n\n\t\t\t// TODO: test move/copy assign with stateful allocators\n\t\t\t// which compare different.\n\t\t}\n\n\t\t{\n\t\t\tEATEST_VERIFY(sv.empty());\n\t\t\t// fill up sv with 100 items.\n\t\t\tfor (int i = 0; i < 100; ++i)\n\t\t\t{\n\t\t\t\tsv.push_back(i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(sv.capacity() == 104);\n\n\t\t\t// check we can clear() and retain capacity.\n\t\t\tsv.clear();\n\t\t\tEATEST_VERIFY(sv.size() == 0);\n\t\t\tEATEST_VERIFY(sv.capacity() == 104);\n\t\t}\n\t}\n\n\t{\n\t\t// resize/reserve\n\t\teastl::segmented_vector<int, 10> sv;\n\t\tsv.reserve(27);\n\t\tEATEST_VERIFY(sv.capacity() >= 27);\n\n\t\tsv.resize(55);\n\t\tEATEST_VERIFY(sv.size() == 55);\n\t\tfor (auto i : sv)\n\t\t{\n\t\t\tEATEST_VERIFY(i == 0);\n\t\t}\n\n\t\tsv.resize(100, 5);\n\t\tEATEST_VERIFY(sv.size() == 100);\n\t\tint i = 0;\n\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(*it == (i < 55) ? 0 : 5);\n\t\t}\n\n\t\tsv.resize(10);\n\t\tEATEST_VERIFY(sv.size() == 10);\n\t}\n\n\t{\n\t\t// emplace_back\n\t\tTestObject::Reset();\n\t\teastl::segmented_vector<TestObject, 8> sv;\n\t\tfor (int i = 0; i < 25; ++i)\n\t\t{\n\t\t\tsv.emplace_back(i);\n\t\t}\n\n\t\t{\n\t\t\tint i = 0;\n\t\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(it->mX == i);\n\t\t\t}\n\t\t}\n\n\t\t// no copies are made when we emplace_back\n\t\tEATEST_VERIFY(sv.size() == 25);\n\t\tEATEST_VERIFY(TestObject::sTOCopyCtorCount == 0);\n\t\tEATEST_VERIFY(TestObject::sTOCopyAssignCount == 0);\n\n\t\t// move construction should make no copies.\n\t\teastl::segmented_vector<TestObject, 8> sv2 = eastl::move(sv);\n\t\tEATEST_VERIFY(sv2.size() == 25);\n\t\tEATEST_VERIFY(TestObject::sTOCopyCtorCount == 0);\n\t\tEATEST_VERIFY(TestObject::sTOCopyAssignCount == 0);\n\n\t\t// no copies on move assignment either\n\t\tsv = eastl::move(sv2);\n\t\tEATEST_VERIFY(sv.size() == 25);\n\t\tEATEST_VERIFY(TestObject::sTOCopyCtorCount == 0);\n\t\tEATEST_VERIFY(TestObject::sTOCopyAssignCount == 0);\n\t}\n\n\t{\n\t\t// Construct segmented_vectors of different types.\n\t\teastl::segmented_vector<int, 8> vectorOfInt;\n\t\teastl::segmented_vector<TestObject, 8> vectorOfTO;\n\t\teastl::segmented_vector<eastl::list<TestObject>, 8> vectorOfListOfTO;\n\n\t\tEATEST_VERIFY(vectorOfInt.empty());\n\t\tEATEST_VERIFY(vectorOfTO.empty());\n\t\tEATEST_VERIFY(vectorOfListOfTO.empty());\n\t}\n\n\t{\n\t\t// Support for non-default constructible types.\n\t\tstruct S\n\t\t{\n\t\t\tint mX;\n\t\t\texplicit S(int i) : mX{i} {}\n\t\t};\n\t\teastl::segmented_vector<S, 4> sv;\n\n\t\tsv.push_back(S{0});\n\t\tsv.push_back(S{1});\n\t\tsv.push_back(S{2});\n\t\tsv.push_back(S{3});\n\t\tsv.push_back(S{4});\n\t\tsv.emplace_back(S{5});\n\t\tsv.emplace_back(S{6});\n\t\tsv.emplace_back(S{7});\n\t\tsv.emplace_back(S{8});\n\t\tsv.emplace_back(S{9});\n\n\n\t\tEATEST_VERIFY(sv.size() == 10);\n\n\t\tint i = 0;\n\t\tfor (auto it = sv.begin(); it != sv.end(); ++it, ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(it->mX == i);\n\t\t}\n\t}\n\n\t{\n\t\t// Test basic segmented_vector operations.\n\t\teastl::segmented_vector<int, 4> vectorOfInt;\n\n\t\tvectorOfInt.push_back(42);\n\t\tEATEST_VERIFY(vectorOfInt.size() == 1);\n\t\tEATEST_VERIFY(vectorOfInt.segment_count() == 1);\n\t\tEATEST_VERIFY(vectorOfInt.empty() == false);\n\n\t\tvectorOfInt.push_back(43);\n\t\tvectorOfInt.push_back(44);\n\t\tvectorOfInt.push_back(45);\n\t\tvectorOfInt.push_back(46);\n\t\tEATEST_VERIFY(vectorOfInt.size() == 5);\n\t\tEATEST_VERIFY(vectorOfInt.segment_count() == 2);\n\n\t\tEATEST_VERIFY(vectorOfInt.front() == 42);\n\t\tEATEST_VERIFY(vectorOfInt.back() == 46);\n\n\t\tvectorOfInt.pop_back();\n\t\tEATEST_VERIFY(vectorOfInt.size() == 4);\n\t\tEATEST_VERIFY(vectorOfInt.segment_count() == 1);\n\n\t\tvectorOfInt.clear();\n\t\tEATEST_VERIFY(vectorOfInt.empty());\n\t\tEATEST_VERIFY(vectorOfInt.size() == 0);\n\t\tEATEST_VERIFY(vectorOfInt.segment_count() == 0);\n\t}\n\n\t{\n\t\t// global operators (==, !=, <, etc.)\n\t\teastl::segmented_vector<int, 4> sv1;\n\t\teastl::segmented_vector<int, 4> sv2;\n\n\t\tfor (auto i = 0; i < 10; ++i)\n\t\t{\n\t\t\tsv1.push_back(i);\n\t\t\tsv2.push_back(i);\n\t\t}\n\n\t\tEATEST_VERIFY((sv1 == sv2));\n\t\tEATEST_VERIFY(!(sv1 != sv2));\n\t\tEATEST_VERIFY((sv1 <= sv2));\n\t\tEATEST_VERIFY((sv1 >= sv2));\n\t\tEATEST_VERIFY(!(sv1 < sv2));\n\t\tEATEST_VERIFY(!(sv1 > sv2));\n\n\t\tsv1.push_back(100);  // Make sv1 less than sv2.\n\t\tsv2.push_back(101);\n\n\t\tEATEST_VERIFY(!(sv1 == sv2));\n\t\tEATEST_VERIFY((sv1 != sv2));\n\t\tEATEST_VERIFY((sv1 <= sv2));\n\t\tEATEST_VERIFY(!(sv1 >= sv2));\n\t\tEATEST_VERIFY((sv1 < sv2));\n\t\tEATEST_VERIFY(!(sv1 > sv2));\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\n\t{ // Test <=>\n\t\teastl::segmented_vector<int, 4> sv1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\t\teastl::segmented_vector<int, 4> sv2 = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };\n\t\teastl::segmented_vector<int, 4> sv3 = { 1, 2, 3, 4, 5 };\n\t\teastl::segmented_vector<int, 4> sv4 = { 10 };\n\n\t\tEATEST_VERIFY(sv1 != sv2);\n\t\tEATEST_VERIFY(sv1 < sv2);\n\t\tEATEST_VERIFY(sv1 != sv3);\n\t\tEATEST_VERIFY(sv1 > sv3);\n\t\tEATEST_VERIFY(sv4 > sv1);\n\t\tEATEST_VERIFY(sv4 > sv2);\n\t\tEATEST_VERIFY(sv4 > sv3);\n\n\t\tEATEST_VERIFY((sv1 <=> sv2) != 0);\n\t\tEATEST_VERIFY((sv1 <=> sv2) < 0);\n\t\tEATEST_VERIFY((sv1 <=> sv3) != 0);\n\t\tEATEST_VERIFY((sv1 <=> sv3) > 0);\n\t\tEATEST_VERIFY((sv4 <=> sv1) > 0);\n\t\tEATEST_VERIFY((sv4 <=> sv2) > 0);\n\t\tEATEST_VERIFY((sv4 <=> sv3) > 0);\n\t}\n#endif\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestSet.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"TestSet.h\"\n#include \"EASTLTest.h\"\n#include <EASTL/map.h>\n#include <EASTL/set.h>\n#include <EASTL/functional.h>\n#include <EASTL/internal/config.h>\n#include <EABase/eabase.h>\n#include \"TestAssociativeContainers.h\"\n\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdio.h>\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <set>\n\t#include <map>\n\t#include <algorithm>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::set<int>;\ntemplate class eastl::multiset<float>;\ntemplate class eastl::set<TestObject>;\ntemplate class eastl::multiset<TestObject>;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// typedefs\n//\ntypedef eastl::set<int> VS1;\ntypedef eastl::set<TestObject> VS4;\ntypedef eastl::multiset<int> VMS1;\ntypedef eastl::multiset<TestObject> VMS4;\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\ttypedef std::set<int> VS3;\n\ttypedef std::set<TestObject> VS6;\n\ttypedef std::multiset<int> VMS3;\n\ttypedef std::multiset<TestObject> VMS6;\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\n\n///////////////////////////////////////////////////////////////////////////////\n// xvalue_test\n//\n// Test utility type that sets the class data to known value when its data has\n// has been moved out.  This enables us to write tests that verify that the\n// destruction action taken on container elements occured during move operations.\n//\nstruct xvalue_test\n{\n\tstatic const int MOVED_FROM = -1;\n\n\tint data = 42;\n\n\txvalue_test(int in) : data(in) {}\n\t~xvalue_test() = default;\n\n\txvalue_test(const xvalue_test& other) \n\t\t: data(other.data) {}\n\n\txvalue_test& operator=(const xvalue_test& other)\n\t{\n\t\tdata = other.data;\n\t\treturn *this;\n\t}\n\n\txvalue_test(xvalue_test&& other)\n\t{\n\t\tdata = other.data;\n\t\tother.data = MOVED_FROM;\n\t}\n\n\txvalue_test& operator=(xvalue_test&& other)\n\t{\n\t\tdata = other.data;\n\t\tother.data = MOVED_FROM;\n\t\treturn *this;\n\t}\n\n\tfriend bool operator<(const xvalue_test& rhs, const xvalue_test& lhs) \n\t\t{ return rhs.data < lhs.data; }\n};\n\n\nstruct EA_REMOVE_AT_2025_OCT LessNonTransparent\n{\n\ttemplate<typename A, typename B>\n\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t{\n\t\treturn eastl::forward<A>(a) < eastl::forward<B>(b);\n\t}\n};\n\n\nint TestSet()\n{\n\tint nErrorCount = 0;\n\n\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t{   // Test construction\n\t\t\tnErrorCount += TestSetConstruction<VS1, VS3, false>();\n\t\t\tnErrorCount += TestSetConstruction<VS4, VS6, false>();\n\t\t\tnErrorCount += TestSetConstruction<eastl::set<int, eastl::less<void>>, std::set<int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestSetConstruction<VMS1, VMS3, true>();\n\t\t\tnErrorCount += TestSetConstruction<VMS4, VMS6, true>();\n\t\t\tnErrorCount += TestSetConstruction<eastl::multiset<int, eastl::less<void>>, std::multiset<int, std::less<void>>, true>();\n\t\t}\n\n\n\t\t{   // Test mutating functionality.\n\t\t\tnErrorCount += TestSetMutation<VS1, VS3, false>();\n\t\t\tnErrorCount += TestSetMutation<VS4, VS6, false>();\n\t\t\tnErrorCount += TestSetMutation<eastl::set<int, eastl::less<void>>, std::set<int, std::less<void>>, false>();\n\n\t\t\tnErrorCount += TestSetMutation<VMS1, VMS3, true>();\n\t\t\tnErrorCount += TestSetMutation<VMS4, VMS6, true>();\n\t\t\tnErrorCount += TestSetMutation<eastl::multiset<int, eastl::less<void>>, std::multiset<int, std::less<void>>, true>();\n\t\t}\n\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n\t{   // Test searching functionality.\n\t\tnErrorCount += TestSetSearch<VS1, false>();\n\t\tnErrorCount += TestSetSearch<VS4, false>();\n\t\tnErrorCount += TestSetSearch<eastl::set<int, eastl::less<void>>, false>();\n\n\t\tnErrorCount += TestSetSearch<VMS1, true>();\n\t\tnErrorCount += TestSetSearch<VMS4, true>();\n\t\tnErrorCount += TestSetSearch<eastl::multiset<int, eastl::less<void>>, true>();\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestSetCpp11<eastl::set<TestObject> >();\n\t\tnErrorCount += TestSetCpp11<eastl::set<TestObject, eastl::less<void>>>();\n\n\t\tnErrorCount += TestMultisetCpp11<eastl::multiset<TestObject> >();\n\t\tnErrorCount += TestMultisetCpp11<eastl::multiset<TestObject, eastl::less<void>>>();\n\t}\n\n\n\t{ // Misc tests\n\n\t\t// const key_compare& key_comp() const;\n\t\t// key_compare&       key_comp();\n\t\tVS1       vs;\n\t\tconst VS1 vsc;\n\n\t\tconst VS1::key_compare& kc = vsc.key_comp();\n\t\tvs.key_comp() = kc;\n\t}\n\n\t{ // non-const comparator test\n\t\tstruct my_less\n\t\t{\n\t\t\tbool operator()(int a, int b) { return a < b; }\n\t\t};\n\n\t\t{\n\t\t\tset<int, my_less> a = {0, 1, 2, 3, 4};\n\t\t\tauto i = a.find(42);\n\t\t\tVERIFY(i == a.end());\n\t\t}\n\t}\n\n\t{ // set erase_if tests\n\t\tset<int> s = {0, 1, 2, 3, 4};\n\t\tauto numErased = eastl::erase_if(s, [](auto i) { return i % 2 == 0;});\n\t\tVERIFY((s == set<int>{1,3}));\n\t\tVERIFY(numErased == 3);\n\t}\n\n\t{ // multiset erase_if tests\n\t\tmultiset<int> s = {0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4};\n\t\tauto numErased = eastl::erase_if(s, [](auto i) { return i % 2 == 0;});\n\t\tVERIFY((s == multiset<int>{1, 1, 1, 3, 3, 3}));\n\t\tVERIFY(numErased == 7);\n\t}\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{ // Test set <=>\n\t    set<int> s1 = {0, 1, 2, 3, 4};\n\t    set<int> s2 = {4, 3, 2, 1, 0};\n\t    set<int> s3 = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t    set<int> s4 = {1, 2, 3, 4, 5, 6};\n\t    set<int> s5 = {9};\n\n\t    VERIFY(s1 == s2);\n\t    VERIFY(s1 != s3);\n\t    VERIFY(s3 > s4);\n\t    VERIFY(s5 > s4);\n\t    VERIFY(s5 > s3);\n\n\t    VERIFY((s1 <=> s2) == 0);\n\t    VERIFY((s1 <=> s3) != 0);\n\t    VERIFY((s3 <=> s4) > 0);\n\t    VERIFY((s5 <=> s4) > 0);\n\t    VERIFY((s5 <=> s3) > 0);\n\t}\n\n\t{ // Test multiset <=>\n\t    multiset<int> s1 = {0, 0, 0, 1, 1, 2, 3, 3, 4};\n\t    multiset<int> s2 = {4, 3, 3, 2, 1, 1, 0, 0, 0};\n\t    multiset<int> s3 = {1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9};\n\t    multiset<int> s4 = {1, 1, 2, 2, 3, 4, 5, 5, 6};\n\t    multiset<int> s5 = {9};\n\n\t    VERIFY(s1 == s2);\n\t    VERIFY(s1 != s3);\n\t    VERIFY(s3 > s4);\n\t    VERIFY(s5 > s4);\n\t    VERIFY(s5 > s3);\n\n\t    VERIFY((s1 <=> s2) == 0);\n\t    VERIFY((s1 <=> s3) != 0);\n\t    VERIFY((s3 <=> s4) > 0);\n\t    VERIFY((s5 <=> s4) > 0);\n\t    VERIFY((s5 <=> s3) > 0);\n\t}\n#endif\n\n\t{\n\t\t// user reported regression: ensure container elements are NOT \n\t\t// moved from during the eastl::set construction process.\n\t\teastl::vector<xvalue_test> m1 = {{0}, {1}, {2}, {3}, {4}, {5}};\n\t\teastl::set<xvalue_test> m2{m1.begin(), m1.end()};\n\n\t\tbool result = eastl::all_of(m1.begin(), m1.end(), \n\t\t\t\t[&](auto& e) { return e.data != xvalue_test::MOVED_FROM; });\n\n\t\tVERIFY(result);\n\t}\n\n\t{\n\t\t// user reported regression: ensure container elements are moved from during the\n\t\t// eastl::set construction process when using an eastl::move_iterator.\n\t\teastl::vector<xvalue_test> m1 = {{0}, {1}, {2}, {3}, {4}, {5}};\n\t\teastl::set<xvalue_test> m2{eastl::make_move_iterator(m1.begin()), eastl::make_move_iterator(m1.end())};\n\n\t\tbool result = eastl::all_of(m1.begin(), m1.end(), \n\t\t\t\t[&](auto& e) { return e.data == xvalue_test::MOVED_FROM; });\n\n\t\tVERIFY(result);\n\t}\n\n\t{ // heterogenous functions - set\n\t\teastl::set<ExplicitString, eastl::less<void>> s = { ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestSetHeterogeneousInsertion<decltype(s)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // heterogenous functions - multiset\n\t\teastl::multiset<ExplicitString, eastl::less<void>> s = { ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // insert(P&&) was incorrectly defined in the rbtree base type.\n\t\t// should never have been defined for set, multiset.\n\t\t// it does not correctly support heterogeneous insertion (unconditionally creates a key_type).\n\t\t// this test exists purely to check that the addition of insert(KX&&) for hterogeneous keys didn't break existing (unlikely) calls to insert(P&&) that\n\t\t// shouldn't have been supported.\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\teastl::set<ExplicitString, LessNonTransparent> s = { ExplicitString::Create(\"a\") };\n\t\ts.insert(\"a\");\n\n\t\teastl::multiset<ExplicitString, LessNonTransparent> s2 = { ExplicitString::Create(\"a\") };\n\t\ts2.insert(\"a\");\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\t\teastl::set<ExplicitString, eastl::less<void>> s3 = { ExplicitString::Create(\"a\") };\n\t\ts3.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\n\t\teastl::multiset<eastl::string, eastl::less<void>> s4 = { \"a\" };\n\t\ts4.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\n\t\teastl::set<eastl::string> s5 = { \"a\" };\n\t\ts5.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestSet.h",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/vector.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/type_traits.h>\n#include <EASTL/scoped_ptr.h>\n#include <EASTL/random.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <algorithm>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestSetConstruction\n//\n// This test compares eastl::set/multiset to std::set/multiset. It could possibly\n// work for comparing eastl::hash_set to C++11 std::unordered_set, but we would \n// rather move towards making this test be independent of any std comparisons.\n//\n// Requires a container that can hold at least 1000 items.\n//\ntemplate <typename T1, typename T2, bool bMultiset>\nint TestSetConstruction()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{\n\t\teastl::scoped_ptr<T1> pt1A(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\teastl::scoped_ptr<T2> pt2A(new T2);\n\t\tT1& t1A = *pt1A;\n\t\tT2& t2A = *pt2A;\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set ctor\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\tVERIFY(t1A.validate());\n\n\n\t\teastl::scoped_ptr<T1> pt1B(new T1);\n\t\teastl::scoped_ptr<T2> pt2B(new T2);\n\t\tT1& t1B = *pt1B;\n\t\tT2& t2B = *pt2B;\n\t\tnErrorCount += CompareContainers(t1B, t2B, \"Set ctor\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\teastl::scoped_ptr<T1> pt1C(new T1);\n\t\teastl::scoped_ptr<T2> pt2C(new T2);\n\t\tT1& t1C = *pt1C;\n\t\tT2& t2C = *pt2C;\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t{\n\t\t\tt1C.insert(typename T1::value_type(typename T1::value_type(i)));\n\t\t\tt2C.insert(typename T2::value_type(typename T2::value_type(i)));\n\t\t\tVERIFY(t1C.validate());\n\t\t\tnErrorCount += CompareContainers(t1C, t2C, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\t}\n\n\n\t\teastl::scoped_ptr<T1> pt1D(new T1);\n\t\teastl::scoped_ptr<T2> pt2D(new T2);\n\t\tT1& t1D = *pt1D;\n\t\tT2& t2D = *pt2D;\n\t\tnErrorCount += CompareContainers(t1D, t2D, \"Set ctor\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\teastl::scoped_ptr<T1> pt1E(new T1(t1C));\n\t\teastl::scoped_ptr<T2> pt2E(new T2(t2C));\n\t\tT1& t1E = *pt1E;\n\t\tT2& t2E = *pt2E;\n\t\tVERIFY(t1E.validate());\n\t\tnErrorCount += CompareContainers(t1E, t2E, \"Set ctor\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\teastl::scoped_ptr<T1> pt1F(new T1(t1C.begin(), t1C.end()));\n\t\teastl::scoped_ptr<T2> pt2F(new T2(t2C.begin(), t2C.end()));\n\t\tT1& t1F = *pt1F;\n\t\tT2& t2F = *pt2F;\n\t\tVERIFY(t1F.validate());\n\t\tnErrorCount += CompareContainers(t1F, t2F, \"Set ctor\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// operator=\n\t\tt1E = t1D;\n\t\tt2E = t2D;\n\t\tnErrorCount += CompareContainers(t1D, t2D, \"Set operator=\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\tnErrorCount += CompareContainers(t1E, t2E, \"Set operator=\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// operator=(set&&)\n\t\t// We test just the EASTL container here.\n\t\teastl::scoped_ptr<T1> pT1P(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\teastl::scoped_ptr<T1> pT1Q(new T1);\n\t\tT1& t1P = *pT1P;\n\t\tT1& t1Q = *pT1Q;\n\n\t\ttypename T1::value_type v10(0);\n\t\ttypename T1::value_type v11(1);\n\t\ttypename T1::value_type v12(2);\n\t\ttypename T1::value_type v13(3);\n\t\ttypename T1::value_type v14(4);\n\t\ttypename T1::value_type v15(5);\n\n\t\tt1P.insert(v10);\n\t\tt1P.insert(v11);\n\t\tt1P.insert(v12);\n\n\t\tt1Q.insert(v13);\n\t\tt1Q.insert(v14);\n\t\tt1Q.insert(v15);\n\n\t\tt1Q = eastl::move(t1P); // We are effectively requesting to swap t1A with t1B.\n\t  //EATEST_VERIFY((t1P.size() == 3) && (t1P.find(v13) != t1P.end()) && (t1P.find(v14) != t1P.end()) && (t1P.find(v15) != t1P.end()));  // Currently operator=(this_type&& x) clears x instead of swapping with it.\n\n\n\t\t// swap\n\t\tt1E.swap(t1D);\n\t\tt2E.swap(t2D);\n\t\tVERIFY(t1D.validate());\n\t\tVERIFY(t1E.validate());\n\t\tnErrorCount += CompareContainers(t1D, t2D, \"Set swap\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\tnErrorCount += CompareContainers(t1E, t2E, \"Set swap\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// eastl::swap\n\t\teastl::swap(t1E, t1D);\n\t\t  std::swap(t2E, t2D);\n\t\tVERIFY(t1D.validate());\n\t\tVERIFY(t1E.validate());\n\t\tnErrorCount += CompareContainers(t1D, t2D, \"Global swap\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\tnErrorCount += CompareContainers(t1E, t2E, \"Global swap\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// clear\n\t\tt1A.clear();\n\t\tt2A.clear();\n\t\tVERIFY(t1A.validate());\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set clear\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\t\tt1B.clear();\n\t\tt2B.clear();\n\t\tVERIFY(t1B.validate());\n\t\tnErrorCount += CompareContainers(t1B, t2B, \"Set clear\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// global operators (==, !=, <, etc.)\n\t\tt1A.clear();\n\t\tt1B.clear();\n\t\t\t\t\t\t\t   // Make t1A equal to t1B\n\t\tt1A.insert(typename T1::value_type(0));\n\t\tt1A.insert(typename T1::value_type(1));\n\t\tt1A.insert(typename T1::value_type(2));\n\n\t\tt1B.insert(typename T1::value_type(0));\n\t\tt1B.insert(typename T1::value_type(1));\n\t\tt1B.insert(typename T1::value_type(2));\n\n\t\tVERIFY( (t1A == t1B));\n\t\tVERIFY(!(t1A != t1B));\n\t\tVERIFY( (t1A <= t1B));\n\t\tVERIFY( (t1A >= t1B));\n\t\tVERIFY(!(t1A  < t1B));\n\t\tVERIFY(!(t1A  > t1B));\n\t\t\t\t\t\t\t   // Make t1A less than t1B\n\t\tt1A.insert(typename T1::value_type(3));\n\t\tt1B.insert(typename T1::value_type(4));\n\n\t\tVERIFY(!(t1A == t1B));\n\t\tVERIFY( (t1A != t1B));\n\t\tVERIFY( (t1A <= t1B));\n\t\tVERIFY(!(t1A >= t1B));\n\t\tVERIFY( (t1A  < t1B));\n\t\tVERIFY(!(t1A  > t1B));\n\t}\n\n\tVERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestSetMutation\n//\n// Requires a container that can hold at least 1000 items.\n//\nEA_DISABLE_VC_WARNING(6262)\ntemplate <typename T1, typename T2, bool bMultiset>\nint TestSetMutation()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{\n\t\teastl::scoped_ptr<T1> pt1A(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\teastl::scoped_ptr<T2> pt2A(new T2);\n\t\tT1& t1A = *pt1A;\n\t\tT2& t2A = *pt2A;\n\t\tint i, iEnd, p;\n\n\t\t// Set up an array of values to randomize / permute.\n\t\teastl::vector<typename T1::value_type> valueArrayInsert;\n\n\t\tif(gEASTL_TestLevel >= kEASTL_TestLevelLow)\n\t\t{\n\t\t\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\t\tvalueArrayInsert.clear();\n\n\t\t\tfor(i = 0; i < 1000; i++)\n\t\t\t{\n\t\t\t\tvalueArrayInsert.push_back(typename T1::value_type(i));\n\n\t\t\t\t// Occasionally attempt to duplicate an element, both for set and multiset.\n\t\t\t\tif(((i + 1) < 1000) && (rng.RandLimit(4) == 0))\n\t\t\t\t{\n\t\t\t\t\tvalueArrayInsert.push_back(typename T1::value_type(i));\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor(p = 0; p < gEASTL_TestLevel * 100; p++) // For each permutation...\n\t\t\t{\n\t\t\t\teastl::random_shuffle(valueArrayInsert.begin(), valueArrayInsert.end(), rng);\n\n\t\t\t\t// insert\n\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t{\n\t\t\t\t\ttypename T1::value_type& k = valueArrayInsert[i];\n\n\t\t\t\t\tt1A.insert(typename T1::value_type(k)); // We expect that both arguments are the same.\n\t\t\t\t\tt2A.insert(typename T2::value_type(k));\n\n\t\t\t\t\tVERIFY(t1A.validate());\n\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\t\t\t}\n\n\n\t\t\t\t// reverse iteration\n\t\t\t\ttypename T1::reverse_iterator r1 = t1A.rbegin();\n\t\t\t\ttypename T2::reverse_iterator r2 = t2A.rbegin();\n\n\t\t\t\twhile(r1 != t1A.rend())\n\t\t\t\t{\n\t\t\t\t\ttypename T1::value_type k1 = *r1;\n\t\t\t\t\ttypename T2::value_type k2 = *r2;\n\t\t\t\t\tVERIFY(k1 == k2);\n\t\t\t\t}\n\n\n\t\t\t\t// erase\n\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t{\n\t\t\t\t\ttypename T1::value_type& k = valueArrayInsert[i];\n\n\t\t\t\t\ttypename T1::size_type n1 = t1A.erase(k);\n\t\t\t\t\ttypename T2::size_type n2 = t2A.erase(k);\n\n\t\t\t\t\tVERIFY(n1 == n2);\n\t\t\t\t\tVERIFY(t1A.validate());\n\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set erase\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\t\t\t}\n\n\t\t\t\tVERIFY((TestObject::sTOCount == 0) || (TestObject::sTOCount == (int64_t)valueArrayInsert.size())); // This test will only have meaning when T1 contains TestObject.\n\t\t\t}\n\t\t}\n\n\n\t\tVERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\n\n\t\t// Possibly do extended testing.\n\t\tif(gEASTL_TestLevel > 6)\n\t\t{\n\t\t\tvalueArrayInsert.clear();\n\n\t\t\tfor(i = 0; i < 9; i++) // Much more than this count would take too long to test all permutations.\n\t\t\t\tvalueArrayInsert.push_back(typename T1::value_type(i));\n\n\t\t\t// Insert these values into the set in every existing permutation.\n\t\t\tfor(p = 0; std::next_permutation(valueArrayInsert.begin(), valueArrayInsert.end()); p++) // For each permutation...\n\t\t\t{\n\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t{\n\t\t\t\t\ttypename T1::value_type& k = valueArrayInsert[i];\n\n\t\t\t\t\tt1A.insert(typename T1::value_type(k)); // We expect that both arguments are the same.\n\t\t\t\t\tt2A.insert(typename T2::value_type(k));\n\n\t\t\t\t\tVERIFY(t1A.validate());\n\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\t\t\t}\n\n\t\t\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t\t\t{\n\t\t\t\t\ttypename T1::value_type& k = valueArrayInsert[i];\n\n\t\t\t\t\tt1A.erase(k);\n\t\t\t\t\tt2A.erase(k);\n\n\t\t\t\t\tVERIFY(t1A.validate());\n\t\t\t\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set erase\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t\t\t\t}\n\n\t\t\t\tVERIFY((TestObject::sTOCount == 0) || (TestObject::sTOCount == (int64_t)valueArrayInsert.size())); // This test will only have meaning when T1 contains TestObject.\n\t\t\t}\n\t\t}\n\t}\n\n\n\tVERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\n\t{  // Other insert and erase operations\n\n\t\teastl::scoped_ptr<T1> pt1A(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\teastl::scoped_ptr<T2> pt2A(new T2);\n\t\tT1& t1A = *pt1A;\n\t\tT2& t2A = *pt2A;\n\t\tint i;\n\n\t\t// Set up an array of values to randomize / permute.\n\t\teastl::vector<typename T1::value_type> valueArrayInsert1;\n\t\teastl::vector<typename T2::value_type> valueArrayInsert2;\n\n\t\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\tfor(i = 0; i < 100; i++)\n\t\t{\n\t\t\tvalueArrayInsert1.push_back(typename T1::value_type(i));\n\t\t\tvalueArrayInsert2.push_back(typename T2::value_type(i));\n\n\t\t\tif(rng.RandLimit(3) == 0)\n\t\t\t{\n\t\t\t\tvalueArrayInsert1.push_back(typename T1::value_type(i));\n\t\t\t\tvalueArrayInsert2.push_back(typename T2::value_type(i));\n\t\t\t}\n\t\t}\n\n\n\t\t// insert(InputIterator first, InputIterator last)\n\t\tt1A.insert(valueArrayInsert1.begin(), valueArrayInsert1.end());\n\t\tt2A.insert(valueArrayInsert2.begin(), valueArrayInsert2.end());\n\t\tVERIFY(t1A.validate());\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// iterator insert(iterator position, const value_type& value);\n\t\t//\n\t\t// If bMultiset == true, then the insertions below should fail due to the \n\t\t// item being present. But they should return the correct iterator value.\n\t\ttypename T1::iterator it1 = t1A.insert(t1A.find(typename T1::value_type(2)), typename T1::value_type(1));\n\t\ttypename T2::iterator it2 = t2A.insert(t2A.find(typename T2::value_type(2)), typename T2::value_type(1));\n\t\tVERIFY(t1A.validate());\n\t\tVERIFY(*it1 == typename T1::value_type(1));\n\t\tVERIFY(*it2 == typename T2::value_type(1));\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\t\tit1 = t1A.insert(t1A.end(), typename T1::value_type(5));\n\t\tit2 = t2A.insert(t2A.end(), typename T2::value_type(5));\n\t\tVERIFY(t1A.validate());\n\t\tVERIFY(*it1 == typename T1::value_type(5));\n\t\tVERIFY(*it2 == typename T2::value_type(5));\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\t\t// Now we remove these items so that the insertions above can succeed.\n\t\tt1A.erase(t1A.find(typename T1::value_type(1)));\n\t\tt2A.erase(t2A.find(typename T2::value_type(1)));\n\t\tit1 = t1A.insert(t1A.find(typename T1::value_type(2)), typename T1::value_type(1));\n\t\tit2 = t2A.insert(t2A.find(typename T2::value_type(2)), typename T2::value_type(1));\n\t\tVERIFY(t1A.validate());\n\t\tVERIFY(*it1 == typename T1::value_type(1));\n\t\tVERIFY(*it2 == typename T2::value_type(1));\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\t\tt1A.erase(t1A.find(typename T1::value_type(5)));\n\t\tt2A.erase(t2A.find(typename T2::value_type(5)));\n\t\tit1 = t1A.insert(t1A.end(), typename T1::value_type(5));\n\t\tit2 = t2A.insert(t2A.end(), typename T2::value_type(5));\n\t\tVERIFY(t1A.validate());\n\t\tVERIFY(*it1 == typename T1::value_type(5));\n\t\tVERIFY(*it2 == typename T2::value_type(5));\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set insert\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\t\t// iterator erase(iterator first, iterator last);\n\t\ttypename T1::iterator it11 = t1A.find(typename T1::value_type(17));\n\t\ttypename T1::iterator it12 = t1A.find(typename T2::value_type(37));\n\t\tt1A.erase(it11, it12);\n\n\t\ttypename T2::iterator it21 = t2A.find(typename T1::value_type(17));\n\t\ttypename T2::iterator it22 = t2A.find(typename T2::value_type(37));\n\t\tt2A.erase(it21, it22);\n\n\t\tVERIFY(t1A.validate());\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set erase(first, last)\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// iterator erase(iterator position);\n\t\tt1A.erase(t1A.find(typename T1::value_type(60)));\n\t\tt2A.erase(t2A.find(typename T1::value_type(60)));\n\t\tVERIFY(t1A.validate());\n\t\tnErrorCount += CompareContainers(t1A, t2A, \"Set erase(first, last)\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\n\n\t\t// Disabled because this function isn't exposed outside the rbtree yet.\n\t\t// void erase(const value_type* first, const value_type* last);\n\t\t//typename T1::value_type keyArray1[3] = { typename T1::value_type(70), typename T1::value_type(71), typename T1::value_type(72) };\n\t\t//typename T2::value_type keyArray2[3] = { typename T2::value_type(70), typename T2::value_type(71), typename T2::value_type(72) };\n\t\t//t1A.erase(keyArray1 + 0, keyArray1 + 3);\n\t\t//t2A.erase(keyArray2 + 0, keyArray2 + 3);\n\t\t//VERIFY(t1A.validate());\n\t\t//nErrorCount += CompareContainers(t1A, t2A, \"Set erase(first, last)\", eastl::use_self<typename T1::value_type>(), eastl::use_self<typename T2::value_type>());\n\t}\n\n\t{\n\t\t// set(std::initializer_list<value_type> ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_MAP_DEFAULT_ALLOCATOR);\n\t\t// this_type& operator=(std::initializer_list<T> ilist);\n\t\t// void insert(std::initializer_list<value_type> ilist);\n\t\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\tT1 mySet = { typename T1::value_type(10), typename T1::value_type(11) };\n\t\t\tEATEST_VERIFY(mySet.size() == 2);\n\t\t\ttypename T1::iterator it = mySet.begin();\n\t\t\tEATEST_VERIFY(*it == typename T1::value_type(10));\n\t\t\tit = mySet.rbegin().base();\n\t\t\tEATEST_VERIFY(*--it == typename T1::value_type(11));\n\n\t\t\tmySet = {typename T1::value_type(20), typename T1::value_type(21) };\n\t\t\tEATEST_VERIFY(mySet.size() == 2);\n\t\t\tEATEST_VERIFY(*mySet.begin() == typename T1::value_type(20));\n\t\t\tit = mySet.rbegin().base();\n\t\t\tEATEST_VERIFY(*--it == typename T1::value_type(21));\n\n\t\t\tmySet.insert({ typename T1::value_type(40), typename T1::value_type(41) });\n\t\t\tEATEST_VERIFY(mySet.size() == 4);\n\t\t\tit = mySet.rbegin().base();\n\t\t\tEATEST_VERIFY(*--it == typename T1::value_type(41));\n\t\t#endif\n\t}\n\n\tVERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\nEA_RESTORE_VC_WARNING()\n\n\n#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n\n\ntemplate <typename T1>\nint TestSetSpecific(T1& /*t1A*/, eastl::false_type) // false_type means this is a map and not a multimap.\n{\n\treturn 0;\n}\n\n\ntemplate <typename T1>\nint TestSetSpecific(T1& t1A, eastl::true_type) // true_type means this is a multimap and not a map.\n{\n\tint nErrorCount = 0;\n\n\t// equal_range_small (multiset only)\n\teastl::pair<typename T1::iterator, typename T1::iterator> er = t1A.equal_range_small(typename T1::value_type(499));\n\tVERIFY(*er.first  == typename T1::value_type(499));\n\tVERIFY(*er.second == typename T1::value_type(501));\n\n\ter = t1A.equal_range_small(typename T1::value_type(-1));\n\tVERIFY(er.first == er.second);\n\tVERIFY(er.first == t1A.begin());\n\n\treturn nErrorCount;\n}\n\n\n// Just for the purposes of the map::find_as test below, we declare the following.\n// The map::find_as function searches a container of X for a type Y, where the user \n// defines the equality of X to Y. The purpose of TSetComparable is to be a generic type Y\n// that can be used for any X. We need to make this generic because the whole TestMapSearch\n// function below is templated on type T1 and so we don't know what T1 is ahead of time.\n\ntemplate <typename T>\nstruct TSetComparable\n{\n\tT b;\n\n\tTSetComparable() : b() { }\n\tTSetComparable(const T& a) : b(a){ }\n\tconst TSetComparable& operator=(const T& a) { b = a; return *this; }\n\tconst TSetComparable& operator=(const TSetComparable& x) { b = x.b; return *this; }\n\toperator const T&() const { return b; }\n};\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestSetSearch\n//\n// This function is designed to work with set, fixed_set (and not hash containers).\n// Requires a container that can hold at least 1000 items.\n//\ntemplate <typename T1, bool bMultimap>\nint TestSetSearch()\n{\n\tint nErrorCount = 0;\n\n\tTestObject::Reset();\n\n\t{  // Test find, lower_bound, upper_bound, etc..\n\t\teastl::scoped_ptr<T1> pt1A(new T1); // We use a pointers instead of concrete object because it's size may be huge.\n\t\tT1& t1A = *pt1A;\n\t\tint i, iEnd;\n\t\ttypename T1::iterator it;\n\n\t\t// Set up an array of values to randomize / permute.\n\t\teastl::vector<typename T1::value_type> valueArrayInsert;\n\n\t\tfor(i = 0; i < 1000; i++)\n\t\t\tvalueArrayInsert.push_back(typename T1::value_type(i));\n\n\t\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\t\teastl::random_shuffle(valueArrayInsert.begin(), valueArrayInsert.end(), rng);\n\n\n\t\t// insert\n\t\tfor(i = 0, iEnd = (int)valueArrayInsert.size(); i < iEnd; i++)\n\t\t{\n\t\t\ttypename T1::value_type k(i);\n\t\t\tt1A.insert(typename T1::value_type(k));\n\n\t\t\tit = t1A.find(k);\n\t\t\tVERIFY(it != t1A.end());\n\t\t}\n\n\n\t\t// find\n\t\tfor(i = 0; i < 1000; i++)\n\t\t{\n\t\t\ttypename T1::value_type k(i);\n\t\t\tit = t1A.find(k);\n\n\t\t\tVERIFY(it != t1A.end());\n\t\t\tVERIFY(*it == k);\n\t\t}\n\n\t\tit = t1A.find(typename T1::value_type(-1));\n\t\tVERIFY(it == t1A.end());\n\n\t\tit = t1A.find(typename T1::value_type(1001));\n\t\tVERIFY(it == t1A.end());\n\n\n\t\t// find_as\n\t\ttypedef TSetComparable<typename T1::key_type> TC;\n\n\t\t// Normally we use find_as to find via a different type, but we can test it here like this.\n\t\tfor(i = 0; i < 1000; i++)\n\t\t{\n\t\t\tTC k = typename T1::key_type(i);\n\t\t\tit = t1A.find_as(k, eastl::less<>());\n\n\t\t\tVERIFY(it != t1A.end());\n\t\t\tVERIFY(*it == k);\n\t\t}\n\n\t\tit = t1A.find_as(TC(typename T1::key_type(-1)), eastl::less<>());\n\t\tVERIFY(it == t1A.end());\n\n\t\tit = t1A.find_as(TC(typename T1::key_type(1001)), eastl::less<>());\n\t\tVERIFY(it == t1A.end());\n\n\n\t\t// lower_bound\n\t\tit = t1A.lower_bound(typename T1::value_type(0));\n\t\tVERIFY(it == t1A.begin());\n\n\t\tit = t1A.lower_bound(typename T1::value_type(-1));\n\t\tVERIFY(it == t1A.begin());\n\n\t\tit = t1A.lower_bound(typename T1::value_type(1001));\n\t\tVERIFY(it == t1A.end());\n\n\t\tt1A.erase(typename T1::value_type(500));\n\t\tit = t1A.lower_bound(typename T1::value_type(500));\n\t\tVERIFY(*it  == typename T1::value_type(501));\n\n\n\t\t// upper_bound\n\t\tit = t1A.upper_bound(typename T1::value_type(-1));\n\t\tVERIFY(it == t1A.begin());\n\n\t\tit = t1A.upper_bound(typename T1::value_type(499));\n\t\tVERIFY(*it  == typename T1::value_type(501));\n\n\t\tit = t1A.upper_bound(typename T1::value_type(-1));\n\t\tVERIFY(*it  == typename T1::value_type(0));\n\n\t\tit = t1A.upper_bound(typename T1::value_type(1000));\n\t\tVERIFY(it == t1A.end());\n\n\n\t\t// count\n\t\ttypename T1::size_type n = t1A.count(typename T1::value_type(-1));\n\t\tVERIFY(n == 0);\n\n\t\tn = t1A.count(typename T1::value_type(0));\n\t\tVERIFY(n == 1);\n\n\t\tn = t1A.count(typename T1::value_type(500)); // We removed 500 above.\n\t\tVERIFY(n == 0);\n\n\t\tn = t1A.count(typename T1::value_type(1001));\n\t\tVERIFY(n == 0);\n\n\n\t\t// equal_range\n\t\teastl::pair<typename T1::iterator, typename T1::iterator> er = t1A.equal_range(typename T1::value_type(200));\n\t\tVERIFY(*er.first == typename T1::value_type(200));\n\n\t\ter = t1A.equal_range(typename T1::value_type(499));\n\t\tVERIFY(*er.first  == typename T1::value_type(499));\n\t\tVERIFY(*er.second == typename T1::value_type(501));\n\n\t\ter = t1A.equal_range(typename T1::value_type(-1));\n\t\tVERIFY(er.first == er.second);\n\t\tVERIFY(er.first == t1A.begin());\n\n\n\t\t// Some tests need to be differently between map and multimap.\n\t\tnErrorCount += TestSetSpecific(t1A, eastl::integral_constant<bool, bMultimap>());\n\t}\n\n\tVERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestSetCpp11\n//\n// This function is designed to work with set, fixed_set, hash_set, fixed_hash_set\n//\ntemplate <typename T1>\nint TestSetCpp11()\n{\n\tint nErrorCount = 0;\n\n\t// template <class... Args>\n\t// insert_return_type emplace(Args&&... args);\n\t//\n\t// template <class... Args> \n\t// iterator emplace_hint(const_iterator position, Args&&... args);\n\t//\n\t// insert_return_type insert(value_type&& value);\n\t// iterator insert(const_iterator position, value_type&& value);\n\tTestObject::Reset();\n\n\ttypedef T1 TOSet;\n\ttypename TOSet::insert_return_type toSetInsertResult;\n\ttypename TOSet::iterator toSetIterator;\n\n\tTOSet      toSet;\n\tTestObject to0(0);\n\tTestObject to1(1);\n\n\ttoSetInsertResult = toSet.emplace(to0);\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\t//EATEST_VERIFY((TestObject::sTOCopyCtorCount == 2) && (TestObject::sTOMoveCtorCount == 1));  // Disabled until we can guarantee its behavior and deal with how it's different between compilers of differing C++11 support.\n\n\ttoSetInsertResult = toSet.emplace(eastl::move(to1));\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\n\t// insert_return_type t1A.emplace(value_type&& value);\n\tTestObject to40(4);\n\tEATEST_VERIFY(toSet.find(to40) == toSet.end());\n\tEATEST_VERIFY(to40.mX == 4); // It should change to 0 below during the move swap.\n\ttoSetInsertResult = toSet.emplace(eastl::move(to40));\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\tEATEST_VERIFY(toSet.find(to40) != toSet.end());\n\tEATEST_VERIFY(to40.mX == 0);\n\n\tTestObject to41(4);\n\ttoSetInsertResult = toSet.emplace(eastl::move(to41));\n\tEATEST_VERIFY(toSetInsertResult.second == false);\n\tEATEST_VERIFY(toSet.find(to41) != toSet.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, value_type&& value);\n\tTestObject to50(5);\n\ttoSetInsertResult = toSet.emplace(eastl::move(to50));\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\tEATEST_VERIFY(toSet.find(to50) != toSet.end());\n\n\tTestObject to51(5);\n\ttoSetIterator = toSet.emplace_hint(toSetInsertResult.first, eastl::move(to51));\n\tEATEST_VERIFY(*toSetIterator == TestObject(5));\n\tEATEST_VERIFY(toSet.find(to51) != toSet.end());\n\n\tTestObject to6(6);\n\ttoSetIterator = toSet.emplace_hint(toSet.begin(), eastl::move(to6)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(*toSetIterator == TestObject(6));\n\tEATEST_VERIFY(toSet.find(to6) != toSet.end());\n\t\t\n\tTestObject to2(2);\n\tEATEST_VERIFY(toSet.find(to2) == toSet.end());\n\ttoSetInsertResult = toSet.emplace(to2);\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\tEATEST_VERIFY(toSet.find(to2) != toSet.end());\n\ttoSetInsertResult = toSet.emplace(to2);\n\tEATEST_VERIFY(toSetInsertResult.second == false);\n\tEATEST_VERIFY(toSet.find(to2) != toSet.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, const value_type& value);\n\tTestObject to70(7);\n\ttoSetInsertResult = toSet.emplace(to70);\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\tEATEST_VERIFY(toSet.find(to70) != toSet.end());\n\n\tTestObject to71(7);\n\ttoSetIterator = toSet.emplace_hint(toSetInsertResult.first, to71);\n\tEATEST_VERIFY(*toSetIterator == to71);\n\tEATEST_VERIFY(toSet.find(to71) != toSet.end());\n\n\tTestObject to8(8);\n\ttoSetIterator = toSet.emplace_hint(toSet.begin(), to8); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(*toSetIterator == to8);\n\tEATEST_VERIFY(toSet.find(to8) != toSet.end());\n\n\t//pair<iterator,bool> t1A.insert(value_type&& value);\n\tTestObject to3(3);\n\tEATEST_VERIFY(toSet.find(to3) == toSet.end());\n\ttoSetInsertResult = toSet.insert(TestObject(to3));\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\tEATEST_VERIFY(toSet.find(to3) != toSet.end());\n\ttoSetInsertResult = toSet.insert(TestObject(to3));\n\tEATEST_VERIFY(toSetInsertResult.second == false);\n\tEATEST_VERIFY(toSet.find(to3) != toSet.end());\n\n\n\t// iterator t1A.insert(const_iterator position, value_type&& value);\n\tTestObject to90(9);\n\ttoSetInsertResult = toSet.emplace(eastl::move(to90));\n\tEATEST_VERIFY(toSetInsertResult.second == true);\n\tEATEST_VERIFY(toSet.find(to90) != toSet.end());\n\n\tTestObject to91(9);\n\ttoSetIterator = toSet.emplace_hint(toSetInsertResult.first, eastl::move(to91));\n\tEATEST_VERIFY(*toSetIterator == TestObject(9));\n\tEATEST_VERIFY(toSet.find(to91) != toSet.end());\n\n\tTestObject to10(10);\n\ttoSetIterator = toSet.emplace_hint(toSet.begin(), eastl::move(to10)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(*toSetIterator == TestObject(10));\n\tEATEST_VERIFY(toSet.find(to10) != toSet.end());\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n// TestMultisetCpp11\n//\n// This function is designed to work with multiset, fixed_multiset, hash_multiset, fixed_hash_multiset\n//\n// This is similar to the TestSetCpp11 function, with some differences related \n// to handling of duplicate entries.\n//\ntemplate <typename T1>\nint TestMultisetCpp11()\n{\n\tint nErrorCount = 0;\n\n\t// template <class... Args>\n\t// insert_return_type emplace(Args&&... args);\n\t//\n\t// template <class... Args> \n\t// iterator emplace_hint(const_iterator position, Args&&... args);\n\t//\n\t// insert_return_type insert(value_type&& value);\n\t// iterator insert(const_iterator position, value_type&& value);\n\tTestObject::Reset();\n\n\ttypedef T1 TOSet;\n\ttypename TOSet::iterator toSetIterator;\n\n\tTOSet      toSet;\n\tTestObject to0(0);\n\tTestObject to1(1);\n\n\ttoSetIterator = toSet.emplace(to0);\n\tEATEST_VERIFY(*toSetIterator == TestObject(0));\n\t//EATEST_VERIFY((TestObject::sTOCopyCtorCount == 2) && (TestObject::sTOMoveCtorCount == 1));  // Disabled until we can guarantee its behavior and deal with how it's different between compilers of differing C++11 support.\n\n\ttoSetIterator = toSet.emplace(eastl::move(to1));\n\tEATEST_VERIFY(*toSetIterator == TestObject(1));\n\n\t// insert_return_type t1A.emplace(value_type&& value);\n\tTestObject to40(4);\n\tEATEST_VERIFY(toSet.find(to40) == toSet.end());\n\tEATEST_VERIFY(to40.mX == 4); // It should change to 0 below during the move swap.\n\ttoSetIterator = toSet.emplace(eastl::move(to40));\n\tEATEST_VERIFY(*toSetIterator == TestObject(4));\n\tEATEST_VERIFY(toSet.find(to40) != toSet.end());\n\tEATEST_VERIFY(to40.mX == 0);\n\n\tTestObject to41(4);\n\ttoSetIterator = toSet.emplace(eastl::move(to41));  // multiset can insert another of these.\n\tEATEST_VERIFY(*toSetIterator == TestObject(4));\n\tEATEST_VERIFY(toSet.find(to41) != toSet.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, value_type&& value);\n\tTestObject to50(5);\n\ttoSetIterator = toSet.emplace(eastl::move(to50));\n\tEATEST_VERIFY(*toSetIterator == TestObject(5));\n\tEATEST_VERIFY(toSet.find(to50) != toSet.end());\n\n\tTestObject to51(5);\n\ttoSetIterator = toSet.emplace_hint(toSetIterator, eastl::move(to51));\n\tEATEST_VERIFY(*toSetIterator == TestObject(5));\n\tEATEST_VERIFY(toSet.find(to51) != toSet.end());\n\n\tTestObject to6(6);\n\ttoSetIterator = toSet.emplace_hint(toSet.begin(), eastl::move(to6)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(*toSetIterator == TestObject(6));\n\tEATEST_VERIFY(toSet.find(to6) != toSet.end());\n\t\t\n\tTestObject to2(2);\n\tEATEST_VERIFY(toSet.find(to2) == toSet.end());\n\ttoSetIterator = toSet.emplace(to2);\n\tEATEST_VERIFY(*toSetIterator == TestObject(2));\n\tEATEST_VERIFY(toSet.find(to2) != toSet.end());\n\ttoSetIterator = toSet.emplace(to2);\n\tEATEST_VERIFY(*toSetIterator == TestObject(2));\n\tEATEST_VERIFY(toSet.find(to2) != toSet.end());\n\n\t// iterator t1A.emplace_hint(const_iterator position, const value_type& value);\n\tTestObject to70(7);\n\ttoSetIterator = toSet.emplace(to70);\n\tEATEST_VERIFY(*toSetIterator == TestObject(7));\n\tEATEST_VERIFY(toSet.find(to70) != toSet.end());\n\n\tTestObject to71(7);\n\ttoSetIterator = toSet.emplace_hint(toSetIterator, to71);\n\tEATEST_VERIFY(*toSetIterator == to71);\n\tEATEST_VERIFY(toSet.find(to71) != toSet.end());\n\n\tTestObject to8(8);\n\ttoSetIterator = toSet.emplace_hint(toSet.begin(), to8); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(*toSetIterator == to8);\n\tEATEST_VERIFY(toSet.find(to8) != toSet.end());\n\n\t// insert_return_type t1A.insert(value_type&& value);\n\tTestObject to3(3);\n\tEATEST_VERIFY(toSet.find(to3) == toSet.end());\n\ttoSetIterator = toSet.insert(TestObject(to3));\n\tEATEST_VERIFY(*toSetIterator == TestObject(3));\n\tEATEST_VERIFY(toSet.find(to3) != toSet.end());\n\ttoSetIterator = toSet.insert(TestObject(to3));\n\tEATEST_VERIFY(*toSetIterator == TestObject(3));\n\tEATEST_VERIFY(toSet.find(to3) != toSet.end());\n\n\t// iterator t1A.insert(const_iterator position, value_type&& value);\n\tTestObject to90(9);\n\ttoSetIterator = toSet.emplace(eastl::move(to90));\n\tEATEST_VERIFY(*toSetIterator == TestObject(9));\n\tEATEST_VERIFY(toSet.find(to90) != toSet.end());\n\n\tTestObject to91(9);\n\ttoSetIterator = toSet.emplace_hint(toSetIterator, eastl::move(to91));\n\tEATEST_VERIFY(*toSetIterator == TestObject(9));\n\tEATEST_VERIFY(toSet.find(to91) != toSet.end());\n\n\tTestObject to10(10);\n\ttoSetIterator = toSet.emplace_hint(toSet.begin(), eastl::move(to10)); // specify a bad hint. Insertion should still work.\n\tEATEST_VERIFY(*toSetIterator == TestObject(10));\n\tEATEST_VERIFY(toSet.find(to10) != toSet.end());\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestSmartPtr.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EABase/eabase.h>\n#include \"EASTLTest.h\"\n#include \"GetTypeName.h\"\n#include <EAStdC/EAString.h>\n#include <EAStdC/EAStopwatch.h>\n#include <EASTL/atomic.h>\n#include <EASTL/core_allocator_adapter.h>\n#include <EASTL/core_allocator.h>\n#include <EASTL/intrusive_ptr.h>\n#include <EASTL/linked_array.h>\n#include <EASTL/linked_ptr.h>\n#include <EASTL/safe_ptr.h>\n#include <EASTL/scoped_array.h>\n#include <EASTL/scoped_ptr.h>\n#include <EASTL/shared_array.h>\n#include <EASTL/shared_ptr.h>\n#include <EASTL/unique_ptr.h>\n#include <EASTL/weak_ptr.h>\n#include <eathread/eathread_thread.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <stdio.h>\n#include <string.h>\n#ifdef EA_PLATFORM_WINDOWS\n\t#ifndef WIN32_LEAN_AND_MEAN\n\t\t#define WIN32_LEAN_AND_MEAN\n\t#endif\n\t#include <Windows.h>\n#elif defined(EA_PLATFORM_ANDROID)\n\t#include <android/log.h>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nEA_DISABLE_VC_WARNING(4702 4800)  // 4702: unreachable code\n\t\t\t\t\t\t\t\t  // 4800: forcing value to bool 'true' or 'false'\n\n\n\nnamespace SmartPtrTest\n{\n\t/// CustomDeleter\n\t///\n\t/// Used for testing unique_ptr deleter overrides. Otherwise acts the same as the default deleter.\n\t///\n\tstruct CustomDeleter\n\t{\n\t\ttemplate <typename T>\n\t\tvoid operator()(const T* p) const // We use a const argument type in order to be most flexible with what types we accept. \n\t\t\t{ delete const_cast<T*>(p); }\n\n\t\tCustomDeleter() {}\n\t\tCustomDeleter(const CustomDeleter&) {}\n\t\tCustomDeleter(CustomDeleter&&) {}\n\t\tCustomDeleter& operator=(const CustomDeleter&) { return *this; }\n\t\tCustomDeleter& operator=(CustomDeleter&&) { return *this; }\n\t};\n\n\n\tstruct CustomArrayDeleter\n\t{\n\t\ttemplate <typename T>\n\t\tvoid operator()(const T* p) const // We use a const argument type in order to be most flexible with what types we accept. \n\t\t\t{ delete[] const_cast<T*>(p); }\n\n\t\tCustomArrayDeleter() {}\n\t\tCustomArrayDeleter(const CustomArrayDeleter&) {}\n\t\tCustomArrayDeleter(CustomArrayDeleter&&) {}\n\t\tCustomArrayDeleter& operator=(const CustomArrayDeleter&) { return *this; }\n\t\tCustomArrayDeleter& operator=(CustomArrayDeleter&&) { return *this; }\n\t};\n\n\n\t/// A\n\t///\n\t/// This is used for various tests. \n\t///\n\tstruct A\n\t{\n\t\tchar mc;\n\t\tstatic int mCount;\n\n\t\tA(char c = 0) \n\t\t\t: mc(c) { ++mCount; }\n\n\t\tA(const A& x) \n\t\t\t: mc(x.mc) { ++mCount; }\n\n\t\tA& operator=(const A& x) \n\t\t\t{ mc = x.mc; return *this; }\n\n\t\tvirtual ~A() // Virtual because we subclass A below.\n\t\t\t{ --mCount; }\n\t};\n\n\n\tint A::mCount = 0;\n\n\n\t/// B\n\t///\n\tstruct B : public A\n\t{\n\t};\n\n\n\n\t/// RefCountTest\n\t///\n\t/// This is used for tests involving intrusive_ptr.\n\t/// \n\tstruct RefCountTest\n\t{\n\t\tint mRefCount;\n\t\tstatic int mCount;\n\n\t\tRefCountTest()\n\t\t\t: mRefCount(0) { ++mCount; }\n\n\t\tRefCountTest(const RefCountTest&)\n\t\t\t: mRefCount(0) { ++mCount; }\n\n\t\tRefCountTest& operator=(const RefCountTest&)\n\t\t\t{ return *this; }\n\n\t\tvirtual ~RefCountTest()\n\t\t\t{ --mCount; }\n\n\t\tvirtual int AddRef()\n\t\t\t{ return (int)((mRefCount++) + 1); }\n\n\t\tvirtual int Release()\n\t\t{\n\t\t\tint rc = (int)((mRefCount--) - 1);\n\t\t\tif(rc)\n\t\t\t\treturn rc;\n\t\t\tmRefCount = 1;\n\t\t\tdelete this;\n\t\t\treturn 0;\n\t\t}\n\t};\n\n\tint RefCountTest::mCount = 0;\n\n\n\n\t/// Test\n\t///\n\t/// This is used for tests involving intrusive_ptr.\n\t/// \n\tstruct Test : public RefCountTest\n\t{\n\t\tbool* mpBool;\n\n\t\tTest(bool* pBool)\n\t\t\t: mpBool(pBool) { *pBool = true; }\n\n\t\tTest(const Test& x): \n\t\t\tRefCountTest(x), mpBool(x.mpBool) { }\n\n\t\tTest& operator=(const Test& x)\n\t\t\t{ mpBool = x.mpBool; return *this; }\n\n\t   ~Test()\n\t\t\t{ *mpBool = false; }\n\t};\n\n\n\n\t/// IntrusiveParent / IntrusiveChild\n\t///\n\t/// This is used for tests involving intrusive_ptr.\n\t/// \n\tstruct IntrusiveParent : public RefCountTest\n\t{\n\t};\n\n\tstruct IntrusiveChild : public IntrusiveParent\n\t{\n\t};\n\n\n\t/// intrusive_ptr_add_ref / intrusive_ptr_release\n\t///\n\t/// This is used for tests involving intrusive_ptr.\n\t/// \n\tstruct IntrusiveCustom : public RefCountTest\n\t{\n\t\tstatic int mAddRefCallCount;\n\t\tstatic int mReleaseCallCount;\n\n\t\tvirtual int AddRef()\n\t\t{\n\t\t\t++mAddRefCallCount;\n\t\t\treturn RefCountTest::AddRef();\n\t\t}\n\n\t\tvirtual int Release()\n\t\t{\n\t\t\t++mReleaseCallCount;\n\t\t\treturn RefCountTest::Release();\n\t\t}\n\t};\n\n\tint IntrusiveCustom::mAddRefCallCount  = 0;\n\tint IntrusiveCustom::mReleaseCallCount = 0;\n\n\tvoid intrusive_ptr_add_ref(IntrusiveCustom* p)\n\t{\n\t\tp->AddRef();\n\t}\n\t \n\tvoid intrusive_ptr_release(IntrusiveCustom* p)\n\t{\n\t\tp->Release();\n\t}\n\n\n\t/// ParentClass / ChildClass / GrandChildClass\n\t///\n\t/// This is used for tests involving shared_ptr.\n\t/// \n\tstruct ParentClass\n\t{\n\t\tvirtual ~ParentClass() { }\n\t\tvirtual void DoNothingParentClass() { }\n\t};\n\n\tstruct ChildClass : public ParentClass\n\t{\n\t\tvirtual void DoNothingChildClass() { }\n\t};\n\n\tstruct GrandChildClass : public ChildClass\n\t{\n\t\tvirtual void DoNothingGrandChildClass() { }\n\t};\n\n\n\n\t/// NamedClass\n\t///\n\tstruct NamedClass\n\t{\n\t\tconst char* mpName;\n\t\tconst char* mpName2;\n\t\tstatic int  mnCount;\n\n\t\tNamedClass(const char* pName = NULL)\n\t\t\t: mpName(pName), mpName2(NULL) { ++mnCount; }\n\n\t\tNamedClass(const char* pName, const char* pName2)\n\t\t\t: mpName(pName), mpName2(pName2) { ++mnCount; }\n\n\t\tNamedClass(const NamedClass& x)\n\t\t\t: mpName(x.mpName), mpName2(x.mpName2) { ++mnCount; }\n\n\t\tNamedClass& operator=(const NamedClass& x)\n\t\t\t{ mpName = x.mpName; mpName2 = x.mpName2; return *this; }\n\n\t   ~NamedClass()\n\t\t\t{ --mnCount; }\n\t};\n\n\tint NamedClass::mnCount = 0;\n\n\n\n\t/// Y\n\t///\n\t/// This is used for tests involving shared_ptr and enabled_shared_from_this.\n\t/// \n\tstruct Y : public eastl::enable_shared_from_this<Y>\n\t{\n\t\tstatic int mnCount;\n\n\t\tY() { ++mnCount; }\n\t\tY(const Y&) { ++mnCount; }\n\t\tY& operator=(const Y&) { return *this; }\n\t   ~Y() { --mnCount; }\n\n\t\teastl::shared_ptr<Y> f()\n\t\t\t{ return shared_from_this(); }\n\t};\n\n\tint Y::mnCount = 0;\n\n\n\n\t/// ACLS / BCLS\n\t///\n\t/// This is used for tests involving shared_ptr.\n\t/// \n\tclass ACLS : public eastl::enable_shared_from_this<ACLS>\n\t{\n\tpublic:\n\t\tstatic int mnCount;\n\t\tint a;\n\n\t\tACLS(int _a_ = 0) : a(_a_) { ++mnCount; }\n\t\tACLS(const ACLS& x) : a(x.a) { ++mnCount; }\n\t\tACLS& operator=(const ACLS& x) { a = x.a; return *this; }\n\t   ~ACLS() { --mnCount; }\n\t};\n\n\tint ACLS::mnCount = 0;\n\n\n\tclass BCLS : public ACLS\n\t{\n\tpublic:\n\t\tstatic int mnCount;\n\t\tint b;\n\n\t\tBCLS(int _b_ = 0) : b(_b_) { ++mnCount; }\n\t\tBCLS(const BCLS& x) : ACLS(x), b(x.b) { ++mnCount; }\n\t\tBCLS& operator=(const BCLS& x) { b = x.b; ACLS::operator=(x); return *this; }\n\t   ~BCLS() { --mnCount; }\n\t};\n\n\tint BCLS::mnCount = 0;\n\n\n\n\t/// A1 / B1\n\t///\n\t/// This is used for tests involving shared_ptr.\n\t/// \n\tstruct A1\n\t{\n\t\tstatic int mnCount;\n\t\tint a;\n\n\t\tA1(int _a_ = 0) : a(_a_) { ++mnCount; }\n\t\tA1(const A1& x) : a(x.a) { ++mnCount; }\n\t\tA1& operator=(const A1& x) { a = x.a; return *this; }\n\t   ~A1() { --mnCount; }\n\t};\n\n\tint A1::mnCount = 0;\n\n\n\n\tstruct B1 : public A1\n\t{\n\t\tstatic int mnCount;\n\t\tint b;\n\n\t\tB1(int _b_ = 0) : b(_b_) { ++mnCount; }\n\t\tB1(const B1& x) : A1(x), b(x.b) { ++mnCount; }\n\t\tB1& operator=(const B1& x) { b = x.b; A1::operator=(x); return *this; }\n\t   ~B1() { --mnCount; }\n\t};\n\n\tint B1::mnCount = 0;\n\n\n\n\tclass MockObject\n\t{\n\tpublic:\n\t\tMockObject(bool* pAlloc) \n\t\t  : mpAlloc(pAlloc){ *mpAlloc = true; }\n\n\t   ~MockObject()\n\t\t\t{ *mpAlloc = false; }\n\n\t\tbool IsAllocated() const\n\t\t\t{ return *mpAlloc; }\n\n\t\tbool* GetAllocPtr() const\n\t\t\t{ return mpAlloc; }\n\n\tprivate:\n\t\tbool* mpAlloc;\n\t};\n\n\tclass DerivedMockObject : public MockObject\n\t{\n\tpublic:\n\t\tDerivedMockObject(bool* pAlloc)\n\t\t  : MockObject(pAlloc) {}\n\t};\n\n\n\tstruct foo : public eastl::enable_shared_from_this<foo>\n\t{\n\t\tfoo() : mX(0){}\n\t\tint mX;\n\t};\n\n\tstruct CheckUPtrEmptyInDestructor\n\t{\n\t\t~CheckUPtrEmptyInDestructor()\n\t\t{\n\t\t\tif(mpUPtr)\n\t\t\t\tmCheckUPtrEmpty = (*mpUPtr == nullptr);\n\t\t}\n\n\t\teastl::unique_ptr<CheckUPtrEmptyInDestructor>* mpUPtr{};\n\t\tstatic bool mCheckUPtrEmpty;\n\t};\n\n\tbool CheckUPtrEmptyInDestructor::mCheckUPtrEmpty = false;\n\n\tstruct CheckUPtrArrayEmptyInDestructor\n\t{\n\t\t~CheckUPtrArrayEmptyInDestructor()\n\t\t{\n\t\t\tif(mpUPtr)\n\t\t\t\tmCheckUPtrEmpty = (*mpUPtr == nullptr);\n\t\t}\n\n\t\teastl::unique_ptr<CheckUPtrArrayEmptyInDestructor[]>* mpUPtr{};\n\t\tstatic bool mCheckUPtrEmpty;\n\t};\n\n\tbool CheckUPtrArrayEmptyInDestructor::mCheckUPtrEmpty = false;\n} // namespace SmartPtrTest\n\n\n\n\nstatic int Test_unique_ptr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t{\n\t\tEATEST_VERIFY(A::mCount == 0);\n\n\t\t// explicit unique_ptr(pointer pValue) noexcept\n\t\tunique_ptr<int> pT1(new int(5));\n\t\tEATEST_VERIFY(*pT1 == 5);\n\n\t\t// (reference) operator*() const\n\t\t*pT1 = 3;\n\t\tEATEST_VERIFY(*pT1 == 3);\n\n\t\t// explicit unique_ptr(pointer pValue) noexcept\n\t\tunique_ptr<A> pT2(new A(1));\n\t\tEATEST_VERIFY(pT2->mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\n\t\t// Pointers of derived types are allowed (unlike array unique_ptr) \n\t\tunique_ptr<A> pT1B(new B);\n\t\tEATEST_VERIFY(pT1B.get() != NULL);\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\tA* pA = pT1B.release(); // release simply forgets the owned pointer.\n\t\tEATEST_VERIFY(pT1B.get() == NULL);\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\tdelete pA;\n\t\tEATEST_VERIFY(A::mCount == 1);\n\n\t\t// pointer operator->() const noexcept\n\t\tpT2->mc = 5;\n\t\tEATEST_VERIFY(pT2.get()->mc == 5);\n\n\t\t// void reset(pointer pValue = pointer()) noexcept\n\t\tpT2.reset(new A(2));\n\t\tEATEST_VERIFY(pT2->mc == 2);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\n\t\tpT2.reset(0);\n\t\tEATEST_VERIFY(pT2.get() == (A*)0);\n\t\tEATEST_VERIFY(A::mCount == 0);\n\n\t\tpT2.reset(new A(3));\n\t\tEATEST_VERIFY(pT2->mc == 3);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\n\t\tunique_ptr<A> pT3(new A(4));\n\t\tEATEST_VERIFY(pT3->mc == 4);\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\t// void swap(this_type& scopedPtr) noexcept\n\t\tpT2.swap(pT3);\n\t\tEATEST_VERIFY(pT2->mc == 4);\n\t\tEATEST_VERIFY(pT3->mc == 3);\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\t// void swap(unique_ptr<T, D>& scopedPtr1, unique_ptr<T, D>& scopedPtr2) noexcept\n\t\tswap(pT2, pT3);\n\t\tEATEST_VERIFY(pT2->mc == 3);\n\t\tEATEST_VERIFY(pT3->mc == 4);\n\t\tEATEST_VERIFY((pT2 < pT3) == (pT2.get() < pT3.get()));\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\t// pointer release() noexcept\n\t\tunique_ptr<A> pRelease(new A);\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t\tpA = pRelease.release();\n\t\tdelete pA;\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\t// constexpr unique_ptr() noexcept\n\t\tunique_ptr<A> pT4;\n\t\tEATEST_VERIFY(pT4.get() == (A*)0);\n\t\tif(pT4)\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\t\tif(!(!pT4))\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\n\t\tpT4.reset(new A(0));\n\t\tif(!pT4)\n\t\t\tEATEST_VERIFY(!pT4.get()); // Will fail\n\n\t\tEATEST_VERIFY(A::mCount == 3);\n\n\t\t// unique_ptr(nullptr_t) noexcept\n\t\tunique_ptr<A> pT5(nullptr);\n\t\tEATEST_VERIFY(pT5.get() == (A*)0);\n\n\t\t// unique_ptr(pointer pValue, deleter) noexcept\n\t\tCustomDeleter customADeleter;\n\t\tunique_ptr<A, CustomDeleter> pT6(new A(17), customADeleter);\n\t\tEATEST_VERIFY(pT6->mc == 17);\n\n\t\t// unique_ptr(pointer pValue, typename eastl::remove_reference<Deleter>::type&& deleter) noexcept\n\t\tunique_ptr<A, CustomDeleter> pT7(new A(18), CustomDeleter());\n\t\tEATEST_VERIFY(pT7->mc == 18);\n\n\t\t// unique_ptr(this_type&& x) noexcept\n\t\tunique_ptr<A, CustomDeleter> pT8(eastl::move(pT7));\n\t\tEATEST_VERIFY(pT8->mc == 18);\n\n\t\t// unique_ptr(unique_ptr<U, E>&& u, ...)\n\t\tunique_ptr<A, default_delete<A> > pT9(eastl::move(pT2));\n\n\t\t// this_type& operator=(this_type&& u) noexcept\n\t\t// operator=(unique_ptr<U, E>&& u) noexcept\n\t\t//unique_ptr<void, CustomDeleter> pTVoid;\n\t\t//unique_ptr<int, CustomDeleter>  pTInt(new int(1));\n\t\t//pTVoid.operator=<int, CustomDeleter>(eastl::move(pTInt));  // This doesn't work because CustomDeleter doesn't know how to delete void*. Need to rework this test.\n\n\t\t// this_type& operator=(nullptr_t) noexcept\n\t\tpT6 = nullptr;\n\t\tEATEST_VERIFY(pT6.get() == (A*)0);\n\n\t\t// user reported regression\n\t\t// ensure a unique_ptr containing nullptr doesn't call the deleter when its destroyed.\n\t\t{\n\t\t\tstatic bool sLocalDeleterCalled;\n\t\t\tsLocalDeleterCalled = false;\n\n\t\t\tstruct LocalDeleter\n\t\t\t{\n\t\t\t\tvoid operator()(int* p) const\n\t\t\t\t{\n\t\t\t\t\tsLocalDeleterCalled = true;\n\t\t\t\t\tdelete p;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tusing local_unique_ptr = eastl::unique_ptr<int, LocalDeleter>;\n\n\t\t\tlocal_unique_ptr pEmpty{nullptr};\n\n\t\t\tpEmpty = local_unique_ptr{new int(42), LocalDeleter()};\n\n\t\t\tEATEST_VERIFY(sLocalDeleterCalled == false);\n\t\t}\n\t}\n\n\t{\n\t\t// Test that unique_ptr internal pointer is reset before calling the destructor\n\t\tCheckUPtrEmptyInDestructor::mCheckUPtrEmpty = false;\n\n\t\tunique_ptr<CheckUPtrEmptyInDestructor> uptr(new CheckUPtrEmptyInDestructor);\n\t\tuptr->mpUPtr = &uptr;\n\t\tuptr.reset();\n\t\tEATEST_VERIFY(CheckUPtrEmptyInDestructor::mCheckUPtrEmpty);\n\t}\n\n\t{\n\t\t// Test that unique_ptr<[]> internal pointer is reset before calling the destructor\n\t\tCheckUPtrArrayEmptyInDestructor::mCheckUPtrEmpty = false;\n\n\t\tunique_ptr<CheckUPtrArrayEmptyInDestructor[]> uptr(new CheckUPtrArrayEmptyInDestructor[1]);\n\t\tuptr[0].mpUPtr = &uptr;\n\t\tuptr.reset();\n\t\tEATEST_VERIFY(CheckUPtrArrayEmptyInDestructor::mCheckUPtrEmpty);\n\t}\n\n\t{\n\t\t#if EASTL_CORE_ALLOCATOR_ENABLED\n\t\t\t// Test EA::Allocator::EASTLICoreDeleter usage within eastl::shared_ptr.\n\t\t\t// http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr\n\n\t\t\t// Consider the following for standards compliance.\n\t\t\t// eastl::shared_ptr<A, EASTLCoreDeleterAdapter> foo(pA, EASTLCoreDeleterAdapter());\n\n\t\t\tconst int cacheAllocationCount = gEASTLTest_AllocationCount.load(eastl::memory_order_relaxed);\n\n\t\t\tusing namespace EA::Allocator;\n\n\t\t\tEASTLCoreAllocatorAdapter ta;\n\t\t\tvoid* pMem = ta.allocate(sizeof(A));\n\n\t\t\tEATEST_VERIFY(pMem != nullptr);     \n\t\t\tEATEST_VERIFY(gEASTLTest_AllocationCount.load(eastl::memory_order_relaxed) > cacheAllocationCount);\n\t\t\t{            \n\t\t\t\tA* pA = new (pMem) A();\n\t\t\t\teastl::shared_ptr<A> foo(pA, EASTLCoreDeleterAdapter());  // Not standards complaint code.  Update EASTL implementation to provide the type of the deleter.\n\t\t\t}\n\t\t\tEATEST_VERIFY(gEASTLTest_AllocationCount.load(eastl::memory_order_relaxed) == cacheAllocationCount);\n\t\t\tEATEST_VERIFY(A::mCount == 0);\n\t\t#endif\n\t}\n\n\t{\n\t\t// Test array specialization of unique_ptr\n\n\t\tEATEST_VERIFY(A::mCount == 0);\n\n\t\t// template <typename P>\n\t\t// explicit unique_ptr(P pValue) noexcept\n\t\tunique_ptr<int[]> pT1(new int[5]);\n\t\tpT1[0] = 5;\n\t\tEATEST_VERIFY(pT1[0] == 5);\n\n\t\t// Arrays of derived types are not allowed (unlike regular unique_ptr) \n\t\t// unique_ptr<A[]> pT1B(new B[5]); // Disabled because it should not compile.\n\n\t\t// (reference) operator[]() const\n\t\tpT1[1] = 1;\n\t\tEATEST_VERIFY(pT1[1] == 1);\n\n\t\t// explicit unique_ptr(pointer pValue) noexcept\n\t\tunique_ptr<A[]> pT2(new A[1]);\n\t\tpT2[0].mc = 1;\n\t\tEATEST_VERIFY(pT2[0].mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\n\t\t// pointer operator->() const noexcept\n\t\tpT2[0].mc = 5;\n\t\tEATEST_VERIFY(pT2[0].mc == 5);\n\n\t\t// void reset(pointer pValue = pointer()) noexcept\n\t\tpT2.reset(new A[2]);\n\t\tpT2[0].mc = 2;\n\t\tEATEST_VERIFY(pT2[0].mc == 2);\n\n\t\tpT2.reset(0);\n\t\tEATEST_VERIFY(pT2.get() == (A*)0);\n\n\t\tpT2.reset(new A[3]);\n\t\tpT2[0].mc = 3;\n\t\tEATEST_VERIFY(pT2[0].mc == 3);\n\n\t\tunique_ptr<A[]> pT3(new A[4]);\n\t\tpT3[0].mc = 4;\n\t\tEATEST_VERIFY(pT3[0].mc == 4);\n\n\t\t// void swap(this_type& scopedPtr) noexcept\n\t\tpT2.swap(pT3);\n\t\tEATEST_VERIFY(pT2[0].mc == 4);\n\t\tEATEST_VERIFY(pT3[0].mc == 3);\n\n\t\t// void swap(unique_ptr<T, D>& scopedPtr1, unique_ptr<T, D>& scopedPtr2) noexcept\n\t\tswap(pT2, pT3);\n\t\tEATEST_VERIFY(pT2[0].mc == 3);\n\t\tEATEST_VERIFY(pT3[0].mc == 4);\n\t\tEATEST_VERIFY((pT2 < pT3) == (pT2.get() < pT3.get()));\n\n\t\t// pointer release() noexcept\n\t\tunique_ptr<A[]> pRelease(new A[1]);\n\t\tA* pAArray = pRelease.release();\n\t\tdelete[] pAArray;\n\n\t\t// constexpr unique_ptr() noexcept\n\t\tunique_ptr<A[]> pT4;\n\t\tEATEST_VERIFY(pT4.get() == (A*)0);\n\t\tif(pT4)\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\t\tif(!(!pT4))\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\n\t\tpT4.reset(new A[1]);\n\t\tif(!pT4)\n\t\t\tEATEST_VERIFY(!pT4.get()); // Will fail\n\n\t\tEATEST_VERIFY(A::mCount == 8);  // There were a number of array creations and deletions above that make this so.\n\n\t\t// unique_ptr(nullptr_t) noexcept\n\t\tunique_ptr<A[]> pT5(nullptr);\n\t\tEATEST_VERIFY(pT5.get() == (A*)0);\n\n\t\t// unique_ptr(pointer pValue, deleter) noexcept\n\t\tCustomArrayDeleter customADeleter;\n\t\tunique_ptr<A[], CustomArrayDeleter> pT6(new A[17], customADeleter);\n\t\tpT6[0].mc = 17;\n\t\tEATEST_VERIFY(pT6[0].mc == 17);\n\n\t\t// unique_ptr(pointer pValue, typename eastl::remove_reference<Deleter>::type&& deleter) noexcept\n\t\tunique_ptr<A[], CustomArrayDeleter> pT7(new A[18], CustomArrayDeleter());\n\t\tpT7[0].mc = 18;\n\t\tEATEST_VERIFY(pT7[0].mc == 18);\n\n\t\t// unique_ptr(this_type&& x) noexcept\n\t\tunique_ptr<A[], CustomArrayDeleter> pT8(eastl::move(pT7));\n\t\tEATEST_VERIFY(pT8[0].mc == 18);\n\n\t\t// unique_ptr(unique_ptr<U, E>&& u, ...)\n\t\tunique_ptr<A[], default_delete<A[]> > pT9(eastl::move(pT2));\n\t\tEATEST_VERIFY(pT9[0].mc == 3);\n\n\t\t// this_type& operator=(this_type&& u) noexcept\n\t\t// operator=(unique_ptr<U, E>&& u) noexcept\n\t\t//unique_ptr<void, CustomDeleter> pTVoid;\n\t\t//unique_ptr<int, CustomDeleter>  pTInt(new int(1));\n\t\t//pTVoid.operator=<int, CustomDeleter>(eastl::move(pTInt));  // This doesn't work because CustomDeleter doesn't know how to delete void*. Need to rework this test.\n\n\t\t// this_type& operator=(nullptr_t) noexcept\n\t\tpT6 = nullptr;\n\t\tEATEST_VERIFY(pT6.get() == (A*)0);\n\n\t\t// unique_ptr<> make_unique(Args&&... args);\n\t\tunique_ptr<NamedClass> p = eastl::make_unique<NamedClass>(\"test\", \"test2\");\n\t\tEATEST_VERIFY(EA::StdC::Strcmp(p->mpName, \"test\") == 0 && EA::StdC::Strcmp(p->mpName2, \"test2\") == 0);\n\n\t\tunique_ptr<NamedClass[]> pArray = eastl::make_unique<NamedClass[]>(4);\n\t\tpArray[0].mpName = \"test\";\n\t\tEATEST_VERIFY(EA::StdC::Strcmp(p->mpName, \"test\") == 0);\n\n\t\tconst size_t kAlignedStructAlignment = 512;\n\t\tstruct alignas(kAlignedStructAlignment) AlignedStruct {};\n\n\t\tunique_ptr<AlignedStruct> pAlignedStruct = eastl::make_unique<AlignedStruct>();\n\t\tEATEST_VERIFY_MSG(intptr_t(pAlignedStruct.get()) % kAlignedStructAlignment == 0, \"pAlignedStruct didn't have proper alignment\");\n\n\t\t//Expected to not be valid:\n\t\t//unique_ptr<NamedClass[4]> p2Array4 = eastl::make_unique<NamedClass[4]>();\n\t\t//p2Array4[0].mpName = \"test\";\n\t\t//EATEST_VERIFY(EA::StdC::Strcmp(p2Array4[0].mpName, \"test\") == 0);\n\t}\n\n\tEATEST_VERIFY(A::mCount == 0); // This check verifies that no A instances were lost, which also verifies that the [] version of the deleter was used in all cases.\n\n\t// validate unique_ptr's compressed_pair implementation is working. \n\t{\n\t\tconst int ARBITRARY_SIZE = 256;\n\t\tstatic_assert(sizeof(unique_ptr<short>)     == sizeof(uintptr_t), \"\");\n\t\tstatic_assert(sizeof(unique_ptr<long>)      == sizeof(uintptr_t), \"\");\n\n\t\t// unique_ptr should be the same size as a pointer. The deleter object is empty so the\n\t\t// eastl::compressed_pair implementation will remove that deleter data member from the unique_ptr.\n\t\t{\n\t\t\tauto deleter = [](void* pMem) { free(pMem); };\n\t\t\tunique_ptr<void, decltype(deleter)> sptr(malloc(ARBITRARY_SIZE), deleter);\n\t\t\tstatic_assert(sizeof(sptr) == (sizeof(uintptr_t)), \"unexpected unique_ptr size\");\n\t\t}\n\n\t\t// unique_ptr should be larger than a pointer when the deleter functor is capturing state.  This state forces\n\t\t// the compressed_pair to cached the data in unique_ptr locally. \n\t\t{\n\t\t\tint a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;\n\t\t\tauto deleter = [=](void* pMem) { auto result = (a+b+c+d+e+f); EA_UNUSED(result); free(pMem); };\n\t\t\tunique_ptr<void, decltype(deleter)> sptr(malloc(ARBITRARY_SIZE), deleter);\n\t\t\tstatic_assert(sizeof(sptr) == ((6 * sizeof(int)) + (sizeof(uintptr_t))), \"unexpected unique_ptr size\");\n\t\t}\n\n\t\t// Simply test moving the one unique pointer to another.\n\t\t// Exercising operator=(T&&)\n\t\t{\n\t\t\t{\n\t\t\t\tunique_ptr<int> ptr(new int(3));\n\t\t\t\tEATEST_VERIFY(ptr.get() && *ptr == 3);\n\n\t\t\t\tunique_ptr<int> newPtr(new int(4));\n\t\t\t\tEATEST_VERIFY(newPtr.get() && *newPtr == 4);\n\n\t\t\t\tptr = eastl::move(newPtr);  // Deletes int(3) and assigns mpValue to int(4)\n\t\t\t\tEATEST_VERIFY(ptr.get() && *ptr == 4);\n\t\t\t\tEATEST_VERIFY(newPtr.get() == nullptr);\n\t\t\t}\n\n\t\t#if EA_HAVE_CPP11_INITIALIZER_LIST\n\t\t\t{\n\t\t\t\tunique_ptr<int[]> ptr(new int[3]{ 0, 1, 2 });\n\t\t\t\tEATEST_VERIFY(ptr.get() && ptr[0] == 0 && ptr[1] == 1 && ptr[2] == 2);\n\n\t\t\t\tunique_ptr<int[]> newPtr(new int[3]{ 3, 4, 5 });\n\t\t\t\tEATEST_VERIFY(newPtr.get() && newPtr[0] == 3 && newPtr[1] == 4 && newPtr[2] == 5);\n\n\t\t\t\tptr = eastl::move(newPtr);  // Deletes int(3) and assigns mpValue to int(4)\n\t\t\t\tEATEST_VERIFY(ptr.get() && ptr[0] == 3 && ptr[1] == 4 && ptr[2] == 5);\n\t\t\t\tEATEST_VERIFY(newPtr.get() == nullptr);\n\t\t\t}\n\t\t#endif\n\n\t\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\t\t{\n\t\t\t\tunique_ptr<int> pT1(new int(5));\n\t\t\t\tunique_ptr<int> pT2(new int(10));\n\t\t\t\tunique_ptr<int> pT3(new int(0));\n\n\t\t\t\tEATEST_VERIFY((pT1 <=> pT2) != 0);\n\t\t\t\tEATEST_VERIFY((pT2 <=> pT1) != 0);\n\n\t\t\t\tEATEST_VERIFY((pT1 <=> pT2) < 0);\n\t\t\t\tEATEST_VERIFY((pT1 <=> pT2) <= 0);\n\t\t\t\tEATEST_VERIFY((pT2 <=> pT1) > 0);\n\t\t\t\tEATEST_VERIFY((pT2 <=> pT1) >= 0);\n\n\t\t\t\tEATEST_VERIFY((pT3 <=> pT1) < 0);\n\t\t\t\tEATEST_VERIFY((pT3 <=> pT2) < 0);\n\t\t\t\tEATEST_VERIFY((pT1 <=> pT3) > 0);\n\t\t\t\tEATEST_VERIFY((pT2 <=> pT3) > 0);\n\n\t\t\t\tunique_ptr<A> pT4(new A(5));\n\t\t\t\tunique_ptr<A> pT5(new A(10));\n\n\t\t\t\tEATEST_VERIFY((pT4 <=> pT5) != 0);\n\t\t\t\tEATEST_VERIFY((pT5 <=> pT4) != 0);\n\n\t\t\t\tEATEST_VERIFY((pT4 <=> pT5) < 0);\n\t\t\t\tEATEST_VERIFY((pT4 <=> pT5) <= 0);\n\t\t\t\tEATEST_VERIFY((pT5 <=> pT4) > 0);\n\t\t\t\tEATEST_VERIFY((pT5 <=> pT4) >= 0);\n\t\t\t}\n\t\t#endif\n\n\t\t\t// ToDo: Test move assignment between two convertible types with an is_assignable deleter_type\n\t\t\t//{\n\t\t\t//\tstruct Base {};\n\t\t\t//\tstruct Child : public Base {};\n\n\t\t\t//\ttypedef unique_ptr<Base, CustomDeleter> BaseSPtr;\n\t\t\t//\ttypedef unique_ptr<Child, CustomDeleter> ChildSPtr;\n\n\t\t\t//\tstatic_assert(!is_array<BaseSPtr::element_type>::value, \"This test requires a non-array type\");\n\t\t\t//\tstatic_assert(is_convertible<ChildSPtr::pointer, BaseSPtr::pointer>::value, \"UniquePtr ptr types must be convertible for this test\");\n\t\t\t//\tstatic_assert(is_assignable<BaseSPtr::deleter_type&, ChildSPtr::deleter_type&&>::value, \"Deleter types must be assignable to one another\");\n\n\t\t\t//\tBaseSPtr ptr(new Base);\n\t\t\t//\tEATEST_VERIFY(ptr.get());\n\n\t\t\t//\tunique_ptr<Child> newPtr(new Child);\n\t\t\t//\tEATEST_VERIFY(newPtr.get());\n\n\t\t\t//\tptr = eastl::move(newPtr);\n\t\t\t//\tEATEST_VERIFY(ptr);\n\t\t\t//\tEATEST_VERIFY(newPtr.get() == nullptr);\n\t\t\t//}\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\n\nstatic int Test_scoped_ptr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t{\n\t\tEATEST_VERIFY(A::mCount == 0);\n\n\t\tscoped_ptr<int> pT1(new int(5));\n\t\tEATEST_VERIFY(*pT1 == 5);\n\n\t\t*pT1 = 3;\n\t\tEATEST_VERIFY(*pT1 == 3);\n\t\tEATEST_VERIFY(pT1.get() == get_pointer(pT1));\n\n\t\tscoped_ptr<A> pT2(new A(1));\n\t\tEATEST_VERIFY(pT2->mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\n\t\tpT2.reset(new A(2));\n\t\tEATEST_VERIFY(pT2->mc == 2);\n\n\t\tpT2.reset(0);\n\t\tEATEST_VERIFY(pT2.get() == (A*)0);\n\t\tEATEST_VERIFY(pT2.get() == get_pointer(pT2));\n\n\t\tpT2.reset(new A(3));\n\t\tEATEST_VERIFY(pT2->mc == 3);\n\n\t\tscoped_ptr<A> pT3(new A(4));\n\t\tEATEST_VERIFY(pT3->mc == 4);\n\n\t\tpT2.swap(pT3);\n\t\tEATEST_VERIFY(pT2->mc == 4);\n\t\tEATEST_VERIFY(pT3->mc == 3);\n\n\t\tswap(pT2, pT3);\n\t\tEATEST_VERIFY(pT2->mc == 3);\n\t\tEATEST_VERIFY(pT3->mc == 4);\n\t\tEATEST_VERIFY((pT2 < pT3) == (pT2.get() < pT3.get()));\n\n\t\tscoped_ptr<A> pT4;\n\t\tEATEST_VERIFY(pT4.get() == (A*)0);\n\t\tif(pT4)\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\t\tif(!(!pT4))\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\n\t\tpT4.reset(new A(0));\n\t\tif(!pT4)\n\t\t\tEATEST_VERIFY(!pT4.get()); // Will fail\n\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t}\n\n\t{   // Test the detach function.\n\t\tscoped_ptr<A> ptr(new A);\n\t\tA* pA = ptr.detach();\n\t\tdelete pA;\n\t}\n\n\t{\n\t\tscoped_ptr<void> ptr(new int);\n\t\t(void)ptr;\n\t}\n\n\tEATEST_VERIFY(A::mCount == 0);\n\n\treturn nErrorCount;\n}\n\n\n\nstatic int Test_scoped_array()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t{\n\t\tscoped_array<int> pT1(new int[5]);\n\t\tpT1[0] = 5;\n\t\tEATEST_VERIFY(pT1[0] == 5);\n\t\tEATEST_VERIFY(pT1.get()[0] == 5);\n\n\t\tscoped_array<A> pT2(new A[2]);\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t\tEATEST_VERIFY(pT2[0].mc == 0);\n\t\tEATEST_VERIFY(pT2.get()[0].mc == 0);\n\t\tEATEST_VERIFY(get_pointer(pT2)[0].mc == 0);\n\n\t\tpT2.reset(new A[4]);\n\t\tEATEST_VERIFY(A::mCount == 4);\n\t\tif(!pT2)\n\t\t\tEATEST_VERIFY(!pT2.get()); // Will fail\n\n\t\tpT2.reset(0);\n\t\tEATEST_VERIFY(A::mCount == 0);\n\t\tif(pT2)\n\t\t\tEATEST_VERIFY(pT2.get()); // Will fail\n\t\tif(!(!pT2))\n\t\t\tEATEST_VERIFY(pT2.get()); // Will fail\n\n\t\tscoped_array<A> pT3(new A[3]);\n\t\tEATEST_VERIFY(A::mCount == 3);\n\n\t\tpT2.swap(pT3);\n\t\tEATEST_VERIFY(A::mCount == 3);\n\n\t\tswap(pT2, pT3);\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t\tEATEST_VERIFY((pT2 < pT3) == (pT2.get() < pT3.get()));\n\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t}\n\n\t{   // Test the detach function.\n\t\tscoped_array<A> ptr(new A[6]);\n\t\tA* pArray = ptr.detach();\n\t\tdelete[] pArray;\n\t}\n\n\t{\n\t\tscoped_array<void> ptr(new int[6]);\n\t\t(void)ptr;\n\t}\n\n\tEATEST_VERIFY(A::mCount == 0);\n\n\treturn nErrorCount;\n}\n\n\nstatic int Test_shared_ptr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t// Name test.\n\t#if EASTLTEST_GETTYPENAME_AVAILABLE\n\t\t//eastl::string sTypeName = GetTypeName<typename eastl::unique_ptr<int>::pointer>();\n\t\t//EA::UnitTest::Report(\"type name of (typename shared_ptr<int>::pointer): %s\", sTypeName.c_str());\n\n\t\t//sTypeName = GetTypeName<typename eastl::common_type<int*, int*>::type>();\n\t\t//EA::UnitTest::Report(\"type name of (typename eastl::common_type<int*, int*>::type): %s\", sTypeName.c_str());\n\t#endif\n\n\t{\n\t\tshared_ptr<int> pT1;\n\t\tEATEST_VERIFY(pT1.get() == NULL);\n\t}\n\n\t{\n\t\tshared_ptr<int> pT1(new int(5));\n\t\tEATEST_VERIFY(*pT1 == 5);\n\t\tEATEST_VERIFY(pT1.get() == get_pointer(pT1));\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique() );\n\n\t\tshared_ptr<int> pT2;\n\t\tEATEST_VERIFY(pT1 != pT2);\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\n\t\tpT2 = pT1;\n\t\tEATEST_VERIFY(pT1.use_count() == 2);\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\t\tEATEST_VERIFY(!pT1.unique());\n\t\tEATEST_VERIFY(!(pT1 < pT2)); // They should be equal\n\t\tEATEST_VERIFY(pT1 == pT2);\n\n\t\t*pT1 = 3;\n\t\tEATEST_VERIFY(*pT1 == 3);\n\t\tEATEST_VERIFY(*pT1 == 3);\n\t\tEATEST_VERIFY(*pT2 == 3);\n\n\t\tpT2.reset((int*)NULL);\n\t\tEATEST_VERIFY(pT2.unique());\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1 != pT2);\n\t}\n\n\t{\n\t\tEATEST_VERIFY(A::mCount == 0);\n\n\t\tshared_ptr<A> pT2(new A(0));\n\t\tEATEST_VERIFY(A::mCount == 1);\n\t\tEATEST_VERIFY(pT2->mc == 0);\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\n\t\tpT2.reset(new A(1));\n\t\tEATEST_VERIFY(pT2->mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\n\t\tshared_ptr<A> pT3(new A(2));\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\tpT2.swap(pT3);\n\t\tEATEST_VERIFY(pT2->mc == 2);\n\t\tEATEST_VERIFY(pT3->mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\tswap(pT2, pT3);\n\t\tEATEST_VERIFY(pT2->mc == 1);\n\t\tEATEST_VERIFY(pT3->mc == 2);\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t\tif(!pT2)\n\t\t\tEATEST_VERIFY(!pT2.get()); // Will fail\n\n\t\tshared_ptr<A> pT4;\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t\tif(pT4)\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\t\tif(!(!pT4))\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\n\t\tpT4 = pT2;\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\t\tEATEST_VERIFY(pT4.use_count() == 2);\n\t\tEATEST_VERIFY(!pT2.unique());\n\t\tEATEST_VERIFY(!pT4.unique());\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t\tEATEST_VERIFY(pT2 == pT4);\n\t\tEATEST_VERIFY(pT2 != pT3);\n\t\tEATEST_VERIFY(!(pT2 < pT4)); // They should be equal\n\n\t\tshared_ptr<A> pT5(pT4);\n\t\tEATEST_VERIFY(pT4 == pT5);\n\t\tEATEST_VERIFY(pT2.use_count() == 3);\n\t\tEATEST_VERIFY(pT4.use_count() == 3);\n\t\tEATEST_VERIFY(pT5.use_count() == 3);\n\t\tEATEST_VERIFY(!pT5.unique());\n\n\t\tpT4 = shared_ptr<A>((A*)NULL);\n\t\tEATEST_VERIFY(pT4.unique());\n\t\tEATEST_VERIFY(pT4.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t}\n\n\n\t// Regression test reported by a user.\n\t// typename eastl::enable_if<!eastl::is_array<U>::value && eastl::is_convertible<U*, element_type*>::value, this_type&>::type\n\t// operator=(unique_ptr<U, Deleter> && uniquePtr)\n\t{\n\t\t{\n\t\t\tshared_ptr<A> rT1(new A(42));\n\t\t\tunique_ptr<B> rT2(new B);  // default ctor uses 0\n\t\t\trT2->mc = 115;\n\n\t\t\tEATEST_VERIFY(rT1->mc == 42);\n\t\t\tEATEST_VERIFY(rT2->mc == 115);\n\n\t\t\trT1 = eastl::move(rT2);\n\n\t\t\tEATEST_VERIFY(rT1->mc == 115);\n\t\t\t// EATEST_VERIFY(rT2->mc == 115);  // state of object post-move is undefined.\n\t\t}\n\n\t\t// test the state of the shared_ptr::operator= return\n\t\t{\n\t\t\tshared_ptr<A> rT1(new A(42));\n\t\t\tunique_ptr<B> rT2(new B);  // default ctor uses 0\n\t\t\trT2->mc = 115;\n\n\t\t\tshared_ptr<A> operatorReturn = (rT1 = eastl::move(rT2));\n\n\t\t\tEATEST_VERIFY(operatorReturn == rT1);\n\n\t\t\tEATEST_VERIFY(operatorReturn->mc == 115);\n\t\t\t// EATEST_VERIFY(rT1->mc == 115); // implied as both are pointing to the same address\n\t\t}\n\t}\n\n\n\t{ // Test member template functions.\n\t\tshared_ptr<ChildClass>      pCC(new GrandChildClass);\n\t\tshared_ptr<ParentClass>     pPC(pCC);\n\t\tshared_ptr<GrandChildClass> pGCC(static_pointer_cast<GrandChildClass>(pPC));\n\t}\n\n\n\t{ // Test enable_shared_from_this\n\t\tshared_ptr<Y> p(new Y);\n\t\tshared_ptr<Y> q = p->f();\n\n\t\tEATEST_VERIFY(p == q);\n\t\tEATEST_VERIFY(!(p < q || q < p)); // p and q must share ownership\n\n\t\tshared_ptr<BCLS> bctrlp = shared_ptr<BCLS>(new BCLS);\n\t}\n\n\n\t{ // Test static_pointer_cast, etc.\n\t\tshared_ptr<GrandChildClass> pGCC(new GrandChildClass);\n\t\tshared_ptr<ParentClass>     pPC = static_pointer_cast<ParentClass>(pGCC);\n\n\t\tEATEST_VERIFY(pPC == pGCC);\n\n\t\t#if EASTL_RTTI_ENABLED\n\t\tshared_ptr<ChildClass>      pCC = dynamic_pointer_cast<ChildClass>(pPC);\n\t\tEATEST_VERIFY(pCC == pGCC);\n\t\t#endif\n\n\t\t#if !defined(__GNUC__) ||  (__GNUC__ >= 3) // If not using old GCC (GCC 2.x is broken)...\n\t\t\teastl::shared_ptr<const void> pVoidPtr = shared_ptr<ParentClass>(new ParentClass);\n\t\t\tshared_ptr<ParentClass> ap = const_pointer_cast<ParentClass>(static_pointer_cast<const ParentClass>(pVoidPtr));\n\t\t#endif\n\n\t\t//typedef shared_ptr<void const> ASPtr;\n\t\t//shared_ptr<void const> pVoidPtr = ASPtr(new ParentClass);\n\t\t//ASPtr ap = const_pointer_cast<ParentClass>(static_pointer_cast<const ParentClass>(pVoidPtr));\n\t}\n\n\n\t{ // Test static_shared_pointer_cast, etc.\n\t\tshared_ptr<GrandChildClass> pGCC(new GrandChildClass);\n\t\tshared_ptr<ParentClass>     pPC = static_shared_pointer_cast<ParentClass /*, EASTLAllocatorType, smart_ptr_deleter<ParentClass>*/ >(pGCC);\n\n\t\tEATEST_VERIFY(pPC == pGCC);\n\n\t\t#if EASTL_RTTI_ENABLED\n\t\tshared_ptr<ChildClass>      pCC = dynamic_shared_pointer_cast<ChildClass /*, EASTLAllocatorType, smart_ptr_deleter<ParentClass>*/ >(pPC);\n\t\tEATEST_VERIFY(pCC == pGCC);\n\t\t#endif\n\t}\n\n\n\t{ // Test smart_ptr_deleter\n\t\tshared_ptr<void> pVoid(new ParentClass, smart_ptr_deleter<ParentClass>());\n\t\tEATEST_VERIFY(pVoid.get() != NULL);\n\n\t\tpVoid = shared_ptr<ParentClass>(new ParentClass, smart_ptr_deleter<ParentClass>());\n\t\tEATEST_VERIFY(pVoid.get() != NULL);\n\t}\n\n\n\t{ // Test shared_ptr lambda deleter\n\t\tauto deleter = [](int*) {}; \n\t\teastl::shared_ptr<int> ptr(nullptr, deleter);\n\n\t\tEATEST_VERIFY(!ptr);\n\t\tEATEST_VERIFY(ptr.get() == nullptr);\n\t}\n\n\n\t{ // Test of shared_ptr<void const>\n\t\t#if !defined(__GNUC__) ||  (__GNUC__ >= 3) // If not using old GCC (GCC 2.x is broken)...\n\t\t\tshared_ptr<void const> voidPtr = shared_ptr<A1>(new A1);\n\t\t\tshared_ptr<A1>         a1Ptr   = const_pointer_cast<A1>(static_pointer_cast<const A1>(voidPtr));\n\t\t#endif\n\t}\n\n\n\t{ // Test of static_pointer_cast\n\t\tshared_ptr<B1> bPtr = shared_ptr<B1>(new B1);\n\t\tshared_ptr<A1> aPtr = static_pointer_cast<A1, B1>(bPtr);\n\t}\n\n\n\t{ // Test shared_ptr<void>\n\t\t{\n\t\t\t#if !defined(__GNUC__) ||  (__GNUC__ >= 3) // If not using old GCC (GCC 2.x is broken)...\n\t\t\t\tconst char* const pName = \"NamedClassTest\";\n\n\t\t\t\tNamedClass* const pNamedClass0 = new NamedClass(pName);\n\t\t\t\tEATEST_VERIFY(pNamedClass0->mpName == pName);\n\n\t\t\t  //shared_ptr<void const, EASTLAllocatorType, smart_ptr_deleter<NamedClass> > voidPtr(pNamedClass0);\n\t\t\t\tshared_ptr<void const> voidPtr(pNamedClass0);\n\t\t\t\tEATEST_VERIFY(voidPtr.get() == pNamedClass0);\n\n\t\t\t\tNamedClass* const pNamedClass1 = (NamedClass*)voidPtr.get();\n\t\t\t\tEATEST_VERIFY(pNamedClass1->mpName == pName);\n\t\t\t#endif\n\t\t}\n\n\t\t{\n\t\t\t#if !defined(__GNUC__) ||  (__GNUC__ >= 3) // If not using old GCC (GCC 2.x is broken)...\n\t\t\t\tconst char* const pName = \"NamedClassTest\";\n\n\t\t\t\tNamedClass* const pNamedClass0 = new NamedClass(pName);\n\t\t\t\tEATEST_VERIFY(pNamedClass0->mpName == pName);\n\n\t\t\t\tshared_ptr<void const> voidPtr(pNamedClass0, smart_ptr_deleter<NamedClass>());\n\t\t\t\tEATEST_VERIFY(voidPtr.get() == pNamedClass0);\n\n\t\t\t\tNamedClass* const pNamedClass1 = (NamedClass*)voidPtr.get();\n\t\t\t\tEATEST_VERIFY(pNamedClass1->mpName == pName);\n\t\t\t#endif\n\t\t}\n\t}\n\n\n\t{\n\t\tconst char* const pName1 = \"NamedClassTest1\";\n\t\tconst char* const pName2 = \"NamedClassTest2\";\n\n\t\tshared_ptr<NamedClass> sp(new NamedClass(pName1));\n\t\tEATEST_VERIFY(!sp == false);\n\t\tEATEST_VERIFY(sp.unique());\n\t\tEATEST_VERIFY(sp->mpName == pName1);\n\n\t\tshared_ptr<NamedClass> sp2 = sp;\n\t\tEATEST_VERIFY(sp2.use_count() == 2);\n\n\t\tsp2.reset(new NamedClass(pName2));\n\t\tEATEST_VERIFY(sp2.use_count() == 1);\n\t\tEATEST_VERIFY(sp.unique());\n\t\tEATEST_VERIFY(sp2->mpName == pName2);\n\n\t\tsp.reset();\n\t\tEATEST_VERIFY(!sp == true);\n\t}\n\n\t{\n\t\t// Exception handling tests\n\t\t#if EASTL_EXCEPTIONS_ENABLED\n\t\t\ttry {\n\t\t\t\tweak_ptr<A>   pWeakA;             // leave uninitalized\n\t\t\t\tshared_ptr<A> pSharedA(pWeakA);   // This should throw eastl::bad_weak_ptr\n\t\t\t\tEATEST_VERIFY(false);\n\t\t\t}\n\t\t\tcatch(eastl::bad_weak_ptr&)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(true);            // This pathway should be taken.\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(false);\n\t\t\t}\n\n\n\t\t\tThrowingAllocator<true> throwingAllocator; // Throw on first attempt to allocate.\n\t\t\tshared_ptr<A> pA0;\n\n\t\t\ttry {\n\t\t\t\tA::mCount = 0;\n\t\t\t\tpA0 = eastl::allocate_shared<A, ThrowingAllocator<true> >(throwingAllocator, 'a');\n\t\t\t\tEATEST_VERIFY(false);\n\t\t\t}\n\t\t\tcatch(std::bad_alloc&)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(true);                // This pathway should be taken.\n\t\t\t\tEATEST_VERIFY(pA0.get() == NULL);   // The C++11 Standard doesn't seem to require this, but that's how we currently do it until we learn it should be otherwise.\n\t\t\t\tEATEST_VERIFY(pA0.use_count() == 0);\n\t\t\t\tEATEST_VERIFY(A::mCount == 0);      // Verify that there were no surviving A instances since the exception.\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(false);\n\t\t\t}\n\n\n\t\t\ttry {\n\t\t\t\tshared_ptr<A> pA1(new A('a'), default_delete<A>(), throwingAllocator);\n\t\t\t\tEATEST_VERIFY(false);\n\t\t\t}\n\t\t\tcatch(std::bad_alloc&)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(true);                // This pathway should be taken.\n\t\t\t\tEATEST_VERIFY(A::mCount == 0);\n\t\t\t}\n\t\t\tcatch(...)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(false);\n\t\t\t}\n\n\t\t#endif\n\n\t}\n\n\t#if EASTL_RTTI_ENABLED\n\t{\n\t\t// template <typename U, typename A, typename D>\n\t\t// shared_ptr(const shared_ptr<U, A, D>& sharedPtr, dynamic_cast_tag);\n\t\t// To do.\n\n\t\t// template <typename U, typename A, typename D, typename UDeleter>\n\t\t// shared_ptr(const shared_ptr<U, A, D>& sharedPtr, dynamic_cast_tag, const UDeleter&);\n\t\t// To do.\n\t}\n\t#endif\n\n\tEATEST_VERIFY(A::mCount == 0);\n\n\treturn nErrorCount;\n}\n\n\n\n\n#if EASTL_THREAD_SUPPORT_AVAILABLE\n\t// C++ Standard section 20.7.2.5 -- shared_ptr atomic access\n\t// shared_ptr thread safety is about safe use of the pointer itself and not about what it points to. shared_ptr thread safety\n\t// allows you to safely use shared_ptr from different threads, but if the object shared_ptr holds requires thread safety then\n\t// you need to separately handle that in a thread-safe way. A good way to think about it is this: \"shared_ptr is as thread-safe as a raw pointer.\"\n\t//\n\t// Some helper links:\n\t//     http://stackoverflow.com/questions/9127816/stdshared-ptr-thread-safety-explained\n\t//     http://stackoverflow.com/questions/14482830/stdshared-ptr-thread-safety\n\t//     http://cppwisdom.quora.com/shared_ptr-is-almost-thread-safe\n\t// \n\n\t// Test the ability of Futex to report the callstack of another thread holding a futex.\n\tstruct SharedPtrTestThread : public EA::Thread::IRunnable\n\t{\n\t\tEA::Thread::ThreadParameters    mThreadParams;\n\t\tEA::Thread::Thread              mThread;\n\t\teastl::atomic<bool>             mbShouldContinue;\n\t\tint                             mnErrorCount;\n\t\teastl::shared_ptr<TestObject>*  mpSPTO;\n\t\teastl::weak_ptr<TestObject>*    mpWPTO;\n\n\t\tSharedPtrTestThread() : mThreadParams(), mThread(), mbShouldContinue(true), mnErrorCount(0), mpSPTO(NULL), mpWPTO(NULL) {}\n\t\tSharedPtrTestThread(const SharedPtrTestThread&){}\n\t\tvoid operator=(const SharedPtrTestThread&){}\n\n\t\tintptr_t Run(void*)\n\t\t{\n\t\t\tint& nErrorCount = mnErrorCount; // declare nErrorCount so that EATEST_VERIFY can work, as it depends on it being declared.\n\n\t\t\twhile(mbShouldContinue.load(eastl::memory_order_relaxed))\n\t\t\t{\n\t\t\t\tEA::UnitTest::ThreadSleepRandom(1, 10);\n\n\t\t\t\tEATEST_VERIFY(mpSPTO->get()->mX == 99);\n\n\t\t\t\teastl::shared_ptr<TestObject> temp(mpWPTO->lock());\n\t\t\t\tEATEST_VERIFY(temp->mX == 99);\n\n\t\t\t\teastl::shared_ptr<TestObject> spTO2(*mpSPTO);\n\t\t\t\tEATEST_VERIFY(spTO2->mX == 99);\n\t\t\t\tEATEST_VERIFY(spTO2.use_count() >= 2);\n\n\t\t\t\teastl::weak_ptr<TestObject> wpTO2(spTO2);\n\t\t\t\ttemp = mpWPTO->lock();\n\t\t\t\tEATEST_VERIFY(temp->mX == 99);\n\n\t\t\t\ttemp = spTO2;\n\t\t\t\tspTO2.reset();\n\t\t\t\tEATEST_VERIFY(mpSPTO->get()->mX == 99);\n\t\t\t}\n\n\t\t\treturn nErrorCount;\n\t\t}\n\t};\n#endif\n\n\nstatic int Test_shared_ptr_thread()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\tusing namespace EA::Thread;\n\n\tint nErrorCount(0);\n\n\t#if EASTL_THREAD_SUPPORT_AVAILABLE\n\t\t{\n\t\t\tSharedPtrTestThread    thread[4];\n\t\t\tshared_ptr<TestObject> spTO(new TestObject(99));\n\t\t\tweak_ptr<TestObject>   wpTO(spTO);\n\n\t\t\tfor(size_t i = 0; i < EAArrayCount(thread); i++)\n\t\t\t{\n\t\t\t\tthread[i].mpSPTO = &spTO;\n\t\t\t\tthread[i].mpWPTO = &wpTO;\n\t\t\t\tthread[i].mThreadParams.mpName = \"SharedPtrTestThread\";\n\t\t\t}\n\n\t\t\tfor(size_t i = 0; i < EAArrayCount(thread); i++)\n\t\t\t\tthread[i].mThread.Begin(&thread[0], NULL, &thread[0].mThreadParams);\n\n\t\t\tEA::UnitTest::ThreadSleep(2000);\n\n\t\t\tfor(size_t i = 0; i < EAArrayCount(thread); i++)\n\t\t\t\tthread[i].mbShouldContinue.store(false, eastl::memory_order_relaxed);\n\n\t\t\tfor(size_t i = 0; i < EAArrayCount(thread); i++)\n\t\t\t{\n\t\t\t\tthread[i].mThread.WaitForEnd();\n\t\t\t\tnErrorCount += thread[i].mnErrorCount;\n\t\t\t}\n\t\t}\n\t#endif\n\n\t#if EASTL_THREAD_SUPPORT_AVAILABLE\n\t\t{\n\t\t\t// We currently do light testing of the atomic functions. It would take a bit of work to fully test\n\t\t\t// the memory behavior of these in a rigorous way. Also, as of this writing we don't have a portable\n\t\t\t// way to use the std::memory_order functionality.\n\n\t\t\tshared_ptr<TestObject> spTO(new TestObject(55));\n\n\t\t\t// bool atomic_is_lock_free(const shared_ptr<T>*);\n\t\t\tEATEST_VERIFY(!atomic_is_lock_free(&spTO));\n\n\t\t\t// shared_ptr<T> atomic_load(const shared_ptr<T>* pSharedPtr);\n\t\t\t// shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* pSharedPtr, ... /*std::memory_order memoryOrder*/);\n\t\t\tshared_ptr<TestObject> spTO2 = atomic_load(&spTO);\n\t\t\tEATEST_VERIFY(spTO->mX == 55);\n\t\t\tEATEST_VERIFY(spTO2->mX == 55);\n\n\t\t\t// void atomic_store(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB);\n\t\t\t// void atomic_store_explicit(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB, ... /*std::memory_order memoryOrder*/);\n\t\t\tspTO2->mX = 56;\n\t\t\tEATEST_VERIFY(spTO->mX == 56);\n\t\t\tEATEST_VERIFY(spTO2->mX == 56);\n\n\t\t\tatomic_store(&spTO, shared_ptr<TestObject>(new TestObject(77)));\n\t\t\tEATEST_VERIFY(spTO->mX == 77);\n\t\t\tEATEST_VERIFY(spTO2->mX == 56);\n\n\t\t\t// shared_ptr<T> atomic_exchange(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB);\n\t\t\t// shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* pSharedPtrA, shared_ptr<T> sharedPtrB, ... /*std::memory_order memoryOrder*/);\n\t\t\tspTO = atomic_exchange(&spTO2, spTO);\n\t\t\tEATEST_VERIFY(spTO->mX == 56);\n\t\t\tEATEST_VERIFY(spTO2->mX == 77);\n\t\t\t\n\t\t\tspTO = atomic_exchange_explicit(&spTO2, spTO);\n\t\t\tEATEST_VERIFY(spTO->mX == 77);\n\t\t\tEATEST_VERIFY(spTO2->mX == 56);\n\n\t\t\t// bool atomic_compare_exchange_strong(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew);\n\t\t\t// bool atomic_compare_exchange_weak(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew);\n\t\t\t// bool atomic_compare_exchange_strong_explicit(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew, ... /*memory_order memoryOrderSuccess, memory_order memoryOrderFailure*/);\n\t\t\t// bool atomic_compare_exchange_weak_explicit(shared_ptr<T>* pSharedPtr, shared_ptr<T>* pSharedPtrCondition, shared_ptr<T> sharedPtrNew, ... /*memory_order memoryOrderSuccess, memory_order memoryOrderFailure*/);\n\t\t\tshared_ptr<TestObject> spTO3 = atomic_load(&spTO2);\n\t\t\tbool result = atomic_compare_exchange_strong(&spTO3, &spTO, make_shared<TestObject>(88));   // spTO3 != spTO, so this should do no exchange and return false.\n\t\t\tEATEST_VERIFY(!result);\n\t\t\tEATEST_VERIFY(spTO3->mX == 56);\n\t\t\tEATEST_VERIFY(spTO->mX == 56);\n\n\t\t\tresult = atomic_compare_exchange_strong(&spTO3, &spTO2, make_shared<TestObject>(88));       // spTO3 == spTO2, so this should succeed.\n\t\t\tEATEST_VERIFY(result);\n\t\t\tEATEST_VERIFY(spTO2->mX == 56);\n\t\t\tEATEST_VERIFY(spTO3->mX == 88);\n\t\t}\n\t#endif\n\n\tEATEST_VERIFY(A::mCount == 0);\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n\nstatic int Test_weak_ptr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t{\n\t\tweak_ptr<int>   pW0;\n\t\tshared_ptr<int> pS0(new int(0));\n\t\tshared_ptr<int> pS1(new int(1));\n\t\tweak_ptr<int>   pW1(pS1);\n\t\tweak_ptr<int>   pW2;\n\t\tweak_ptr<int>   pW3(pW2);\n\n\t\tEATEST_VERIFY(pS1.use_count() == 1);\n\t\tEATEST_VERIFY(pW1.use_count() == 1);\n\t\tEATEST_VERIFY(pW2.use_count() == 0);\n\t\tEATEST_VERIFY(pW3.use_count() == 0);\n\t\tEATEST_VERIFY(pW1.expired() == false);\n\t\tEATEST_VERIFY(pW2.expired() == true);\n\t\tEATEST_VERIFY(pW3.expired() == true);\n\t\tpS1.reset();\n\t\tEATEST_VERIFY(pW1.expired() == true);\n\t\tpW1 = pS0;\n\t\tEATEST_VERIFY(pW1.expired() == false);\n\t\tpW1.swap(pW2);\n\t\tEATEST_VERIFY(pW1.expired() == true);\n\t\tEATEST_VERIFY(pW2.expired() == false);\n\t\tpW1 = pW2;\n\t\tEATEST_VERIFY(pW1.expired() == false);\n\t\tpW3 = pW1;\n\t\tEATEST_VERIFY(pW3.expired() == false);\n\t\tEATEST_VERIFY(pS1.use_count() == 0);\n\t\tpW3.reset();\n\t\tEATEST_VERIFY(pW3.expired() == true);\n\t\tpS1.reset(new int(3));\n\t\tEATEST_VERIFY(pS1.use_count() == 1);\n\t\tpW3 = pS1;\n\t\tEATEST_VERIFY(pS1.use_count() == 1);\n\t\tEATEST_VERIFY(pS1.use_count() == pW3.use_count());\n\n\t\tshared_ptr<int> pShared2(pW2.lock());\n\t\tshared_ptr<int> pShared3(pW3.lock());\n\n\t\tEATEST_VERIFY(pShared2.use_count() == 2);\n\t\tEATEST_VERIFY(pShared3.use_count() == 2); \n\t\tswap(pW2, pW3);\n\t\tEATEST_VERIFY(pW2.use_count() == 2);\n\t\tEATEST_VERIFY(pW3.use_count() == 2);\n\t\tpW1 = pW3;\n\t\tEATEST_VERIFY(pW3.use_count() == 2);\n\n\t\tEATEST_VERIFY((pW2 < pW3) || (pW3 < pW2));\n\n\t\tEATEST_VERIFY(pS0.use_count() == 2);\n\t\tpW0 = pS0; // This tests the deletion of a weak_ptr after its associated shared_ptr has destructed.\n\t\tEATEST_VERIFY(pS0.use_count() == 2);\n\t}\n\n\n\t{\n\t\tweak_ptr<NamedClass> wp;\n\n\t\tEATEST_VERIFY(wp.use_count() == 0);\n\t\tEATEST_VERIFY(wp.expired() == true);\n\n\t\t{\n\t\t\tshared_ptr<NamedClass> sp(new NamedClass(\"NamedClass\"));\n\t\t\twp = sp;\n\n\t\t\tEATEST_VERIFY(wp.use_count() == 1);\n\t\t\tEATEST_VERIFY(wp.expired() == false);\n\t\t}\n\n\t\tEATEST_VERIFY(wp.use_count() == 0);\n\t\tEATEST_VERIFY(wp.expired() == true);\n\t}\n\n\t{   // shared_from_this\n\t\t// This example is taken from the C++11 Standard doc.\n\t\tshared_ptr<const foo> pFoo(new foo);\n\t\tshared_ptr<const foo> qFoo = pFoo->shared_from_this();\n\n\t\tEATEST_VERIFY(pFoo == qFoo);\n\t\tEATEST_VERIFY(!(pFoo < qFoo) && !(qFoo < pFoo)); // p and q share ownership\n\t}\n\n\t{   // weak_from_this const\n\t\tshared_ptr<const foo> pFoo(new foo);\n\t\tweak_ptr<const foo> qFoo = pFoo->weak_from_this();\n\n\t\tEATEST_VERIFY(pFoo == qFoo.lock());\n\t\tEATEST_VERIFY(!(pFoo < qFoo.lock()) && !(qFoo.lock() < pFoo)); // p and q share ownership\n\t}\n\n\t{   // weak_from_this\n\t\tshared_ptr<foo> pFoo(new foo);\n\t\tweak_ptr<foo> qFoo = pFoo->weak_from_this();\n\n\t\tEATEST_VERIFY(pFoo == qFoo.lock());\n\t\tEATEST_VERIFY(!(pFoo < qFoo.lock()) && !(qFoo.lock() < pFoo)); // p and q share ownership\n\t}\n\t\n\treturn nErrorCount;\n}\n\n\nstatic int Test_shared_array()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t{\n\t\tshared_array<int> pT1(new int[5]);\n\t\tpT1[0] = 5;\n\t\tEATEST_VERIFY(pT1[0] == 5);\n\t\tEATEST_VERIFY(pT1.get() == get_pointer(pT1));\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\n\t\tshared_array<int> pT2;\n\t\tEATEST_VERIFY(pT1 != pT2);\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\n\t\tpT2 = pT1;\n\t\tEATEST_VERIFY(pT1.use_count() == 2);\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\t\tEATEST_VERIFY(!pT1.unique());\n\t\tEATEST_VERIFY(!(pT1 < pT2)); // They should be equal\n\t\tEATEST_VERIFY(pT1 == pT2);\n\n\t\t*pT1 = 3;\n\t\tEATEST_VERIFY(*pT1 == 3);\n\t\tEATEST_VERIFY(*pT1 == 3);\n\t\tEATEST_VERIFY(*pT2 == 3);\n\n\t\tpT2.reset(0);\n\t\tEATEST_VERIFY(pT2.unique());\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1 != pT2);\n\t}\n\n\t{\n\t\tEATEST_VERIFY(A::mCount == 0);\n\n\t\tshared_array<A> pT2(new A[5]);\n\t\tEATEST_VERIFY(A::mCount == 5);\n\t\tEATEST_VERIFY(pT2->mc == 0);\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\n\t\tpT2.reset(new A[1]);\n\t\tpT2[0].mc = 1;\n\t\tEATEST_VERIFY(pT2->mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\n\t\tshared_array<A> pT3(new A[2]);\n\t\tEATEST_VERIFY(A::mCount == 3);\n\n\t\tpT2.swap(pT3);\n\t\tpT2[0].mc = 2;\n\t\tEATEST_VERIFY(pT2->mc == 2);\n\t\tEATEST_VERIFY(pT3->mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 3);\n\n\t\tswap(pT2, pT3);\n\t\tEATEST_VERIFY(pT2->mc == 1);\n\t\tEATEST_VERIFY(pT3->mc == 2);\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t\tif(!pT2)\n\t\t\tEATEST_VERIFY(!pT2.get()); // Will fail\n\n\t\tshared_array<A> pT4;\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t\tif(pT4)\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\t\tif(!(!pT4))\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\n\t\tpT4 = pT2;\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\t\tEATEST_VERIFY(pT4.use_count() == 2);\n\t\tEATEST_VERIFY(!pT2.unique());\n\t\tEATEST_VERIFY(!pT4.unique());\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t\tEATEST_VERIFY(pT2 == pT4);\n\t\tEATEST_VERIFY(pT2 != pT3);\n\t\tEATEST_VERIFY(!(pT2 < pT4)); // They should be equal\n\n\t\tshared_array<A> pT5(pT4);\n\t\tEATEST_VERIFY(pT4 == pT5);\n\t\tEATEST_VERIFY(pT2.use_count() == 3);\n\t\tEATEST_VERIFY(pT4.use_count() == 3);\n\t\tEATEST_VERIFY(pT5.use_count() == 3);\n\t\tEATEST_VERIFY(!pT5.unique());\n\n\t\tpT4 = shared_array<A>(0);\n\t\tEATEST_VERIFY(pT4.unique());\n\t\tEATEST_VERIFY(pT4.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\n\t\tEATEST_VERIFY(A::mCount == 3);\n\t}\n\n\tEATEST_VERIFY(A::mCount == 0);\n\n\treturn nErrorCount;\n}\n\n\n\nstatic int Test_linked_ptr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t{\n\t\tlinked_ptr<int> pT1(new int(5));\n\t\tEATEST_VERIFY(*pT1.get() == 5);\n\t\tEATEST_VERIFY(pT1.get() == get_pointer(pT1));\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\n\t\tlinked_ptr<int> pT2;\n\t\tEATEST_VERIFY(pT1 != pT2);\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\n\t\tpT2 = pT1;\n\t\tEATEST_VERIFY(pT1.use_count() == 2);\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\t\tEATEST_VERIFY(!pT1.unique());\n\t\tEATEST_VERIFY(!(pT1 < pT2)); // They should be equal\n\t\tEATEST_VERIFY(pT1 == pT2);\n\n\t\t*pT1 = 3;\n\t\tEATEST_VERIFY(*pT1.get() == 3);\n\t\tEATEST_VERIFY(*pT1 == 3);\n\t\tEATEST_VERIFY(*pT2 == 3);\n\n\t\tpT2.reset((int*)NULL);\n\t\tEATEST_VERIFY(pT2.unique());\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT1.unique());\n\t\tEATEST_VERIFY(pT1.use_count() == 1);\n\t\tEATEST_VERIFY(pT1 != pT2);\n\t}\n\n\t{\n\t\tEATEST_VERIFY(A::mCount == 0);\n\n\t\tlinked_ptr<A> pT2(new A(0));\n\t\tEATEST_VERIFY(A::mCount == 1);\n\t\tEATEST_VERIFY(pT2->mc == 0);\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\n\t\tpT2.reset(new A(1));\n\t\tEATEST_VERIFY(pT2->mc == 1);\n\t\tEATEST_VERIFY(A::mCount == 1);\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\n\t\tlinked_ptr<A> pT3(new A(2));\n\t\tEATEST_VERIFY(A::mCount == 2);\n\n\t\tlinked_ptr<A> pT4;\n\t\tEATEST_VERIFY(pT2.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.unique());\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t\tif(pT4)\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\t\tif(!(!pT4))\n\t\t\tEATEST_VERIFY(pT4.get()); // Will fail\n\n\t\tpT4 = pT2;\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\t\tEATEST_VERIFY(pT4.use_count() == 2);\n\t\tEATEST_VERIFY(!pT2.unique());\n\t\tEATEST_VERIFY(!pT4.unique());\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t\tEATEST_VERIFY(pT2 == pT4);\n\t\tEATEST_VERIFY(pT2 != pT3);\n\t\tEATEST_VERIFY(!(pT2 < pT4)); // They should be equal\n\n\t\tlinked_ptr<A> pT5(pT4);\n\t\tEATEST_VERIFY(pT4 == pT5);\n\t\tEATEST_VERIFY(pT2.use_count() == 3);\n\t\tEATEST_VERIFY(pT4.use_count() == 3);\n\t\tEATEST_VERIFY(pT5.use_count() == 3);\n\t\tEATEST_VERIFY(!pT5.unique());\n\n\t\tpT4 = linked_ptr<A>((A*)NULL);\n\t\tEATEST_VERIFY(pT4.unique());\n\t\tEATEST_VERIFY(pT4.use_count() == 1);\n\t\tEATEST_VERIFY(pT2.use_count() == 2);\n\n\t\tEATEST_VERIFY(A::mCount == 2);\n\t}\n\t\t\n\t{  // Do some force_delete tests.\n\t\tlinked_ptr<A> pT2(new A(0));\n\t\tlinked_ptr<A> pT3(pT2);\n\t\tpT2.force_delete();\n\t\tpT3.force_delete();\n\t}\n\n\tEATEST_VERIFY(A::mCount == 0);\n\n\n\t{   // Verify that subclasses are usable.\n\t\tbool bAlloc = false;\n\n\t\teastl::linked_ptr<DerivedMockObject> pDMO(new DerivedMockObject(&bAlloc));\n\t\teastl::linked_ptr<MockObject> a1(pDMO);\n\t\teastl::linked_ptr<MockObject> a2;\n\n\t\ta2 = pDMO;\n\t}\n\n\t{ // Test regression for a bug.\n\t\tlinked_ptr<A> pT2;\n\t\tlinked_ptr<A> pT3(pT2);     // In the bug linked_ptr::mpPrev and mpNext were not initialized via this ctor.\n\t\tpT3.reset(new A);           // In the bug this would crash due to unintialized mpPrev/mpNext.\n\n\t\tlinked_ptr<B> pT4;\n\t\tlinked_ptr<A> pT5(pT4);\n\t\tpT5.reset(new A);\n\n\t\tlinked_array<A> pT6;\n\t\tlinked_array<A> pT7(pT6);\n\t\tpT7.reset(new A[1]);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\nstatic int Test_linked_array()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount(0);\n\n\t{\n\t\t// Tests go here.\n\t}\n\n\t{  // Do some force_delete tests.\n\t\tlinked_array<A> pT2(new A[2]);\n\t\tlinked_array<A> pT3(pT2);\n\t\tpT2.force_delete();\n\t\tpT3.force_delete();\n\t}\n\n\tEATEST_VERIFY(A::mCount == 0);\n\n\n\treturn nErrorCount;\n}\n\n\n\nstatic int Test_intrusive_ptr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{   // Test ctor/dtor\n\t\tintrusive_ptr<RefCountTest> ip1;\n\t\tintrusive_ptr<RefCountTest> ip2(NULL, false);\n\t\tintrusive_ptr<RefCountTest> ip3(NULL, true);\n\t\tintrusive_ptr<RefCountTest> ip4(new RefCountTest, true);\n\t\tintrusive_ptr<RefCountTest> ip5(new RefCountTest, false);\n\t\tintrusive_ptr<RefCountTest> ip6(ip1);\n\t\tintrusive_ptr<RefCountTest> ip7(ip4);\n\n\t\tEATEST_VERIFY(ip1.get() == NULL);\n\t\tEATEST_VERIFY(!ip1);\n\n\t\tEATEST_VERIFY(ip2.get() == NULL);\n\t\tEATEST_VERIFY(!ip2);\n\n\t\tEATEST_VERIFY(ip3.get() == NULL);\n\t\tEATEST_VERIFY(!ip3);\n\n\t\tEATEST_VERIFY(ip4.get() != NULL);\n\t\tEATEST_VERIFY(ip4.get()->mRefCount == 2);\n\t\tEATEST_VERIFY(ip4);\n\n\t\tEATEST_VERIFY(ip5.get() != NULL);\n\t\tEATEST_VERIFY(ip5.get()->mRefCount == 0);\n\t\tip5.get()->AddRef();\n\t\tEATEST_VERIFY(ip5.get()->mRefCount == 1);\n\t\tEATEST_VERIFY(ip5);\n\n\t\tEATEST_VERIFY(ip6.get() == NULL);\n\t\tEATEST_VERIFY(!ip6);\n\n\t\tEATEST_VERIFY(ip7.get() != NULL);\n\t\tEATEST_VERIFY(ip7.get()->mRefCount == 2);\n\t\tEATEST_VERIFY(ip7);\n\t}\n\n\t{ \n\t\t// Test move-ctor\n\t\t{\n\t\t\tVERIFY(RefCountTest::mCount == 0);\n\t\t\tintrusive_ptr<RefCountTest> ip1(new RefCountTest);\n\t\t\tVERIFY(RefCountTest::mCount == 1);\n\t\t\tVERIFY(ip1->mRefCount == 1);\n\t\t\t{\n\t\t\t\tintrusive_ptr<RefCountTest> ip2(eastl::move(ip1));\n\t\t\t\tVERIFY(ip1.get() != ip2.get());\n\t\t\t\tVERIFY(ip2->mRefCount == 1);\n\t\t\t\tVERIFY(RefCountTest::mCount == 1);\n\t\t\t}\n\t\t\tVERIFY(ip1.get() == nullptr);\n\t\t\tVERIFY(RefCountTest::mCount == 0);\n\t\t}\n\n\t\t// Test move-assignment\n\t\t{\n\t\t\tVERIFY(RefCountTest::mCount == 0);\n\t\t\tintrusive_ptr<RefCountTest> ip1(new RefCountTest);\n\t\t\tVERIFY(RefCountTest::mCount == 1);\n\t\t\tVERIFY(ip1->mRefCount == 1);\n\t\t\t{\n\t\t\t\tintrusive_ptr<RefCountTest> ip2; \n\t\t\t\tip2 = eastl::move(ip1);\n\t\t\t\tVERIFY(ip1.get() != ip2.get());\n\t\t\t\tVERIFY(ip2->mRefCount == 1);\n\t\t\t\tVERIFY(RefCountTest::mCount == 1);\n\t\t\t}\n\t\t\tVERIFY(ip1.get() == nullptr);\n\t\t\tVERIFY(RefCountTest::mCount == 0);\n\t\t}\n\t}\n\n\t{   // Test modifiers (assign, attach, detach, reset, swap)\n\t\tRefCountTest* const p1 = new RefCountTest;\n\t\tRefCountTest* const p2 = new RefCountTest;\n\t\tintrusive_ptr<RefCountTest> ip1;\n\t\tintrusive_ptr<RefCountTest> ip2;\n\n\t\tip1 = p1;\n\t\tip2 = p2;\n\t\tEATEST_VERIFY(ip1.get() == p1);\n\t\tEATEST_VERIFY((*ip1).mRefCount == 1);\n\t\tEATEST_VERIFY(ip1->mRefCount == 1);\n\t\tip1.detach();\n\t\tEATEST_VERIFY(ip1.get() == NULL);\n\t\tip1.attach(p1);\n\t\tEATEST_VERIFY(ip1.get() == p1);\n\t\tEATEST_VERIFY(ip1->mRefCount == 1);\n\t\tip1.swap(ip2);\n\t\tEATEST_VERIFY(ip1.get() == p2);\n\t\tEATEST_VERIFY(ip2.get() == p1);\n\t\tip1.swap(ip2);\n\t\tip1 = ip2;\n\t\tEATEST_VERIFY(ip1 == p2);\n\t\tip1.reset();\n\t\tEATEST_VERIFY(ip1.get() == NULL);\n\t\tEATEST_VERIFY(ip2.get() == p2);\n\t\tip2.reset();\n\t\tEATEST_VERIFY(ip2.get() == NULL);\n\t}\n\n\t{   // Test external functions\n\t\tintrusive_ptr<RefCountTest> ip1;\n\t\tintrusive_ptr<RefCountTest> ip2(new RefCountTest);\n\t\tintrusive_ptr<RefCountTest> ip3(ip1);\n\t\tintrusive_ptr<RefCountTest> ip4(ip2);\n\n\t\t// The VC++ code scanner crashes when it scans this code. \n\t\tEATEST_VERIFY(get_pointer(ip1) == NULL);\n\t\tEATEST_VERIFY(get_pointer(ip2) != NULL);\n\t\tEATEST_VERIFY(get_pointer(ip3) == get_pointer(ip1));\n\t\tEATEST_VERIFY(get_pointer(ip4) == get_pointer(ip2));\n\n\t\tEATEST_VERIFY(ip3 == ip1);\n\t\tEATEST_VERIFY(ip4 == ip2);\n\t\tEATEST_VERIFY(ip1 == ip3);\n\t\tEATEST_VERIFY(ip2 == ip4);\n\n\t\tEATEST_VERIFY(ip1 != ip2);\n\t\tEATEST_VERIFY(ip3 != ip4);\n\t\tEATEST_VERIFY(ip2 != ip1);\n\t\tEATEST_VERIFY(ip4 != ip3);\n\n\t\tEATEST_VERIFY(ip3 == ip1.get());\n\t\tEATEST_VERIFY(ip4 == ip2.get());\n\t\tEATEST_VERIFY(ip1 == ip3.get());\n\t\tEATEST_VERIFY(ip2 == ip4.get());\n\n\t\tEATEST_VERIFY(ip1 != ip2.get());\n\t\tEATEST_VERIFY(ip3 != ip4.get());\n\t\tEATEST_VERIFY(ip2 != ip1.get());\n\t\tEATEST_VERIFY(ip4 != ip3.get());\n\n\t\tEATEST_VERIFY(ip3.get() == ip1);\n\t\tEATEST_VERIFY(ip4.get() == ip2);\n\t\tEATEST_VERIFY(ip1.get() == ip3);\n\t\tEATEST_VERIFY(ip2.get() == ip4);\n\n\t\tEATEST_VERIFY(ip1.get() != ip2);\n\t\tEATEST_VERIFY(ip3.get() != ip4);\n\t\tEATEST_VERIFY(ip2.get() != ip1);\n\t\tEATEST_VERIFY(ip4.get() != ip3);\n\n\t\tEATEST_VERIFY((ip4 < ip3) || (ip3 < ip4));\n\n\t\tswap(ip1, ip3);\n\t\tEATEST_VERIFY(get_pointer(ip3) == get_pointer(ip1));\n\n\t\tswap(ip2, ip4);\n\t\tEATEST_VERIFY(get_pointer(ip2) == get_pointer(ip4));\n\n\t\tswap(ip1, ip2);\n\t\tEATEST_VERIFY(get_pointer(ip1) != NULL);\n\t\tEATEST_VERIFY(get_pointer(ip2) == NULL);\n\t\tEATEST_VERIFY(get_pointer(ip1) == get_pointer(ip4));\n\t\tEATEST_VERIFY(get_pointer(ip2) == get_pointer(ip3));\n\t}\n\n\t{   // Misc tests.\n\t\tintrusive_ptr<Test> ip;\n\t\tEATEST_VERIFY(ip.get() == NULL);\n\n\t\tip.reset();\n\t\tEATEST_VERIFY(ip.get() == NULL);\n\n\t\tintrusive_ptr<Test> ip2(NULL, false);\n\t\tEATEST_VERIFY(ip.get() == NULL);\n\n\t\tbool boolValue = false;\n\t\tTest* pTest = new Test(&boolValue);\n\t\tEATEST_VERIFY(boolValue);\n\t\tpTest->AddRef();\n\t\tintrusive_ptr<Test> ip3(pTest, false);\n\t\tEATEST_VERIFY(ip3.get() == pTest);\n\t\tip3.reset();\n\t\tEATEST_VERIFY(!boolValue);\n\t}\n\n\t{   // Misc tests.\n\t\tbool boolArray[3];\n\t\tmemset(boolArray, 0, sizeof(boolArray));\n\n\t\tTest* p1 = new Test(boolArray + 0);\n\t\tEATEST_VERIFY(boolArray[0] && !boolArray[1] && !boolArray[2]);\n\t\tintrusive_ptr<Test> arc1(p1);\n\t\tEATEST_VERIFY(boolArray[0] && !boolArray[1] && !boolArray[2]);\n\n\t\tTest* p2 = new Test(boolArray + 1);\n\t\tEATEST_VERIFY(boolArray[0] && boolArray[1] && !boolArray[2]);\n\t\tarc1 = p2;\n\t\tEATEST_VERIFY(!boolArray[0] && boolArray[1] && !boolArray[2]);\n\n\t\tTest* p3 = new Test(boolArray + 2);\n\t\tEATEST_VERIFY(!boolArray[0] && boolArray[1] && boolArray[2]);\n\t\tarc1 = p3;\n\t\tEATEST_VERIFY(!boolArray[0] && !boolArray[1] && boolArray[2]);\n\t\tarc1 = NULL;\n\t\t\n\t\tEATEST_VERIFY(!boolArray[0] && !boolArray[1] && !boolArray[2]);\n\t}\n\n\t{ // Test intrusive_ptr_add_ref() / intrusive_ptr_release()\n\t\tIntrusiveCustom* const pIC = new IntrusiveCustom;\n\n\t\t{\n\t\t\tintrusive_ptr<IntrusiveCustom> bp = intrusive_ptr<IntrusiveCustom>(pIC);\n\t\t\tintrusive_ptr<IntrusiveCustom> ap = bp;\n\t\t}\n\t\t\n\t\tEATEST_VERIFY((IntrusiveCustom::mAddRefCallCount > 0) && (IntrusiveCustom::mReleaseCallCount == IntrusiveCustom::mAddRefCallCount));\n\t}\n\n\t{ // Regression\n\t\tintrusive_ptr<IntrusiveChild>  bp = intrusive_ptr<IntrusiveChild>(new IntrusiveChild);\n\t\tintrusive_ptr<IntrusiveParent> ap = bp;\n\t}\n\n\treturn nErrorCount;\n}\n\n\nstruct RandomLifetimeObject : public eastl::safe_object\n{\n\tvoid DoSomething() const { }\n};\n\n\n\nstatic int Test_safe_ptr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{   // non-const RandomLifetimeObject\n\t\tRandomLifetimeObject* pObject = new RandomLifetimeObject;\n\t\teastl::safe_ptr<RandomLifetimeObject> pSafePtr(pObject);\n\n\t\teastl::safe_ptr<RandomLifetimeObject> pSafePtrCopy1 = pSafePtr;\n\t\teastl::safe_ptr<RandomLifetimeObject> pSafePtrCopy2(pSafePtr);\n\n\t\tpSafePtr->DoSomething();\n\n\t\teastl::safe_ptr<RandomLifetimeObject>* pSafePtrCopy3 = new eastl::safe_ptr<RandomLifetimeObject>(pSafePtr);\n\t\teastl::safe_ptr<RandomLifetimeObject>* pSafePtrCopy4 = new eastl::safe_ptr<RandomLifetimeObject>(pSafePtr);\n\t\tEATEST_VERIFY(pSafePtrCopy3->get() == pObject);\n\t\tEATEST_VERIFY(pSafePtrCopy4->get() == pObject);\n\t\tdelete pSafePtrCopy3;\n\t\tdelete pSafePtrCopy4;\n\n\t\tdelete pSafePtr;\n\n\t\tEATEST_VERIFY(pSafePtrCopy1.get() == NULL);\n\t\tEATEST_VERIFY(pSafePtrCopy2.get() == NULL);\n\t}\n\n\t{   // const RandomLifetimeObject\n\t\tRandomLifetimeObject* pObject = new RandomLifetimeObject;\n\t\teastl::safe_ptr<const RandomLifetimeObject> pSafePtr(pObject);\n\n\t\teastl::safe_ptr<const RandomLifetimeObject> pSafePtrCopy1(pSafePtr);\n\t\teastl::safe_ptr<const RandomLifetimeObject> pSafePtrCopy2 = pSafePtr;\n\n\t\tpSafePtr->DoSomething();\n\n\t\teastl::safe_ptr<const RandomLifetimeObject>* pSafePtrCopy3 = new eastl::safe_ptr<const RandomLifetimeObject>(pSafePtr);\n\t\teastl::safe_ptr<const RandomLifetimeObject>* pSafePtrCopy4 = new eastl::safe_ptr<const RandomLifetimeObject>(pSafePtr);\n\t\tEATEST_VERIFY(pSafePtrCopy3->get() == pObject);\n\t\tEATEST_VERIFY(pSafePtrCopy4->get() == pObject);\n\t\tdelete pSafePtrCopy3;\n\t\tdelete pSafePtrCopy4;\n\n\t\tdelete pSafePtr;\n\n\t\tEATEST_VERIFY(pSafePtrCopy1.get() == NULL);\n\t\tEATEST_VERIFY(pSafePtrCopy2.get() == NULL);\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate<typename T, typename U>\nbool equivalent_owner_before(const T& lhs, const U& rhs) { return !lhs.owner_before(rhs) && !rhs.owner_before(lhs); }\n\ntemplate<typename T, typename U, typename Compare>\nbool equivalent(const T& lhs, const U& rhs, const Compare& cmp) { return !cmp(lhs, rhs) && !cmp(rhs, lhs); }\n\nstatic int Test_owner_before()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tstruct Foo\n\t{\n\t\tint n1;\n\t\tint n2;\n\t\tFoo(int a, int b) : n1(a), n2(b) {}\n\t};\n\n\tauto p1 = make_shared<Foo>(1, 2);\n\tshared_ptr<int> p2(p1, &p1->n1);\n\tshared_ptr<int> p3(p1, &p1->n2);\n\n\tauto unrelated = make_shared<Foo>(1, 2);\n\n\t// owner_before\n\t{\n\t\tEATEST_VERIFY(equivalent_owner_before(p1, p2));\n\t\tEATEST_VERIFY(equivalent_owner_before(p1, p3));\n\t\tEATEST_VERIFY(equivalent_owner_before(p2, p3));\n\n\t\tEATEST_VERIFY(!equivalent_owner_before(p1, unrelated));\n\t\tEATEST_VERIFY(!equivalent_owner_before(p2, unrelated));\n\t\tEATEST_VERIFY(!equivalent_owner_before(p3, unrelated));\n\t}\n\n\t// owner_less<shared_ptr<T>>\n\t{\n\t\tEATEST_VERIFY(equivalent(p1, p1, owner_less<shared_ptr<Foo>>{}));\n\t\tEATEST_VERIFY(equivalent(p2, p3, owner_less<shared_ptr<int>>{}));\n\n\t\tEATEST_VERIFY(!equivalent(p1, unrelated, owner_less<shared_ptr<Foo>>{}));\n\t}\n\n\t// owner_less<void>\n\t{\n\t\towner_less<void> cmp;\n\n\t\tEATEST_VERIFY(equivalent(p1, p2, cmp));\n\t\tEATEST_VERIFY(equivalent(p1, p3, cmp));\n\t\tEATEST_VERIFY(equivalent(p2, p3, cmp));\n\n\t\tEATEST_VERIFY(!equivalent(p1, unrelated, cmp));\n\t\tEATEST_VERIFY(!equivalent(p2, unrelated, cmp));\n\t\tEATEST_VERIFY(!equivalent(p3, unrelated, cmp));\n\t}\n\n\treturn nErrorCount;\n}\n\n\nint TestSmartPtr()\n{\n\tusing namespace SmartPtrTest;\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\tnErrorCount += Test_unique_ptr();\n\tnErrorCount += Test_scoped_ptr();\n\tnErrorCount += Test_scoped_array();\n\tnErrorCount += Test_shared_ptr();\n\tnErrorCount += Test_shared_ptr_thread();\n\tnErrorCount += Test_weak_ptr();\n\tnErrorCount += Test_shared_array();\n\tnErrorCount += Test_linked_ptr();\n\tnErrorCount += Test_linked_array();\n\tnErrorCount += Test_intrusive_ptr();\n\tnErrorCount += Test_safe_ptr();\n\tnErrorCount += Test_owner_before();\n\n\tEATEST_VERIFY(A::mCount == 0);\n\tEATEST_VERIFY(RefCountTest::mCount == 0);\n\tEATEST_VERIFY(NamedClass::mnCount == 0);\n\tEATEST_VERIFY(Y::mnCount == 0);\n\tEATEST_VERIFY(ACLS::mnCount == 0);\n\tEATEST_VERIFY(BCLS::mnCount == 0);\n\tEATEST_VERIFY(A1::mnCount == 0);\n\tEATEST_VERIFY(B1::mnCount == 0);\n\n\treturn nErrorCount;\n}\n\nEA_RESTORE_VC_WARNING()  // 4702\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestSort.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include <EABase/eabase.h>\n\n// Some versions of GCC generate an array bounds warning in opt builds which \n// doesn't say what line below it comes from and doesn't appear to be a valid \n// warning. In researching this on the Internet it appears that this is a \n// known problem with GCC.\n#if defined(EA_DISABLE_GCC_WARNING)\n\tEA_DISABLE_GCC_WARNING(-Warray-bounds)\n#endif\n\n#include \"EASTLTest.h\"\n#include <EASTL/sort.h>\n#include <EASTL/bonus/sort_extra.h>\n#include <EASTL/vector.h>\n#include <EASTL/list.h>\n#include <EASTL/deque.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/allocator.h>\n#include <EASTL/numeric.h>\n#include <EASTL/random.h>\n#include <EABase/eahave.h>\n#include <cmath>\n\n\nnamespace eastl\n{\n\tnamespace Internal\n\t{\n\t\ttypedef eastl::vector<int>      IntArray;\n\t\ttypedef eastl::vector<IntArray> IntArrayArray;\n\n\n\t\t// IntArrayCompare\n\t\t// Used to compare IntArray objects.\n\t\tstruct IntArrayCompare\n\t\t{\n\t\t\tbool operator()(const IntArray& a, const IntArray& b)\n\t\t\t\t{ return a.front() < b.front(); }\n\t\t};\n\n\n\t\t// SafeFloatCompare\n\t\t//\n\t\t// Float comparison has a problem for the case that either of the floats are a NaN.\n\t\t// If you use a NaN in a sort function that uses default floating point comparison then\n\t\t// you will get undefined behavior, as all NaNs compare false. This compare function \n\t\t// class sorts floats such that all negative NaNs sort lower than all integers, and all\n\t\t// positive NaNs sort higher than all integers.\n\t\t//\n\t\t// Example usage:\n\t\t//     eastl::sort(floatArray.begin(), floatArray.end(), SafeFloatCompare());\n\t\t//\n\t\tstruct SafeFloatCompare\n\t\t{\n\t\t\tunion FloatInt32{ float f; int32_t i; };\n\n\t\t\tbool operator()(float a, float b) const\n\t\t\t{\n\t\t\t\t#if defined(EA_HAVE_ISNAN)\n\t\t\t\t\tbool aNan = (EA_HAVE_ISNAN(a) != 0);\n\t\t\t\t\tbool bNan = (EA_HAVE_ISNAN(b) != 0);\n\t\t\t\t#else\n\t\t\t\t\tbool aNan = (a != a); // This works as long as the compiler doesn't do any tricks to optimize it away.\n\t\t\t\t\tbool bNan = (b != b);\n\t\t\t\t#endif\n\n\t\t\t\tif(!aNan && !bNan)\n\t\t\t\t\treturn (a < b);\n\n\t\t\t\tFloatInt32 fia = { a };\n\t\t\t\tFloatInt32 fib = { b };\n\n\t\t\t\tif(aNan)\n\t\t\t\t{\n\t\t\t\t\tif(bNan)\n\t\t\t\t\t\treturn (fia.i < fib.i); // Both are NaNs, so do a binary compare.\n\t\t\t\t\telse\n\t\t\t\t\t\treturn (fia.i < 0);  // All negative NaNs are assumed to be less than all non-NaNs.\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\treturn (0 < fib.i); // All negative NaNs are assumed to be less than all non-NaNs.\n\t\t\t}\n\t\t};\n\n\n\n\t\t// StatefulCompare\n\t\t// Used to verify that sort<int, StatefulCompare&>() respects the \n\t\t// fact that StatefulCompare is passed by reference instead of by value.\n\t\t// All existing commercial STL implementations fail to do what the user\n\t\t// wants and instead pass around the compare object by value, even if\n\t\t// the user specifically asks to use it by reference. EASTL doesn't \n\t\t// have this problem. \n\t\tstruct StatefulCompare\n\t\t{\n\t\t\tstatic int nCtorCount;\n\t\t\tstatic int nDtorCount;\n\t\t\tstatic int nCopyCount;\n\n\t\t\tStatefulCompare()\n\t\t\t\t{ nCtorCount++; }\n\n\t\t\tStatefulCompare(StatefulCompare&)\n\t\t\t\t{ nCopyCount++; }\n\n\t\t   ~StatefulCompare()\n\t\t\t\t{ nDtorCount++; }\n\n\t\t\tStatefulCompare& operator=(const StatefulCompare&)\n\t\t\t\t{ nCopyCount++; return *this; }\n\n\t\t\tbool operator()(int a, int b)\n\t\t\t\t{ return a < b; }\n\n\t\t\tstatic void Reset()\n\t\t\t\t{ nCtorCount = 0; nDtorCount = 0; nCopyCount = 0; }\n\t\t};\n\n\t\tint StatefulCompare::nCtorCount = 0;\n\t\tint StatefulCompare::nDtorCount = 0;\n\t\tint StatefulCompare::nCopyCount = 0;\n\n\n\t\t// TestObjectPtrCompare\n\t\t// Used to compare sorted objects by pointer instead of value.\n\t\tstruct TestObjectPtrCompare\n\t\t{\n\t\t\tbool operator()(TestObject* a, TestObject* b)\n\t\t\t   { return a->mX < b->mX; }\n\t\t};\n\n\n\t\t// TestObjectIndexCompare\n\t\t// Used to compare sorted objects by array index instead of value.\n\t\tstruct TestObjectIndexCompare\n\t\t{\n\t\t\tvector<TestObject>* mpArray;\n\n\t\t\tTestObjectIndexCompare(vector<TestObject>* pArray) : mpArray(pArray) { }\n\t\t\tTestObjectIndexCompare(const TestObjectIndexCompare& x)   : mpArray(x.mpArray){ }\n\t\t\tTestObjectIndexCompare& operator=(const TestObjectIndexCompare& x) { mpArray = x.mpArray; return *this; }\n\n\t\t\tbool operator()(eastl_size_t a, eastl_size_t b)\n\t\t\t   { return (*mpArray)[a] < (*mpArray)[b]; }\n\t\t};\n\n\t\t// Radix sort elements\n\t\ttemplate <typename Key>\n\t\tstruct RadixSortElement\n\t\t{\n\t\t\ttypedef Key radix_type;\n\t\t\tKey  mKey;\n\t\t\tuint16_t mData;\n\n\t\t\tbool operator<(const RadixSortElement<Key> &other) const\n\t\t\t{\n\t\t\t\treturn mKey < other.mKey;\n\t\t\t}\n\t\t};\n\n\t\ttypedef RadixSortElement<uint8_t> RadixSortElement8;\n\t\ttypedef RadixSortElement<uint16_t> RadixSortElement16;\n\t\ttypedef RadixSortElement<uint32_t> RadixSortElement32;\n\n\t\ttemplate <typename integer_type>\n\t\tstruct identity_extract_radix_key\n\t\t{\n\t\t\ttypedef integer_type radix_type;\n\n\t\t\tconst radix_type operator()(const integer_type& x) const\n\t\t\t{\n\t\t\t\treturn x;\n\t\t\t}\n\t\t};\n\t} // namespace Internal\n\n} // namespace eastl\n\nint TestSort()\n{\n\tusing namespace eastl;\n\tusing namespace Internal;\n\n\tint nErrorCount = 0;\n\n\tEASTLTest_Rand rng(EA::UnitTest::GetRandSeed());\n\n\t{\n\t\t// is_sorted\n\t\tint array[] = { 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 2, 2, 1, 0 };\n\t\n\t\tEATEST_VERIFY( is_sorted(array +  0, array +  0));\n\t\tEATEST_VERIFY( is_sorted(array +  2, array +  4));\n\t\tEATEST_VERIFY( is_sorted(array +  0, array + 10));\n\t\tEATEST_VERIFY(!is_sorted(array +  0, array + 14));\n\t\tEATEST_VERIFY( is_sorted(array + 11, array + 23, eastl::greater<int>()));\n\t}\n\n\t{\n\t\t// is_sorted_until\n\t\tint sorted[]    = { 0, 1, 2, 3, 4,  5, 6, 7, 8, 9 };\n\t\tint notsorted[] = { 0, 1, 2, 3, 4, 42, 6, 7, 8, 9 };\n\t\t\t\n\t\tEATEST_VERIFY( is_sorted_until(sorted + EAArrayCount(sorted),  sorted + EAArrayCount(sorted)) == sorted + EAArrayCount(sorted) );\n\t\tEATEST_VERIFY( is_sorted_until(sorted                       ,  sorted + EAArrayCount(sorted)) == sorted + EAArrayCount(sorted) );\n\n\t\tEATEST_VERIFY( is_sorted_until(sorted +  0, sorted +  0) == sorted     );\n\t\tEATEST_VERIFY( is_sorted_until(sorted +  2, sorted +  8) == sorted + 8 );\n\n\t\tEATEST_VERIFY( is_sorted_until(notsorted +  2, notsorted +  8) == notsorted + 6 );\n\t\t\n\t\t// is_sorted_until (with compare function)\n\t\tEATEST_VERIFY( is_sorted_until(sorted + EAArrayCount(sorted),  sorted + EAArrayCount(sorted), eastl::less<int>()) == sorted + EAArrayCount(sorted) );\n\t\tEATEST_VERIFY( is_sorted_until(notsorted +  2, notsorted +  8, eastl::less<int>()) == notsorted + 6 );\n\t}\n\n\t// Sort arrays of size 0 - N. Sort M random permutations of each.\n\t{\n\t\tvector<int64_t> intArray, intArraySaved;\n\n\t\tfor(int i = 0; i < (150 + (gEASTL_TestLevel * 200)); i += (i < 5) ? 1 : 37) // array sizes of 0 to 300 - 2100, depending on test level.\n\t\t{\n\t\t\t// intArraySaved.clear(); // Do we want to do this?\n\n\t\t\tfor(int n = 0; n < i; n++)\n\t\t\t{\n\t\t\t\tintArraySaved.push_back(n);\n\n\t\t\t\tif(rng.RandLimit(10) == 0)\n\t\t\t\t{\n\t\t\t\t\tintArraySaved.push_back(n);\n\n\t\t\t\t\tif(rng.RandLimit(5) == 0)\n\t\t\t\t\t\tintArraySaved.push_back(n);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst int64_t expectedSum = eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0));\n\n\t\t\tfor(int j = 0; j < 300 + (gEASTL_TestLevel * 50); j++)\n\t\t\t{\n\t\t\t\teastl::random_shuffle(intArraySaved.begin(), intArraySaved.end(), rng);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tbubble_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tshaker_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tinsertion_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tselection_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tshell_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tcomb_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\theap_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tmerge_sort(intArray.begin(), intArray.end(), *get_default_allocator((EASTLAllocatorType*)NULL));\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tvector<int64_t> buffer(intArray.size());\n\t\t\t\tmerge_sort_buffer(intArray.begin(), intArray.end(), buffer.data());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tquick_sort(intArray.begin(), intArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\n\t\t\t\tintArray = intArraySaved;\n\t\t\t\tbuffer.resize(intArray.size()/2);\n\t\t\t\ttim_sort_buffer(intArray.begin(), intArray.end(), buffer.data());\n\t\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t\t\tEATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Test tim sort with a specific array size and seed that caused a crash \n\t{\n\t\tvector<int64_t> intArray;\n\t\tint i = 1000000;\n\t\t{\n\t\t\tEASTLTest_Rand testRng(232526);\n\n\t\t\tfor (int n = 0; n < i; n++)\n\t\t\t{\n\t\t\t\tintArray.push_back(testRng.Rand());\n\t\t\t}\n\t\t\tvector<int64_t> buffer(intArray.size() / 2);\n\t\t\ttim_sort_buffer(intArray.begin(), intArray.end(), buffer.data());\n\t\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t\t}\n\t}\n\n\t// Test insertion_sort() does not invalidate a BidirectionalIterator by doing --BidirectionalIterator.begin()\n\t{\n\t\t// Test Passes if the Test doesn't crash\n\t\teastl::deque<int> deque;\n\t\tdeque.push_back(1);\n\n\t\tinsertion_sort(deque.begin(), deque.end());\n\n\t\tinsertion_sort(deque.begin(), deque.end(), eastl::less<int>{});\n\t}\n\n\n\t// TestObject sorting\n\tTestObject::Reset();\n\t{\n\t\tvector<TestObject> toArray, toArraySaved;\n\n\t\tfor(int i = 0; i < (150 + (gEASTL_TestLevel * 200)); i += (i < 5) ? 1 : 37) // array sizes of 0 to 300 - 2100, depending on test level.\n\t\t{\n\t\t\tfor(int n = 0; n < i; n++)\n\t\t\t{\n\t\t\t\ttoArraySaved.push_back(TestObject(n));\n\n\t\t\t\tif(rng.RandLimit(10) == 0)\n\t\t\t\t{\n\t\t\t\t\ttoArraySaved.push_back(TestObject(n));\n\n\t\t\t\t\tif(rng.RandLimit(5) == 0)\n\t\t\t\t\t\ttoArraySaved.push_back(TestObject(n));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor(int j = 0; j < 300 + (gEASTL_TestLevel * 50); j++)\n\t\t\t{\n\t\t\t\teastl::random_shuffle(toArraySaved.begin(), toArraySaved.end(), rng);\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tbubble_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tshaker_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tinsertion_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tselection_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tshell_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tcomb_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\theap_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\t// Not ready yet:\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tmerge_sort(toArray.begin(), toArray.end(), *get_default_allocator((EASTLAllocatorType*)NULL));\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tquick_sort(toArray.begin(), toArray.end());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tvector<TestObject> buffer(toArray.size()/2);\n\t\t\t\ttim_sort_buffer(toArray.begin(), toArray.end(), buffer.data());\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end()));\n\t\t\t}\n\t\t}\n\t}\n\n\t// Test that stable sorting algorithms are actually stable\n\t{\n\t\tstruct StableSortTestObj\n\t\t{\n\t\t\tStableSortTestObj()\n\t\t\t{\n\t\t\t}\n\n\t\t\tStableSortTestObj(int value)\n\t\t\t\t:value(value)\n\t\t\t\t,initialPositionIndex(0)\n\t\t\t{\n\t\t\t}\n\n\t\t\tint value;\n\t\t\tsize_t initialPositionIndex;\n\t\t};\n\n\t\t// During the test this comparison is used to sort elements based on value.\n\t\tstruct StableSortCompare\n\t\t{\n\t\t\tbool operator()(const StableSortTestObj& a, const StableSortTestObj& b)\n\t\t\t{\n\t\t\t\treturn a.value < b.value;\n\t\t\t}\n\t\t};\n\n\t\t// During the test this comparison is used to verify the sort was a stable sort.  i.e. if values are the same then\n\t\t// their relative position should be maintained.\n\t\tstruct StableSortCompareForStability\n\t\t{\n\t\t\tbool operator()(const StableSortTestObj& a, const StableSortTestObj& b)\n\t\t\t{\n\t\t\t\tif (a.value != b.value)\n\t\t\t\t{\n\t\t\t\t\treturn a.value < b.value;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn a.initialPositionIndex < b.initialPositionIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvector<StableSortTestObj> toArray, toArraySaved;\n\t\tStableSortCompare compare;\n\t\tStableSortCompareForStability compareForStability;\n\n\t\tfor (int i = 0; i < (150 + (gEASTL_TestLevel * 200)); i += (i < 5) ? 1 : 37) // array sizes of 0 to 300 - 2100, depending on test level.\n\t\t{\n\t\t\tfor (int n = 0; n < i; n++)\n\t\t\t{\n\t\t\t\ttoArraySaved.push_back(StableSortTestObj(n));\n\n\t\t\t\tif (rng.RandLimit(10) == 0)\n\t\t\t\t{\n\t\t\t\t\ttoArraySaved.push_back(StableSortTestObj(n));\n\n\t\t\t\t\tif (rng.RandLimit(5) == 0)\n\t\t\t\t\t\ttoArraySaved.push_back(StableSortTestObj(n));\n\t\t\t\t}\n\t\t\t}\n\t\t\tvector<StableSortTestObj> tempBuffer;\n\t\t\ttempBuffer.resize(toArraySaved.size());\n\n\t\t\tfor (int j = 0; j < 300 + (gEASTL_TestLevel * 50); j++)\n\t\t\t{\n\t\t\t\teastl::random_shuffle(toArraySaved.begin(), toArraySaved.end(), rng);\n\t\t\t\t// Store the intial position of each element in the array before sorting.  This position can then be used to verify that the sorting operation is stable.\n\t\t\t\tfor (vector<StableSortTestObj>::size_type k = 0; k < toArraySaved.size(); k++)\n\t\t\t\t{\n\t\t\t\t\ttoArraySaved[k].initialPositionIndex = k;\n\t\t\t\t}\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tbubble_sort(toArray.begin(), toArray.end(), compare);\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end(), compareForStability));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tshaker_sort(toArray.begin(), toArray.end(), compare);\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end(), compareForStability));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tinsertion_sort(toArray.begin(), toArray.end(), compare);\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end(), compareForStability));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\ttim_sort_buffer(toArray.begin(), toArray.end(), tempBuffer.data(), compare);\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end(), compareForStability));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tmerge_sort(toArray.begin(), toArray.end(), *get_default_allocator((EASTLAllocatorType*)NULL), compare);\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end(), compareForStability));\n\n\t\t\t\ttoArray = toArraySaved;\n\t\t\t\tmerge_sort_buffer(toArray.begin(), toArray.end(), tempBuffer.data(), compare);\n\t\t\t\tEATEST_VERIFY(is_sorted(toArray.begin(), toArray.end(), compareForStability));\n\t\t\t}\n\t\t}\n\t}\n\n\t{\n\t\t// OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)\n\t\t// This is tested by merge_sort.\n\t}\n\n\n\t{\n\t\t// void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)\n\t\t// This is tested by quick_sort.\n\t}\n\n\n\t{\n\t\t// void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)\n\t\t// void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare compare)\n\t\tconst int intArrayInit[16] = { 4, 2, 8, 6, 9, 1, 1, 4, 0, 5, 5, 7, 8, 9, 3, 3 };\n\t\tint intArraySorted[16]; // Same as intArrayInit but sorted\n\t\tint intArray[16];\n\t\tsize_t i, j;\n\n\t\t// We test many combinations of nth_element on the int array.\n\t\tfor(i = 1; i < 16; i++)\n\t\t{\n\t\t\tfor(j = 0; j < i; j++)\n\t\t\t{\n\t\t\t\teastl::copy(intArrayInit, intArrayInit + i, intArraySorted);\n\t\t\t\teastl::sort(intArraySorted, intArraySorted + i);\n\n\t\t\t\teastl::copy(intArrayInit, intArrayInit + i, intArray);\n\t\t\t\tnth_element(intArray, intArray + j, intArray + i);\n\t\t\t\tEATEST_VERIFY(intArray[j] == intArraySorted[j]);\n\t\t\t}\n\t\t}\n\n\t\tfor(i = 1; i < 16; i++)\n\t\t{\n\t\t\tfor(j = 0; j < i; j++)\n\t\t\t{\n\t\t\t\teastl::copy(intArrayInit, intArrayInit + i, intArraySorted);\n\t\t\t\teastl::sort(intArraySorted, intArraySorted + i);\n\n\t\t\t\teastl::copy(intArrayInit, intArrayInit + 16, intArray);\n\t\t\t\tnth_element(intArray, intArray + j, intArray + i, eastl::less<int>());\n\t\t\t\tEATEST_VERIFY(intArray[j] == intArraySorted[j]);\n\t\t\t}\n\t\t}\n\t}\n\n\n\t{\n\t\t// void radix_sort(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator buffer);\n\t\tconst uint32_t kCount = 100;\n\n\t\t{\n\t\t\tRadixSortElement32* pRadixSortElementArray32     = new RadixSortElement32[kCount];\n\t\t\tRadixSortElement32* pRadixSortElementArrayTemp32 = new RadixSortElement32[kCount];\n\t\t\tfor(uint32_t i = 0; i < kCount; i++)\n\t\t\t{\n\t\t\t\tpRadixSortElementArray32[i].mKey  = (uint16_t)(kCount - i);\n\t\t\t\tpRadixSortElementArray32[i].mData = (uint16_t)i;\n\t\t\t}\n\t\t\tradix_sort<RadixSortElement32*, extract_radix_key<RadixSortElement32> >(pRadixSortElementArray32, pRadixSortElementArray32 + kCount, pRadixSortElementArrayTemp32);\n\t\t\tEATEST_VERIFY(is_sorted(pRadixSortElementArray32, pRadixSortElementArray32 + kCount));\n\t\t\tdelete[] pRadixSortElementArray32;\n\t\t\tdelete[] pRadixSortElementArrayTemp32;\n\t\t}\n\n\t\t{\n\t\t\tRadixSortElement16* pRadixSortElementArray16     = new RadixSortElement16[kCount];\n\t\t\tRadixSortElement16* pRadixSortElementArrayTemp16 = new RadixSortElement16[kCount];\n\t\t\tfor(uint32_t i = 0; i < kCount; i++)\n\t\t\t{\n\t\t\t\tpRadixSortElementArray16[i].mKey  = (uint16_t)(kCount - i);\n\t\t\t\tpRadixSortElementArray16[i].mData = (uint16_t)i;\n\t\t\t}\n\t\t\tradix_sort<RadixSortElement16*, extract_radix_key<RadixSortElement16> >(pRadixSortElementArray16, pRadixSortElementArray16 + kCount, pRadixSortElementArrayTemp16);\n\t\t\tEATEST_VERIFY(is_sorted(pRadixSortElementArray16, pRadixSortElementArray16 + kCount));\n\t\t\tdelete[] pRadixSortElementArray16;\n\t\t\tdelete[] pRadixSortElementArrayTemp16;\n\t\t}\n\n\t\t{\n\t\t\tRadixSortElement8* pRadixSortElementArray8     = new RadixSortElement8[kCount];\n\t\t\tRadixSortElement8* pRadixSortElementArrayTemp8 = new RadixSortElement8[kCount];\n\t\t\tfor(uint32_t i = 0; i < kCount; i++)\n\t\t\t{\n\t\t\t\tpRadixSortElementArray8[i].mKey  = (uint8_t)(kCount - i);\n\t\t\t\tpRadixSortElementArray8[i].mData = (uint8_t)i;\n\t\t\t}\n\t\t\tradix_sort<RadixSortElement8*, extract_radix_key<RadixSortElement8> >(pRadixSortElementArray8, pRadixSortElementArray8 + kCount, pRadixSortElementArrayTemp8);\n\t\t\tEATEST_VERIFY(is_sorted(pRadixSortElementArray8, pRadixSortElementArray8 + kCount));\n\t\t\tdelete[] pRadixSortElementArray8;\n\t\t\tdelete[] pRadixSortElementArrayTemp8;\n\t\t}\n\t}\n\n\t{\n\t\t// Do some white-box testing of radix sort to verify internal optimizations work properly for some edge cases.\n\n\t\t{\n\t\t\tuint32_t input[] = { 123, 15, 76, 2, 74, 12, 62, 91 };\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\t// Test values where some digit positions have identical values\n\t\t\tuint32_t input[] = { 0x75000017, 0x74000003, 0x73000045, 0x76000024, 0x78000033, 0x76000099, 0x78000043, 0x75000010 };\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\t// Test values where some digit positions have identical values\n\t\t\tuint32_t input[] = { 0x00750017, 0x00740003, 0x00730045, 0x00760024, 0x00780033, 0x00760099, 0x00780043, 0x00750010 };\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\t// Test values where an odd number of scatter operations will be done during sorting (which forces a copy operation to move values back to the input buffer).\n\t\t\tuint32_t input[] = { 0x00000017, 0x00000003, 0x00000045, 0x00000024, 0x00000033, 0x00000099, 0x00000043, 0x00000010 };\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\t// Test case for bug where the last histogram bucket was not being cleared to zero\n\t\t\tuint32_t input[] = { 0xff00, 0xff };\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t}\n\n\t{\n\t\t// Test different values for DigitBits\n\n\t\t{\n\t\t\tuint32_t input[] = {2514513, 6278225, 2726217, 963245656, 35667326, 2625624562, 3562562562, 1556256252};\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>, 1>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\tuint32_t input[] = { 2514513, 6278225, 2726217, 963245656, 35667326, 2625624562, 3562562562, 1556256252 };\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>, 3>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\tuint32_t input[] = { 2514513, 6278225, 2726217, 963245656, 35667326, 2625624562, 3562562562, 1556256252 };\n\t\t\tuint32_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint32_t*, identity_extract_radix_key<uint32_t>, 6>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\t// Test a value for DigitBits that is more than half the size of the type.\n\t\t\tuint16_t input[] = { 14513, 58225, 26217, 34656, 63326, 24562, 35562, 15652 };\n\t\t\tuint16_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint16_t*, identity_extract_radix_key<uint16_t>, 11>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\t\t{\n\t\t\t// Test a value for DigitBits that is the size of the type itself.\n\t\t\tuint8_t input[] = { 113, 225, 217, 56, 26, 162, 62, 152 };\n\t\t\tuint8_t buffer[EAArrayCount(input)];\n\t\t\tradix_sort<uint8_t*, identity_extract_radix_key<uint8_t>, 8>(begin(input), end(input), buffer);\n\t\t\tEATEST_VERIFY(is_sorted(begin(input), end(input)));\n\t\t}\n\n\t}\n\n\t{\n\t\t// void bucket_sort(ForwardIterator first, ForwardIterator last, ContainerArray& bucketArray, HashFunction hash)\n\n\t\tconst size_t kElementRange = 32;\n\t\tvector<int>  intArray(1000);\n\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t\tintArray[i] = rng() % kElementRange;\n\n\t\tvector< vector<int> > bucketArray(kElementRange);\n\t\tbucket_sort(intArray.begin(), intArray.end(), bucketArray, eastl::hash_use_self<int>());\n\t\tEATEST_VERIFY(is_sorted(intArray.begin(), intArray.end()));\n\t}\n\n\n\t{ \n\t\t// stable_sort general test\n\t\ttypedef eastl::less<int> IntCompare;\n\n\t\tint intArray[2] = { 0, 1 };\n\n\t\tstable_sort(intArray, intArray + 2);\n\t\tstable_sort(intArray, intArray + 2, IntCompare());\n\t\tstable_sort<int*>(intArray, intArray + 2);\n\t\tstable_sort<int*, IntCompare>(intArray, intArray + 2, IntCompare());\n\n\t\tMallocAllocator mallocAllocator;\n\n\t\t//stable_sort(intArray, intArray + 2, mallocAllocator);\n\t\tstable_sort(intArray, intArray + 2, mallocAllocator, IntCompare());\n\t\t//stable_sort<int*, MallocAllocator>(intArray, intArray + 2, mallocAllocator);\n\t\tstable_sort<int*, MallocAllocator, IntCompare>(intArray, intArray + 2, mallocAllocator, IntCompare());\n\t}\n\n\t{\n\t\t// stable_sort special test\n\t\tIntArrayArray   intArrayArray(2);\n\t\tIntArrayCompare compare;\n\n\t\tintArrayArray[0].push_back(0);\n\t\tintArrayArray[1].push_back(1);\n\t\t \n\t\tstable_sort(intArrayArray.begin(), intArrayArray.end(), compare);\n\t}\n\n\n\t{\n\t\t// Test to verify that Compare object references are preserved.\n\t\ttypedef deque<int>         IntDeque;\n\t\ttypedef IntDeque::iterator IntDequeIterator;\n\n\t\tIntDeque        intDeque, intDequeSaved;\n\t\tStatefulCompare compare;\n\n\t\t// Set up intDequeSaved with random data.\n\t\tfor(int n = 0; n < 500; n++)\n\t\t{\n\t\t\tintDequeSaved.push_back(n);\n\n\t\t\tif(rng.RandLimit(10) == 0)\n\t\t\t{\n\t\t\t\tintDequeSaved.push_back(n);\n\n\t\t\t\tif(rng.RandLimit(5) == 0)\n\t\t\t\t\tintDequeSaved.push_back(n);\n\t\t\t}\n\t\t}\n\n\t\teastl::random_shuffle(intDequeSaved.begin(), intDequeSaved.end(), rng);\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tbubble_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tshaker_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tinsertion_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tselection_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tshell_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tcomb_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\theap_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tmerge_sort<IntDequeIterator, EASTLAllocatorType, StatefulCompare&>(intDeque.begin(), intDeque.end(), *get_default_allocator((EASTLAllocatorType*)NULL), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tintDeque = intDequeSaved;\n\t\tquick_sort<IntDequeIterator, StatefulCompare&>(intDeque.begin(), intDeque.end(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\n\t\tStatefulCompare::Reset();\n\t\tvector<int> buffer(intDeque.size()/2);\n\t\tintDeque = intDequeSaved;\n\t\ttim_sort_buffer<IntDequeIterator, int, StatefulCompare&>(intDeque.begin(), intDeque.end(), buffer.data(), compare);\n\t\tEATEST_VERIFY((StatefulCompare::nCtorCount == 0) && (StatefulCompare::nDtorCount == 0) && (StatefulCompare::nCopyCount == 0));\n\t}\n\n\t{\n\t\t// EATEST_VERIFY deque sorting can compile.\n\t\tdeque<int>  intDeque;\n\t\tvector<int> intVector;\n\n\t\tstable_sort(intDeque.begin(),  intDeque.end());\n\t\tstable_sort(intVector.begin(), intVector.end());\n\t}\n\n\n\t{\n\t\t// Test sorting of a container of pointers to objects as opposed to a container of objects themselves.\n\t\tvector<TestObject>  toArray;\n\t\tvector<TestObject*> topArray;\n\n\t\tfor(eastl_size_t i = 0; i < 32; i++)\n\t\t\ttoArray.push_back(TestObject((int)rng.RandLimit(20)));\n\t\tfor(eastl_size_t i = 0; i < 32; i++) // This needs to be a second loop because the addresses might change in the first loop due to container resizing.\n\t\t\ttopArray.push_back(&toArray[i]);\n\n\t\tquick_sort(topArray.begin(), topArray.end(), TestObjectPtrCompare());\n\t\tEATEST_VERIFY(is_sorted(topArray.begin(), topArray.end(), TestObjectPtrCompare()));\n\t}\n\n\n\t{\n\t\t// Test sorting of a container of array indexes to objects as opposed to a container of objects themselves.\n\n\t\tvector<TestObject>   toArray;\n\t\tvector<eastl_size_t> toiArray;\n\n\t\tfor(eastl_size_t i = 0; i < 32; i++)\n\t\t{\n\t\t\ttoArray.push_back(TestObject((int)rng.RandLimit(20)));\n\t\t\ttoiArray.push_back(i);\n\t\t}\n\n\t\tquick_sort(toiArray.begin(), toiArray.end(), TestObjectIndexCompare(&toArray));\n\t\tEATEST_VERIFY(is_sorted(toiArray.begin(), toiArray.end(), TestObjectIndexCompare(&toArray)));\n\t}\n\n\n\t{\n\t\t// Test of special floating point sort in the presence of NaNs.\n\t\tvector<float> floatArray;\n\t\tunion FloatInt32{ float f; int32_t i; } fi;\n\n\t\tfor(int i = 0; i < 1000; i++)\n\t\t{\n\t\t\tfi.i = (int32_t)rng.Rand();\n\t\t\tfloatArray.push_back(fi.f);\n\t\t}\n\n\t\t// Without SafeFloatCompare, the following quick_sort will crash, hang, or generate inconsistent results. \n\t\tquick_sort(floatArray.begin(), floatArray.end(), SafeFloatCompare());\n\t\tEATEST_VERIFY(is_sorted(floatArray.begin(), floatArray.end(), SafeFloatCompare()));\n\t}\n\n\t{\n\t\tauto test_stable_sort = [&](auto testArray, size_t count)\n\t\t{\n\t\t\tauto isEven = [](auto val) { return (val % 2) == 0; };\n\t\t\tauto isOdd  = [](auto val) { return (val % 2) != 0; };\n\n\t\t\tfor (size_t i = 0; i < count; i++)\n\t\t\t\ttestArray.push_back((uint16_t)rng.Rand());\n\n\t\t\tvector<uint16_t> evenArray;\n\t\t\tvector<uint16_t> oddArray;\n\n\t\t\teastl::copy_if(testArray.begin(), testArray.end(), eastl::back_inserter(evenArray), isEven);\n\t\t\teastl::copy_if(testArray.begin(), testArray.end(), eastl::back_inserter(oddArray), isOdd);\n\n\t\t\tconst auto boundary = eastl::stable_partition(testArray.begin(), testArray.end(), isEven);\n\n\t\t\tconst auto evenCount = eastl::distance(testArray.begin(), boundary);\n\t\t\tconst auto oddCount = eastl::distance(boundary, testArray.end());\n\n\t\t\tconst auto evenExpectedCount = (ptrdiff_t)evenArray.size();\n\t\t\tconst auto oddExpectedCount = (ptrdiff_t)oddArray.size();\n\n\t\t\tEATEST_VERIFY(evenCount == evenExpectedCount);\n\t\t\tEATEST_VERIFY(oddCount == oddExpectedCount);\n\t\t\tEATEST_VERIFY(eastl::equal(testArray.begin(), boundary, evenArray.begin()));\n\t\t\tEATEST_VERIFY(eastl::equal(boundary, testArray.end(), oddArray.begin()));\n\t\t};\n\n\t\ttest_stable_sort(vector<uint16_t>(), 1000); // Test stable_partition\n\t\ttest_stable_sort(vector<uint16_t>(), 0);\t// Test stable_partition on empty container\n\t\ttest_stable_sort(vector<uint16_t>(), 1);\t// Test stable_partition on container of one element\n\t\ttest_stable_sort(vector<uint16_t>(), 2);\t// Test stable_partition on container of two element\n\t\ttest_stable_sort(list<uint16_t>(),   0);\t// Test stable_partition on bidirectional iterator (not random access)\n\t}\n\n\t#if 0 // Disabled because it takes a long time and thus far seems to show no bug in quick_sort.\n\t{\n\t\t// Regression of Coverity report for Madden 2014 that quick_sort is reading beyond an array bounds within insertion_sort_simple.\n\t\t// The Madden code was sorting the 11 players on the field for a team by some criteria. We write \n\t\tvector<int> intArray(11);\n\t\tfor(eastl_size_t i = 0; i < intArray.size(); i++)\n\t\t\tintArray[i] = i;\n\t\t\n\t\tdo {\n\t\t\tvector<int> intArrayCopy(intArray);\n\n\t\t\t// We need to verify that intArray[12] is never accessed. We could do that with a stomp allocator, \n\t\t\t// which we don't currently have set up for the EASTL unit tests, or we could put a breakpoint in \n\t\t\t// the debugger. Until we get a stomp allocator installed, do the breakpoint solution.\n\t\t\tquick_sort(intArrayCopy.begin(), intArrayCopy.end());\n\t\t} while(next_permutation(intArray.begin(), intArray.end()));\n\t}\n\t#endif\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestSpan.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/array.h>\n#include <EASTL/span.h>\n#include <EASTL/vector.h>\n\nvoid TestSpanCtor(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\t{\n\t\tspan<int> s;\n\t\tVERIFY(s.empty());\n\t\tVERIFY(s.size() == 0);\n\t\tVERIFY(s.data() == nullptr);\n\t}\n\t{\n\t\tspan<float> s;\n\t\tVERIFY(s.empty());\n\t\tVERIFY(s.size() == 0);\n\t\tVERIFY(s.data() == nullptr);\n\t}\n\t{\n\t\tspan<TestObject> s;\n\t\tVERIFY(s.empty());\n\t\tVERIFY(s.size() == 0);\n\t\tVERIFY(s.data() == nullptr);\n\t}\n\n\t{\n\t\tint arr[5] = {0, 1, 2, 3, 4};\n\t\tspan<int> s(eastl::begin(arr), 5);\n\t\tVERIFY(s.data() == eastl::begin(arr));\n\t\tVERIFY(s.size() == 5);\n\t\tVERIFY(!s.empty());\n\t}\n\n\t{\n\t\tint arr[5] = {0, 1, 2, 3, 4};\n\t\tspan<int> s(eastl::begin(arr), eastl::end(arr));\n\t\tVERIFY(s.data() == eastl::begin(arr));\n\t\tVERIFY(s.size() == 5);\n\t\tVERIFY(!s.empty());\n\t}\n\n\t{\n\t\tint arr[5] = {0, 1, 2, 3, 4};\n\t\tspan<int> s(arr);\n\t\tVERIFY(s.data() == eastl::begin(arr));\n\t\tVERIFY(s.size() == 5);\n\t\tVERIFY(s.data()[2] == arr[2]);\n\t\tVERIFY(!s.empty());\n\t}\n\n\t{\n\t\teastl::array<int, 5> arr = {{0, 1, 2, 3, 4}};\n\t\tspan<int> s(arr);\n\t\tVERIFY(s.data() == eastl::begin(arr));\n\t\tVERIFY(s.size() == 5);\n\t\tVERIFY(s.data()[2] == arr.data()[2]);\n\t\tVERIFY(!s.empty());\n\t}\n\n\t{\n\t\tconst eastl::array<int, 5> arr = {{0, 1, 2, 3, 4}};\n\t\tspan<const int> s(arr);\n\t\tVERIFY(s.data() == eastl::begin(arr));\n\t\tVERIFY(s.size() == 5);\n\t\tVERIFY(s.data()[2] == arr.data()[2]);\n\t\tVERIFY(!s.empty());\n\t}\n\n\t{\n\t\tconst eastl::array<int, 5> arr = {{0, 1, 2, 3, 4}};\n\t\tconst span<const int> s(arr);\n\t\tVERIFY(s.data() == eastl::begin(arr));\n\t\tVERIFY(s.size() == 5);\n\t\tVERIFY(s.data()[2] == arr.data()[2]);\n\t}\n\n\t{\n\t\tclass foo {};\n\n\t\tfoo* pFoo = nullptr;\n\n\t\tauto f = [](eastl::span<const foo*>) {};\n\n\t\teastl::array<const foo*, 1> foos = {{pFoo}};\n\n\t\tf(foos);\n\t}\n}\n\nvoid TestSpanSizeBytes(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\t{\n\t\tint arr[5] = {0, 1, 2, 3, 4};\n\t\tspan<int> s(arr);\n\t\tVERIFY(s.size_bytes() == sizeof(arr));\n\t\tVERIFY(s.size_bytes() == (5 * sizeof(int)));\n\t}\n\n\t{\n\t\tfloat arr[8] = {0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f};\n\t\tspan<float> s(arr);\n\t\tVERIFY(s.size_bytes() == sizeof(arr));\n\t\tVERIFY(s.size_bytes() == (8 * sizeof(float)));\n\t}\n\n\t{\n\t\tint64_t arr[5] = {0, 1, 2, 3, 4};\n\t\tspan<int64_t> s(arr);\n\t\tVERIFY(s.size_bytes() == sizeof(arr));\n\t\tVERIFY(s.size_bytes() == (5 * sizeof(int64_t)));\n\t}\n}\n\nvoid TestSpanElementAccess(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\t{\n\t\tint arr[5] = {0, 1, 2, 3, 4};\n\t\tspan<int> s(arr);\n\n\t\tVERIFY(s.front() == 0);\n\t\tVERIFY(s.back() == 4);\n\n\t\tVERIFY(s[0] == 0);\n\t\tVERIFY(s[1] == 1);\n\t\tVERIFY(s[2] == 2);\n\t\tVERIFY(s[3] == 3);\n\t\tVERIFY(s[4] == 4);\n\n\t\tVERIFY(s(0) == 0);\n\t\tVERIFY(s(1) == 1);\n\t\tVERIFY(s(2) == 2);\n\t\tVERIFY(s(3) == 3);\n\t\tVERIFY(s(4) == 4);\n\t}\n}\n\nvoid TestSpanIterators(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\tint arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\tspan<int> s(arr);\n\n\t// ranged-for test\n\t{\n\t\tint* pBegin = arr;\n\t\tfor(auto& e : arr)\n\t\t{\n\t\t\tVERIFY(e == *pBegin++);\n\t\t}\n\t}\n\n\t{\n\t\tauto testIteratorBegin = [&](auto p)\n\t\t{\n\t\t\tVERIFY(*p++ == 0);\n\t\t\tVERIFY(*p++ == 1);\n\t\t\tVERIFY(*p++ == 2);\n\t\t\tVERIFY(*p++ == 3);\n\t\t\tVERIFY(*p++ == 4);\n\t\t\tVERIFY(*p++ == 5);\n\t\t\tVERIFY(*p++ == 6);\n\t\t\tVERIFY(*p++ == 7);\n\t\t\tVERIFY(*p++ == 8);\n\t\t\tVERIFY(*p++ == 9);\n\t\t};\n\n\t\tauto testIteratorEnd = [&](auto p)\n\t\t{\n\t\t\tp--; // move pointer to a valid element\n\n\t\t\tVERIFY(*p-- == 9);\n\t\t\tVERIFY(*p-- == 8);\n\t\t\tVERIFY(*p-- == 7);\n\t\t\tVERIFY(*p-- == 6);\n\t\t\tVERIFY(*p-- == 5);\n\t\t\tVERIFY(*p-- == 4);\n\t\t\tVERIFY(*p-- == 3);\n\t\t\tVERIFY(*p-- == 2);\n\t\t\tVERIFY(*p-- == 1);\n\t\t\tVERIFY(*p-- == 0);\n\t\t};\n\n\t\ttestIteratorBegin(s.begin());\n\t\ttestIteratorBegin(s.cbegin());\n\t\ttestIteratorEnd(s.end());\n\t\ttestIteratorEnd(s.cend());\n\t}\n\n\t{\n\t\tauto testReverseIteratorBegin = [&](auto p)\n\t\t{\n\t\t\tVERIFY(*p++ == 9);\n\t\t\tVERIFY(*p++ == 8);\n\t\t\tVERIFY(*p++ == 7);\n\t\t\tVERIFY(*p++ == 6);\n\t\t\tVERIFY(*p++ == 5);\n\t\t\tVERIFY(*p++ == 4);\n\t\t\tVERIFY(*p++ == 3);\n\t\t\tVERIFY(*p++ == 2);\n\t\t\tVERIFY(*p++ == 1);\n\t\t\tVERIFY(*p++ == 0);\n\t\t};\n\n\t\tauto testReverseIteratorEnd = [&](auto p)\n\t\t{\n\t\t\tp--; // move pointer to a valid element\n\n\t\t\tVERIFY(*p-- == 0);\n\t\t\tVERIFY(*p-- == 1);\n\t\t\tVERIFY(*p-- == 2);\n\t\t\tVERIFY(*p-- == 3);\n\t\t\tVERIFY(*p-- == 4);\n\t\t\tVERIFY(*p-- == 5);\n\t\t\tVERIFY(*p-- == 6);\n\t\t\tVERIFY(*p-- == 7);\n\t\t\tVERIFY(*p-- == 8);\n\t\t\tVERIFY(*p-- == 9);\n\t\t};\n\n\t\ttestReverseIteratorBegin(s.rbegin());\n\t\ttestReverseIteratorBegin(s.crbegin());\n\t\ttestReverseIteratorEnd(s.rend());\n\t\ttestReverseIteratorEnd(s.crend());\n\t}\n}\n\nvoid TestSpanCopyAssignment(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\t{\n\t\tint arr[5] = {0, 1, 2, 3, 4};\n\t\tspan<int> s(arr);\n\t\tspan<int> sc = s;\n\n\t\tVERIFY(s[0] == sc[0]);\n\t\tVERIFY(s[1] == sc[1]);\n\t\tVERIFY(s[2] == sc[2]);\n\t\tVERIFY(s[3] == sc[3]);\n\t\tVERIFY(s[4] == sc[4]);\n\n\t\tVERIFY(s(0) == sc(0));\n\t\tVERIFY(s(1) == sc(1));\n\t\tVERIFY(s(2) == sc(2));\n\t\tVERIFY(s(3) == sc(3));\n\t\tVERIFY(s(4) == sc(4));\n\t}\n}\n\nvoid TestSpanContainerConversion(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\t{\n\t\tvector<int> v = {0, 1, 2, 3, 4, 5};\n\t\tspan<const int> s(v);\n\n\t\tVERIFY(s.size() == static_cast<span<int>::index_type>(eastl::size(v)));\n\t\tVERIFY(s.data() == eastl::data(v));\n\n\t\tVERIFY(s[0] == v[0]);\n\t\tVERIFY(s[1] == v[1]);\n\t\tVERIFY(s[2] == v[2]);\n\t\tVERIFY(s[3] == v[3]);\n\t\tVERIFY(s[4] == v[4]);\n\t\tVERIFY(s[5] == v[5]);\n\t}\n\n\t{\n\t\tconst vector<int> v = {0, 1, 2, 3, 4, 5};\n\t\tspan<const int> s(v);\n\n\t\tVERIFY(s.size() == static_cast<span<int>::index_type>(eastl::size(v)));\n\t\tVERIFY(s.data() == eastl::data(v));\n\n\t\tVERIFY(s[0] == v[0]);\n\t\tVERIFY(s[1] == v[1]);\n\t\tVERIFY(s[2] == v[2]);\n\t\tVERIFY(s[3] == v[3]);\n\t\tVERIFY(s[4] == v[4]);\n\t\tVERIFY(s[5] == v[5]);\n\t}\n\n\t{\n\t\tvector<int> v = {0, 1, 2, 3, 4, 5};\n\t\tspan<const int, 6> s1(v);\n\t\tspan<const int> s2(s1);\n\t\t\n\t\tVERIFY(s2.size() == (span<const int>::index_type)v.size());\n\t\tVERIFY(s2[0] == v[0]);\n\t\tVERIFY(s2[1] == v[1]);\n\n\t\tVERIFY(s1.data() ==  v.data());\n\t\tVERIFY(s1.data() == s2.data());\n\t}\n\n\t{ // user reported regression for calling non-const span overload with a vector.\n\t\tauto f1 = [](span<int> s) { return s.size(); };\n\t\tauto f2 = [](span<const int> s) { return s.size(); };\n\n\t\t{\n\t\t\tvector<int> v = {0, 1, 2, 3, 4, 5};\n\n\t\t\tVERIFY(f1(v) == v.size());\n\t\t\tVERIFY(f2(v) == v.size());\n\t\t}\n\n\t\t{\n\t\t\tint a[] = {0, 1, 2, 3, 4, 5};\n\n\t\t\tVERIFY(f1(a) == EAArrayCount(a));\n\t\t\tVERIFY(f2(a) == EAArrayCount(a));\n\t\t}\n\t}\n}\n\nvoid TestSpanComparison(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\tint arr1[5] = {0, 1, 2, 3, 4};\n\tint arr2[8] = {0, 1, 2, 3, 4, 5, 6, 7};\n\t{\n\t\tspan<int> s1 = arr1;\n\t\tspan<int> s2 = arr2;\n\t\tspan<int> s3 = arr2;\n\t\tVERIFY(s2 == s3);\n\t\tVERIFY(s1 != s2);\n\t\tVERIFY(s1 < s2);\n\t\tVERIFY(s1 <= s2);\n\t\tVERIFY(s2 > s1);\n\t\tVERIFY(s2 >= s1);\n\t}\n}\n\nvoid TestSpanSubViews(int& nErrorCount)\n{\n\tusing namespace eastl;\n\n\tint arr1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t{\n\t\tspan<int> s =  arr1;\n\t\tauto first_span = s.first<4>();\n\t\tVERIFY(first_span.size() == 4);\n\t\tVERIFY(first_span[0] == 0);\n\t\tVERIFY(first_span[1] == 1);\n\t\tVERIFY(first_span[2] == 2);\n\t\tVERIFY(first_span[3] == 3);\n\t}\n\n\t{\n\t\tspan<int> s =  arr1;\n\t\tauto first_span = s.first(4);\n\t\tVERIFY(first_span.size() == 4);\n\t\tVERIFY(first_span[0] == 0);\n\t\tVERIFY(first_span[1] == 1);\n\t\tVERIFY(first_span[2] == 2);\n\t\tVERIFY(first_span[3] == 3);\n\t}\n\n\t{\n\t\tspan<int> s =  arr1;\n\t\tauto first_span = s.last<4>();\n\t\tVERIFY(first_span.size() == 4);\n\t\tVERIFY(first_span[0] == 6);\n\t\tVERIFY(first_span[1] == 7);\n\t\tVERIFY(first_span[2] == 8);\n\t\tVERIFY(first_span[3] == 9);\n\t}\n\n\t{\n\t\tspan<int> s =  arr1;\n\t\tauto first_span = s.last(4);\n\t\tVERIFY(first_span.size() == 4);\n\t\tVERIFY(first_span[0] == 6);\n\t\tVERIFY(first_span[1] == 7);\n\t\tVERIFY(first_span[2] == 8);\n\t\tVERIFY(first_span[3] == 9);\n\t}\n\n\t{ // empty range\n\t\tspan<int, 0> s{};\n\n\t\tauto fixed_span = s.subspan<0, 0>();\n\t\tVERIFY(fixed_span.empty());\n\t\tfixed_span = s.first<0>();\n\t\tVERIFY(fixed_span.empty());\n\t\tfixed_span = s.last<0>();\n\t\tVERIFY(fixed_span.empty());\n\n\t\tspan<int> dynamic_span;\n\t\tVERIFY(dynamic_span.empty());\n\t\tdynamic_span = s.first(0);\n\t\tVERIFY(dynamic_span.empty());\n\t\tdynamic_span = s.last(0);\n\t\tVERIFY(dynamic_span.empty());\n\t}\n\n\t{ // subspan: full range\n\t\tspan<int, 10> s =  arr1;\n\n\t\tauto fixed_span = s.subspan<0, 10>();\n\t\tVERIFY(fixed_span.size() == 10);\n\t\tVERIFY(fixed_span[0] == 0);\n\t\tVERIFY(fixed_span[1] == 1);\n\t\tVERIFY(fixed_span[8] == 8);\n\t\tVERIFY(fixed_span[9] == 9);\n\n\t\tauto dynamic_span = s.subspan(0, s.size());\n\t\tVERIFY(dynamic_span.size() == 10);\n\t\tVERIFY(dynamic_span[0] == 0);\n\t\tVERIFY(dynamic_span[1] == 1);\n\t\tVERIFY(dynamic_span[8] == 8);\n\t\tVERIFY(dynamic_span[9] == 9);\n\t}\n\n\t{ // subspan: subrange\n\t\tspan<int, 10> s =  arr1;\n\n\t\tauto fixed_span = s.subspan<3, 4>();\n\t\tVERIFY(fixed_span.size() == 4);\n\t\tVERIFY(fixed_span[0] == 3);\n\t\tVERIFY(fixed_span[1] == 4);\n\t\tVERIFY(fixed_span[2] == 5);\n\t\tVERIFY(fixed_span[3] == 6);\n\n\t\tauto dynamic_span = s.subspan(3, 4);\n\t\tVERIFY(dynamic_span.size() == 4);\n\t\tVERIFY(dynamic_span[0] == 3);\n\t\tVERIFY(dynamic_span[1] == 4);\n\t\tVERIFY(dynamic_span[2] == 5);\n\t\tVERIFY(dynamic_span[3] == 6);\n\t}\n\n\t{ // subspan: default count\n\t\tspan<int, 10> s =  arr1;\n\n\t\tauto fixed_span = s.subspan<3>();\n\t\tVERIFY(fixed_span.size() == 7);\n\t\tVERIFY(fixed_span[0] == 3);\n\t\tVERIFY(fixed_span[1] == 4);\n\t\tVERIFY(fixed_span[5] == 8);\n\t\tVERIFY(fixed_span[6] == 9);\n\n\t\tauto dynamic_span = s.subspan(3);\n\t\tVERIFY(dynamic_span.size() == 7);\n\t\tVERIFY(dynamic_span[0] == 3);\n\t\tVERIFY(dynamic_span[1] == 4);\n\t\tVERIFY(dynamic_span[5] == 8);\n\t\tVERIFY(dynamic_span[6] == 9);\n\t}\n}\n\nint TestSpan()\n{\n\tint nErrorCount = 0;\n\n\tTestSpanCtor(nErrorCount);\n\tTestSpanSizeBytes(nErrorCount);\n\tTestSpanElementAccess(nErrorCount);\n\tTestSpanIterators(nErrorCount);\n\tTestSpanCopyAssignment(nErrorCount);\n\tTestSpanContainerConversion(nErrorCount);\n\tTestSpanComparison(nErrorCount);\n\tTestSpanSubViews(nErrorCount);\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestString.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EABase/eabase.h>\n#include <EAStdC/EAMemory.h>\n#include <EAStdC/EAString.h>\n#include <EASTL/string.h>\n#include <EASTL/fixed_string.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/allocator_malloc.h>\n\nusing namespace eastl;\n\n// Verify char8_t support is present if the test build requested it.\n#if defined(EASTL_EXPECT_CHAR8T_SUPPORT) && !EA_CHAR8_UNIQUE\nstatic_assert(false, \"Building with char8_t tests enabled, but EA_CHAR8_UNIQUE evaluates to false.\");\n#endif\n\n\n// inject string literal string conversion macros into the unit tests\n#define TEST_STRING_NAME TestBasicString\n#define LITERAL(x) x\n#include \"TestString.inl\"\n\n#define TEST_STRING_NAME TestBasicStringW\n#define LITERAL(x) EA_WCHAR(x)\n#include \"TestString.inl\"\n\n#define TEST_STRING_NAME TestBasicString8\n#define LITERAL(x) EA_CHAR8(x)\n#include \"TestString.inl\"\n\n#define TEST_STRING_NAME TestBasicString16\n#define LITERAL(x) EA_CHAR16(x)\n#include \"TestString.inl\"\n\n#define TEST_STRING_NAME TestBasicString32\n#define LITERAL(x) EA_CHAR32(x)\n#include \"TestString.inl\"\n\nint TestString()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestBasicString<eastl::basic_string<char, StompDetectAllocator>>();\n\tnErrorCount += TestBasicString<eastl::string>();\n\n\tnErrorCount += TestBasicStringW<eastl::basic_string<wchar_t, StompDetectAllocator>>();\n\tnErrorCount += TestBasicStringW<eastl::wstring>();\n\n#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\tnErrorCount += TestBasicString8<eastl::basic_string<char8_t, StompDetectAllocator>>();\n\tnErrorCount += TestBasicString8<eastl::u8string>();\n#endif\n\n\tnErrorCount += TestBasicString16<eastl::basic_string<char16_t, StompDetectAllocator>>();\n\tnErrorCount += TestBasicString16<eastl::u16string>();\n\n#if defined(EA_CHAR32_NATIVE) && EA_CHAR32_NATIVE\n\tnErrorCount += TestBasicString32<eastl::basic_string<char32_t, StompDetectAllocator>>();\n\tnErrorCount += TestBasicString32<eastl::u32string>();\n#endif\n\n\t// Check for memory leaks by using the 'CountingAllocator' to ensure no active allocation after tests have completed.\n\tCountingAllocator::resetCount();\n\tnErrorCount += TestBasicString<eastl::basic_string<char, CountingAllocator>>();\n\tVERIFY(CountingAllocator::getActiveAllocationCount() == 0); \n\n\tnErrorCount += TestBasicStringW<eastl::basic_string<wchar_t, CountingAllocator>>();\n\tVERIFY(CountingAllocator::getActiveAllocationCount() == 0); \n\n#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\tnErrorCount += TestBasicString8<eastl::basic_string<char8_t, CountingAllocator>>();\n\tVERIFY(CountingAllocator::getActiveAllocationCount() == 0);\n#endif\n\n\tnErrorCount += TestBasicString16<eastl::basic_string<char16_t, CountingAllocator>>();\n\tVERIFY(CountingAllocator::getActiveAllocationCount() == 0); \n\n#if defined(EA_CHAR32_NATIVE) && EA_CHAR32_NATIVE\n\tnErrorCount += TestBasicString32<eastl::basic_string<char32_t, CountingAllocator>>();\n\tVERIFY(CountingAllocator::getActiveAllocationCount() == 0); \n#endif\n\n\t// to_string\n\t{\n\t\tVERIFY(eastl::to_string(42)    == \"42\");\n\t\tVERIFY(eastl::to_string(42l)   == \"42\");\n\t\tVERIFY(eastl::to_string(42ll)  == \"42\");\n\t\tVERIFY(eastl::to_string(42u)   == \"42\");\n\t\tVERIFY(eastl::to_string(42ul)  == \"42\");\n\t\tVERIFY(eastl::to_string(42ull) == \"42\");\n\t\tVERIFY(eastl::to_string(42.f)  == \"42.000000\");\n\t\tVERIFY(eastl::to_string(42.0)  == \"42.000000\");\n\t#if !defined(EA_COMPILER_GNUC) && !defined(EA_PLATFORM_MINGW)\n\t\t// todo:  long double sprintf functionality is unrealiable on unix-gcc, requires further debugging.  \n\t\tVERIFY(eastl::to_string(42.0l) == \"42.000000\");\n\t#endif\n\t}\n\n\t// to_wstring\n\t{\n\t\tVERIFY(eastl::to_wstring(42)    == L\"42\");\n\t\tVERIFY(eastl::to_wstring(42l)   == L\"42\");\n\t\tVERIFY(eastl::to_wstring(42ll)  == L\"42\");\n\t\tVERIFY(eastl::to_wstring(42u)   == L\"42\");\n\t\tVERIFY(eastl::to_wstring(42ul)  == L\"42\");\n\t\tVERIFY(eastl::to_wstring(42ull) == L\"42\");\n\t\tVERIFY(eastl::to_wstring(42.f)  == L\"42.000000\");\n\t\tVERIFY(eastl::to_wstring(42.0)  == L\"42.000000\");\n\t#if !defined(EA_COMPILER_GNUC) && !defined(EA_PLATFORM_MINGW)\n\t\t// todo:  long double sprintf functionality is unrealiable on unix-gcc, requires further debugging.  \n\t\tVERIFY(eastl::to_wstring(42.0l) == L\"42.000000\");\n\t#endif\n\t}\n\n\t#if EASTL_USER_LITERALS_ENABLED \n\t{\n\t\tVERIFY(\"cplusplus\"s == \"cplusplus\");\n\t\tVERIFY(L\"cplusplus\"s == L\"cplusplus\");\n\t\tVERIFY(u\"cplusplus\"s == u\"cplusplus\");\n\t\tVERIFY(U\"cplusplus\"s == U\"cplusplus\");\n\t\tVERIFY(u8\"cplusplus\"s == u8\"cplusplus\");\n\t}\n\t#endif\n\n\n\t{\n\t\t// CustomAllocator has no data members which reduces the size of an eastl::basic_string via the empty base class optimization.\n\t\tusing EboString = eastl::basic_string<char, CustomAllocator>;\n\n\t\t// this must match the eastl::basic_string heap memory layout struct which is a pointer and 2 eastl_size_t.\n\t\tconst int expectedSize = sizeof(EboString::pointer) + (2 * sizeof(EboString::size_type));\n\n\t\tstatic_assert(sizeof(EboString) == expectedSize, \"unexpected layout size of basic_string\");\n\t}\n\n\t// transparent_string_hash\n\t{\n\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\teastl::string str;\n\n\t\tfor (auto i = 0; i < 1000; ++i)\n\t\t{\n\t\t\tstr.clear();\n\t\t\tfor (auto j = 0; j < 8; ++j)\n\t\t\t\tstr.push_back(static_cast<char>(rng.RandRange(1, eastl::numeric_limits<char>::max()))); // don't append null terminator.\n\n\t\t\t// eastl::DecodePart() is not implemented for (un)signed char.\n\t\t\t//eastl::basic_string<signed char> signed_str(eastl::basic_string<signed char>::CtorConvert{}, str.c_str());\n\t\t\t//eastl::basic_string<unsigned char> unsigned_str(eastl::basic_string<unsigned char>::CtorConvert{}, str.c_str());\n#if EA_CHAR8_UNIQUE\n\t\t\teastl::basic_string<char8_t> str8(eastl::basic_string<char8_t>::CtorConvert{}, str.c_str());\n#endif\n\t\t\teastl::string_view view(str);\n\t\t\teastl::fixed_string<char, 16, false> fixed_str;\n\t\t\tfixed_str.append_convert(str.c_str());\n\n\t\t\ttransparent_string_hash hash;\n\n\t\t\t//EATEST_VERIFY(hash(str) == hash(signed_str));\n\t\t\t//EATEST_VERIFY(hash(str) == hash(signed_str.c_str()));\n\t\t\t//EATEST_VERIFY(hash(str) == hash(unsigned_str));\n\t\t\t//EATEST_VERIFY(hash(str) == hash(unsigned_str.c_str()));\n#if EA_CHAR8_UNIQUE\n\t\t\tEATEST_VERIFY(hash(str) == hash(str8));\n\t\t\tEATEST_VERIFY(hash(str) == hash(str8.c_str()));\n#endif\n\t\t\tEATEST_VERIFY(hash(str) == hash(view));\n\t\t\tEATEST_VERIFY(hash(str) == hash(fixed_str));\n\t\t}\n\t}\n\n\t// transparent_string16_hash\n\t{\n\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\teastl::string16 str;\n\n\t\tfor (auto i = 0; i < 1000; ++i)\n\t\t{\n\t\t\tstr.clear();\n\t\t\tfor (auto j = 0; j < 8; ++j)\n\t\t\t\tstr.push_back(static_cast<char16_t>(rng.RandRange(1, eastl::numeric_limits<char16_t>::max()))); // don't append null terminator.\n\n#if (EA_WCHAR_SIZE == 2)\n\t\t\teastl::basic_string<wchar_t> wstr(eastl::basic_string<wchar_t>::CtorConvert{}, str.c_str());\n#endif\n\t\t\teastl::u16string_view view(str);\n\t\t\teastl::fixed_string<char16_t, 16, false> fixed_str;\n\t\t\tfixed_str.append_convert(str.c_str());\n\n\t\t\ttransparent_string16_hash hash;\n\n#if (EA_WCHAR_SIZE == 2)\n\t\t\tEATEST_VERIFY(hash(str) == hash(wstr));\n\t\t\tEATEST_VERIFY(hash(str) == hash(wstr.c_str()));\n#endif\n\t\t\tEATEST_VERIFY(hash(str) == hash(view));\n\t\t\tEATEST_VERIFY(hash(str) == hash(fixed_str));\n\t\t}\n\t}\n\n\t// transparent_string32_hash\n\t{\n\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\teastl::string32 str;\n\n\t\tfor (auto i = 0; i < 1000; ++i)\n\t\t{\n\t\t\tstr.clear();\n\t\t\tfor (auto j = 0; j < 8; ++j)\n\t\t\t\tstr.push_back(static_cast<char32_t>(rng.RandRange(1, eastl::numeric_limits<char32_t>::max()))); // don't append null terminator.\n\n#if (EA_WCHAR_SIZE == 4)\n\t\t\teastl::basic_string<wchar_t> wstr(eastl::basic_string<wchar_t>::CtorConvert{}, str.c_str());\n#endif\n\t\t\teastl::u32string_view view(str);\n\t\t\teastl::fixed_string<char32_t, 16, false> fixed_str;\n\t\t\tfixed_str.append_convert(str.c_str());\n\n\t\t\ttransparent_string32_hash hash;\n\n#if (EA_WCHAR_SIZE == 4)\n\t\t\tEATEST_VERIFY(hash(str) == hash(wstr));\n\t\t\tEATEST_VERIFY(hash(str) == hash(wstr.c_str()));\n#endif\n\t\t\tEATEST_VERIFY(hash(str) == hash(view));\n\t\t\tEATEST_VERIFY(hash(str) == hash(fixed_str));\n\t\t}\n\t}\n\n\t// transparent_wstring_hash\n\t{\n\t\tEA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());\n\n\t\teastl::wstring str;\n\n\t\tfor (auto i = 0; i < 1000; ++i)\n\t\t{\n\t\t\tstr.clear();\n\t\t\tfor (auto j = 0; j < 8; ++j)\n\t\t\t\tstr.push_back(static_cast<wchar_t>(rng.RandRange(1, eastl::numeric_limits<wchar_t>::max()))); // don't append null terminator.\n\n#if (EA_WCHAR_SIZE == 2)\n\t\t\teastl::basic_string<char16_t> str16(eastl::basic_string<char16_t>::CtorConvert{}, str.c_str());\n#elif (EA_WCHAR_SIZE == 4)\n\t\t\teastl::basic_string<char32_t> str32(eastl::basic_string<char32_t>::CtorConvert{}, str.c_str());\n#endif\n\t\t\teastl::wstring_view view(str);\n\t\t\teastl::fixed_string<wchar_t, 16, false> fixed_str;\n\t\t\tfixed_str.append_convert(str.c_str());\n\n\t\t\ttransparent_wstring_hash hash;\n\n#if (EA_WCHAR_SIZE == 2)\n\t\t\tEATEST_VERIFY(hash(str) == hash(str16));\n\t\t\tEATEST_VERIFY(hash(str) == hash(str16.c_str()));\n#elif (EA_WCHAR_SIZE == 4)\n\t\t\tEATEST_VERIFY(hash(str) == hash(str32));\n\t\t\tEATEST_VERIFY(hash(str) == hash(str32.c_str()));\n#endif\n\t\t\tEATEST_VERIFY(hash(str) == hash(view));\n\t\t\tEATEST_VERIFY(hash(str) == hash(fixed_str));\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\n\n"
  },
  {
    "path": "test/source/TestString.inl",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n// todo:\n// Test Encoding\n// Test StringHash\n// Test exceptions\n\n#if EASTL_OPENSOURCE\n\t#define EASTL_SNPRINTF_TESTS_ENABLED 0\n#else\n\t#define EASTL_SNPRINTF_TESTS_ENABLED 1\n#endif\n\n\ntemplate<typename StringType>\nint TEST_STRING_NAME()\n{\n\tint nErrorCount = 0;\n\n\tstruct Failocator\n\t{\n\t\tFailocator() = default;\n\t\tFailocator(const char*) {}\n\n\t\tvoid* allocate(size_t) { EA_FAIL(); return nullptr; }\n\t\tvoid deallocate(void*, size_t) { EA_FAIL(); }\n\t};\n\n\t#if defined(EA_PLATFORM_ANDROID)\n\t\tEA_DISABLE_CLANG_WARNING(-Wunknown-warning-option)  // warning: disable unknown warning suppression pragmas\n\t\tEA_DISABLE_CLANG_WARNING(-Wunknown-pragmas)         // warning: disable unknown warning suppression pragmas\n\t\tEA_DISABLE_CLANG_WARNING(-Winherited-variadic-ctor) // warning: inheriting constructor does not inherit ellipsis\n\t#endif\n\n\tstruct SSOStringType : public StringType\n\t{\n\t\tusing StringType::StringType;\n\t\tusing StringType::IsSSO;\n\t};\n\n\t// Use custom string type that always fails to allocate memory to highlight when SSO is not functioning correctly.\n\tstruct SSOFailocatorString : public eastl::basic_string<typename StringType::value_type, Failocator>\n\t{\n\t\tusing eastl::basic_string<typename StringType::value_type, Failocator>::basic_string;\n\t\tusing eastl::basic_string<typename StringType::value_type, Failocator>::IsSSO;\n\t};\n\n\t#if defined(EA_PLATFORM_ANDROID)\n\t\tEA_RESTORE_CLANG_WARNING()\n\t\tEA_RESTORE_CLANG_WARNING()\n\t\tEA_RESTORE_CLANG_WARNING()\n\t#endif\n\n\t// SSO (short string optimization) tests\n\t{\n\t\t{\n\t\t\tSSOFailocatorString str;\n\t\t\tVERIFY(str.validate());\n\t\t\tVERIFY(str.empty());\n\t\t\tVERIFY(str.IsSSO());\n\t\t}\n\n\t\tEA_CONSTEXPR_IF(EA_PLATFORM_WORD_SIZE == 8 && EASTL_SIZE_T_32BIT == 0)\n\t\t{\n\t\t\t// test SSO size on 64 bit platforms\n\t\t\tEA_CONSTEXPR_IF(sizeof(typename StringType::value_type) == 1)\n\t\t\t{\n\t\t\t\t// we can fit 23 characters on 64bit system with 1 byte chars\n\t\t\t\tconst auto* pLiteral = LITERAL(\"aaaaaaaaaaaaaaaaaaaaaaa\");\n\t\t\t\tSSOFailocatorString str(pLiteral);\n\n\t\t\t\tVERIFY(EA::StdC::Strlen(pLiteral) == 23);\n\t\t\t\tVERIFY(str == pLiteral);\n\t\t\t\tVERIFY(str.validate());\n\t\t\t\tVERIFY(str.IsSSO());\n\t\t\t}\n\n\t\t\tEA_CONSTEXPR_IF(sizeof(typename StringType::value_type) == 2)\n\t\t\t{\n\t\t\t\t// we can fit 11 characters on 64 bit system with 2 byte chars\n\t\t\t\tconst auto* pLiteral = LITERAL(\"aaaaaaaaaaa\");\n\t\t\t\tSSOFailocatorString str(pLiteral);\n\n\t\t\t\tVERIFY(EA::StdC::Strlen(pLiteral) == 11);\n\t\t\t\tVERIFY(str == pLiteral);\n\t\t\t\tVERIFY(str.validate());\n\t\t\t\tVERIFY(str.IsSSO());\n\t\t\t}\n\n\t\t\tEA_CONSTEXPR_IF(sizeof(typename StringType::value_type) == 4)\n\t\t\t{\n\t\t\t\t// we can fit 5 characters on 64 bit system with 4 byte chars\n\t\t\t\tconst auto* pLiteral = LITERAL(\"aaaaa\");\n\t\t\t\tSSOFailocatorString str(pLiteral);\n\n\t\t\t\tVERIFY(EA::StdC::Strlen(pLiteral) == 5);\n\t\t\t\tVERIFY(str == pLiteral);\n\t\t\t\tVERIFY(str.validate());\n\t\t\t\tVERIFY(str.IsSSO());\n\t\t\t}\n\t\t}\n\n\t\tEA_CONSTEXPR_IF(EA_PLATFORM_WORD_SIZE == 4)\n\t\t{\n\t\t\t// test SSO size on 32 bit platforms\n\t\t\tEA_CONSTEXPR_IF(sizeof(typename StringType::value_type) == 1)\n\t\t\t{\n\t\t\t\t// we can fit 11 characters on 32bit system with 1 byte chars\n\t\t\t\tconst auto* pLiteral = LITERAL(\"aaaaaaaaaaa\");\n\t\t\t\tSSOFailocatorString str(pLiteral);\n\n\t\t\t\tVERIFY(EA::StdC::Strlen(pLiteral) == 11);\n\t\t\t\tVERIFY(str == pLiteral);\n\t\t\t\tVERIFY(str.validate());\n\t\t\t\tVERIFY(str.IsSSO());\n\t\t\t}\n\n\t\t\tEA_CONSTEXPR_IF(sizeof(typename StringType::value_type) == 2)\n\t\t\t{\n\t\t\t\t// we can fit 5 characters on 32 bit system with 2 byte chars\n\t\t\t\tconst auto* pLiteral = LITERAL(\"aaaaa\");\n\t\t\t\tSSOFailocatorString str(pLiteral);\n\n\t\t\t\tVERIFY(EA::StdC::Strlen(pLiteral) == 5);\n\t\t\t\tVERIFY(str == pLiteral);\n\t\t\t\tVERIFY(str.validate());\n\t\t\t\tVERIFY(str.IsSSO());\n\t\t\t}\n\n\t\t\tEA_CONSTEXPR_IF(sizeof(typename StringType::value_type) == 4)\n\t\t\t{\n\t\t\t\t// we can fit 2 characters on 32 bit system with 4 byte chars\n\t\t\t\tconst auto* pLiteral = LITERAL(\"aa\");\n\t\t\t\tSSOFailocatorString str(pLiteral);\n\n\t\t\t\tVERIFY(EA::StdC::Strlen(pLiteral) == 2);\n\t\t\t\tVERIFY(str == pLiteral);\n\t\t\t\tVERIFY(str.validate());\n\t\t\t\tVERIFY(str.IsSSO());\n\t\t\t}\n\t\t}\n\t}\n\n\t// basic_string();\n\t{\n\t\tStringType str;\n\t\tVERIFY(str.empty());\n\t\tVERIFY(str.length() == 0);\n\t\tVERIFY(str.validate());\n\t}\n\n\t// explicit basic_string(const allocator_type& allocator);\n\t{\n\t\ttypename StringType::allocator_type alloc;\n\t\tStringType str(alloc);\n\t\tVERIFY(str.validate());\n\t}\n\n\t// basic_string(const value_type* p, size_type n, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t\t{\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"), 26);\n\t\t\tVERIFY(str[5] == LITERAL('f'));\n\t\t\tVERIFY(!str.empty());\n\t\t\tVERIFY(str.length() == 26);\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tVERIFY(str[5] == LITERAL('f'));\n\t\t\tVERIFY(!str.empty());\n\t\t\tVERIFY(str.length() == 26);\n\t\t\tVERIFY(str.validate());\n\t\t}\n\t}\n\n\t// basic_string(const this_type& x, size_type position, size_type n = npos);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tStringType str2(str1, 3, 3);\n\t\tVERIFY(str2 == LITERAL(\"def\"));\n\t\tVERIFY(str2.size() == 3);\n\t\tVERIFY(str2.length() == 3);\n\t\tVERIFY(str2.capacity() >= 3);  // SSO buffer size\n\n\t\tStringType str3(str1, 25, 3);\n\t\tVERIFY(str3 == LITERAL(\"z\"));\n\t\tVERIFY(str3.size() == 1);\n\t\tVERIFY(str3.length() == 1);\n\t\tVERIFY(str3.capacity() >= 1); // SSO buffer size\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t\tVERIFY(str3.validate());\n\t}\n\n\t// EASTL_STRING_EXPLICIT basic_string(const value_type* p, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t\tauto* pLiteral = LITERAL(\"abcdefghijklmnopqrstuvwxyz\");\n\t\tStringType str(pLiteral);\n\t\tVERIFY(str == pLiteral);\n\t}\n\n\t// basic_string(size_type n, value_type c, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t\tStringType str(32, LITERAL('a'));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.size() == 32);\n\t\tVERIFY(str.length() == 32);\n\t\tVERIFY(str == LITERAL(\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"));\n\n\t\tVERIFY(str.validate());\n\t}\n\n\t// basic_string(const this_type& x);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2(str1);\n\n\t\tVERIFY(str1 == str2);\n\t\tVERIFY(str1.size() == str2.size());\n\t\tVERIFY(str1.empty() == str2.empty());\n\t\tVERIFY(str1.length() == str2.length());\n\t\tVERIFY(EA::StdC::Memcmp(str1.data(), str2.data(), str1.size()) == 0);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\n\t// basic_string(const value_type* pBegin, const value_type* pEnd, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto* pStart = str1.data() + 5;\n\t\tauto* pEnd = str1.data() + 20;\n\n\t\tStringType str(pStart, pEnd);\n\t\tVERIFY(str == LITERAL(\"fghijklmnopqrst\"));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.size() == 15);\n\t}\n\n\t// basic_string(CtorDoNotInitialize, size_type n, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t\tStringType str(typename StringType::CtorDoNotInitialize(), 42);\n\t\tVERIFY(str.size() == 0);\n\t\tVERIFY(str.length() == 0);\n\t\tVERIFY(str.capacity() == 42);\n\t}\n\n\t// basic_string(CtorSprintf, const value_type* pFormat, ...);\n\t{\n\t#if EASTL_SNPRINTF_TESTS_ENABLED\n\t\t{\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, %d\"), 42);\n\t\t\tVERIFY(str == LITERAL(\"Hello, 42\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, %d %d %d %d %d %d %d %d %d\"), 42, 42, 42, 42, 42, 42, 42, 42, 42);\n\t\t\tVERIFY(str == LITERAL(\"Hello, 42 42 42 42 42 42 42 42 42\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tconstexpr eastl_ssize_t signedValue = -42;\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, %\" EASTL_PRIdSIZE), signedValue);\n\t\t\tVERIFY(str == LITERAL(\"Hello, -42\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tconstexpr eastl_ssize_t signedValue = -42;\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, %\" EASTL_PRIiSIZE), signedValue);\n\t\t\tVERIFY(str == LITERAL(\"Hello, -42\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tconstexpr eastl_size_t unsignedValue = 42u;\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, 0%\" EASTL_PRIoSIZE), unsignedValue);\n\t\t\tVERIFY(str == LITERAL(\"Hello, 052\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tconstexpr eastl_size_t unsignedValue = 42u;\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, %\" EASTL_PRIuSIZE), unsignedValue);\n\t\t\tVERIFY(str == LITERAL(\"Hello, 42\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tconstexpr eastl_size_t unsignedValue = 42u;\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, 0x%\" EASTL_PRIxSIZE), unsignedValue);\n\t\t\tVERIFY(str == LITERAL(\"Hello, 0x2a\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{\n\t\t\tconstexpr eastl_size_t unsignedValue = 42u;\n\t\t\tStringType str(typename StringType::CtorSprintf(), LITERAL(\"Hello, 0x%\" EASTL_PRIXSIZE), unsignedValue);\n\t\t\tVERIFY(str == LITERAL(\"Hello, 0x2A\"));\n\t\t\tVERIFY(str.validate());\n\t\t}\n\t#endif\n\t}\n\n\t// basic_string(std::initializer_list<value_type> init, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\tStringType str({'a','b','c','d','e','f'});\n\t\tVERIFY(str == LITERAL(\"abcdef\"));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.length() == 6);\n\t\tVERIFY(str.size() == 6);\n\t\tVERIFY(str.validate());\n\t#endif\n\t}\n\n\t// basic_string(this_type&& x);\n\t// basic_string(this_type&& x, const allocator_type& allocator);\n\t{  // test heap string\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2(eastl::move(str1));\n\n\t\tVERIFY(str1 != LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(str2 == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str1.empty());\n\t\tVERIFY(!str2.empty());\n\n\t\tVERIFY(str1.length() == 0);\n\t\tVERIFY(str2.length() == 26);\n\n\t\tVERIFY(str1.size() == 0);\n\t\tVERIFY(str2.size() == 26);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\t{  // test sso string\n\t\tStringType str1(LITERAL(\"a\"));\n\t\tStringType str2(eastl::move(str1));\n\n\t\tVERIFY(str1 != LITERAL(\"a\"));\n\t\tVERIFY(str2 == LITERAL(\"a\"));\n\n\t\tVERIFY(str1.empty());\n\t\tVERIFY(!str2.empty());\n\n\t\tVERIFY(str1.length() == 0);\n\t\tVERIFY(str2.length() == 1);\n\n\t\tVERIFY(str1.size() == 0);\n\t\tVERIFY(str2.size() == 1);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\n\t// basic_string(const view_type& sv, const allocator_type& allocator);\n\t// basic_string(const view_type& sv, size_type position, size_type n, const allocator_type& allocator);\n\t{\n\t\t{ // test string_view\n\t\t\ttypename StringType::view_type sv(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tStringType str(sv);\n\n\t\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tVERIFY(!str.empty());\n\t\t\tVERIFY(str.length() == 26);\n\t\t\tVERIFY(str.size() == 26);\n\t\t\tVERIFY(str.validate());\n\t\t}\n\n\t\t{  // test string_view substring\n\t\t\ttypename StringType::view_type sv(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tStringType str(sv, 2, 22);\n\n\t\t\tVERIFY(str == LITERAL(\"cdefghijklmnopqrstuvwx\"));\n\t\t\tVERIFY(!str.empty());\n\t\t\tVERIFY(str.length() == 22);\n\t\t\tVERIFY(str.size() == 22);\n\t\t\tVERIFY(str.validate());\n\t\t}\n\t}\n\n\t// template <typename OtherCharType>\n\t// basic_string(CtorConvert, const OtherCharType* p, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str(typename StringType::CtorConvert(), EA_CHAR8(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str(typename StringType::CtorConvert(), EA_CHAR16(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str(typename StringType::CtorConvert(), EA_CHAR32(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str(typename StringType::CtorConvert(), EA_WCHAR(\"123456789\"));\n\t\t    VERIFY(str == LITERAL(\"123456789\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// template <typename OtherCharType>\n\t// basic_string(CtorConvert, const OtherCharType* p, size_type n, const allocator_type& allocator = EASTL_BASIC_STRING_DEFAULT_ALLOCATOR);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str(typename StringType::CtorConvert(), EA_CHAR8(\"123456789\"), 4);\n\t\t\tVERIFY(str == LITERAL(\"1234\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str(typename StringType::CtorConvert(), EA_CHAR16(\"123456789\"), 4);\n\t\t\tVERIFY(str == LITERAL(\"1234\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str(typename StringType::CtorConvert(), EA_CHAR32(\"123456789\"), 4);\n\t\t\tVERIFY(str == LITERAL(\"1234\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str(typename StringType::CtorConvert(), EA_WCHAR(\"123456789\"), 4);\n\t\t    VERIFY(str == LITERAL(\"1234\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// template <typename OtherStringType>\n\t// basic_string(CtorConvert, const OtherStringType& x);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str(typename StringType::CtorConvert(), eastl::basic_string<char8_t, typename StringType::allocator_type>(EA_CHAR8(\"123456789\")));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str(typename StringType::CtorConvert(), eastl::basic_string<char16_t, typename StringType::allocator_type>(EA_CHAR16(\"123456789\")));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str(typename StringType::CtorConvert(), eastl::basic_string<char32_t, typename StringType::allocator_type>(EA_CHAR32(\"123456789\")));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str(typename StringType::CtorConvert(), eastl::basic_string<wchar_t, typename StringType::allocator_type>(EA_WCHAR(\"123456789\")));\n\t\t    VERIFY(str == LITERAL(\"123456789\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// const allocator_type& get_allocator() const EA_NOEXCEPT;\n\t// allocator_type&       get_allocator() EA_NOEXCEPT;\n\t// void                  set_allocator(const allocator_type& allocator);\n\t{\n\t}\n\n\t// this_type& operator=(const this_type& x);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str1_copy(LITERAL(\"\"));\n\n\t\tVERIFY(str1_copy.empty());\n\n\t\tstr1_copy = str1;\n\n\t\tVERIFY(str1 == str1_copy);\n\t\tVERIFY(!str1_copy.empty());\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str1_copy.validate());\n\t}\n\n\t// this_type& operator=(const value_type* p);\n\t{\n\t\tStringType str;\n\t\tstr = LITERAL(\"abcdefghijklmnopqrstuvwxyz\");\n\n\t\tVERIFY(str[5] == LITERAL('f'));\n\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.length() == 26);\n\t\tVERIFY(str.validate());\n\t}\n\n\t// this_type& operator=(value_type c);\n\t{\n\t\tStringType str;\n\t\tstr = LITERAL('a');\n\n\t\tVERIFY(str == LITERAL(\"a\"));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.length() == 1);\n\t\tVERIFY(str.size() == 1);\n\t\tVERIFY(str.validate());\n\t}\n\n\t// this_type& operator=(std::initializer_list<value_type> ilist);\n\t{\n\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\tStringType str = {'a','b','c','d','e','f'};\n\n\t\tVERIFY(str == LITERAL(\"abcdef\"));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.length() == 6);\n\t\tVERIFY(str.size() == 6);\n\t\tVERIFY(str.validate());\n\t#endif\n\t}\n\n\t// this_type& operator=(this_type&& x);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2 = eastl::move(str1);\n\n\t\tVERIFY(str1 != LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(str2 == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str1.empty());\n\t\tVERIFY(!str2.empty());\n\n\t\tVERIFY(str1.length() == 0);\n\t\tVERIFY(str2.length() == 26);\n\n\t\tVERIFY(str1.size() == 0);\n\t\tVERIFY(str2.size() == 26);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\t{\n\t\tStringType str1(LITERAL(\"a\"));\n\t\tStringType str2 = eastl::move(str1);\n\n\t\tVERIFY(str1 != LITERAL(\"a\"));\n\t\tVERIFY(str2 == LITERAL(\"a\"));\n\n\t\tVERIFY(str1.empty());\n\t\tVERIFY(!str2.empty());\n\n\t\tVERIFY(str1.length() == 0);\n\t\tVERIFY(str2.length() == 1);\n\n\t\tVERIFY(str1.size() == 0);\n\t\tVERIFY(str2.size() == 1);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\n\t//     this_type& operator=(value_type* p);\n\t//\n\t//     template <typename OtherCharType>\n\t//     this_type& operator=(const OtherCharType* p);\n\t//\n\t//     template <typename OtherStringType>\n\t//     this_type& operator=(const OtherStringType& x);\n\t{\n\t#if EASTL_OPERATOR_EQUALS_OTHER_ENABLED\n\t\t{\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr = LITERAL(\"123456789\");\n\t\t\tVERIFY(str == LITERAL(\"123456789\");\n\t\t\tVERIFY(str.validate());\n\t\t}\n\t\t{\n\t\t\t{\n\t\t\t#if defined(EA_CHAR8)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = EA_CHAR8(\"123456789\");\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t\t{\n\t\t\t#if defined(EA_CHAR16)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = EA_CHAR16(\"123456789\");\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t\t{\n\t\t\t#if defined(EA_CHAR32)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = EA_CHAR32(\"123456789\");\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t\t{\n\t\t\t#if defined(EA_WCHAR)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = EA_WCHAR(\"123456789\");\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t}\n\t\t{\n\t\t\t{\n\t\t\t#if defined(EA_CHAR8)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = eastl::basic_string<char8_t>(EA_CHAR8(\"123456789\"));\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t\t{\n\t\t\t#if defined(EA_CHAR16)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = eastl::basic_string<char16_t>(EA_CHAR16(\"123456789\"));\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t\t{\n\t\t\t#if defined(EA_CHAR32)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = eastl::basic_string<char32_t>(EA_CHAR32(\"123456789\"));\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t\t{\n\t\t\t#if defined(EA_WCHAR)\n\t\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\t\tstr = eastl::basic_string<wchar_t>(EA_WCHAR(\"123456789\"));\n\t\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\t\tVERIFY(str.validate());\n\t\t\t#endif\n\t\t\t}\n\t\t}\n    #endif\n\t}\n\n\t// void swap(this_type& x);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2;\n\n\t\tstr1.swap(str2);\n\n\t\tVERIFY(str1 != LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(str2 == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str1.empty());\n\t\tVERIFY(!str2.empty());\n\n\t\tVERIFY(str1.length() == 0);\n\t\tVERIFY(str2.length() == 26);\n\t\tVERIFY(str1.size() == 0);\n\t\tVERIFY(str2.size() == 26);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\n\t// this_type& assign(const this_type& x);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2;\n\n\t\tstr2.assign(str1);\n\n\t\tVERIFY(str1 == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(str2 == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(!str1.empty());\n\t\tVERIFY(!str2.empty());\n\n\t\tVERIFY(str1.length() == 26);\n\t\tVERIFY(str2.length() == 26);\n\t\tVERIFY(str1.size() == 26);\n\t\tVERIFY(str2.size() == 26);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\n\t// this_type& assign(const this_type& x, size_type position, size_type n);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2(LITERAL(\"123456789\"));\n\n\t\tstr1.assign(str2, 3, 3);\n\n\t\tVERIFY(str1 == LITERAL(\"456\"));\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\n\t// this_type& assign(const value_type* p, size_type n);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tstr.assign(LITERAL(\"123456789\"), 5);\n\n\t\tVERIFY(str == LITERAL(\"12345\"));\n\t\tVERIFY(str.validate());\n\t}\n\n\t// this_type& assign(const value_type* p);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tstr.assign(LITERAL(\"123\"));\n\n\t\tVERIFY(str == LITERAL(\"123\"));\n\t\tVERIFY(str.validate());\n\t}\n\n\t// this_type& assign(size_type n, value_type c);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tstr.assign(32, LITERAL('c'));\n\n\t\tVERIFY(str == LITERAL(\"cccccccccccccccccccccccccccccccc\"));\n\t\tVERIFY(str.validate());\n\t}\n\n\t// this_type& assign(const value_type* pBegin, const value_type* pEnd);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto* pLiteral = LITERAL(\"0123456789\");\n\t\tauto* pBegin = pLiteral + 4;\n\t\tauto* pEnd = pLiteral + 7;\n\n\t\tstr.assign(pBegin, pEnd);\n\n\t\tVERIFY(str == LITERAL(\"456\"));\n\t\tVERIFY(str.validate());\n\t}\n\n\t// this_type& assign(this_type&& x);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2;\n\n\t\tstr1.assign(eastl::move(str2));\n\n\t\tVERIFY(str1 != LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(str2 == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str1.empty());\n\t\tVERIFY(!str2.empty());\n\n\t\tVERIFY(str1.length() == 0);\n\t\tVERIFY(str2.length() == 26);\n\t\tVERIFY(str1.size() == 0);\n\t\tVERIFY(str2.size() == 26);\n\n\t\tVERIFY(str1.validate());\n\t\tVERIFY(str2.validate());\n\t}\n\n\t// this_type& assign(std::initializer_list<value_type>);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tstr.assign({'1','2','3'});\n\n\t\tVERIFY(str == LITERAL(\"123\"));\n\t\tVERIFY(str.validate());\n\t}\n\n\t// template <typename OtherCharType>\n\t// this_type& assign_convert(const OtherCharType* p);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.assign_convert(EA_CHAR8(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.assign_convert(EA_CHAR16(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.assign_convert(EA_CHAR32(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t    str.assign_convert(EA_WCHAR(\"123456789\"));\n\t\t    VERIFY(str == LITERAL(\"123456789\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// template <typename OtherCharType>\n\t// this_type& assign_convert(const OtherCharType* p, size_type n);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.assign_convert(EA_CHAR8(\"123456789\"), 3);\n\t\t\tVERIFY(str == LITERAL(\"123\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.assign_convert(EA_CHAR16(\"123456789\"), 3);\n\t\t\tVERIFY(str == LITERAL(\"123\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.assign_convert(EA_CHAR32(\"123456789\"), 3);\n\t\t\tVERIFY(str == LITERAL(\"123\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t    str.assign_convert(EA_WCHAR(\"123456789\"), 3);\n\t\t    VERIFY(str == LITERAL(\"123\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// template <typename OtherStringType>\n\t// this_type& assign_convert(const OtherStringType& x);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\teastl::basic_string<char8_t> str2(EA_CHAR8(\"123456789\"));\n\n\t\t\tstr.assign_convert(str2);\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\teastl::basic_string<char16_t> str2(EA_CHAR16(\"123456789\"));\n\n\t\t\tstr.assign_convert(str2);\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\teastl::basic_string<char32_t> str2(EA_CHAR32(\"123456789\"));\n\n\t\t\tstr.assign_convert(str2);\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t    eastl::basic_string<wchar_t> str2(EA_WCHAR(\"123456789\"));\n\n\t\t    str.assign_convert(str2);\n\t\t    VERIFY(str == LITERAL(\"123456789\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// iterator       begin() EA_NOEXCEPT;\n\t// const_iterator begin() const EA_NOEXCEPT;\n\t// const_iterator cbegin() const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto iBegin = str.begin();\n\n\t\tVERIFY(*iBegin++ == LITERAL('a'));\n\t\tVERIFY(*iBegin++ == LITERAL('b'));\n\t\tVERIFY(*iBegin++ == LITERAL('c'));\n\t\tVERIFY(*iBegin++ == LITERAL('d'));\n\t\tVERIFY(*iBegin++ == LITERAL('e'));\n\t\tVERIFY(*iBegin++ == LITERAL('f'));\n\t\tVERIFY(*(str.begin() + 25) == LITERAL('z'));\n\n\t}\n\n\t// iterator       end() EA_NOEXCEPT;\n\t// const_iterator end() const EA_NOEXCEPT;\n\t// const_iterator cend() const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto iEnd = str.end()-1;\n\n\t\tVERIFY(*iEnd-- == LITERAL('z'));\n\t\tVERIFY(*iEnd-- == LITERAL('y'));\n\t\tVERIFY(*iEnd-- == LITERAL('x'));\n\t\tVERIFY(*iEnd-- == LITERAL('w'));\n\t\tVERIFY(*iEnd-- == LITERAL('v'));\n\t\tVERIFY(*iEnd-- == LITERAL('u'));\n\t\tVERIFY(*(str.end() - 26) == LITERAL('a'));\n\t}\n\n\t// reverse_iterator       rbegin() EA_NOEXCEPT;\n\t// const_reverse_iterator rbegin() const EA_NOEXCEPT;\n\t// const_reverse_iterator crbegin() const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto iRBegin = str.rbegin();\n\n\t\tVERIFY(*iRBegin++ == LITERAL('z'));\n\t\tVERIFY(*iRBegin++ == LITERAL('y'));\n\t\tVERIFY(*iRBegin++ == LITERAL('x'));\n\t\tVERIFY(*iRBegin++ == LITERAL('w'));\n\t\tVERIFY(*iRBegin++ == LITERAL('v'));\n\t\tVERIFY(*iRBegin++ == LITERAL('u'));\n\t\tVERIFY(*(str.rbegin() + 25) == LITERAL('a'));\n\t}\n\n\t// reverse_iterator       rend() EA_NOEXCEPT;\n\t// const_reverse_iterator rend() const EA_NOEXCEPT;\n\t// const_reverse_iterator crend() const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto iREnd = str.rend() - 1;\n\n\t\tVERIFY(*iREnd-- == LITERAL('a'));\n\t\tVERIFY(*iREnd-- == LITERAL('b'));\n\t\tVERIFY(*iREnd-- == LITERAL('c'));\n\t\tVERIFY(*iREnd-- == LITERAL('d'));\n\t\tVERIFY(*iREnd-- == LITERAL('e'));\n\t\tVERIFY(*iREnd-- == LITERAL('f'));\n\t\tVERIFY(*(str.rend() - 26) == LITERAL('z'));\n\t}\n\n\t// bool empty() const EA_NOEXCEPT;\n\t// size_type size() const EA_NOEXCEPT;\n\t// size_type length() const EA_NOEXCEPT;\n\t// size_type capacity() const EA_NOEXCEPT;\n\t// void resize(size_type n, value_type c);\n\t// void resize(size_type n);\n\t// void set_capacity(size_type n = npos);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.size() == 26);\n\t\tVERIFY(str.length() == 26);\n\t\tVERIFY(str.capacity() >= 26);\n\n\t\tstr.assign(LITERAL(\"\"));\n\t\tVERIFY(str.empty());\n\t\tVERIFY(str.size() == 0);\n\t\tVERIFY(str.length() == 0);\n\t\tVERIFY(str.capacity() >= 26);  // should not free existing capacity\n\n\t\tstr.resize(0);\n\t\tVERIFY(str.empty());\n\t\tVERIFY(str.size() == 0);\n\t\tVERIFY(str.length() == 0);\n\t\tVERIFY(str.capacity() >= 26);  // should not free existing capacity\n\n\t\tstr.set_capacity(0);\n\t\t// VERIFY(str.capacity() == 0); // frees existing capacity, but has a minimun of SSO capacity\n\n\t\tstr.resize(32, LITERAL('c'));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.size() == 32);\n\t\tVERIFY(str.length() == 32);\n\t\tVERIFY(str.capacity() >= 32);\n\t\tVERIFY(str == LITERAL(\"cccccccccccccccccccccccccccccccc\"));\n\t}\n\n\t// void shrink_to_fit\n\t{\n\t\tSSOStringType str(LITERAL(\"a\"));\n\t\tstr.reserve(100);\n\t\tVERIFY(str.capacity() == 100);\n\t\tstr.shrink_to_fit();\n\t\t// string should shrink to SSO\n\t\tVERIFY(str.IsSSO());\n\n\t\tstr = LITERAL(\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"); // 32 characters\n\t\tstr.reserve(100);\n\t\tVERIFY(str.capacity() == 100);\n\t\tstr.shrink_to_fit();\n\t\t// string should shrink but still be heap\n\t\tVERIFY(str.capacity() == 32);\n\t\tVERIFY(!str.IsSSO());\n\t}\n\n\t// void set_capacity(n)\n\t{\n\t\tconst auto *pLiteral32 = LITERAL(\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");\n\t\tconst auto *pLiteral31 = LITERAL(\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");\n\t\tconst auto *pLiteral1 = LITERAL(\"a\");\n\t\tconst auto *pLiteral2 = LITERAL(\"aa\");\n\n\t\tSSOStringType str = pLiteral32;\n\t\t// set_capacity(0) - deallocate and reset to SSO;\n\t\t{\n\t\t\t// heap -> sso\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tstr.set_capacity(0);\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tVERIFY(str == LITERAL(\"\"));\n\t\t}\n\t\t{\n\t\t\t// sso -> sso\n\t\t\tstr = pLiteral1;\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tstr.set_capacity(0);\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tVERIFY(str == LITERAL(\"\"));\n\t\t}\n\n\t\t// set_capacity(npos) - set capacity equal to current size - should realloc\n\t\t{\n\t\t\t// heap -> heap\n\t\t\tstr = pLiteral32;\n\t\t\tstr.reserve(100);\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tVERIFY(str.capacity() == 100);\n\t\t\tstr.set_capacity(StringType::npos);\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tVERIFY(str.capacity() == 32);\n\t\t\tVERIFY(str == pLiteral32);\n\t\t}\n\t\t{\n\t\t\t// heap -> sso\n\t\t\tstr = pLiteral1;\n\t\t\tstr.reserve(100);\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tVERIFY(str.capacity() == 100);\n\t\t\tstr.set_capacity(StringType::npos);\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tVERIFY(str == pLiteral1);\n\t\t}\n\t\t{\n\t\t\t// sso -> sso\n\t\t\tstr = pLiteral1;\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tstr.set_capacity(StringType::npos);\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tVERIFY(str == pLiteral1);\n\t\t}\n\n\t\t// set_capacity(n > capacity) - set capacity greater than out current capacity\n\t\t{\n\t\t\t// heap -> heap\n\t\t\tstr = pLiteral32;\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tauto nSavedCap = str.capacity();\n\t\t\tstr.set_capacity(nSavedCap + 1);\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tVERIFY(str == pLiteral32);\n\t\t\tVERIFY(str.capacity() > nSavedCap);\n\t\t}\n\t\t{\n\t\t\t// sso -> heap\n\t\t\tstr.set_capacity(0); // reset to sso\n\t\t\tstr = pLiteral1;\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tauto nSavedCap = str.capacity();\n\t\t\tstr.set_capacity(nSavedCap + 1);\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tVERIFY(str == pLiteral1);\n\t\t\tVERIFY(str.capacity() > nSavedCap);\n\t\t}\n\t\t{\n\t\t\t// sso -> sso\n\t\t\tstr.set_capacity(0); // reset to sso\n\t\t\tstr = pLiteral1;\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tauto nSavedCap = str.capacity();\n\t\t\tstr.set_capacity(str.size() + 1);\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tVERIFY(str == pLiteral1);\n\t\t\tVERIFY(str.capacity() == nSavedCap);\n\t\t}\n\n\t\t// set_capacity(n < size) - set capacity less than current size, str should truncate\n\t\t{\n\t\t\t// sso -> sso\n\t\t\tstr = pLiteral2;\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tstr.set_capacity(1);\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tVERIFY(str == pLiteral1);\n\t\t}\n\t\t{\n\t\t\t// heap -> sso\n\t\t\tstr = pLiteral32;\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tstr.set_capacity(1);\n\t\t\tVERIFY(str.IsSSO());\n\t\t\tVERIFY(str == pLiteral1);\n\t\t}\n\t\t{\n\t\t\t// heap -> heap\n\t\t\tstr = pLiteral32;\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tstr.set_capacity(31);\n\t\t\tVERIFY(!str.IsSSO());\n\t\t\tVERIFY(str == pLiteral31);\n\t\t}\n\t}\n\n\t// void reserve(size_type = 0);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.size() == 26);\n\t\tVERIFY(str.length() == 26);\n\t\tVERIFY(str.capacity() >= 26);\n\n\t\t// verifies that we allocate memory\n\t\tstr.reserve(64);\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.size() == 26);\n\t\tVERIFY(str.length() == 26);\n\t\tVERIFY(str.capacity() >= 64);\n\n\t\t// verifies that we do not free memory\n\t\tstr.reserve(32);\n\t\tVERIFY(!str.empty());\n\t\tVERIFY(str.size() == 26);\n\t\tVERIFY(str.length() == 26);\n\t\tVERIFY(str.capacity() >= 64);\n\t}\n\n\t// void force_size(size_type n);\n\t{\n\t\t// force_size does not write terminating null, meant to set size when using external\n\t\t// string writing mnethods like strcpy or sprintf\n\t\tStringType str(LITERAL(\"aaa\"));\n\t\tVERIFY(str.size() == 3);\n\t\tstr.force_size(0);\n\t\tVERIFY(str.size() == 0);\n\t\tstr.reserve(4); // 32 bit platform with char32_t can only hold 2 characters\n\t\tstr.force_size(4);\n\t\tVERIFY(str.size() == 4);\n\t\tstr[4] = '0';\n\t\tstr = LITERAL(\"aaa\");\n\t\tVERIFY(str.size() == 3);\n\t}\n\n\t// const value_type* data() const EA_NOEXCEPT;\n\t// const value_type* c_str() const EA_NOEXCEPT;\n\t{\n\t\tconst StringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tconst typename StringType::value_type* pData = str.data();\n\t\tconst typename StringType::value_type* pCStr = str.c_str();\n\n\t\tVERIFY(pData != nullptr);\n\t\tVERIFY(pCStr != nullptr);\n\t\tVERIFY(pData == pCStr);\n\t\tVERIFY(EA::StdC::Memcmp(pData, pCStr, str.size()) == 0);\n\t}\n\n\t// value_type* data() EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\ttypename StringType::value_type* pData = str.data();\n\n\t\tVERIFY(pData != nullptr);\n\t\tVERIFY(EA::StdC::Memcmp(pData, LITERAL(\"abcdefghijklmnopqrstuvwxyz\"), str.size()) == 0);\n\t}\n\n\t// reference       operator[](size_type n);\n\t// const_reference operator[](size_type n) const;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str[0]  == LITERAL('a'));\n\t\tVERIFY(str[14] == LITERAL('o'));\n\t\tVERIFY(str[25] == LITERAL('z'));\n\t}\n\n\t// reference       at(size_type n);\n\t// const_reference at(size_type n) const;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str.at(0)  == LITERAL('a'));\n\t\tVERIFY(str.at(14) == LITERAL('o'));\n\t\tVERIFY(str.at(25) == LITERAL('z'));\n\t}\n\n\t// reference       front();\n\t// const_reference front() const;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(str.front()  == LITERAL('a'));\n\t}\n\n\t// reference       back();\n\t// const_reference back() const;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tVERIFY(str.back()  == LITERAL('z'));\n\t}\n\n\t// this_type& operator+=(const this_type& x);\n\t// this_type& operator+=(const value_type* p);\n\t// this_type& operator+=(value_type c);\n\t{\n\t\tStringType str1(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tStringType str2(LITERAL(\"123\"));\n\t\tstr1 += str2;\n\t\tstr1 += LITERAL(\"456\");\n\t\tstr1 += LITERAL('7');\n\n\t\tVERIFY(str1 == LITERAL(\"abcdefghijklmnopqrstuvwxyz1234567\"));\n\t}\n\n\t// this_type& append(const this_type& x);\n\t// this_type& append(const this_type& x, size_type position, size_type n);\n\t// this_type& append(const value_type* p, size_type n);\n\t// this_type& append(const value_type* p);\n\t// this_type& append(size_type n, value_type c);\n\t// this_type& append(const value_type* pBegin, const value_type* pEnd);\n\t{\n\t\tconst StringType src(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tStringType str;\n\t\tstr.append(StringType(LITERAL(\"abcd\")));        // \"abcd\"\n\t\tstr.append(src, 4, 4); \t\t   \t\t\t\t\t// \"abcdefgh\"\n\t\tstr.append(src.data() + 8, 4); \t\t\t\t\t// \"abcdefghijkl\"\n\t\tstr.append(LITERAL(\"mnop\"));   \t\t\t\t\t// \"abcdefghijklmnop\"\n\t\tstr.append(1, LITERAL('q'));   \t\t\t\t\t// \"abcdefghijklmnopq\"\n\t\tstr.append(src.data() + 17, src.data() + 26);   // \"abcdefghijklmnopqrstuvwxyz\"\n\n\t\tVERIFY(str == src);\n\t}\n\n\t// this_type& append_sprintf_va_list(const value_type* pFormat, va_list arguments);\n\t// this_type& append_sprintf(const value_type* pFormat, ...);\n\t{\n\t#if EASTL_SNPRINTF_TESTS_ENABLED\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tstr.append_sprintf(LITERAL(\"Hello, %d\"), 42);\n\n\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyzHello, 42\"));\n\t\tVERIFY(str.validate());\n\t#endif\n\t}\n\n\t// template <typename OtherCharType>\n\t// this_type& append_convert(const OtherCharType* p);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str;\n\t\t\tstr.append_convert(EA_CHAR8(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str;\n\t\t\tstr.append_convert(EA_CHAR16(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str;\n\t\t\tstr.append_convert(EA_CHAR32(\"123456789\"));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str;\n\t\t    str.append_convert(EA_WCHAR(\"123456789\"));\n\t\t    VERIFY(str == LITERAL(\"123456789\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// template <typename OtherCharType>\n\t// this_type& append_convert(const OtherCharType* p, size_type n);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str;\n\t\t\tstr.append_convert(EA_CHAR8(\"123456789\"), 5);\n\t\t\tVERIFY(str == LITERAL(\"12345\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str;\n\t\t\tstr.append_convert(EA_CHAR16(\"123456789\"), 5);\n\t\t\tVERIFY(str == LITERAL(\"12345\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str;\n\t\t\tstr.append_convert(EA_CHAR32(\"123456789\"), 5);\n\t\t\tVERIFY(str == LITERAL(\"12345\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str;\n\t\t    str.append_convert(EA_WCHAR(\"123456789\"), 5);\n\t\t    VERIFY(str == LITERAL(\"12345\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// template <typename OtherStringType>\n\t// this_type& append_convert(const OtherStringType& x);\n\t{\n\t\t{\n\t\t#if defined(EA_CHAR8)\n\t\t\tStringType str; \n\t\t\tstr.append_convert(eastl::u8string(EA_CHAR8(\"123456789\")));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR16)\n\t\t\tStringType str; \n\t\t\tstr.append_convert(eastl::string16(EA_CHAR16(\"123456789\")));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_CHAR32)\n\t\t\tStringType str;\n\t\t\tstr.append_convert(eastl::string32(EA_CHAR32(\"123456789\")));\n\t\t\tVERIFY(str == LITERAL(\"123456789\"));\n\t\t\tVERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t\t{\n\t\t#if defined(EA_WCHAR)\n\t\t    StringType str;\n\t\t    str.append_convert(eastl::wstring(EA_WCHAR(\"123456789\")));\n\t\t    VERIFY(str == LITERAL(\"123456789\"));\n\t\t    VERIFY(str.validate());\n\t\t#endif\n\t\t}\n\t}\n\n\t// void push_back(value_type c);\n\t{\n\t\tStringType str;\n\t\tconst StringType src(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\teastl::for_each(eastl::begin(src), eastl::end(src), [&str](const typename StringType::value_type& c)\n\t\t                { str.push_back(c); });\n\n\t\tVERIFY(str == src);\n\t\tVERIFY(str.validate());\n\t}\n\n\t// void pop_back();\n\t{\n\t\tStringType str(LITERAL(\"123456789\"));\n\t\tVERIFY(str == LITERAL(\"123456789\"));\n\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"12345678\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"1234567\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"123456\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"12345\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"1234\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"123\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"12\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"1\"));\n\t\tstr.pop_back(); VERIFY(str == LITERAL(\"\"));\n\n\t\tVERIFY(str.validate());\n\t}\n\n\t// this_type& insert(size_type position, const this_type& x);\n\t// this_type& insert(size_type position, const this_type& x, size_type beg, size_type n);\n\t// this_type& insert(size_type position, const value_type* p, size_type n);\n\t// this_type& insert(size_type position, const value_type* p);\n\t// this_type& insert(size_type position, size_type n, value_type c);\n\t// iterator insert(const_iterator p, value_type c);\n\t// iterator insert(const_iterator p, size_type n, value_type c);\n\t// iterator insert(const_iterator p, const value_type* pBegin, const value_type* pEnd);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tstr.insert((typename StringType::size_type)0, (typename StringType::size_type)1, LITERAL('1'));   // todo: elminiate the cast to disambiguate\n\t\tVERIFY(str == LITERAL(\"1abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tstr.insert(2, LITERAL(\"234\"));\n\t\tVERIFY(str == LITERAL(\"1a234bcdefghijklmnopqrstuvwxyz\"));\n\n\t\tstr.insert(15, StringType(LITERAL(\"567\")));\n\t\tVERIFY(str == LITERAL(\"1a234bcdefghijk567lmnopqrstuvwxyz\"));\n\n\t\tstr.insert(30, StringType(LITERAL(\" is an example of a substring\")), 1, 14);\n\t\tVERIFY(str == LITERAL(\"1a234bcdefghijk567lmnopqrstuvwis an example xyz\"));\n\n\t\t{\n\t\t\tStringType strSSO;\n\t\t\tauto nSSOCap = strSSO.capacity();\n\t\t\tStringType strCheck;\n\t\t\tstrCheck.append(nSSOCap, LITERAL('a'));\n\n\t\t\tstrSSO.append(nSSOCap - 1, LITERAL('a'));\n\n\t\t\tstrSSO.insert(strSSO.size() - 1, LITERAL(\"a\"));\n\t\t\tVERIFY(strSSO.validate());\n\t\t\tVERIFY(strSSO == strCheck);\n\t\t}\n\n\t\t{\n\t\t\tStringType strSSO;\n\t\t\tauto nSSOCap = strSSO.capacity();\n\n\t\t\t// 32 bit platform with char32_t can only hold 2 characters in SSO\n\t\t\tif (nSSOCap - 2 > 0)\n\t\t\t{\n\t\t\t\tStringType strCheck;\n\t\t\t\tstrCheck.append(nSSOCap, LITERAL('a'));\n\n\t\t\t\tstrSSO.append(nSSOCap - 2, LITERAL('a'));\n\n\t\t\t\tstrSSO.insert(strSSO.size() - 1, LITERAL(\"aa\"));\n\t\t\t\tVERIFY(strSSO.validate());\n\t\t\t\tVERIFY(strSSO == strCheck);\n\t\t\t}\n\t\t}\n\t}\n\n\t// iterator insert(const_iterator p, std::initializer_list<value_type>);\n\t{\n\t#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\tStringType str;\n\t\tstr.insert(str.begin(),     {'a','b','c'});\n\t\tstr.insert(str.end(),       {'d','e','f'});\n\t\tstr.insert(str.begin() + 3, {'1','2','3'});\n\n\t\tVERIFY(str == LITERAL(\"abc123def\"));\n\t\tVERIFY(str.validate());\n\t#endif\n\t}\n\n\t// insert(const_iterator p, value_type c)\n\t{\n\t\tStringType str = LITERAL(\"aaa\");\n\t\tauto it = str.insert(str.end(), 'b');\n\t\tVERIFY(*it == LITERAL('b'));\n\t\tVERIFY(str == LITERAL(\"aaab\"));\n\t\tit = str.insert(str.begin(), 'c');\n\t\tVERIFY(*it == LITERAL('c'));\n\t\tVERIFY(str == LITERAL(\"caaab\"));\n\t\tit = str.insert(str.begin() + 2, 'd');\n\t\tVERIFY(*it == LITERAL('d'));\n\t\tVERIFY(str == LITERAL(\"cadaab\"));\n\t}\n\n\t// this_type&       erase(size_type position = 0, size_type n = npos);\n\t// iterator         erase(const_iterator p);\n\t// iterator         erase(const_iterator pBegin, const_iterator pEnd);\n\t// reverse_iterator erase(reverse_iterator position);\n\t// reverse_iterator erase(reverse_iterator first, reverse_iterator last);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tstr.erase(0,5);\n\t\tVERIFY(str == LITERAL(\"fghijklmnopqrstuvwxyz\"));\n\n\t\tstr.erase(5,10);\n\t\tVERIFY(str == LITERAL(\"fghijuvwxyz\"));\n\n\t\tstr.erase(str.find(LITERAL('v')));\n\t\tVERIFY(str == LITERAL(\"fghiju\"));\n\n\t\tstr.erase(str.find(LITERAL('g')), str.find(LITERAL('i')));\n\t\tVERIFY(str == LITERAL(\"fju\"));\n\n\t\ttypename StringType::const_iterator it = str.begin() + 1; // 'j'\n\t\tstr.erase(it);\n\t\tVERIFY(str == LITERAL(\"fu\"));\n\n\t}\n\n\t// void clear() EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"123456789\"));\n\t\tVERIFY(str == LITERAL(\"123456789\"));\n\n\t\tstr.clear();\n\t\tVERIFY(str == LITERAL(\"\"));\n\t\tVERIFY(str.empty());\n\t\tVERIFY(str.validate());\n\t}\n\n\n\t// pointer detach() EA_NOEXCEPT;\n\t{\n\t\t{\n\t\t\t// Heap\n\t\t\tauto* pLiteral = LITERAL(\"abcdefghijklmnopqrstuvwxyz\");\n\t\t\tStringType str(pLiteral);\n\t\t\tconst auto sz = str.size() + 1;  // +1 for null-terminator\n\n\t\t\tauto* pDetach = str.detach();\n\n\t\t\tVERIFY(pDetach != nullptr);\n\t\t\tVERIFY(EA::StdC::Strcmp(pDetach, pLiteral) == 0);\n\t\t\tVERIFY(pDetach != pLiteral);\n\t\t\tVERIFY(str.empty());\n\t\t\tVERIFY(str.size() == 0);\n\n\t\t\tstr.get_allocator().deallocate(pDetach, sz);\n\t\t}\n\n\t\t{\n\t\t\t// SSO\n\t\t\tauto* pLiteral = LITERAL(\"a\");\n\t\t\tStringType str(pLiteral);\n\t\t\tconst auto sz = str.size() + 1;  // +1 for null-terminator\n\n\t\t\tauto* pDetach = str.detach();\n\n\t\t\tVERIFY(pDetach != nullptr);\n\t\t\tVERIFY(EA::StdC::Strcmp(pDetach, pLiteral) == 0);\n\t\t\tVERIFY(pDetach != pLiteral);\n\t\t\tVERIFY(str.empty());\n\t\t\tVERIFY(str.size() == 0);\n\n\t\t\tstr.get_allocator().deallocate(pDetach, sz);\n\t\t}\n\n\t\t{\n\t\t\t// SSO, empty string\n\t\t\tauto* pLiteral = LITERAL(\"\");\n\t\t\tStringType str(pLiteral);\n\t\t\tconst auto sz = str.size() + 1;  // +1 for null-terminator\n\n\t\t\tauto* pDetach = str.detach();\n\n\t\t\tVERIFY(pDetach != nullptr);\n\t\t\tVERIFY(EA::StdC::Strcmp(pDetach, pLiteral) == 0);\n\t\t\tVERIFY(pDetach != pLiteral);\n\t\t\tVERIFY(str.empty());\n\t\t\tVERIFY(str.size() == 0);\n\n\t\t\tstr.get_allocator().deallocate(pDetach, sz);\n\t\t}\n\n\t\t{\n\t\t\t// SSO, empty string via default ctor\n\t\t\tStringType str;\n\t\t\tconst auto sz = str.size() + 1;  // +1 for null-terminator\n\n\t\t\tauto* pDetach = str.detach();\n\n\t\t\tVERIFY(pDetach != nullptr);\n\t\t\tVERIFY(pDetach[0] == 0);\n\t\t\tVERIFY(str.empty());\n\t\t\tVERIFY(str.size() == 0);\n\n\t\t\tstr.get_allocator().deallocate(pDetach, sz);\n\t\t}\n\t}\n\n\t// this_type&  replace(size_type position, size_type n, const this_type& x);\n\t// this_type&  replace(size_type pos1, size_type n1, const this_type& x, size_type pos2, size_type n2);\n\t// this_type&  replace(size_type position, size_type n1, const value_type* p, size_type n2);\n\t// this_type&  replace(size_type position, size_type n1, const value_type* p);\n\t// this_type&  replace(size_type position, size_type n1, size_type n2, value_type c);\n\t// this_type&  replace(const_iterator first, const_iterator last, const this_type& x);\n\t// this_type&  replace(const_iterator first, const_iterator last, const value_type* p, size_type n);\n\t// this_type&  replace(const_iterator first, const_iterator last, const value_type* p);\n\t// this_type&  replace(const_iterator first, const_iterator last, size_type n, value_type c);\n\t// this_type&  replace(const_iterator first, const_iterator last, const value_type* pBegin, const value_type* pEnd);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tstr.replace(5, 10, StringType(LITERAL(\"123\")));\n\t\tVERIFY(str == LITERAL(\"abcde123pqrstuvwxyz\"));\n\n\t\tstr.replace(13, 1, StringType(LITERAL(\"0123456789\")), 4, 6 );\n\t\tVERIFY(str == LITERAL(\"abcde123pqrst456789vwxyz\"));\n\n\t\tstr.replace(24, 1, LITERAL(\"0123456789\"));\n\t\tVERIFY(str == LITERAL(\"abcde123pqrst456789vwxyz0123456789\"));\n\n\t\tstr.replace(16, 4, 4, LITERAL('@'));\n\t\tVERIFY(str == LITERAL(\"abcde123pqrst456@@@@wxyz0123456789\"));\n\t}\n\n\t// size_type copy(value_type* p, size_type n, size_type position = 0) const;\n\t{\n\t\ttypename StringType::value_type buf[64];\n\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tstr.copy(buf, 10, 10);\n\n\t\tVERIFY(EA::StdC::Memcmp(buf, LITERAL(\"klmnopqrst\"), 10) == 0);\n\t}\n\n\t// size_type find(const this_type& x, size_type position = 0) const EA_NOEXCEPT;\n\t// size_type find(const value_type* p, size_type position = 0) const;\n\t// size_type find(const value_type* p, size_type position, size_type n) const;\n\t// size_type find(value_type c, size_type position = 0) const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str.find(StringType(LITERAL(\"d\")))    != StringType::npos);\n\t\tVERIFY(str.find(StringType(LITERAL(\"tuv\")))  != StringType::npos);\n\t\tVERIFY(str.find(StringType(LITERAL(\"123r\"))) == StringType::npos);\n\n\t\tVERIFY(str.find(LITERAL(\"d\"))    != StringType::npos);\n\t\tVERIFY(str.find(LITERAL(\"tuv\"))  != StringType::npos);\n\t\tVERIFY(str.find(LITERAL(\"123r\")) == StringType::npos);\n\n\t\tVERIFY(str.find(LITERAL(\"d\"), 0)    != StringType::npos);\n\t\tVERIFY(str.find(LITERAL(\"tuv\"), 2)  != StringType::npos);\n\t\tVERIFY(str.find(LITERAL(\"123r\"), 2) == StringType::npos);\n\n\t\tVERIFY(str.find(LITERAL('d'), 0) != StringType::npos);\n\t\tVERIFY(str.find(LITERAL('t'), 2) != StringType::npos);\n\t\tVERIFY(str.find(LITERAL('1'), 2) == StringType::npos);\n\t}\n\n\t// size_type rfind(const this_type& x, size_type position = npos) const EA_NOEXCEPT;\n\t// size_type rfind(const value_type* p, size_type position = npos) const;\n\t// size_type rfind(const value_type* p, size_type position, size_type n) const;\n\t// size_type rfind(value_type c, size_type position = npos) const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"d\")))    != StringType::npos);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"tuv\")))  != StringType::npos);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"123r\"))) == StringType::npos);\n\n\t\tVERIFY(str.rfind(LITERAL(\"d\"))    != StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL(\"tuv\"))  != StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL(\"123r\")) == StringType::npos);\n\n\t\tVERIFY(str.rfind(LITERAL(\"d\"), 20)    != StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL(\"tuv\"), 20)  != StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL(\"123r\"), 20) == StringType::npos);\n\n\t\tVERIFY(str.rfind(LITERAL('d'), 20) != StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL('t'), 20) != StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL('1'), 20) == StringType::npos);\n\t}\n\n\t{\n\t\tStringType str(LITERAL(\"abcdabcdabcdabcd\"));\n\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"d\")))     == (str.size() - 1));\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"abc\")))   == (str.size() - 4));\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"dab\")))   == (str.size() - 5));\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"e\")))     == StringType::npos);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"abcde\"))) == StringType::npos);\n\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"d\")), 8)     == 7);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"abc\")), 8)   == 8);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"abc\")), 7)   == 4);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"dab\")), 8)   == 7);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"dab\")), 7)   == 7);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"e\")), 8)     == StringType::npos);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"abcde\")), 8) == StringType::npos);\n\n\t\tVERIFY(str.rfind(LITERAL(\"d\"))     == (str.size() - 1));\n\t\tVERIFY(str.rfind(LITERAL(\"abcd\"))  == (str.size() - 4));\n\t\tVERIFY(str.rfind(LITERAL(\"abc\"))   == (str.size() - 4));\n\t\tVERIFY(str.rfind(LITERAL(\"e\"))     == StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL(\"abcde\")) == StringType::npos);\n\n\t\tVERIFY(str.rfind(LITERAL(\"d\"), 8)     == 7);\n\t\tVERIFY(str.rfind(LITERAL(\"abc\"), 8)   == 8);\n\t\tVERIFY(str.rfind(LITERAL(\"abc\"), 7)   == 4);\n\t\tVERIFY(str.rfind(LITERAL(\"dab\"), 8)   == 7);\n\t\tVERIFY(str.rfind(LITERAL(\"dab\"), 7)   == 7);\n\t\tVERIFY(str.rfind(LITERAL(\"e\"), 8)     == StringType::npos);\n\t\tVERIFY(str.rfind(LITERAL(\"abcde\"), 8) == StringType::npos);\n\t}\n\n\t{\n\t\tStringType str(LITERAL(\"abcdeaababcdabcdx\"));\n\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"abcde\")))    == 0);\n\t\tVERIFY(str.rfind(StringType(LITERAL(\"abcde\")), 8) == 0);\n\n\t\tVERIFY(str.rfind(LITERAL(\"abcde\"))    == 0);\n\t\tVERIFY(str.rfind(LITERAL(\"abcde\"), 8) == 0);\n\t}\n\n\n\t// size_type find_first_of(const this_type& x, size_type position = 0) const EA_NOEXCEPT;\n\t// size_type find_first_of(const value_type* p, size_type position = 0) const;\n\t// size_type find_first_of(const value_type* p, size_type position, size_type n) const;\n\t// size_type find_first_of(value_type c, size_type position = 0) const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\tVERIFY(str.find_first_of(StringType(LITERAL(\"aaa\"))) == 0);\n\t\tVERIFY(str.find_first_of(LITERAL(\"aab\")) == 0);\n\t\tVERIFY(str.find_first_of(LITERAL(\"baab\")) == 0);\n\t\tVERIFY(str.find_first_of(LITERAL(\"ceg\")) == 10);\n\t\tVERIFY(str.find_first_of(LITERAL(\"eeef\"), 1, 2) == 18);\n\t\tVERIFY(str.find_first_of(LITERAL(\"eeef\"), 1, 4) == 18);\n\t\tVERIFY(str.find_first_of(LITERAL('g')) == 26);\n\t\tVERIFY(str.find_first_of(LITERAL('$')) == StringType::npos);\n\t}\n\n\t// size_type find_last_of(const this_type& x, size_type position = npos) const EA_NOEXCEPT;\n\t// size_type find_last_of(const value_type* p, size_type position = npos) const;\n\t// size_type find_last_of(const value_type* p, size_type position, size_type n) const;\n\t// size_type find_last_of(value_type c, size_type position = npos) const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\tVERIFY(str.find_last_of(StringType(LITERAL(\"aaa\"))) == 4);\n\t\tVERIFY(str.find_last_of(LITERAL(\"aab\")) == 9);\n\t\tVERIFY(str.find_last_of(LITERAL(\"baab\")) == 9);\n\t\tVERIFY(str.find_last_of(LITERAL(\"ceg\")) == 27);\n\t\t// VERIFY(str.find_last_of(LITERAL(\"eeef\"), 1, 2) == StringType::npos);  // todo: FIX ME\n\t\t// VERIFY(str.find_last_of(LITERAL(\"eeef\"), 1, 4) == StringType::npos);  // todo: FIX ME\n\t\tVERIFY(str.find_last_of(LITERAL('g')) == 27);\n\t\tVERIFY(str.find_last_of(LITERAL('$')) == StringType::npos);\n\t}\n\n\t// size_type find_first_not_of(const this_type& x, size_type position = 0) const EA_NOEXCEPT;\n\t// size_type find_first_not_of(const value_type* p, size_type position = 0) const;\n\t// size_type find_first_not_of(const value_type* p, size_type position, size_type n) const;\n\t// size_type find_first_not_of(value_type c, size_type position = 0) const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\tVERIFY(str.find_first_not_of(StringType(LITERAL(\"abcdfg\"))) == 18);\n\t\tVERIFY(str.find_first_not_of(LITERAL(\"abcdfg\")) == 18);\n\t\t// VERIFY(str.find_first_not_of(LITERAL(\"abcdfg\"), 2, 2) == 0);   // todo:  FIX ME\n\t\t// VERIFY(str.find_first_not_of(LITERAL(\"abcdfg\"), 0, 2) == 10);  // todo:  FIX ME\n\t\tVERIFY(str.find_first_not_of(LITERAL('a')) == 5);\n\t}\n\n\t// size_type find_last_not_of(const this_type& x,  size_type position = npos) const EA_NOEXCEPT;\n\t// size_type find_last_not_of(const value_type* p, size_type position = npos) const;\n\t// size_type find_last_not_of(const value_type* p, size_type position, size_type n) const;\n\t// size_type find_last_not_of(value_type c, size_type position = npos) const EA_NOEXCEPT;\n\t{\n\t\tStringType str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\tVERIFY(str.find_last_not_of(StringType(LITERAL(\"a\"))) == 28);\n\t\tVERIFY(str.find_last_not_of(StringType(LITERAL(\"abcdfg\"))) == 28);\n\t\tVERIFY(str.find_last_not_of(StringType(LITERAL(\"abcdfgh\"))) == 22);\n\t\tVERIFY(str.find_last_not_of(LITERAL(\"abcdfgh\")) == 22);\n\t\t// VERIFY(str.find_last_not_of(LITERAL(\"abcdfg\"), 2, 2) == 0);   // todo:  FIX ME\n\t\t// VERIFY(str.find_last_not_of(LITERAL(\"abcdfg\"), 0, 2) == 10);  // todo:  FIX ME\n\t\tVERIFY(str.find_last_not_of(LITERAL('a')) == 28);\n\t}\n\n\t// this_type substr(size_type position = 0, size_type n = npos) const;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto substring = str.substr(0, 6);\n\t\tVERIFY(substring == LITERAL(\"abcdef\"));\n\n\t\tsubstring = str.substr(0, 0);\n\t\tVERIFY(substring == LITERAL(\"\"));\n\n\t\tsubstring = str.substr(16, 0);\n\t\tVERIFY(substring == LITERAL(\"\"));\n\n\t\tsubstring = str.substr(16, 42);\n\t\tVERIFY(substring == LITERAL(\"qrstuvwxyz\"));\n\t}\n\n\t// int        compare(const this_type& x) const EA_NOEXCEPT;\n\t// int        compare(size_type pos1, size_type n1, const this_type& x) const;\n\t// int        compare(size_type pos1, size_type n1, const this_type& x, size_type pos2, size_type n2) const;\n\t// int        compare(const value_type* p) const;\n\t// int        compare(size_type pos1, size_type n1, const value_type* p) const;\n\t// int        compare(size_type pos1, size_type n1, const value_type* p, size_type n2) const;\n\t// static int compare(const value_type* pBegin1, const value_type* pEnd1, const value_type* pBegin2, const value_type* pEnd2);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str.compare(StringType(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"))) == 0);\n\t\tVERIFY(str.compare(StringType(LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))) != 0);\n\t\tVERIFY(str.compare(StringType(LITERAL(\"abcdefghijklmnopqrstuvwxyz123\"))) != 0);\n\t\tVERIFY(str.compare(LITERAL(\"abcdefghijklmnopqrstuvwxyz\")) == 0);\n\t\tVERIFY(str.compare(LITERAL(\"abcdefghijklmnopqrstuvwxyz123\")) != 0);\n\t\tVERIFY(str.compare(LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ123\")) != 0);\n\t}\n\n\t// int        comparei(const this_type& x) const EA_NOEXCEPT;\n\t// int        comparei(const value_type* p) const;\n\t// static int comparei(const value_type* pBegin1, const value_type* pEnd1, const value_type* pBegin2, const value_type* pEnd2);\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tVERIFY(str.comparei(StringType(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"))) == 0);\n\t\tVERIFY(str.comparei(StringType(LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))) == 0);\n\t\tVERIFY(str.comparei(StringType(LITERAL(\"abcdefghijklmnopqrstuvwxyz123\"))) != 0);\n\t\tVERIFY(str.comparei(LITERAL(\"abcdefghijklmnopqrstuvwxyz\")) == 0);\n\t\tVERIFY(str.comparei(LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\")) == 0);\n\t\tVERIFY(str.comparei(LITERAL(\"abcdefghijklmnopqrstuvwxyz123\")) != 0);\n\t}\n\n\t// void make_lower();\n\t{\n\t\t{\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.make_lower();\n\t\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t}\n\t\t{\n\t\t\tStringType str(LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"));\n\t\t\tstr.make_lower();\n\t\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t}\n\t\t{\n\t\t\tStringType str(LITERAL(\"123456789~!@#$%^&*()_+\"));\n\t\t\tstr.make_lower();\n\t\t\tVERIFY(str == LITERAL(\"123456789~!@#$%^&*()_+\"));\n\t\t}\n\t}\n\n\t// void make_upper();\n\t{\n\t\t{\n\t\t\tStringType str(LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"));\n\t\t\tstr.make_upper();\n\t\t\tVERIFY(str == LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"));\n\t\t}\n\t\t{\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tstr.make_upper();\n\t\t\tVERIFY(str == LITERAL(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"));\n\t\t}\n\t\t{\n\t\t\tStringType str(LITERAL(\"123456789~!@#$%^&*()_+\"));\n\t\t\tstr.make_upper();\n\t\t\tVERIFY(str == LITERAL(\"123456789~!@#$%^&*()_+\"));\n\t\t}\n\t}\n\n\t// void ltrim();\n\t// void rtrim();\n\t// void trim();\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t{\n\t\t\tStringType rstr(LITERAL(\"abcdefghijklmnopqrstuvwxyz\t\t\t\\t\t\t\\t\\t\\t\t\t\"));\n\t\t\trstr.ltrim();\n\t\t\tVERIFY(str != rstr);\n\t\t}\n\t\t{\n\t\t\tStringType lstr(LITERAL(\"\t\\t\t\t\t\t\t\tabcdefghijklmnopqrstuvwxyz\"));\n\t\t\tlstr.ltrim();\n\t\t\tVERIFY(str == lstr);\n\t\t}\n\t\t{\n\t\t\tStringType rstr(LITERAL(\"abcdefghijklmnopqrstuvwxyz\t\t\\t\\t\\t\t\t\t\t\t\"));\n\t\t\trstr.rtrim();\n\t\t\tVERIFY(str == rstr);\n\t\t}\n\t\t{\n\t\t\tStringType lstr(LITERAL(\"\t\\t\t\t\t\t\t\tabcdefghijklmnopqrstuvwxyz\"));\n\t\t\tlstr.rtrim();\n\t\t\tVERIFY(str != lstr);\n\t\t}\n\t\t{\n\t\t\tStringType lrstr(LITERAL(\"   \\t                abcdefghijklmnopqrstuvwxyz\t\t\\t\t\t\t\t\t\"));\n\t\t\tlrstr.trim();\n\t\t\tVERIFY(str == lrstr);\n\t\t}\n\t\t{\n\t\t\tauto* pLiteral = LITERAL(\"abcdefghijklmn          opqrstuvwxyz\");\n\t\t\tStringType mstr(pLiteral);\n\t\t\tmstr.trim();\n\t\t\tVERIFY(mstr == pLiteral);\n\t\t}\n\t}\n\n\t// void ltrim(\"a\");\n\t// void rtrim(\"b\");\n\t// void trim(\"?\");\n\t{\n\t\tStringType expected(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\t{\n\t\t\tconst auto source = LITERAL(\"abcdefghijklmnopqrstuvwxyz                                         \");\n\n\t\t\tStringType rstr(source);\n\t\t\trstr.ltrim(LITERAL(\" \"));\n\t\t\tVERIFY(rstr == source);  \n\n\t\t\trstr.rtrim(LITERAL(\" \"));\n\t\t\tVERIFY(expected == rstr);\n\t\t}\n\n\t\t{\n\t\t\tconst auto source = LITERAL(\"abcdefghijklmnopqrstuvwxyz\t\t\t\\t\t\t\\t\\t\\t\t\t\");\n\n\t\t\tStringType rstr(source);\n\t\t\trstr.ltrim(LITERAL(\" \\t\"));\n\t\t\tVERIFY(rstr == source);\n\n\t\t\trstr.rtrim(LITERAL(\" \\t\"));\n\t\t\tVERIFY(expected == rstr);\n\t\t}\n\n\t\t{\n\t\t\tconst auto source = LITERAL(\" \\t\t\t\\t\\t\\t\t\tabcdefghijklmnopqrstuvwxyz\");\n\n\t\t\tStringType rstr(source);\n\t\t\trstr.rtrim(LITERAL(\" \\t\"));\n\t\t\tVERIFY(rstr == source);\n\n\t\t\trstr.ltrim(LITERAL(\" \\t\"));\n\t\t\tVERIFY(expected == rstr);\n\t\t}\n\n\t\t{\n\t\t\tconst auto source = LITERAL(\"$$$%$$$$$$%$$$$$$$$$%$$$$$$$$abcdefghijklmnopqrstuvwxyz*********@*****************@******\");\n\t\t\tStringType rstr(source);\n\t\t\trstr.trim(LITERAL(\"^(\"));\n\t\t\tVERIFY(rstr == source);\n\t\t}\n\n\t\t{\n\t\t\tconst auto source = LITERAL(\"$$$%$$$$$$%$$$$$$$$$%$$$$$$$$abcdefghijklmnopqrstuvwxyz*********@*****************@******\");\n\t\t\tStringType rstr(source);\n\t\t\trstr.rtrim(LITERAL(\"@*\"));\n\n\t\t\tVERIFY(expected != rstr);\n\t\t\tVERIFY(rstr == LITERAL(\"$$$%$$$$$$%$$$$$$$$$%$$$$$$$$abcdefghijklmnopqrstuvwxyz\"));\n\n\t\t\trstr.ltrim(LITERAL(\"$%\"));\n\t\t\tVERIFY(expected == rstr);\n\t\t}\n\n\t\t{\n\t\t\tconst auto source = LITERAL(\"abcdefghijklmnopqrstuvwxyz**********************************\");\n\t\t\tStringType rstr(source);\n\t\t\trstr.ltrim(LITERAL(\"*\"));\n\t\t\tVERIFY(expected != source);\n\t\t}\n\n\t\t{\n\t\t\tconst auto source = LITERAL(\"           ?      abcdefghijklmnopqrstuvwxyz**********************************\");\n\t\t\tStringType rstr(source);\n\t\t\trstr.trim(LITERAL(\"*? \"));\n\t\t\tVERIFY(expected != source);\n\t\t}\n\t}\n\n\t// this_type left(size_type n) const;\n\t// this_type right(size_type n) const;\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\tauto lstr = str.left(6);\n\t\tVERIFY(lstr == LITERAL(\"abcdef\"));\n\n\t\tauto rstr = str.right(8);\n\t\tVERIFY(rstr == LITERAL(\"stuvwxyz\"));\n\t}\n\n\t// this_type& sprintf_va_list(const value_type* pFormat, va_list arguments);\n\t// this_type& sprintf(const value_type* pFormat, ...);\n\t{\n\t#if EASTL_SNPRINTF_TESTS_ENABLED\n\t\tStringType str(LITERAL(\"\"));\n\n\t\tstr.sprintf(LITERAL(\"Hello, %d\"), 42);\n\t\tVERIFY(str == LITERAL(\"Hello, 42\"));\n\t#endif\n\t}\n\n\t// void force_size(size_type n);\n\t{\n\t\tStringType str(LITERAL(\"\"));\n\t\tstr.reserve(10);\n\n\t\tauto p = const_cast<typename StringType::value_type*>(str.data());\n\t\tp[0] = 'a';\n\t\tp[1] = 'a';\n\t\tp[2] = 'a';\n\t\tp[3] = '\\0';\n\n\t\tstr.force_size(3);\n\n\t\tVERIFY(str.size() == 3);\n\t\tVERIFY(str.validate());\n\t\tVERIFY(!str.empty());\n\t}\n\n\t// test basic_string implicit conversion to basic_string_view\n\t// \t\teastl::string implicitly converts to eastl::string_view.\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t[&](basic_string_view<typename StringType::value_type> sv)  // simulate api that requires eastl::string_view.\n\t\t{\n\t\t\tVERIFY(sv.compare(LITERAL(\"abcdefghijklmnopqrstuvwxyz\")) == 0);\n\t\t}(str);\n\t}\n\n\t// test constructing a eastl::basic_string from an eastl::basic_string_view\n\t{\n\t\tusing StringViewType = basic_string_view<typename StringType::value_type>;\n\t\tStringViewType sv = LITERAL(\"abcdefghijklmnopqrstuvwxyz\");\n\n\t\t{\n\t\t\tStringType str(sv);\n\t\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t}\n\n\t\t{\n\t\t\tStringType str(sv, typename StringType::allocator_type(\"test\"));\n\t\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t}\n\n\t\t{\n\t\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t\tVERIFY(sv == str);\n\t\t}\n    }\n\n\t// test assigning from an eastl::basic_string_view\n\t{\n\t\tusing StringViewType = basic_string_view<typename StringType::value_type>;\n\t\tStringViewType sv = LITERAL(\"abcdefghijklmnopqrstuvwxyz\");\n\n\t\t{\n\t\t\tStringType str;\n\t\t\tstr = sv;  // force call to 'operator='\n\t\t\tVERIFY(str == LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\t}\n\t}\n\n\t// test eastl::erase\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tauto numErased = eastl::erase(str, LITERAL('a'));\n\t    VERIFY(numErased == 1);\n\t\tnumErased = eastl::erase(str, LITERAL('f'));\n\t    VERIFY(numErased == 1);\n\t\tnumErased = eastl::erase(str, LITERAL('l'));\n\t    VERIFY(numErased == 1);\n\t\tnumErased = eastl::erase(str, LITERAL('w'));\n\t    VERIFY(numErased == 1);\n\t\tnumErased = eastl::erase(str, LITERAL('y'));\n\t    VERIFY(numErased == 1);\n\t\tVERIFY(str == LITERAL(\"bcdeghijkmnopqrstuvxz\"));\n\t}\n\n\t// test eastl::erase_if\n\t{\n\t\tStringType str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\t\tauto numErased = eastl::erase_if(str, [](auto c) { return c == LITERAL('a') || c == LITERAL('v'); });\n\t\tVERIFY(str == LITERAL(\"bcdefghijklmnopqrstuwxyz\"));\n\t    VERIFY(numErased == 2);\n\t}\n\n\t// template<> struct hash<eastl::string>;\n\t// template<> struct hash<eastl::wstring>;\n\t// template<> struct hash<eastl::u16string>;\n\t// template<> struct hash<eastl::u32string>;\n\t{\n\t\t// NOTE(rparolin): This is required because the string tests inject custom allocators to assist in debugging.\n\t\t// These custom string types require their own hashing specializations which we emulate by constructing a custom\n\t\t// hashing functor that defers to the eastl::basic_string<CharT> hash implementation; effectively ignoring the\n\t\t// custom allocator.\n\t    auto LocalHash = [](auto s) -> size_t {\n\t\t    using UserStringType = decltype(s);\n\t\t    using TargetType = eastl::basic_string<typename UserStringType::value_type>;\n\n\t\t    TargetType t(s.data());\n\t\t    return eastl::hash<TargetType>{}(t);\n\t    };\n\n\t    StringType sw1(LITERAL(\"Hello, World\"));\n\t\tStringType sw2(LITERAL(\"Hello, World\"), 5);\n\t\tStringType sw3(LITERAL(\"Hello\"));\n\n\t\tVERIFY(LocalHash(sw1) != LocalHash(sw2));\n\t\tVERIFY(LocalHash(sw2) == LocalHash(sw3));\n\t}\n\n\t// test <=> operator\n\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{\n\t\tStringType sw1(LITERAL(\"Test String \"));\n\t\tStringType sw2(LITERAL(\"Test String 1\"));\n\t\tStringType sw3(LITERAL(\"Test String 2\"));\n\t\tStringType sw4(LITERAL(\"abcdef\"));\n\n\t\tVERIFY((sw1 <=> sw2) != 0);\n\t\tVERIFY((sw1 <=> sw3) != 0);\n\t\tVERIFY((sw2 <=> sw3) != 0);\n\t\tVERIFY((sw1 <=> sw2) < 0);\n\t\tVERIFY((sw1 <=> sw3) < 0);\n\t\tVERIFY((sw2 <=> sw2) == 0);\n\t\tVERIFY((sw2 <=> sw3) < 0);\n\t\tVERIFY((sw2 <=> sw4) < 0);\n\t\tVERIFY((sw4 <=> sw2) > 0);\n\t\tVERIFY((sw4 <=> sw3) > 0);\n\t\tVERIFY((sw3 <=> sw2) > 0);\n\t}\n\t#endif\n\n\treturn nErrorCount;\n}\n\n// Required to prevent manual undef of macros when 'TestString.inl' preprocessed at the top of the unit test cpp file.\n#undef TEST_STRING_NAME\n#undef LITERAL\n\n"
  },
  {
    "path": "test/source/TestStringHashMap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/string_hash_map.h>\n#include <EAStdC/EAString.h>\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::string_hash_map<int>;\n\n// To silence the following GCC note (not a warning, but noisy in the compile output):\n// \"the ABI for passing parameters with 32-byte alignment has changed in GCC 4.6\"\nEA_DISABLE_GCC_WARNING(-Wpsabi);\ntemplate class eastl::string_hash_map<Align32>;\nEA_RESTORE_GCC_WARNING();\n\nstatic const char* strings[] = { \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\"};\nstatic const size_t kStringCount = 10; // This is intentionally half the length of strings, so that we can test with strings that are not inserted to the map. \n\n\nint TestStringHashMap()\n{   \n\tint nErrorCount = 0;\n\n\t{  // Test declarations\n\t\tstring_hash_map<int>\tstringHashMap;\n\t\t\n\t\tstring_hash_map<int> stringHashMap2(stringHashMap);\n\t\tEATEST_VERIFY(stringHashMap2.size() == stringHashMap.size());\n\t\tEATEST_VERIFY(stringHashMap2 == stringHashMap);\n\n\n\t\t// allocator_type& get_allocator();\n\t\t// void            set_allocator(const allocator_type& allocator);\n\t\tstring_hash_map<int>::allocator_type& allocator = stringHashMap.get_allocator();\n\t\tstringHashMap.set_allocator(EASTLAllocatorType());\n\t\tstringHashMap.set_allocator(allocator);\n\t\t// To do: Try to find something better to test here.\n\n\n\t\t// const key_equal& key_eq() const;\n\t\t// key_equal&       key_eq();\n\t\tstring_hash_map<int>       hs;\n\t\tconst string_hash_map<int> hsc;\n\n\t\tconst string_hash_map<int>::key_equal& ke = hsc.key_eq();\n\t\ths.key_eq() = ke;\n\n\n\t\t// const char*     get_name() const;\n\t\t// void            set_name(const char* pName);\n\t\t#if EASTL_NAME_ENABLED\n\t\t\tstringHashMap.get_allocator().set_name(\"test\");\n\t\t\tconst char* pName = stringHashMap.get_allocator().get_name();\n\t\t\tEATEST_VERIFY(equal(pName, pName + 5, \"test\"));\n\t\t#endif\n\t}\n\n\n\t{\n\t\tstring_hash_map<int> stringHashMap;\n\n\t\t// Clear a newly constructed, already empty container.\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t\tstringHashMap.insert(strings[i], i);\n\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == kStringCount);\n\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t\tstringHashMap.insert(strings[i], i);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == kStringCount);\n\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\t}\n\n\t// emplace/try_emplace\n\t{\n\t\tstring_hash_map<TestObject> stringHashMap;\n\n\t\t// Clear a newly constructed, already empty container.\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\t{\n\t\t\t\t// This should construct the object from i.\n\t\t\t\tauto x = stringHashMap.emplace(strings[i], i);\n\t\t\t\t// insertion did happen.\n\t\t\t\tEATEST_VERIFY(x.second);\n\t\t\t\t// We got the correct value\n\t\t\t\tEATEST_VERIFY(x.first->second.mX == i);\n\t\t\t}\n\t\t\t{\n\t\t\t\t// This should not insert anything.\n\t\t\t\tauto x = stringHashMap.emplace(strings[i], i+1);\n\t\t\t\t// insertion did not happen.\n\t\t\t\tEATEST_VERIFY(!x.second);\n\t\t\t\t// We got the correct (existing) value\n\t\t\t\tEATEST_VERIFY(x.first->second.mX == i);\n\t\t\t}\n\t\t}\n\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == kStringCount);\n\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\t{\n\t\t\t\t// This should construct the object from i.\n\t\t\t\tauto x = stringHashMap.try_emplace(strings[i], i);\n\t\t\t\t// insertion did happen.\n\t\t\t\tEATEST_VERIFY(x.second);\n\t\t\t\t// We got the correct value\n\t\t\t\tEATEST_VERIFY(x.first->second.mX == i);\n\t\t\t}\n\t\t\t{\n\t\t\t\t// This should not insert anything.\n\t\t\t\tauto x = stringHashMap.try_emplace(strings[i], i+1);\n\t\t\t\t// insertion did not happen.\n\t\t\t\tEATEST_VERIFY(!x.second);\n\t\t\t\t// We got the correct (existing) value\n\t\t\t\tEATEST_VERIFY(x.first->second.mX == i);\n\t\t\t}\n\t\t}\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == kStringCount);\n\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\t}\n\n\t// emplace_hint/try_emplace(hint,...)\n\t{\n\t\tstring_hash_map<TestObject> stringHashMap;\n\n\t\t// Clear a newly constructed, already empty container.\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\n\t\tauto hint = stringHashMap.begin();\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\t// This should construct the object from i.\n\t\t\tauto ret = stringHashMap.emplace_hint(hint, strings[i], i);\n\t\t\tEATEST_VERIFY(ret->second.mX == i);\n\t\t\t// Try again, this should return the already existing value.\n\t\t\tauto ret2 = stringHashMap.emplace_hint(hint, strings[i], i+1);\n\t\t\t// Should get the same iterator.\n\t\t\tEATEST_VERIFY(ret2 == ret);\n\t\t\t// Should get old existing value.\n\t\t\tEATEST_VERIFY(ret2->second.mX == i);\n\t\t\thint = ret;\n\t\t}\n\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == kStringCount);\n\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\n\t\thint = stringHashMap.begin();\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\t// This should construct the object from i.\n\t\t\tauto ret = stringHashMap.try_emplace(hint, strings[i], i);\n\t\t\tEATEST_VERIFY(ret->second.mX == i);\n\t\t\t// Try again, this should return the already existing value.\n\t\t\tauto ret2 = stringHashMap.try_emplace(hint, strings[i], i+1);\n\t\t\t// Should get the same iterator.\n\t\t\tEATEST_VERIFY(ret2 == ret);\n\t\t\t// Should get old existing value.\n\t\t\tEATEST_VERIFY(ret2->second.mX == i);\n\t\t\thint = ret;\n\t\t}\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == kStringCount);\n\n\t\tstringHashMap.clear(true);\n\t\tEATEST_VERIFY(stringHashMap.validate());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.bucket_count() == 1);\n\t}\n\n\n\t{   // Test string_hash_map\n\n\t\t// size_type          size() const\n\t\t// bool               empty() const\n\t\t// insert_return_type insert(const value_type& value);\n\t\t// insert_return_type insert(const value_type& value, hash_code_t c, node_type* pNodeNew = NULL);\n\t\t// iterator           insert(const_iterator, const value_type& value);\n\t\t// iterator           find(const key_type& k);\n\t\t// const_iterator     find(const key_type& k) const;\n\t\t// size_type          count(const key_type& k) const;\n\n\t\ttypedef string_hash_map<int> StringHashMapInt;\n\n\t\tStringHashMapInt stringHashMap;\n\n\t\tEATEST_VERIFY(stringHashMap.empty());\n\t\tEATEST_VERIFY(stringHashMap.size() == 0);\n\t\tEATEST_VERIFY(stringHashMap.count(strings[0]) == 0);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t\tstringHashMap.insert(strings[i], i);\n\n\t\tEATEST_VERIFY(!stringHashMap.empty());\n\t\tEATEST_VERIFY(stringHashMap.size() == kStringCount);\n\t\tEATEST_VERIFY(stringHashMap.count(strings[0]) == 1);\n\n\t\tint j = 0;\n\t\tfor (StringHashMapInt::iterator it = stringHashMap.begin(); it != stringHashMap.end(); ++it, ++j)\n\t\t{\n\t\t\tint value = (*it).second;\n\t\t\tEATEST_VERIFY(value < (int)kStringCount);\n\t\t}\n\n\t\tfor(int i = 0; i < (int)kStringCount * 2; i++)\n\t\t{\n\t\t\tStringHashMapInt::iterator it = stringHashMap.find(strings[i]);\n\n\t\t\tif (i < (int)kStringCount)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(it != stringHashMap.end());\n\t\t\t\tconst char* k = it->first;\n\t\t\t\tint v = it->second;\n\t\t\t\tEATEST_VERIFY(EA::StdC::Strcmp(k, strings[i]) == 0);\n\t\t\t\tEATEST_VERIFY(v == i);\n\t\t\t}\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == stringHashMap.end());\n\t\t}\n\n\t\tStringHashMapInt::insert_return_type result = stringHashMap.insert(\"EASTLTEST\");\n\t\tEATEST_VERIFY(result.second == true);\n\t\tresult = stringHashMap.insert(\"EASTLTEST\");\n\t\tEATEST_VERIFY(result.second == false);\n\t\tresult.first->second = 0;\n\n\t\t// iterator erase(const_iterator);\n\t\tsize_t nExpectedSize = stringHashMap.size();\n\n\t\tStringHashMapInt::iterator itD = stringHashMap.find(\"d\");\n\t\tEATEST_VERIFY(itD != stringHashMap.end());\n\n\t\t// erase the element and verify that the size has decreased\n\t\tstringHashMap.erase(itD);\n\t\tnExpectedSize--;\n\t\tEATEST_VERIFY(stringHashMap.size() == nExpectedSize);\n\n\t\t// verify that erased element is gone\n\t\titD = stringHashMap.find(strings[3]);\n\t\tEATEST_VERIFY(itD == stringHashMap.end());\n\n\t\t// iterator erase(const char*)\n\t\tStringHashMapInt::size_type n = stringHashMap.erase(strings[4]);\n\t\tnExpectedSize--;\n\t\tEATEST_VERIFY(n == 1);\n\t\tEATEST_VERIFY(stringHashMap.size() == nExpectedSize);\n\t\t\n\n\t\t// mapped_type& operator[](const key_type& key)\n\t\tstringHashMap.clear();\n\n\t\tint x = stringHashMap[\"A\"]; // A default-constructed int (i.e. 0) should be returned.\n\t\tEATEST_VERIFY(x == 0);\n\n\t\tstringHashMap[\"B\"] = 1;\n\t\tx = stringHashMap[\"B\"];\n\t\tEATEST_VERIFY(x == 1);     // Verify that the value we assigned is returned and a default-constructed value is not returned.\n\n\t\tstringHashMap[\"A\"] = 10;    // Overwrite our previous 0 with 10.\n\t\tstringHashMap[\"B\"] = 11;\n\t\tx = stringHashMap[\"A\"];\n\t\tEATEST_VERIFY(x == 10);    // Verify the value is as expected.\n\t\tx = stringHashMap[\"B\"];\n\t\tEATEST_VERIFY(x == 11);\n\n\t}\n\n\t\n\t{\n\t\t// string_hash_map(const allocator_type& allocator);\n\t\t// string_hash_map& operator=(const this_type& x);\n\t\t// bool validate() const;\n\n\t\tstring_hash_map<int> stringHashMap1(EASTLAllocatorType(\"TestStringHashMap\"));\n\t\tstring_hash_map<int> stringHashMap2(stringHashMap1);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\tstringHashMap1.insert(strings[i], i);\n\t\t}\n\n\t\tstringHashMap2 = stringHashMap1;\n\t\tstring_hash_map<int> stringHashMap3(stringHashMap1);\n\n\t\tEATEST_VERIFY(stringHashMap1.validate());\n\t\tEATEST_VERIFY(stringHashMap2.validate());\n\t\tEATEST_VERIFY(stringHashMap3.validate());\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(stringHashMap1[strings[i]] == stringHashMap2[strings[i]]);\n\t\t\tEATEST_VERIFY(stringHashMap1[strings[i]] == stringHashMap3[strings[i]]);\n\t\t}\n\n\t}\n\n\t// pair<iterator, bool> insert_or_assign(const char* key, const T& value);\n\t{\n\t\t{\n\t\t\tstring_hash_map<int> m;\n\n\t\t\tm.insert_or_assign(\"hello\", 0);\n\t\t\tEATEST_VERIFY(m[\"hello\"] == 0);\n\n\t\t\tm.insert_or_assign(\"hello\", 42);\n\t\t\tEATEST_VERIFY(m[\"hello\"] == 42);\n\n\t\t\tm.insert_or_assign(\"hello\", 43);\n\t\t\tEATEST_VERIFY(m[\"hello\"] == 43);\n\n\t\t\tm.insert_or_assign(\"hello\", 1143);\n\t\t\tEATEST_VERIFY(m[\"hello\"] == 1143);\n\n\t\t\tEATEST_VERIFY(m.size() == 1);\n\t\t\tm.clear(); \n\t\t\tEATEST_VERIFY(m.size() == 0);\n\t\t}\n\n\t\t{\n\t\t\tstring_hash_map<int> m;\n\t\t\tm.insert_or_assign(\"hello\", 0);\n\t\t\tm.insert_or_assign(\"hello2\", 0);\n\n\t\t\tEATEST_VERIFY(m.size() == 2);\n\t\t\tm.clear(); \n\t\t\tEATEST_VERIFY(m.size() == 0);\n\t\t}\n\n\t\t{\n\t\t\tstring_hash_map<int> m;\n\t\t\tm.insert_or_assign(\"hello\", 0);\n\t\t\tm.insert_or_assign(\"hello2\", 0);\n\n\t\t\tEATEST_VERIFY(m.size() == 2);\n\t\t\tm.clear(true); \n\t\t\tEATEST_VERIFY(m.size() == 0);\n\t\t}\n\n\t\t{\n\t\t\tstring_hash_map<int> m;\n\t\t\tm.insert_or_assign(\"hello\", 0);\n\t\t\tm.insert_or_assign(\"hello2\", 0);\n\n\t\t\tEATEST_VERIFY(m.size() == 2);\n\t\t\tm.clear(false); \n\t\t\tEATEST_VERIFY(m.size() == 0);\n\t\t}\n\n\t\t{\n\t\t\tstring_hash_map<TestObject> m;\n\n\t\t\tm.insert_or_assign(\"hello\", TestObject(42));\n\t\t\tEATEST_VERIFY(m[\"hello\"].mX == 42);\n\n\t\t\tm.insert_or_assign(\"hello\", TestObject(43));\n\t\t\tEATEST_VERIFY(m[\"hello\"].mX == 43);\n\n\t\t\tEATEST_VERIFY(m.size() == 1);\n\t\t}\n\n\t\t{\n\t\t\ttypedef string_hash_map<TestObject, hash<const char*>, str_equal_to<const char*>, CountingAllocator> counting_string_hash_map;\n\t\t\tcounting_string_hash_map m;\n\t\t\tEATEST_VERIFY(CountingAllocator::getActiveAllocationCount() == 0);\n\n\t\t\tm.insert_or_assign(\"hello\", TestObject(42));\n\t\t\tEATEST_VERIFY(CountingAllocator::getActiveAllocationCount() == 3);\n\t\t\tEATEST_VERIFY(m[\"hello\"].mX == 42);\n\t\t\tEATEST_VERIFY(CountingAllocator::getActiveAllocationCount() == 3);\n\n\t\t\tm.insert_or_assign(\"hello\", TestObject(43));\n\t\t\tEATEST_VERIFY(CountingAllocator::getActiveAllocationCount() == 3);\n\t\t\tEATEST_VERIFY(m[\"hello\"].mX == 43);\n\t\t\tEATEST_VERIFY(CountingAllocator::getActiveAllocationCount() == 3);\n\n\t\t\tEATEST_VERIFY(m.size() == 1);\n\t\t}\n\t\tEATEST_VERIFY(CountingAllocator::getActiveAllocationCount() == 0);\n\t}\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestStringMap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/string_map.h>\n#include <EAStdC/EAString.h>\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::string_map<int>;\ntemplate class eastl::string_map<Align32>;\n\nstatic const char* strings[] = { \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\" };\nstatic const size_t kStringCount = 10; // This is intentionally half the length of strings, so that we can test with strings that are not inserted to the map. \n\n\nint TestStringMap()\n{\n\tint nErrorCount = 0;\n\n\t{  // Test declarations\n\t\tstring_map<int>\tstringMap;\n\n\t\tstring_map<int> stringMap2(stringMap);\n\t\tEATEST_VERIFY(stringMap2.size() == stringMap.size());\n\t\tEATEST_VERIFY(stringMap2 == stringMap);\n\n\n\t\t// allocator_type& get_allocator();\n\t\t// void            set_allocator(const allocator_type& allocator);\n\t\tstring_map<int>::allocator_type& allocator = stringMap.get_allocator();\n\t\tstringMap.set_allocator(EASTLAllocatorType());\n\t\tstringMap.set_allocator(allocator);\n\t\t// To do: Try to find something better to test here.\n\n\t\t\n\t\t// const char*     get_name() const;\n\t\t// void            set_name(const char* pName);\n#if EASTL_NAME_ENABLED\n\t\tstringMap.get_allocator().set_name(\"test\");\n\t\tconst char* pName = stringMap.get_allocator().get_name();\n\t\tEATEST_VERIFY(equal(pName, pName + 5, \"test\"));\n#endif\n\t}\n\n\n\t{\n\t\tstring_map<int> stringMap;\n\n\t\t// Clear a newly constructed, already empty container.\n\t\tstringMap.clear();\n\t\tEATEST_VERIFY(stringMap.validate());\n\t\tEATEST_VERIFY(stringMap.size() == 0);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t\tstringMap.insert(strings[i], i);\n\n\t\tEATEST_VERIFY(stringMap.validate());\n\t\tEATEST_VERIFY(stringMap.size() == kStringCount);\n\n\t\tstringMap.clear();\n\t\tEATEST_VERIFY(stringMap.validate());\n\t\tEATEST_VERIFY(stringMap.size() == 0);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t\tstringMap.insert(strings[i], i);\n\t\tEATEST_VERIFY(stringMap.validate());\n\t\tEATEST_VERIFY(stringMap.size() == kStringCount);\n\n\t\tstringMap.clear();\n\t\tEATEST_VERIFY(stringMap.validate());\n\t\tEATEST_VERIFY(stringMap.size() == 0);\n\t}\n\n\n\t{   // Test string_map\n\n\t\t// size_type          size() const\n\t\t// bool               empty() const\n\t\t// insert_return_type insert(const value_type& value);\n\t\t// insert_return_type insert(const value_type& value, hash_code_t c, node_type* pNodeNew = NULL);\n\t\t// iterator           insert(const_iterator, const value_type& value);\n\t\t// iterator           find(const key_type& k);\n\t\t// const_iterator     find(const key_type& k) const;\n\t\t// size_type          count(const key_type& k) const;\n\n\t\ttypedef string_map<int> StringMapInt;\n\n\t\tStringMapInt stringMap;\n\n\t\tEATEST_VERIFY(stringMap.empty());\n\t\tEATEST_VERIFY(stringMap.size() == 0);\n\t\tEATEST_VERIFY(stringMap.count(strings[0]) == 0);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t\tstringMap.insert(strings[i], i);\n\n\t\tEATEST_VERIFY(!stringMap.empty());\n\t\tEATEST_VERIFY(stringMap.size() == kStringCount);\n\t\tEATEST_VERIFY(stringMap.count(strings[0]) == 1);\n\n\t\tint j = 0;\n\t\tfor (StringMapInt::iterator it = stringMap.begin(); it != stringMap.end(); ++it, ++j)\n\t\t{\n\t\t\tint value = (*it).second;\n\t\t\tEATEST_VERIFY(value < (int)kStringCount);\n\t\t}\n\n\t\tfor (int i = 0; i < (int)kStringCount * 2; i++)\n\t\t{\n\t\t\tStringMapInt::iterator it = stringMap.find(strings[i]);\n\n\t\t\tif (i < (int)kStringCount)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(it != stringMap.end());\n\t\t\t\tconst char* k = (*it).first;\n\t\t\t\tint v = (*it).second;\n\t\t\t\tEATEST_VERIFY(EA::StdC::Strcmp(k, strings[i]) == 0);\n\t\t\t\tEATEST_VERIFY(v == i);\n\t\t\t}\n\t\t\telse\n\t\t\t\tEATEST_VERIFY(it == stringMap.end());\n\t\t}\n\n\t\tStringMapInt::insert_return_type result = stringMap.insert(\"EASTLTEST\");\n\t\tEATEST_VERIFY(result.second == true);\n\t\tresult = stringMap.insert(\"EASTLTEST\");\n\t\tEATEST_VERIFY(result.second == false);\n\t\tresult.first->second = 0;\n\n\t\t// iterator erase(const_iterator);\n\t\tsize_t nExpectedSize = stringMap.size();\n\n\t\tStringMapInt::iterator itD = stringMap.find(\"d\");\n\t\tEATEST_VERIFY(itD != stringMap.end());\n\n\t\t// erase the element and verify that the size has decreased\n\t\tstringMap.erase(itD);\n\t\tnExpectedSize--;\n\t\tEATEST_VERIFY(stringMap.size() == nExpectedSize);\n\n\t\t// verify that erased element is gone\n\t\titD = stringMap.find(strings[3]);\n\t\tEATEST_VERIFY(itD == stringMap.end());\n\n\t\t// iterator erase(const char*)\n\t\tStringMapInt::size_type n = stringMap.erase(strings[4]);\n\t\tnExpectedSize--;\n\t\tEATEST_VERIFY(n == 1);\n\t\tEATEST_VERIFY(stringMap.size() == nExpectedSize);\n\n\n\t\t// mapped_type& operator[](const key_type& key)\n\t\tstringMap.clear();\n\n\t\tint x = stringMap[\"A\"]; // A default-constructed int (i.e. 0) should be returned.\n\t\tEATEST_VERIFY(x == 0);\n\n\t\tstringMap[\"B\"] = 1;\n\t\tx = stringMap[\"B\"];\n\t\tEATEST_VERIFY(x == 1);     // Verify that the value we assigned is returned and a default-constructed value is not returned.\n\n\t\tstringMap[\"A\"] = 10;    // Overwrite our previous 0 with 10.\n\t\tstringMap[\"B\"] = 11;\n\t\tx = stringMap[\"A\"];\n\t\tEATEST_VERIFY(x == 10);    // Verify the value is as expected.\n\t\tx = stringMap[\"B\"];\n\t\tEATEST_VERIFY(x == 11);\n\n\t}\n\n\n\t{\n\t\t// string_map(const allocator_type& allocator);\n\t\t// string_map& operator=(const this_type& x);\n\t\t// bool validate() const;\n\n\t\tstring_map<int> stringMap1(EASTLAllocatorType(\"TestStringMap\"));\n\t\tstring_map<int> stringMap2(stringMap1);\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\tstringMap1.insert(strings[i], i);\n\t\t}\n\n\t\tstringMap2 = stringMap1;\n\t\tstring_map<int> stringMap3(stringMap1);\n\n\t\tEATEST_VERIFY(stringMap1.validate());\n\t\tEATEST_VERIFY(stringMap2.validate());\n\t\tEATEST_VERIFY(stringMap3.validate());\n\n\t\tfor (int i = 0; i < (int)kStringCount; i++)\n\t\t{\n\t\t\tEATEST_VERIFY(stringMap1[strings[i]] == stringMap2[strings[i]]);\n\t\t\tEATEST_VERIFY(stringMap1[strings[i]] == stringMap3[strings[i]]);\n\t\t}\n\n\t}\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestStringView.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EABase/eabase.h>\n#include <EASTL/numeric_limits.h>\n#include <EASTL/string.h>\n#include <EASTL/string_view.h>\n\n// Verify char8_t support is present if the test build requested it.\n#if defined(EASTL_EXPECT_CHAR8T_SUPPORT) && !EA_CHAR8_UNIQUE\nstatic_assert(false, \"Building with char8_t tests enabled, but EA_CHAR8_UNIQUE evaluates to false.\");\n#endif\n\n// this mess is required inorder to inject string literal string conversion macros into the unit tests\n#define TEST_STRING_NAME TestBasicStringView\n#define LITERAL(x) x\n#include \"TestStringView.inl\"\n\n#define TEST_STRING_NAME TestBasicStringViewW\n#define LITERAL(x) EA_WCHAR(x)\n#include \"TestStringView.inl\"\n\n#define TEST_STRING_NAME TestBasicStringView8\n#define LITERAL(x) EA_CHAR8(x)\n#include \"TestStringView.inl\"\n\n#define TEST_STRING_NAME TestBasicStringView16\n#define LITERAL(x) EA_CHAR16(x)\n#include \"TestStringView.inl\"\n\n#define TEST_STRING_NAME TestBasicStringView32\n#define LITERAL(x) EA_CHAR32(x)\n#include \"TestStringView.inl\"\n\n\nint TestStringView()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestBasicStringView<eastl::basic_string_view<char>>();\n\tnErrorCount += TestBasicStringView<eastl::string_view>();\n\n\tnErrorCount += TestBasicStringViewW<eastl::basic_string_view<wchar_t>>();\n\tnErrorCount += TestBasicStringViewW<eastl::wstring_view>();\n\n#if EA_CHAR8_UNIQUE\n\tnErrorCount += TestBasicStringView8<eastl::basic_string_view<char8_t>>();\n\tnErrorCount += TestBasicStringView8<eastl::u8string_view>();\n#endif\n\n\tnErrorCount += TestBasicStringView16<eastl::basic_string_view<char16_t>>();\n\tnErrorCount += TestBasicStringView16<eastl::u16string_view>();\n\n#if EA_CHAR32_NATIVE\n\tnErrorCount += TestBasicStringView32<eastl::basic_string_view<char32_t>>();\n\tnErrorCount += TestBasicStringView32<eastl::u32string_view>();\n#endif\n\n\n\t// constexpr string_view operator \"\" sv(const char* str, size_t len) noexcept;\n\t// constexpr u8string_view operator \"\" sv(const char8_t* str, size_t len) noexcept;\n\t// constexpr u16string_view operator \"\" sv(const char16_t* str, size_t len) noexcept;\n\t// constexpr u32string_view operator \"\" sv(const char32_t* str, size_t len) noexcept;\n\t// constexpr wstring_view   operator \"\" sv(const wchar_t* str, size_t len) noexcept;\n\t#if EASTL_USER_LITERALS_ENABLED \n\t{\n\t\tVERIFY(\"cplusplus\"_sv.compare(\"cplusplus\") == 0);\n\t\tVERIFY(L\"cplusplus\"_sv.compare(L\"cplusplus\") == 0);\n\t\tVERIFY(u\"cplusplus\"_sv.compare(u\"cplusplus\") == 0);\n\t\tVERIFY(U\"cplusplus\"_sv.compare(U\"cplusplus\") == 0);\n\t\tVERIFY(u8\"cplusplus\"_sv.compare(u8\"cplusplus\") == 0);\n\n\t\tstatic_assert(eastl::is_same_v<decltype(\"abcdef\"_sv), eastl::string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(u8\"abcdef\"_sv), eastl::u8string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(u\"abcdef\"_sv), eastl::u16string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(U\"abcdef\"_sv), eastl::u32string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(L\"abcdef\"_sv), eastl::wstring_view>, \"string_view literal type mismatch\");\n\n\n\t\tVERIFY(\"cplusplus\"sv.compare(\"cplusplus\") == 0);\n\t\tVERIFY(L\"cplusplus\"sv.compare(L\"cplusplus\") == 0);\n\t\tVERIFY(u\"cplusplus\"sv.compare(u\"cplusplus\") == 0);\n\t\tVERIFY(U\"cplusplus\"sv.compare(U\"cplusplus\") == 0);\n\t\tVERIFY(u8\"cplusplus\"sv.compare(u8\"cplusplus\") == 0);\n\n\t\tstatic_assert(eastl::is_same_v<decltype(\"abcdef\"sv), eastl::string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(u8\"abcdef\"sv), eastl::u8string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(u\"abcdef\"sv), eastl::u16string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(U\"abcdef\"sv), eastl::u32string_view>, \"string_view literal type mismatch\");\n\t\tstatic_assert(eastl::is_same_v<decltype(L\"abcdef\"sv), eastl::wstring_view>, \"string_view literal type mismatch\");\n\t}\n\t#endif\n\n\n\t// strlen(char_t) compatibility\n\t{\n\t\tauto* pStr = \"Hello, World\";\n\t\tstring_view sw(pStr, strlen(pStr));\n\t\tVERIFY(sw.size() == strlen(pStr));\n\t}\n\n\t// strlen(wchar_t) compatibility\n\t{\n\t\tauto* pStr = L\"Hello, World\";\n\t\twstring_view sw(pStr, wcslen(pStr));\n\t\tVERIFY(sw.size() == wcslen(pStr));\n\t}\n\n\n\treturn nErrorCount;\n}\n\n"
  },
  {
    "path": "test/source/TestStringView.inl",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\ntemplate<typename StringViewT>\nint TEST_STRING_NAME()\n{\n\tusing StringT = eastl::basic_string<typename StringViewT::value_type>;\n\n\tint nErrorCount = 0;\n\t{\n\t\t// EA_CONSTEXPR basic_string_view() \n\t\t{\n\t\t\tStringViewT sw;\n\t\t\tVERIFY(sw.empty());\n\t\t\tVERIFY(sw.data() == nullptr);\n\t\t\tVERIFY(sw.size() == 0);\n\t\t\tVERIFY(sw.size() == sw.length());\n\t\t}\n\n\t\t// User-reported regression:  constructing string_view from a nullptr, NULL, 0\n\t\t{\n\t\t\t{\n\t\t\t\tStringViewT sw(nullptr);\n\t\t\t\tVERIFY(sw.empty());\n\t\t\t\tVERIFY(sw.data() == nullptr);\n\t\t\t\tVERIFY(sw.size() == 0);\n\t\t\t\tVERIFY(sw.size() == sw.length());\n\t\t\t}\n\t\t\t{\n\t\t\t\tStringViewT sw(0);\n\t\t\t\tVERIFY(sw.empty());\n\t\t\t\tVERIFY(sw.data() == nullptr);\n\t\t\t\tVERIFY(sw.size() == 0);\n\t\t\t\tVERIFY(sw.size() == sw.length());\n\t\t\t}\n\t\t\t{\n\t\t\t\tStringViewT sw(NULL);\n\t\t\t\tVERIFY(sw.empty());\n\t\t\t\tVERIFY(sw.data() == nullptr);\n\t\t\t\tVERIFY(sw.size() == 0);\n\t\t\t\tVERIFY(sw.size() == sw.length());\n\t\t\t}\n\t\t}\n\n\t\t// EA_CONSTEXPR basic_string_view(const basic_string_view& other) = default;\n\t\t{\n\t\t\tauto* pLiteral = LITERAL(\"Hello, World\");\n\t\t\tStringViewT sw1(pLiteral);\n\t\t\tStringViewT sw2(sw1);\n\t\t\tVERIFY(sw1.size() == sw2.size());\n\t\t\tVERIFY(eastl::Compare(sw1.data(), sw2.data(), sw1.size()) == 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR basic_string_view(const T* s, size_type count)\n\t\t{\n\t\t\t{\n\t\t\t\tStringViewT sw(LITERAL(\"Hello, World\"), 12);\n\t\t\t\tVERIFY(!sw.empty());\n\t\t\t\tVERIFY(sw.data() != nullptr);\n\t\t\t\tVERIFY(sw.size() == 12);\n\t\t\t\tVERIFY(sw.size() == sw.length());\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tStringViewT sw(LITERAL(\"Hello, World\"), 5);\n\t\t\t\tVERIFY(!sw.empty());\n\t\t\t\tVERIFY(sw.data() != nullptr);\n\t\t\t\tVERIFY(sw.size() == 5);\n\t\t\t\tVERIFY(sw.size() == sw.length());\n\t\t\t\tVERIFY(eastl::Compare(sw.data(), LITERAL(\"Hello\"), sw.size()) == 0);\n\t\t\t}\n\t\t}\n\n\t\t// EA_CONSTEXPR basic_string_view(const T* s)\n\t\t{\n\t\t\tauto* pLiteral = LITERAL(\"Vancouver, Canada\");\n\t\t\tStringViewT sw(pLiteral);\n\t\t\tVERIFY(!sw.empty());\n\t\t\tVERIFY(sw.data() != nullptr);\n\t\t\tVERIFY(sw.size() == 17);\n\t\t\tVERIFY(sw.size() == sw.length());\n\t\t\tVERIFY(eastl::Compare(sw.data(), pLiteral, sw.size()) == 0);\n\t\t}\n\n\t\t// basic_string_view& operator=(const basic_string_view& view) = default;\n\t\t{\n\t\t\tauto* pLiteral = LITERAL(\"Hello, World\");\n\t\t\tStringViewT sw1(pLiteral);\n\t\t\tStringViewT sw2;\n\t\t\tVERIFY(!sw1.empty());\n\t\t\tVERIFY(sw2.empty());\n\n\t\t\tsw2 = sw1;\n\n\t\t\tVERIFY(!sw1.empty());\n\t\t\tVERIFY(!sw2.empty());\n\t\t\tVERIFY(sw1.size() == sw2.size());\n\t\t\tVERIFY(eastl::Compare(sw1.data(), pLiteral, sw1.size()) == 0);\n\t\t\tVERIFY(eastl::Compare(sw2.data(), pLiteral, sw2.size()) == 0);\n\t\t}\n\n\t\t{\n\t\t\t// EA_CONSTEXPR const_iterator begin() const EA_NOEXCEPT\n\t\t\t// EA_CONSTEXPR const_iterator cbegin() const EA_NOEXCEPT\n\t\t\tStringViewT sw(LITERAL(\"abcdefg\"));\n\t\t\t{\n\t\t\t\tauto i = sw.begin();\n\t\t\t\tauto ci = sw.cbegin();\n\n\t\t\t\tVERIFY(*i++ == LITERAL('a'));\n\t\t\t\tVERIFY(*i++ == LITERAL('b'));\n\n\t\t\t\tVERIFY(*ci++ == LITERAL('a'));\n\t\t\t\tVERIFY(*ci++ == LITERAL('b'));\n\t\t\t}\n\n\t\t\t// EA_CONSTEXPR const_iterator end() const EA_NOEXCEPT\n\t\t\t// EA_CONSTEXPR const_iterator cend() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tauto i = sw.end();\n\t\t\t\tauto ci = sw.cend();\n\n\t\t\t\tVERIFY(*i-- == LITERAL('\\0'));\n\t\t\t\tVERIFY(*i-- == LITERAL('g'));\n\n\t\t\t\tVERIFY(*ci-- == LITERAL('\\0'));\n\t\t\t\tVERIFY(*ci-- == LITERAL('g'));\n\t\t\t}\n\n\t\t\t// EA_CONSTEXPR const_reverse_iterator rbegin() const EA_NOEXCEPT\n\t\t\t// EA_CONSTEXPR const_reverse_iterator crbegin() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tauto i = sw.rbegin();\n\t\t\t\tauto ci = sw.crbegin();\n\n\t\t\t\tVERIFY(*i++ == LITERAL('g'));\n\t\t\t\tVERIFY(*i++ == LITERAL('f'));\n\n\t\t\t\tVERIFY(*ci++ == LITERAL('g'));\n\t\t\t\tVERIFY(*ci++ == LITERAL('f'));\n\t\t\t}\n\n\t\t\t// EA_CONSTEXPR const_reverse_iterator rend() const EA_NOEXCEPT\n\t\t\t// EA_CONSTEXPR const_reverse_iterator crend() const EA_NOEXCEPT\n\t\t\t{\n\t\t\t\tauto i = sw.rend();\n\t\t\t\ti--;\n\n\t\t\t\tauto ci = sw.crend();\n\t\t\t\tci--;\n\n\t\t\t\tVERIFY(*i-- == LITERAL('a'));\n\t\t\t\tVERIFY(*i-- == LITERAL('b'));\n\n\t\t\t\tVERIFY(*ci-- == LITERAL('a'));\n\t\t\t\tVERIFY(*ci-- == LITERAL('b'));\n\t\t\t}\n\t\t}\n\n\t\t// EA_CONSTEXPR const_pointer data() const\n\t\t{\n\t\t\tauto* pLiteral = LITERAL(\"Vancouver, Canada\");\n\t\t\tStringViewT sw(pLiteral);\n\t\t\tVERIFY(sw.data() != nullptr);\n\t\t\tVERIFY(eastl::Compare(sw.data(), pLiteral, sw.size()) == 0);\n\t\t\tVERIFY(eastl::Compare(sw.data() + 11, LITERAL(\"Canada\"), 6) == 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR const_reference front() const\n\t\t// EA_CONSTEXPR const_reference back() const\n\t\t{\n\t\t\t{\n\t\t\t\tStringViewT sw(LITERAL(\"Vancouver, Canada\"));\n\t\t\t\tVERIFY(sw.front() == LITERAL('V'));\n\t\t\t\tVERIFY(sw.back() == LITERAL('a'));\n\n\t\t\t}\n\t\t\t{\n\t\t\t\tStringViewT sw(LITERAL(\"Canada\"));\n\t\t\t\tVERIFY(sw.front() == LITERAL('C'));\n\t\t\t\tVERIFY(sw.back() == LITERAL('a'));\n\t\t\t}\n\t\t}\n\n\t\t// EA_CONSTEXPR const_reference operator[](size_type pos) const\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"Vancouver\"));\n\t\t\tVERIFY(sw[0] == LITERAL('V'));\n\t\t\tVERIFY(sw[1] == LITERAL('a'));\n\t\t\tVERIFY(sw[2] == LITERAL('n'));\n\t\t\tVERIFY(sw[3] == LITERAL('c'));\n\t\t\tVERIFY(sw[4] == LITERAL('o'));\n\t\t\tVERIFY(sw[5] == LITERAL('u'));\n\t\t\tVERIFY(sw[6] == LITERAL('v'));\n\t\t\tVERIFY(sw[7] == LITERAL('e'));\n\t\t\tVERIFY(sw[8] == LITERAL('r'));\n\t\t}\n\n\t\t// EA_CONSTEXPR size_type size() const EA_NOEXCEPT \n\t\t// EA_CONSTEXPR size_type length() const EA_NOEXCEPT\n\t\t// EA_CONSTEXPR size_type max_size() const EA_NOEXCEPT\n\t\t// EA_CONSTEXPR bool empty() const EA_NOEXCEPT \n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"http://en.cppreference.com/w/cpp/header/string_view\"));\n\t\t\tVERIFY(sw.size() == 51); \n\t\t\tVERIFY(sw.length() == 51); \n\t\t\tVERIFY(sw.max_size() == eastl::numeric_limits<typename StringViewT::size_type>::max()); \n\t\t\tVERIFY(!sw.empty()); \n\t\t}\n\n\t\t// EA_CONSTEXPR void swap(basic_string_view& v)\n\t\t{\n\t\t\tauto* pV = LITERAL(\"Vancouver\");\n\t\t\tauto* pC = LITERAL(\"Canada\");\n\t\t\tStringViewT sw1(pV);\n\t\t\tStringViewT sw2(pC);\n\t\t\tsw1.swap(sw2);\n\t\t\tVERIFY(eastl::Compare(sw1.data(), pC, sw1.size()) == 0);\n\t\t\tVERIFY(eastl::Compare(sw2.data(), pV, sw2.size()) == 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR void remove_prefix(size_type n)\n\t\t// EA_CONSTEXPR void remove_suffix(size_type n)\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"Vancouver\"));\n\t\t\tsw.remove_prefix(3);\n\t\t\tVERIFY(eastl::Compare(sw.data(), LITERAL(\"couver\"), sw.size()) == 0);\n\t\t\tVERIFY(sw.size() == 6);\n\n\t\t\tsw.remove_prefix(3);\n\t\t\tVERIFY(eastl::Compare(sw.data(), LITERAL(\"ver\"), sw.size()) == 0);\n\t\t\tVERIFY(sw.size() == 3);\n\n\t\t\tsw.remove_suffix(1);\n\t\t\tVERIFY(eastl::Compare(sw.data(), LITERAL(\"ve\"), sw.size()) == 0);\n\t\t\tVERIFY(sw.size() == 2);\n\t\t\t\n\t\t\tsw.remove_suffix(1);\n\t\t\tVERIFY(eastl::Compare(sw.data(), LITERAL(\"v\"), sw.size()) == 0);\n\t\t\tVERIFY(sw.size() == 1);\n\n\t\t\tsw.remove_suffix(1);\n\t\t\tVERIFY(eastl::Compare(sw.data(), LITERAL(\"\"), sw.size()) == 0);\n\t\t\tVERIFY(sw.size() == 0);\n\t\t}\n\n\t\t// size_type copy(T* s, size_type n, size_type pos = 0) const;\n\t\t{\n\t\t\ttypename StringViewT::value_type buf[256];\n\t\t\tStringViewT sw(LITERAL(\"**Hello, World\"));\n\t\t\tauto cnt = sw.copy(buf, 5, 2);\n\t\t\tVERIFY(eastl::Compare(buf, LITERAL(\"Hello\"), 5) == 0);\n\t\t\tVERIFY(cnt == 5);\n\t\t}\n\n\t\t// EA_CONSTEXPR basic_string_view substr(size_type pos = 0, size_type n = npos) const;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"**Hello, World\"));\n\t\t\tauto sw2 = sw.substr(2, 5);\n\t\t\tVERIFY(eastl::Compare(sw2.data(), LITERAL(\"Hello\"), sw2.size()) == 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR int compare(basic_string_view s) const EA_NOEXCEPT;\n\t\t{\n\t\t\t{\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"A\")).compare(StringViewT(LITERAL(\"A\"))) == 0);\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"a\")).compare(StringViewT(LITERAL(\"a\"))) == 0);\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"A\")).compare(StringViewT(LITERAL(\"a\"))) != 0);\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"A\")).compare(StringViewT(LITERAL(\"a\"))) < 0);\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"A\")).compare(StringViewT(LITERAL(\"A\"))) <= 0);\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"a\")).compare(StringViewT(LITERAL(\"A\"))) > 0);\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"A\")).compare(StringViewT(LITERAL(\"A\"))) >= 0);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"Aa\")).compare(StringViewT(LITERAL(\"A\"))) > 0);\n\t\t\t\tVERIFY(StringViewT(LITERAL(\"A\")).compare(StringViewT(LITERAL(\"Aa\"))) < 0);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tStringViewT sw1(LITERAL(\"Hello, World\"));\n\t\t\t\tStringViewT sw2(LITERAL(\"Hello, WWorld\"));\n\t\t\t\tStringViewT sw3(LITERAL(\"Hello, Wzorld\"));\n\t\t\t\tVERIFY(sw1.compare(sw1) == 0);\n\t\t\t\tVERIFY(sw1.compare(sw2) > 0);\n\t\t\t\tVERIFY(sw1.compare(sw3) < 0);\n\t\t\t}\n\t\t}\n\n\t\t// EA_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view s) const;\n\t\t{\n\t\t\tStringViewT sw1(LITERAL(\"*** Hello ***\"));\n\t\t\tStringViewT sw2(LITERAL(\"Hello\"));\n\t\t\tVERIFY(sw1.compare(4, 5, sw2) == 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2) const;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"Vancouver\"));\n\t\t\tVERIFY(sw.compare(0, 3, StringViewT(LITERAL(\"Van\")), 0, 3) == 0);\n\t\t\tVERIFY(sw.compare(6, 3, StringViewT(LITERAL(\"ver\")), 0, 3) == 0);\n\t\t\tVERIFY(sw.compare(0, 3, StringViewT(LITERAL(\"Tan\")), 0, 3) != 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR int compare(const T* s) const;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"Hello\"));\n\t\t\tVERIFY(sw.compare(LITERAL(\"Vancouver\")) != 0);\n\t\t\tVERIFY(sw.compare(LITERAL(\"Vancouver!\")) != 0);\n\t\t\tVERIFY(sw.compare(LITERAL(\"Hello\")) == 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR int compare(size_type pos1, size_type n1, const T* s) const;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"*** Hello\"));\n\t\t\tVERIFY(sw.compare(4, 5, LITERAL(\"Hello\")) == 0);\n\t\t\tVERIFY(sw.compare(4, 5, LITERAL(\"Hello 555\")) != 0);\n\t\t\tVERIFY(sw.compare(4, 5, LITERAL(\"hello\")) != 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR int compare(size_type pos1, size_type n1, const T* s, size_type n2) const;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"*** Hello ***\"));\n\t\t\tVERIFY(sw.compare(4, 5, LITERAL(\"Hello\"), 5) == 0);\n\t\t\tVERIFY(sw.compare(0, 1, LITERAL(\"*\"), 1) == 0);\n\t\t\tVERIFY(sw.compare(0, 2, LITERAL(\"**\"), 1) != 0);\n\t\t\tVERIFY(sw.compare(0, 2, LITERAL(\"**\"), 2) == 0);\n\t\t\tVERIFY(sw.compare(0, 2, LITERAL(\"^^\"), 2) != 0);\n\t\t}\n\n\n\t\t// EA_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const EA_NOEXCEPT;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"*** Hello ***\"));\n\t\t\tVERIFY(sw.find(StringViewT(LITERAL(\"Hello\"))) != StringViewT::npos);\n\t\t\tVERIFY(sw.find(StringViewT(LITERAL(\"ell\"))) != StringViewT::npos);\n\t\t\tVERIFY(sw.find(StringViewT(LITERAL(\"FailToFindMe\"))) == StringViewT::npos);\n\t\t}\n\n\t\t// EA_CONSTEXPR size_type find(T c, size_type pos = 0) const EA_NOEXCEPT;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"*** Hello ***\"));\n\t\t\tVERIFY(sw.find(LITERAL(\"H\")) == 4);\n\t\t\tVERIFY(sw.find(LITERAL(\"e\")) == 5);\n\t\t\tVERIFY(sw.find(LITERAL(\"l\")) == 6);\n\t\t\tVERIFY(sw.find(LITERAL(\"o\")) == 8);\n\t\t\tVERIFY(sw.find(LITERAL(\"&\")) == StringViewT::npos);\n\t\t\tVERIFY(sw.find(LITERAL(\"@\")) == StringViewT::npos);\n\t\t}\n\n\t\t// EA_CONSTEXPR size_type find(const T* s, size_type pos, size_type n) const;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"Hello, Vancouver\"));\n\t\t\tVERIFY(sw.find(LITERAL(\"Hello\"), 0, 3) != StringViewT::npos);\n\t\t\tVERIFY(sw.find(LITERAL(\"Hello\"), 3, 3) == StringViewT::npos);\n\t\t\tVERIFY(sw.find(LITERAL(\"Vancouv\"), 7, 7) != StringViewT::npos);\n\t\t}\n\n\t\t// EA_CONSTEXPR size_type find(const T* s, size_type pos = 0) const;\n\t\t{\n\t\t\tStringViewT sw(LITERAL(\"Hello, Vancouver\"));\n\t\t\tVERIFY(sw.find(LITERAL(\"Hello\"), 0) != StringViewT::npos);\n\t\t\tVERIFY(sw.find(LITERAL(\"Hello\"), 3) == StringViewT::npos);\n\t\t\tVERIFY(sw.find(LITERAL(\"Vancouv\"), 7) != StringViewT::npos);\n\t\t}\n\n\n\t\t// EA_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type rfind(T c, size_type pos = npos) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type rfind(const T* s, size_type pos, size_type n) const;\n\t\t// EA_CONSTEXPR size_type rfind(const T* s, size_type pos = npos) const;\n\t\t{\n\t\t\tStringViewT str(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"));\n\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"d\")))    != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"tuv\")))  != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"123r\"))) == StringViewT::npos);\n\n\t\t\tVERIFY(str.rfind(LITERAL(\"d\"))    != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL(\"tuv\"))  != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL(\"123r\")) == StringViewT::npos);\n\n\t\t\tVERIFY(str.rfind(LITERAL(\"d\"), str.length())        != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL(\"tuv\"), str.length() - 2)  != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL(\"123r\"), str.length() - 2) == StringViewT::npos);\n\n\t\t\tVERIFY(str.rfind(LITERAL('d'), str.length() - 0) != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL('t'), str.length() - 2) != StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL('1'), str.length() - 2) == StringViewT::npos);\n\t\t}\n\n\t\t{\n\t\t\tStringViewT str(LITERAL(\"abcdabcdabcdabcd\"));\n\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"d\")))     == (str.size() - 1));\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abcd\")))  == (str.size() - 4));\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abc\")))   == (str.size() - 4));\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"dab\")))   == (str.size() - 5));\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"e\")))     == StringViewT::npos);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abcde\"))) == StringViewT::npos);\n\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"d\")), 8)     == 7);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abc\")), 8)   == 8);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abc\")), 7)   == 4);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"dab\")), 8)   == 7);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"dab\")), 7)   == 7);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"e\")), 8)     == StringViewT::npos);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abcde\")), 8) == StringViewT::npos);\n\n\t\t\tVERIFY(str.rfind(LITERAL(\"d\"))     == (str.size() - 1));\n\t\t\tVERIFY(str.rfind(LITERAL(\"abc\"))   == (str.size() - 4));\n\t\t\tVERIFY(str.rfind(LITERAL(\"e\"))     == StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL(\"abcde\")) == StringViewT::npos);\n\n\t\t\tVERIFY(str.rfind(LITERAL(\"d\"), 8)     == 7);\n\t\t\tVERIFY(str.rfind(LITERAL(\"abc\"), 8)   == 8);\n\t\t\tVERIFY(str.rfind(LITERAL(\"abc\"), 7)   == 4);\n\t\t\tVERIFY(str.rfind(LITERAL(\"dab\"), 8)   == 7);\n\t\t\tVERIFY(str.rfind(LITERAL(\"dab\"), 7)   == 7);\n\t\t\tVERIFY(str.rfind(LITERAL(\"e\"), 8)     == StringViewT::npos);\n\t\t\tVERIFY(str.rfind(LITERAL(\"abcde\"), 8) == StringViewT::npos);\n\t\t}\n\n\t\t{\n\t\t\tStringViewT str(LITERAL(\"abcdeaababcdabcdx\"));\n\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abcde\")))    == 0);\n\t\t\tVERIFY(str.rfind(StringViewT(LITERAL(\"abcde\")), 8) == 0);\n\n\t\t\tVERIFY(str.rfind(LITERAL(\"abcde\"))    == 0);\n\t\t\tVERIFY(str.rfind(LITERAL(\"abcde\"), 8) == 0);\n\t\t}\n\n\t\t// EA_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_first_of(T c, size_type pos = 0) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_first_of(const T* s, size_type pos, size_type n) const;\n\t\t// EA_CONSTEXPR size_type find_first_of(const T* s, size_type pos = 0) const;\n\t\t{\n\t\t\tStringViewT str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\t\tVERIFY(str.find_first_of(StringViewT(LITERAL(\"aaa\"))) == 0);\n\t\t\tVERIFY(str.find_first_of(LITERAL(\"aab\")) == 0);\n\t\t\tVERIFY(str.find_first_of(LITERAL(\"baab\")) == 0);\n\t\t\tVERIFY(str.find_first_of(LITERAL(\"ceg\")) == 10);\n\t\t\tVERIFY(str.find_first_of(LITERAL(\"eeef\"), 1, 2) == 18);\n\t\t\tVERIFY(str.find_first_of(LITERAL(\"eeef\"), 1, 4) == 18);\n\t\t\tVERIFY(str.find_first_of(LITERAL('g')) == 26);\n\t\t\tVERIFY(str.find_first_of(LITERAL('$')) == StringViewT::npos);\n\t\t\tVERIFY(str.find_first_of(StringViewT(LITERAL(\" a\"), 1)) == StringViewT::npos);\n\t\t}\n\n\t\t// EA_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_last_of(T c, size_type pos = npos) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_last_of(const T* s, size_type pos, size_type n) const;\n\t\t// EA_CONSTEXPR size_type find_last_of(const T* s, size_type pos = npos) const;\n\t\t{\n\t\t\tStringViewT str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\t\tVERIFY(str.find_last_of(StringViewT(LITERAL(\"aaa\"))) == 4);\n\t\t\tVERIFY(str.find_last_of(LITERAL(\"aab\")) == 9);\n\t\t\tVERIFY(str.find_last_of(LITERAL(\"baab\")) == 9);\n\t\t\tVERIFY(str.find_last_of(LITERAL(\"ceg\")) == 27);\n\t\t\t// VERIFY(str.find_last_of(LITERAL(\"eeef\"), 1, 2) == StringViewT::npos);  // todo: FIX ME\n\t\t\t// VERIFY(str.find_last_of(LITERAL(\"eeef\"), 1, 4) == StringViewT::npos);  // todo: FIX ME\n\t\t\tVERIFY(str.find_last_of(LITERAL('g')) == 27);\n\t\t\tVERIFY(str.find_last_of(LITERAL('$')) == StringViewT::npos);\n\t\t}\n\n\t\t// EA_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_first_not_of(T c, size_type pos = 0) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_first_not_of(const T* s, size_type pos, size_type n) const;\n\t\t// EA_CONSTEXPR size_type find_first_not_of(const T* s, size_type pos = 0) const;\n\t\t{\n\t\t\tStringViewT str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\t\tVERIFY(str.find_first_not_of(StringViewT(LITERAL(\"abcdfg\"))) == 18);\n\t\t\tVERIFY(str.find_first_not_of(LITERAL(\"abcdfg\")) == 18);\n\t\t\t// VERIFY(str.find_first_not_of(LITERAL(\"abcdfg\"), 2, 2) == 0);   // todo:  FIX ME \n\t\t\t// VERIFY(str.find_first_not_of(LITERAL(\"abcdfg\"), 0, 2) == 10);  // todo:  FIX ME \n\t\t\tVERIFY(str.find_first_not_of(LITERAL('a')) == 5);  \n\t\t}\n\n\n\t\t// EA_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_last_not_of(T c, size_type pos = npos) const EA_NOEXCEPT;\n\t\t// EA_CONSTEXPR size_type find_last_not_of(const T* s, size_type pos, size_type n) const;\n\t\t// EA_CONSTEXPR size_type find_last_not_of(const T* s, size_type pos = npos) const;\n\t\t{\n\t\t\tStringViewT str(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\t\tVERIFY(str.find_last_not_of(StringViewT(LITERAL(\"a\"))) == 28);\n\t\t\tVERIFY(str.find_last_not_of(StringViewT(LITERAL(\"abcdfg\"))) == 28);\n\t\t\tVERIFY(str.find_last_not_of(StringViewT(LITERAL(\"abcdfgh\"))) == 22);\n\t\t\tVERIFY(str.find_last_not_of(LITERAL(\"abcdfgh\")) == 22);\n\t\t\t// VERIFY(str.find_last_not_of(LITERAL(\"abcdfg\"), 2, 2) == 0);   // todo:  FIX ME \n\t\t\t// VERIFY(str.find_last_not_of(LITERAL(\"abcdfg\"), 0, 2) == 10);  // todo:  FIX ME \n\t\t\tVERIFY(str.find_last_not_of(LITERAL('a')) == 28);  \n\t\t}\n\n\t\t// template <class CharT, class Traits>\n\t\t// constexpr bool operator==(basic_string_view<CharT, Traits> lhs, basic_string_view<CharT, Traits> rhs);\n\t\t// template <class CharT, class Traits>\n\t\t// constexpr bool operator!=(basic_string_view<CharT, Traits> lhs, basic_string_view<CharT, Traits> rhs);\n\t\t// template <class CharT, class Traits>\n\t\t// constexpr bool operator<(basic_string_view<CharT, Traits> lhs, basic_string_view<CharT, Traits> rhs);\n\t\t// template <class CharT, class Traits>\n\t\t// constexpr bool operator<=(basic_string_view<CharT, Traits> lhs, basic_string_view<CharT, Traits> rhs);\n\t\t// template <class CharT, class Traits>\n\t\t// constexpr bool operator>(basic_string_view<CharT, Traits> lhs, basic_string_view<CharT, Traits> rhs);\n\t\t// template <class CharT, class Traits>\n\t\t// constexpr bool operator>=(basic_string_view<CharT, Traits> lhs, basic_string_view<CharT, Traits> rhs);\n\t\t{\n\t\t\tStringViewT sw1(LITERAL(\"AAAAABBBBBCCCDDDDDEEEEEFFFGGH\"));\n\t\t\tStringViewT sw2(LITERAL(\"aaaaabbbbbcccdddddeeeeefffggh\"));\n\n\t\t\tVERIFY(sw1 == StringViewT(LITERAL(\"AAAAABBBBBCCCDDDDDEEEEEFFFGGH\")));\n\t\t\tVERIFY(sw1 != StringViewT(LITERAL(\"abcdefghijklmnopqrstuvwxyz\")));\n\t\t\tVERIFY(sw1 < sw2);\n\t\t\tVERIFY(sw1 <= sw2);\n\t\t\tVERIFY(sw2 > sw1);\n\t\t\tVERIFY(sw2 >= sw1);\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\t\tVERIFY((sw1 <=> StringViewT(LITERAL(\"AAAAABBBBBCCCDDDDDEEEEEFFFGGH\"))) == 0);\n\t\t\tVERIFY((sw1 <=> StringViewT(LITERAL(\"abcdefghijklmnopqrstuvwxyz\"))) != 0);\n\t\t\tVERIFY((sw1 <=> sw2) < 0);\n\t\t\tVERIFY((sw1 <=> sw2) <= 0);\n\t\t\tVERIFY((sw2 <=> sw1) > 0);\n\t\t\tVERIFY((sw2 <=> sw1) >= 0);\n#endif\n\t\t}\n\t\t\n\t\t{\n\t\t\tauto s = LITERAL(\"Hello, World\");\n\t\t\tStringViewT sv(s);\n\t\t\t\n\t\t\tVERIFY(s == sv);\n\t\t\tVERIFY(sv == s);\n\n\t\t\tVERIFY(s <= sv);\n\t\t\tVERIFY(sv <= s);\n\t\t\tVERIFY(s >= sv);\n\t\t\tVERIFY(sv >= s);\n\t\t\tVERIFY(!(s != sv));\n\t\t\tVERIFY(!(sv != s));\n\t\t\tVERIFY(!(s < sv));\n\t\t\tVERIFY(!(sv < s));\n\t\t\tVERIFY(!(s > sv));\n\t\t\tVERIFY(!(sv > s));\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\t\tVERIFY((s <=> sv) == 0);\n\t\t\tVERIFY((sv <=> s) == 0);\n\n\t\t\tVERIFY((s <=> sv) <= 0);\n\t\t\tVERIFY((sv <=> s) <= 0);\n\t\t\tVERIFY((s <=> sv) >= 0);\n\t\t\tVERIFY((sv <=> s) >= 0);\n\t\t\tVERIFY(!((s <=> sv) != 0));\n\t\t\tVERIFY(!((sv <=> s) != 0));\n\t\t\tVERIFY(!((s <=> sv) > 0));\n\t\t\tVERIFY(!((sv <=> s) < 0));\n#endif\n\t\t}\n\n\t\t// Regression comparison operators should work between basic_string_view and basic_string.\n\t\t// The idea is that type_identity_t on some overloads will force basic_string::operator basic_string_view() to kick in.\n\t\t{\n\t\t\tStringT s(LITERAL(\"Hello, Stockholm\"));\t\n\t\t\tStringViewT sv(s);\n\n\t\t\tVERIFY(s == sv);\n\t\t\tVERIFY(sv == s);\n\n\t\t\t// All the operators bellow used to not work.\n\t\t\tVERIFY(s <= sv);\n\t\t\tVERIFY(sv <= s);\n\t\t\tVERIFY(s >= sv);\n\t\t\tVERIFY(sv >= s);\n\t\t\tVERIFY(!(s != sv));\n\t\t\tVERIFY(!(sv != s));\n\t\t\tVERIFY(!(s < sv));\n\t\t\tVERIFY(!(sv < s));\n\t\t\tVERIFY(!(s > sv));\n\t\t\tVERIFY(!(sv > s));\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\t\tVERIFY((s <=> sv) == 0);\n\t\t\tVERIFY((sv <=> s) == 0);\n\n\t\t\tVERIFY((s <=> sv) <= 0);\n\t\t\tVERIFY((sv <=> s) <= 0);\n\t\t\tVERIFY((s <=> sv) >= 0);\n\t\t\tVERIFY((sv <=> s) >= 0);\n\t\t\tVERIFY(!((s <=> sv) != 0));\n\t\t\tVERIFY(!((sv <=> s) != 0));\n\t\t\tVERIFY(!((s <=> sv) > 0));\n\t\t\tVERIFY(!((sv <=> s) < 0));\n#endif\n\t\t}\n\n\t\t// template<> struct hash<std::string_view>;\n\t\t// template<> struct hash<std::wstring_view>;\n\t\t// template<> struct hash<std::u16string_view>;\n\t\t// template<> struct hash<std::u32string_view>;\n\t\t{\n\t\t\tStringViewT sw1(LITERAL(\"Hello, World\"));\n\t\t\tStringViewT sw2(LITERAL(\"Hello, World\"), 5);\n\t\t\tStringViewT sw3(LITERAL(\"Hello\"));\n\t\t\tauto s = LITERAL(\"Hello\");\n\n\t\t\tVERIFY(eastl::hash<StringViewT>{}(sw1) != eastl::hash<StringViewT>{}(sw2));\n\t\t\tVERIFY(eastl::hash<StringViewT>{}(sw2) == eastl::hash<StringViewT>{}(sw3));\n\t\t\tVERIFY(eastl::hash<StringViewT>{}(sw3) == eastl::hash<decltype(s)>{}(s));\n\t\t}\n\t}\n\n\t{\n\t\tStringViewT sw1(LITERAL(\"AAAAABBBBBCCCDDDDDEEEEEFFFGGH\"));\n\n\t\tVERIFY( sw1.starts_with(LITERAL('A')));\n\t\tVERIFY(!sw1.starts_with(LITERAL('X')));\n\t\tVERIFY( sw1.starts_with(LITERAL(\"AAAA\")));\n\t\tVERIFY( sw1.starts_with(StringViewT(LITERAL(\"AAAA\"))));\n\t\tVERIFY(!sw1.starts_with(LITERAL(\"AAAB\")));\n\n\t\tVERIFY( sw1.ends_with(LITERAL('H')));\n\t\tVERIFY(!sw1.ends_with(LITERAL('X')));\n\t\tVERIFY( sw1.ends_with(LITERAL(\"FGGH\")));\n\t\tVERIFY( sw1.ends_with(StringViewT(LITERAL(\"FGGH\"))));\n\t\tVERIFY(!sw1.ends_with(LITERAL(\"FGGH$\")));\n\t}\n\n\treturn nErrorCount;\n}\n\n// Required to prevent manual undef of macros when 'TestString.inl' preprocessed at the top of the unit test cpp file.\n#undef TEST_STRING_NAME \n#undef LITERAL\n\n"
  },
  {
    "path": "test/source/TestTuple.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n\nEA_DISABLE_VC_WARNING(4623 4625 4413 4510)\n\n#include <EASTL/tuple.h>\n#include <EASTL/unique_ptr.h>\n\n#if EASTL_TUPLE_ENABLED\n\nnamespace TestTupleInternal\n{\n\nstruct DefaultConstructibleType\n{\n\tstatic const int defaultVal = 0x1EE7C0DE;\n\tDefaultConstructibleType() : mVal(defaultVal) {}\n\tint mVal;\n};\n\nstruct OperationCountingType\n{\n\tOperationCountingType() : mVal() { ++mDefaultConstructorCalls; }\n\tOperationCountingType(int x) : mVal(x) { ++mIntConstructorCalls; }\n\tOperationCountingType(const OperationCountingType& x) : mVal(x.mVal) { ++mCopyConstructorCalls; }\n\tOperationCountingType(OperationCountingType&& x) : mVal(x.mVal)\n\t{\n\t\t++mMoveConstructorCalls;\n\t\tx.mVal = 0;\n\t}\n\tOperationCountingType& operator=(const OperationCountingType& x)\n\t{\n\t\tmVal = x.mVal;\n\t\t++mCopyAssignmentCalls;\n\t\treturn *this;\n\t}\n\tOperationCountingType& operator=(OperationCountingType&& x)\n\t{\n\t\tmVal = x.mVal;\n\t\tx.mVal = 0;\n\t\t++mMoveAssignmentCalls;\n\t\treturn *this;\n\t}\n\t~OperationCountingType() { ++mDestructorCalls; }\n\n\tint mVal;\n\n\tstatic void ResetCounters()\n\t{\n\t\tmDefaultConstructorCalls = 0;\n\t\tmIntConstructorCalls = 0;\n\t\tmCopyConstructorCalls = 0;\n\t\tmMoveConstructorCalls = 0;\n\t\tmCopyAssignmentCalls = 0;\n\t\tmMoveAssignmentCalls = 0;\n\t\tmDestructorCalls = 0;\n\t}\n\n\tstatic int mDefaultConstructorCalls;\n\tstatic int mIntConstructorCalls;\n\tstatic int mCopyConstructorCalls;\n\tstatic int mMoveConstructorCalls;\n\tstatic int mCopyAssignmentCalls;\n\tstatic int mMoveAssignmentCalls;\n\tstatic int mDestructorCalls;\n};\n\nint OperationCountingType::mDefaultConstructorCalls = 0;\nint OperationCountingType::mIntConstructorCalls = 0;\nint OperationCountingType::mCopyConstructorCalls = 0;\nint OperationCountingType::mMoveConstructorCalls = 0;\nint OperationCountingType::mCopyAssignmentCalls = 0;\nint OperationCountingType::mMoveAssignmentCalls = 0;\nint OperationCountingType::mDestructorCalls = 0;\n\n}  // namespace TestTupleInternal\n\nint TestTuple()\n{\n\tusing namespace eastl;\n\tusing namespace TestTupleInternal;\n\n\tint nErrorCount = 0;\n\n\tstatic_assert(tuple_size<tuple<int>>::value == 1, \"tuple_size<tuple<T>> test failed.\");\n\tstatic_assert(tuple_size<const tuple<int>>::value == 1, \"tuple_size<const tuple<T>> test failed.\");\n\tstatic_assert(tuple_size<const tuple<const int>>::value == 1, \"tuple_size<const tuple<const T>> test failed.\");\n\tstatic_assert(tuple_size<volatile tuple<int>>::value == 1, \"tuple_size<volatile tuple<T>> test failed.\");\n\tstatic_assert(tuple_size<const volatile tuple<int>>::value == 1, \"tuple_size<const volatile tuple<T>> test failed.\");\n\tstatic_assert(tuple_size<tuple<int, float, bool>>::value == 3, \"tuple_size<tuple<T, T, T>> test failed.\");\n\n\tstatic_assert(is_same<tuple_element_t<0, tuple<int>>, int>::value, \"tuple_element<I, T> test failed.\");\n\tstatic_assert(is_same<tuple_element_t<1, tuple<float, int>>, int>::value, \"tuple_element<I, T> test failed.\");\n\tstatic_assert(is_same<tuple_element_t<1, tuple<float, const int>>, const int>::value, \"tuple_element<I, T> test failed.\");\n\tstatic_assert(is_same<tuple_element_t<1, tuple<float, volatile int>>, volatile int>::value, \"tuple_element<I, T> test failed.\");\n\tstatic_assert(is_same<tuple_element_t<1, tuple<float, const volatile int>>, const volatile int>::value, \"tuple_element<I, T> test failed.\");\n\tstatic_assert(is_same<tuple_element_t<1, tuple<float, int&>>, int&>::value, \"tuple_element<I, T> test failed.\");\n\n\t{\n\t\ttuple<int> aSingleElementTuple(1);\n\t\tEATEST_VERIFY(get<0>(aSingleElementTuple) == 1);\n\t\tget<0>(aSingleElementTuple) = 2;\n\t\tEATEST_VERIFY(get<0>(aSingleElementTuple) == 2);\n\t\tget<int>(aSingleElementTuple) = 3;\n\t\tEATEST_VERIFY(get<int>(aSingleElementTuple) == 3);\n\n\t\tconst tuple<int> aConstSingleElementTuple(3);\n\t\tEATEST_VERIFY(get<0>(aConstSingleElementTuple) == 3);\n\t\tEATEST_VERIFY(get<int>(aConstSingleElementTuple) == 3);\n\n\t\ttuple<DefaultConstructibleType> aDefaultConstructedTuple;\n\t\tEATEST_VERIFY(get<0>(aDefaultConstructedTuple).mVal == DefaultConstructibleType::defaultVal);\n\n\t\tOperationCountingType::ResetCounters();\n\t\ttuple<OperationCountingType> anOperationCountingTuple;\n\t\tEATEST_VERIFY(OperationCountingType::mDefaultConstructorCalls == 1 &&\n\t\t\t\t\t  get<0>(anOperationCountingTuple).mVal == 0);\n\t\tget<0>(anOperationCountingTuple).mVal = 1;\n\t\ttuple<OperationCountingType> anotherOperationCountingTuple(anOperationCountingTuple);\n\t\tEATEST_VERIFY(OperationCountingType::mDefaultConstructorCalls == 1 &&\n\t\t\t\t\t  OperationCountingType::mCopyConstructorCalls == 1 &&\n\t\t\t\t\t  get<0>(anotherOperationCountingTuple).mVal == 1);\n\t\tget<0>(anOperationCountingTuple).mVal = 2;\n\t\tanotherOperationCountingTuple = anOperationCountingTuple;\n\t\tEATEST_VERIFY(\n\t\t\tOperationCountingType::mDefaultConstructorCalls == 1 && OperationCountingType::mCopyConstructorCalls == 1 &&\n\t\t\tOperationCountingType::mCopyAssignmentCalls == 1 && get<0>(anotherOperationCountingTuple).mVal == 2);\n\n\t\tOperationCountingType::ResetCounters();\n\t\ttuple<OperationCountingType> yetAnotherOperationCountingTuple(OperationCountingType(5));\n\t\tEATEST_VERIFY(\n\t\t\tOperationCountingType::mMoveConstructorCalls == 1 && OperationCountingType::mDefaultConstructorCalls == 0 &&\n\t\t\tOperationCountingType::mCopyConstructorCalls == 0 && get<0>(yetAnotherOperationCountingTuple).mVal == 5);\n\t}\n\n\tEATEST_VERIFY(OperationCountingType::mDestructorCalls == 4);\n\n\t{\n\t\t// Test constructor\n\t\ttuple<int, float, bool> aTuple(1, 1.0f, true);\n\t\tEATEST_VERIFY(get<0>(aTuple) == 1);\n\t\tEATEST_VERIFY(get<1>(aTuple) == 1.0f);\n\t\tEATEST_VERIFY(get<2>(aTuple) == true);\n\t\tEATEST_VERIFY(get<int>(aTuple) == 1);\n\t\tEATEST_VERIFY(get<float>(aTuple) == 1.0f);\n\t\tEATEST_VERIFY(get<bool>(aTuple) == true);\n\n\t\tget<1>(aTuple) = 2.0f;\n\t\tEATEST_VERIFY(get<1>(aTuple) == 2.0f);\n\n\t\t// Test copy constructor\n\t\ttuple<int, float, bool> anotherTuple(aTuple);\n\t\tEATEST_VERIFY(get<0>(anotherTuple) == 1 && get<1>(anotherTuple) == 2.0f && get<2>(anotherTuple) == true);\n\n\t\t// Test copy assignment\n\t\ttuple<int, float, bool> yetAnotherTuple(2, 3.0f, true);\n\t\tEATEST_VERIFY(get<0>(yetAnotherTuple) == 2 && get<1>(yetAnotherTuple) == 3.0f &&\n\t\t\t\t\t  get<2>(yetAnotherTuple) == true);\n\t\tyetAnotherTuple = anotherTuple;\n\t\tEATEST_VERIFY(get<0>(yetAnotherTuple) == 1 && get<1>(yetAnotherTuple) == 2.0f &&\n\t\t\t\t\t  get<2>(yetAnotherTuple) == true);\n\n\t\t// Test converting 'copy' constructor (from a tuple of different type whose members are each convertible)\n\t\ttuple<double, double, bool> aDifferentTuple(aTuple);\n\t\tEATEST_VERIFY(get<0>(aDifferentTuple) == 1.0 && get<1>(aDifferentTuple) == 2.0 &&\n\t\t\t\t\t  get<2>(aDifferentTuple) == true);\n\n\t\t// Test converting assignment operator (from a tuple of different type whose members are each convertible)\n\t\ttuple<double, double, bool> anotherDifferentTuple;\n\t\tEATEST_VERIFY(get<0>(anotherDifferentTuple) == 0.0 && get<1>(anotherDifferentTuple) == 0.0 &&\n\t\t\t\t\t  get<2>(anotherDifferentTuple) == false);\n\t\tanotherDifferentTuple = anotherTuple;\n\t\tEATEST_VERIFY(get<0>(anotherDifferentTuple) == 1.0 && get<1>(anotherDifferentTuple) == 2.0 &&\n\t\t\t\t\t  get<2>(anotherDifferentTuple) == true);\n\n\t\t// Test default initialization (built in types should be value initialized rather than default initialized)\n\t\ttuple<int, float, bool> aDefaultInitializedTuple;\n\t\tEATEST_VERIFY(get<0>(aDefaultInitializedTuple) == 0 && get<1>(aDefaultInitializedTuple) == 0.0f &&\n\t\t\t\t\t  get<2>(aDefaultInitializedTuple) == false);\n\t}\n\n\t{\n\t\t// Test some other cases with typed-getter\n\t\ttuple<double, double, bool> aTupleWithRepeatedType(1.0f, 2.0f, true);\n\t\tEATEST_VERIFY(get<bool>(aTupleWithRepeatedType) == true);\n\n\t\ttuple<double, bool, double> anotherTupleWithRepeatedType(1.0f, true, 2.0f);\n\t\tEATEST_VERIFY(get<bool>(anotherTupleWithRepeatedType) == true);\n\n\t\ttuple<bool, double, double> yetAnotherTupleWithRepeatedType(true, 1.0f, 2.0f);\n\t\tEATEST_VERIFY(get<bool>(anotherTupleWithRepeatedType) == true);\n\n\t\tstruct floatOne { float val; };\n\t\tstruct floatTwo { float val; };\n\t\ttuple<floatOne, floatTwo> aTupleOfStructs({ 1.0f }, { 2.0f } );\n\t\tEATEST_VERIFY(get<floatOne>(aTupleOfStructs).val == 1.0f);\n\t\tEATEST_VERIFY(get<floatTwo>(aTupleOfStructs).val == 2.0f);\n\t\t\n\t\tconst tuple<double, double, bool> aConstTuple(aTupleWithRepeatedType);\n\t\tconst bool& constRef = get<bool>(aConstTuple);\n\t\tEATEST_VERIFY(constRef == true);\n\n\t\tconst bool&& constRval = get<bool>(eastl::move(aTupleWithRepeatedType));\n\t\tEATEST_VERIFY(constRval == true);\n\t}\n\n\t{\n\t\ttuple<int, float> aTupleWithDefaultInit(1, {});\n\n\t\t// tuple construction from pair\n\t\tpair<int, float> aPair(1, 2.0f);\n\t\ttuple<int, float> aTuple(aPair);\n\t\tEATEST_VERIFY(get<0>(aTuple) == 1 && get<1>(aTuple) == 2.0f);\n\t\ttuple<double, double> anotherTuple(aPair);\n\t\tEATEST_VERIFY(get<0>(anotherTuple) == 1.0 && get<1>(anotherTuple) == 2.0);\n\t\tanotherTuple = make_pair(2, 3);\n\t\tEATEST_VERIFY(get<0>(anotherTuple) == 2.0 && get<1>(anotherTuple) == 3.0);\n\n\t\t// operators: ==, !=, <\n\t\tanotherTuple = aTuple;\n\t\tEATEST_VERIFY(aTuple == anotherTuple);\n\t\tEATEST_VERIFY(!(aTuple < anotherTuple) && !(anotherTuple < aTuple));\n\t\ttuple<double, double> aDefaultInitTuple;\n\t\tEATEST_VERIFY(aTuple != aDefaultInitTuple);\n\t\tEATEST_VERIFY(aDefaultInitTuple < aTuple);\n\n\t\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\tEATEST_VERIFY((aTuple <=> anotherTuple) == 0);\n\t\tEATEST_VERIFY((aTuple <=> anotherTuple) >= 0);\n\t\tEATEST_VERIFY((anotherTuple <=> aTuple) >= 0);\n\t\tEATEST_VERIFY((aTuple <=> aDefaultInitTuple) != 0);\n\t\tEATEST_VERIFY((aDefaultInitTuple <=> aTuple) < 0);\n\t\t#endif\n\n\t\ttuple<int, int, int> lesserTuple(1, 2, 3);\n\t\ttuple<int, int, int> greaterTuple(1, 2, 4);\n\t\tEATEST_VERIFY(lesserTuple < greaterTuple && !(greaterTuple < lesserTuple) && greaterTuple > lesserTuple &&\n\t\t\t\t\t  !(lesserTuple > greaterTuple));\n\n\t\t#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\tEATEST_VERIFY((lesserTuple <=> greaterTuple) != 0);\n\t\tEATEST_VERIFY((lesserTuple <=> greaterTuple) < 0);\n\t\tEATEST_VERIFY((lesserTuple <=> greaterTuple) <= 0);\n\t\tEATEST_VERIFY((greaterTuple <=> lesserTuple) > 0);\n\t\tEATEST_VERIFY((greaterTuple <=> lesserTuple) >= 0);\n\t\t#endif\n\n\t\ttuple<int, float, TestObject> valTup(2, 2.0f, TestObject(2));\n\t\ttuple<int&, float&, TestObject&> refTup(valTup);\n\t\ttuple<const int&, const float&, const TestObject&> constRefTup(valTup);\n\n\t\tEATEST_VERIFY(get<0>(refTup) == get<0>(valTup));\n\t\tEATEST_VERIFY(get<1>(refTup) == get<1>(valTup));\n\t\tEATEST_VERIFY(refTup == valTup);\n\t\tEATEST_VERIFY(get<0>(refTup) == get<0>(constRefTup));\n\t\tEATEST_VERIFY(get<1>(refTup) == get<1>(constRefTup));\n\t\tEATEST_VERIFY(constRefTup == valTup);\n\t\tEATEST_VERIFY(constRefTup == refTup);\n\n\t\t// swap\n\t\tswap(lesserTuple, greaterTuple);\n\t\tEATEST_VERIFY(get<2>(lesserTuple) == 4 && get<2>(greaterTuple) == 3);\n\t\tswap(greaterTuple, lesserTuple);\n\t\tEATEST_VERIFY(lesserTuple < greaterTuple);\n\t}\n\n\t{\n\t\t// Test construction of tuple containing a move only type\n\t\tstatic_assert(is_constructible<MoveOnlyType, MoveOnlyType>::value, \"is_constructible type trait giving confusing answers.\");\n\t\tstatic_assert(is_constructible<MoveOnlyType, MoveOnlyType&&>::value, \"is_constructible type trait giving wrong answers.\");\n\t\tstatic_assert(is_constructible<MoveOnlyType&&, MoveOnlyType&&>::value, \"is_constructible type trait giving bizarre answers.\");\n\t\ttuple<MoveOnlyType> aTupleWithMoveOnlyMember(1);\n\t\tEATEST_VERIFY(get<0>(aTupleWithMoveOnlyMember).mVal == 1);\n\t\tget<0>(aTupleWithMoveOnlyMember) = MoveOnlyType(2);\n\t\tEATEST_VERIFY(get<0>(aTupleWithMoveOnlyMember).mVal == 2);\n\n\t\ttuple<const MoveOnlyType&> aTupleWithRefToMoveOnlyMember(aTupleWithMoveOnlyMember);\n\t\tEATEST_VERIFY(get<0>(aTupleWithRefToMoveOnlyMember).mVal == 2);\n\n\t\ttuple<const MoveOnlyType&> aTupleWithConstRefToGetMoveOnly(get<0>(aTupleWithMoveOnlyMember));\n\t\tEATEST_VERIFY(get<0>(aTupleWithConstRefToGetMoveOnly).mVal == 2);\n\n\t\ttuple<MoveOnlyType&> aTupleWithRefToGetMoveOnly(get<0>(aTupleWithMoveOnlyMember));\n\t\tEATEST_VERIFY(get<0>(aTupleWithRefToGetMoveOnly).mVal == 2);\n\t}\n\n\t{\n\t\t// Test construction of tuple containing r-value references\n\t\tint x = 42;\n\t\tTestObject object{1337};\n\t\t\n\t\ttuple<int&&, TestObject&&> aTupleWithRValueReference(eastl::move(x), eastl::move(object));\n\t\tstatic_assert(is_same<decltype(get<0>(aTupleWithRValueReference)), int&>::value, \"wrong return type for get when using r-value reference.\");\n\t\tstatic_assert(is_same<decltype(get<1>(aTupleWithRValueReference)), TestObject&>::value, \"wrong return type for get when using r-value reference.\");\n\t\tEATEST_VERIFY(get<0>(aTupleWithRValueReference) == 42);\n\t\tEATEST_VERIFY(get<1>(aTupleWithRValueReference).mX == 1337);\n\n\t\tstatic_assert(!is_constructible<decltype(aTupleWithRValueReference), int&, TestObject&>::value, \"it shouldn't be possible to assign r-value references with l-values.\");\n\t}\n\n\t{\n\t\t// Tuple helpers\n\n\t\t// make_tuple\n\t\tauto makeTuple = make_tuple(1, 2.0, true);\n\t\tEATEST_VERIFY(get<0>(makeTuple) == 1 && get<1>(makeTuple) == 2.0 && get<2>(makeTuple) == true);\n\n\t\t// TODO: reference_wrapper implementation needs to be finished to enable this code\n\t\t{\n\t\t\tint a = 2;\n\t\t\tfloat b = 3.0f;\n\t\t\tauto makeTuple2 = make_tuple(ref(a), b);\n\t\t\tget<0>(makeTuple2) = 3;\n\t\t\tget<1>(makeTuple2) = 4.0f;\n\t\t\tEATEST_VERIFY(get<0>(makeTuple2) == 3 && get<1>(makeTuple2) == 4.0f && a == 3 && b == 3.0f);\n\t\t}\n\n\t\t// forward_as_tuple\n\t\t{\n\t\t\tauto forwardTest = [](tuple<MoveOnlyType&&, MoveOnlyType&&> x) -> tuple<MoveOnlyType, MoveOnlyType>\n\t\t\t{\n\t\t\t\treturn tuple<MoveOnlyType, MoveOnlyType>(move(x));\n\t\t\t};\n\n\t\t\ttuple<MoveOnlyType, MoveOnlyType> aMovableTuple(\n\t\t\t    forwardTest(forward_as_tuple(MoveOnlyType(1), MoveOnlyType(2))));\n\n\t\t\tEATEST_VERIFY(get<0>(aMovableTuple).mVal == 1 && get<1>(aMovableTuple).mVal == 2);\n\t\t}\n\n\t\t{\n\t\t\t// tie\n\t\t\tint a = 0;\n\t\t\tdouble b = 0.0f;\n\t\t\tstatic_assert(is_assignable<const Internal::ignore_t&, int>::value, \"ignore_t not assignable\");\n\t\t\tstatic_assert(Internal::TupleAssignable<tuple<const Internal::ignore_t&>, tuple<int>>::value, \"Not assignable\");\n\t\t\ttie(a, ignore, b) = make_tuple(1, 3, 5);\n\t\t\tEATEST_VERIFY(a == 1 && b == 5.0f);\n\n\t\t\tauto aCattedRefTuple = tuple_cat(make_tuple(1), tie(a, ignore, b));\n\t\t\tget<1>(aCattedRefTuple) = 2;\n\t\t\tEATEST_VERIFY(a == 2);\n\t\t}\n\n\t\t// tuple_cat\n\t\t{\n\t\t\t// zero args\n\t\t\t{\t\t\t\t\n\t\t\t\tauto result = tuple_cat();\n\t\t\t\tstatic_assert(eastl::is_same_v<decltype(result), tuple<>>, \"type mismatch\");\n\t\t\t}\n\n\t\t\t// one arg - l-value\n\t\t\t{\n\t\t\t\ttuple<int, bool> t{42, true};\n\t\t\t\t\n\t\t\t\tauto result = tuple_cat(t);\n\t\t\t\t\n\t\t\t\tstatic_assert(eastl::is_same_v<decltype(result), tuple<int, bool>>, \"type mismatch\");\n\t\t\t\t\n\t\t\t\tEATEST_VERIFY(get<0>(result) == 42);\n\t\t\t\tEATEST_VERIFY(get<1>(result));\n\t\t\t}\n\n\t\t\t// one arg - r-value\n\t\t\t{\n\t\t\t\ttuple<int, unique_ptr<bool>> t{42, new bool(true)};\n\t\t\t\t\n\t\t\t\tauto result = tuple_cat(eastl::move(t));\n\n\t\t\t\tstatic_assert(eastl::is_same_v<decltype(result), tuple<int, unique_ptr<bool>>>, \"type mismatch\");\n\t\t\t\t\n\t\t\t\tEATEST_VERIFY(get<0>(result) == 42);\n\t\t\t\tEATEST_VERIFY(get<1>(result) != nullptr && *get<1>(result));\n\t\t\t\tEATEST_VERIFY(get<1>(t) == nullptr);\n\t\t\t}\n\t\t\t\n\t\t\t// two args - l-values\n\t\t\t{\n\t\t\t\ttuple<int, bool> t1{42, true};\n\t\t\t\ttuple<float, int> t2{3.14f, 1337};\n\t\t\t\t\n\t\t\t\tauto result = tuple_cat(t1, t2);\n\n\t\t\t\tstatic_assert(eastl::is_same_v<decltype(result), tuple<int, bool, float, int>>, \"type mismatch\");\n\t\t\t\t\n\t\t\t\tEATEST_VERIFY(get<0>(result) == 42);\n\t\t\t\tEATEST_VERIFY(get<1>(result));\n\t\t\t\tEATEST_VERIFY(get<2>(result) == 3.14f);\n\t\t\t\tEATEST_VERIFY(get<3>(result) == 1337);\n\t\t\t}\n\n\t\t\t// two args - r-values\n\t\t\t{\n\t\t\t\ttuple<int, unique_ptr<bool>> t1{42, new bool(true)};\n\t\t\t\ttuple<unique_ptr<float>, int> t2{new float(3.14f), 1337};\n\t\t\t\t\n\t\t\t\tauto result = tuple_cat(eastl::move(t1), eastl::move(t2));\n\n\t\t\t\tstatic_assert(eastl::is_same_v<decltype(result), tuple<int, unique_ptr<bool>, unique_ptr<float>, int>>, \"type mismatch\");\n\t\t\t\t\n\t\t\t\tEATEST_VERIFY(get<0>(result) == 42);\n\t\t\t\tEATEST_VERIFY(get<1>(result) != nullptr && *get<1>(result));\n\t\t\t\tEATEST_VERIFY(get<1>(t1) == nullptr);\n\t\t\t\tEATEST_VERIFY(get<2>(result) != nullptr && *get<2>(result) == 3.14f);\n\t\t\t\tEATEST_VERIFY(get<3>(result) == 1337);\n\t\t\t\tEATEST_VERIFY(get<0>(t2) == nullptr);\n\t\t\t}\n\n\t\t\t// More than two parameters and empty tuples.\n\t\t\t{\n\t\t\t\ttuple<int, bool> t1{42, true};\n\t\t\t\ttuple<unique_ptr<float>, int> t2{new float(3.14f), 1337};\n\t\t\t\ttuple<> t3{};\n\t\t\t\ttuple<unique_ptr<short>> t4{new short(10)};\n\t\t\t\t\n\t\t\t\tauto result = tuple_cat(t1, eastl::move(t2), t3, eastl::move(t4));\n\n\t\t\t\tstatic_assert(eastl::is_same_v<decltype(result), tuple<int, bool, unique_ptr<float>, int, unique_ptr<short>>>, \"type mismatch\");\n\t\t\t\t\n\t\t\t\tEATEST_VERIFY(get<0>(result) == 42);\n\t\t\t\tEATEST_VERIFY(get<1>(result));\n\t\t\t\tEATEST_VERIFY(get<2>(result) != nullptr && *get<2>(result) == 3.14f);\n\t\t\t\tEATEST_VERIFY(get<3>(result) == 1337);\n\t\t\t\tEATEST_VERIFY(get<4>(result) != nullptr && *get<4>(result) == 10);\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\t// Empty tuple\n\t\t\ttuple<> emptyTuple;\n\t\t\tEATEST_VERIFY(tuple_size<decltype(emptyTuple)>::value == 0);\n\t\t\temptyTuple = make_tuple();\n\t\t\tauto anotherEmptyTuple = make_tuple();\n\t\t\tswap(anotherEmptyTuple, emptyTuple);\n\t\t}\n\t}\n\n\t// test piecewise_construct\n\t{\n\t\t{\n\t\t\tstruct local\n\t\t\t{\n\t\t\t\tlocal() = default;\n\t\t\t\tlocal(int a, int b) : mA(a), mB(b) {}\n\n\t\t\t\tint mA = 0;\n\t\t\t\tint mB = 0;\n\t\t\t};\n\n\t\t\tauto t = make_tuple(42, 43);\n\n\t\t\teastl::pair<local, local> p(eastl::piecewise_construct, t, t);\n\n\t\t\tEATEST_VERIFY(p.first.mA  == 42);\n\t\t\tEATEST_VERIFY(p.second.mA == 42);\n\t\t\tEATEST_VERIFY(p.first.mB  == 43);\n\t\t\tEATEST_VERIFY(p.second.mB == 43);\n\t\t}\n\n\t\t{\n\t\t\tstruct local\n\t\t\t{\n\t\t\t\tlocal() = default;\n\t\t\t\tlocal(int a, int b, int c, int d) : mA(a), mB(b), mC(c), mD(d) {}\n\n\t\t\t\tint mA = 0;\n\t\t\t\tint mB = 0;\n\t\t\t\tint mC = 0;\n\t\t\t\tint mD = 0;\n\t\t\t};\n\n\t\t\tauto t = make_tuple(42, 43, 44, 45);\n\n\t\t\teastl::pair<local, local> p(eastl::piecewise_construct, t, t);\n\n\t\t\tEATEST_VERIFY(p.first.mA  == 42);\n\t\t\tEATEST_VERIFY(p.second.mA == 42);\n\n\t\t\tEATEST_VERIFY(p.first.mB  == 43);\n\t\t\tEATEST_VERIFY(p.second.mB == 43);\n\n\t\t\tEATEST_VERIFY(p.first.mC  == 44);\n\t\t\tEATEST_VERIFY(p.second.mC == 44);\n\n\t\t\tEATEST_VERIFY(p.first.mD  == 45);\n\t\t\tEATEST_VERIFY(p.second.mD == 45);\n\t\t}\n\n\t\t{\n\t\t\tstruct local1\n\t\t\t{\n\t\t\t\tlocal1() = default;\n\t\t\t\tlocal1(int a) : mA(a) {}\n\t\t\t\tint mA = 0;\n\t\t\t};\n\n\t\t\tstruct local2\n\t\t\t{\n\t\t\t\tlocal2() = default;\n\t\t\t\tlocal2(char a) : mA(a) {}\n\t\t\t\tchar mA = 0;\n\t\t\t};\n\n\t\t\tauto t1 = make_tuple(42);\n\t\t\tauto t2 = make_tuple('a');\n\n\t\t\teastl::pair<local1, local2> p(eastl::piecewise_construct, t1, t2);\n\n\t\t\tEATEST_VERIFY(p.first.mA  == 42);\n\t\t\tEATEST_VERIFY(p.second.mA == 'a');\n\t\t}\n\t}\n\n\t// apply\n\t{\n\t\t// test with tuples\n\t\t{\n\t\t\t{\n\t\t\t\tauto result = eastl::apply([](int i) { return i; }, make_tuple(1));\n\t\t\t\tEATEST_VERIFY(result == 1);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tauto result = eastl::apply([](int i, int j) { return i + j; }, make_tuple(1, 2));\n\t\t\t\tEATEST_VERIFY(result == 3);\n\t\t\t}\n\n\n\t\t\t{\n\t\t\t\tauto result = eastl::apply([](int i, int j, int k, int m) { return i + j + k + m; }, make_tuple(1, 2, 3, 4));\n\t\t\t\tEATEST_VERIFY(result == 10);\n\t\t\t}\n\t\t}\n\n\t\t// test with pair\n\t\t{\n\t\t\tauto result = eastl::apply([](int i, int j) { return i + j; }, make_pair(1, 2));\n\t\t\tEATEST_VERIFY(result == 3);\n\t\t}\n\n\t\t// test with array\n\t\t{\n\t\t\t// TODO(rparolin):   \n\t\t\t// eastl::array requires eastl::get support before we can support unpacking eastl::arrays with eastl::apply.\n\t\t\t//\n\t\t\t// {\n\t\t\t//     auto result = eastl::apply([](int i) { return i; }, eastl::array<int, 1>{1});\n\t\t\t//     EATEST_VERIFY(result == 1);\n\t\t\t// }\n\t\t\t// {\n\t\t\t//     auto result = eastl::apply([](int i, int j) { return i + j; }, eastl::array<int, 2>{1,2});\n\t\t\t//     EATEST_VERIFY(result == 3);\n\t\t\t// }\n\t\t\t// {\n\t\t\t//     auto result = eastl::apply([](int i, int j, int k, int m) { return i + j + k + m; }, eastl::array<int, 4>{1, 2, 3, 4});\n\t\t\t//     EATEST_VERIFY(result == 10);\n\t\t\t// }\n\t\t}\n\t}\n\n\t// make_from_tuple\n\t{\n\t\t{\n\t\t\tTestObject x = eastl::make_from_tuple<TestObject>(eastl::make_tuple(1, true));\n\t\t\tEATEST_VERIFY(x.mX == 1);\n\t\t\tEATEST_VERIFY(x.mbThrowOnCopy == true);\n\t\t}\n\n\t\t{\n\t\t\tTestObject x = eastl::make_from_tuple<TestObject>(eastl::make_tuple(1, 2, 3));\n\t\t\tEATEST_VERIFY(x.mX == 6);\n\t\t}\n\t}\n\n\t// Compilation test to make sure that the conditionally-explicit cast works\n\t{\n\t\teastl::tuple<int, float, TestObject> arrayTup[] = {\n\t\t\t{1, 1.0f, TestObject(1)},\n\t\t\t{2, 2.0f, TestObject(2)},\n\t\t\t{3, 3.0f, TestObject(3)},\n\t\t\t{4, 4.0f, TestObject(4)}\n\t\t};\n\t\t(void)arrayTup;\n\n#if false\n\t\t// the following code should not compile with conditionally-explicit behaviour (but does with fully implicit behaviour)\n\t\teastl::tuple<eastl::vector<float>, float> arrayOfArrayTup[] = {\n\t\t\t{1.0f, 1.0f},\n\t\t\t{2.0f, 2.0f}\n\t\t};\n\n\t\teastl::tuple<eastl::vector<int>, float> arrayOfArrayTup2[] = {\n\t\t\t{1, 1.0f},\n\t\t\t{2, 2.0f}\n\t\t};\n#endif\n\t}\n\n\t// Compilation test to make sure that we can handle reference to forward-declared types\n\t{\n\t\tstruct ForwardDeclared;\n\n\t\tauto fill_tuple = [](ForwardDeclared& f) {\n\t\t\teastl::tuple<ForwardDeclared&, const ForwardDeclared&> t{f, f};\n\t\t\treturn t;\n\t\t};\n\n\t\tstruct ForwardDeclared\n\t\t{\n\t\t\tint x;\n\t\t};\n\n\t\tForwardDeclared f{666};\n\t\tauto t = fill_tuple(f);\n\n\t\tEATEST_VERIFY(get<0>(t).x == 666);\n\t\tEATEST_VERIFY(get<1>(t).x == 666);\n\t}\n\n\t#ifndef EA_COMPILER_NO_STRUCTURED_BINDING\n\t// tuple structured bindings test \n\t{\n\t\teastl::tuple<int, int, int> t = {1,2,3};\n\t\tauto [x,y,z] = t;\n\t\tEATEST_VERIFY(x == 1);\n\t\tEATEST_VERIFY(y == 2);\n\t\tEATEST_VERIFY(z == 3);\n\t}\n\n\t{ // const unpacking test\n\t\teastl::tuple<int, int, int> t = {1,2,3};\n\t\tconst auto [x,y,z] = t;\n\t\tEATEST_VERIFY(x == 1);\n\t\tEATEST_VERIFY(y == 2);\n\t\tEATEST_VERIFY(z == 3);\n\t}\n\t#endif\n\n\t// user reported regression that exercises type_traits trying to pull out the element_type from \"fancy pointers\"\n\t{\n\t\tauto up = eastl::make_unique<int[]>(100);\n\t\tauto t = eastl::make_tuple(eastl::move(up));\n\n\t\tusing ResultTuple_t = decltype(t);\n\t\tstatic_assert(eastl::is_same_v<ResultTuple_t, eastl::tuple<eastl::unique_ptr<int[]>>>); \n\t\tstatic_assert(eastl::is_same_v<eastl::tuple_element_t<0, ResultTuple_t>, eastl::unique_ptr<int[]>>);\n\t}\n\n\t// user reported issue that a tuple was not default constructible if a tuple element type had no members (ie. is_empty_v<T>).\n\t{\n\t\ttuple<> emptyTuple;\n\t\tEA_UNUSED(emptyTuple);\n\n\t\ttuple<NoDataMembers> tupleWithEmptyMember;\n\t\tEA_UNUSED(tupleWithEmptyMember);\n\t\ttuple<NoDataMembers, int> tupleWithEmptyMember2;\n\t\tEA_UNUSED(tupleWithEmptyMember2);\n\t\ttuple<int, NoDataMembers> tupleWithEmptyMember3;\n\t\tEA_UNUSED(tupleWithEmptyMember3);\n\n\t\tstatic_assert(sizeof(tuple<NoDataMembers, int>) <= sizeof(tuple<int>));\n\t\tstatic_assert(sizeof(tuple<int, NoDataMembers>) <= sizeof(tuple<int>));\n\n\t\ttuple<NoDataMembers> tupleWithEmptyMember4(NoDataMembers{});\n\t\tEA_UNUSED(tupleWithEmptyMember4);\n\n\t\tstruct EmptyNoDefaultCtor\n\t\t{\n\t\t\tEmptyNoDefaultCtor() = delete;\n\t\t\tEmptyNoDefaultCtor(int) {}\n\t\t};\n\n\t\ttuple<EmptyNoDefaultCtor> tupleWithEmptyMember5(EmptyNoDefaultCtor{3});\n\t\tEA_UNUSED(tupleWithEmptyMember5);\n\t}\n\n\t// tests for an empty nested tuple element.\n\t// Empty tuples as elements of a tuple caused compilation errors in get<I>(some-tuple) in an earlier version.\n\t{\n\t\tEATEST_VERIFY(get<0>(tuple<tuple<>>{}) == tuple<>{});\n\t\tEATEST_VERIFY(get<0>(tuple<int, tuple<>>{}) == 0);\n\t\tEATEST_VERIFY(get<1>(tuple<int, tuple<>>{}) == tuple<>{});\n\t\tEATEST_VERIFY(get<0>(tuple<tuple<>, int>{}) == tuple<>{});\n\t\tEATEST_VERIFY(get<1>(tuple<tuple<>, int>{}) == 0);\n\n\t\tEATEST_VERIFY(get<tuple<>>(tuple<tuple<>>{}) == tuple<>{});\n\t\tEATEST_VERIFY(get<int>(tuple<int, tuple<>>{}) == 0);\n\t\tEATEST_VERIFY(get<tuple<>>(tuple<int, tuple<>>{}) == tuple<>{});\n\t\tEATEST_VERIFY(get<tuple<>>(tuple<tuple<>, int>{}) == tuple<>{});\n\t\tEATEST_VERIFY(get<int>(tuple<tuple<>, int>{}) == 0);\n\n\t\t// test special member functions.\n\t\ttuple<tuple<>, int> a;\n\t\ttuple<tuple<>, int> b(a);\n\t\tEATEST_VERIFY(b == a);\n\t\tb = a;\n\t\tEATEST_VERIFY(b == a);\n\t\tb = eastl::move(a);\n\t\tEATEST_VERIFY(b == a);\n\t}\n\n\t{\n\n\t\t// check that we can assign from/to tuples of references.\n\t\tint a{1};\n\t\tint b{2};\n\t\ttuple<int&> t1{a};\n\t\ttuple<int&> t2{b};\n\t\tEATEST_VERIFY(get<0>(t1) == 1);\n\t\tEATEST_VERIFY(get<0>(t2) == 2);\n\n\t\tt1 = eastl::move(t2);\n\t\tEATEST_VERIFY(get<0>(t1) == 2);\n\t\tEATEST_VERIFY(a == 2);\n\n\t\tget<0>(t2) = 3;\n\t\tt1 = t2;\n\t\tEATEST_VERIFY(get<0>(t1) == 3);\n\t\tEATEST_VERIFY(a == 3);\n\t\tEATEST_VERIFY(b == 3);\n\n\t\ta = 1;\n\t\tEATEST_VERIFY(get<0>(t1) == 1);\n\n\t\tconst tuple<int&> t3{b};\n\t\tt1 = t3;\n\t\tEATEST_VERIFY(get<0>(t1) == 3);\n\t}\n\n\t{\n\t\ttuple<NoCopyMove> t;\n\t\t[[maybe_unused]] auto& x = get<0>(t);\n\t}\n\n\t{\n\t\ttuple<NoCopyMoveNonEmpty> t;\n\t\t[[maybe_unused]] auto& x = get<0>(t);\n\t}\n\n\t{\n\t\tNoCopyMove x;\n\t\ttuple<NoCopyMove&> t{x};\n\t\t[[maybe_unused]] auto& y = get<0>(t);\n\t}\n\n\t{\n\t\t// Check that this still compiles:\n\t\tNoCopyMoveNonEmpty x;\n\t\ttuple<NoCopyMoveNonEmpty&> t{x};\n\t\t[[maybe_unused]] auto& y = get<0>(t);\n\t}\n\n\treturn nErrorCount;\n}\n\n#else\n\nint TestTuple() { return 0; }\n\n#endif  // EASTL_TUPLE_ENABLED\n\nEA_RESTORE_VC_WARNING()\n"
  },
  {
    "path": "test/source/TestTupleVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// TestTupleVector.cpp\n//\n// Copyright (c) 2018, Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n\n#include <EASTL/bonus/tuple_vector.h>\n\n#include <EASTL/sort.h>\n\nusing namespace eastl;\n\nint TestTupleVector()\n{\n\tint nErrorCount = 0;\n\n\t// Test push-backs and accessors\n\t{\n\t\ttuple_vector<int> singleElementVec;\n\t\tEATEST_VERIFY(singleElementVec.size() == 0);\n\t\tEATEST_VERIFY(singleElementVec.capacity() == 0);\n\t\tEATEST_VERIFY(singleElementVec.empty() == true);\n\t\tEATEST_VERIFY(singleElementVec.validate());\n\t\tsingleElementVec.push_back_uninitialized();\n\t\tsingleElementVec.push_back(5);\n\t\tEATEST_VERIFY(singleElementVec.size() == 2);\n\t\tEATEST_VERIFY(singleElementVec.capacity() > 0);\n\t\tEATEST_VERIFY(singleElementVec.get<0>()[1] == 5);\n\t\tEATEST_VERIFY(singleElementVec.get<int>()[1] == 5);\n\t\tEATEST_VERIFY(singleElementVec.empty() == false);\n\t\tEATEST_VERIFY(singleElementVec.validate());\n\n\t\ttuple_vector<int, float, bool> complexVec;\n\t\tcomplexVec.reserve(5);\n\t\t{\n\t\t\t// need to call an overload of push_back that specifically grabs lvalue candidates - providing constants tend to prefer rvalue path\n\t\t\tint intArg = 3;\n\t\t\tfloat floatArg = 2.0f;\n\t\t\tbool boolArg = true;\n\t\t\tcomplexVec.push_back(intArg, floatArg, boolArg);\n\t\t}\n\t\tcomplexVec.push_back(1, 4.0f, false);\n\t\tcomplexVec.push_back(2, 1.0f, true);\n\t\t{\n\t\t\ttuple<int, float, bool> complexTup(4, 3.0f, false);\n\t\t\tcomplexVec.push_back(complexTup);\n\t\t}\n\t\tcomplexVec.push_back();\n\t\tEATEST_VERIFY(complexVec.capacity() == 5);\n\t\tEATEST_VERIFY(*(complexVec.get<0>()) == 3);\n\t\tEATEST_VERIFY(complexVec.get<float>()[1] == 4.0f);\n\t\tEATEST_VERIFY(complexVec.get<2>()[2] == complexVec.get<bool>()[2]);\n\t\tEATEST_VERIFY(complexVec.validate());\n\n\t\ttuple<int, float, bool> defaultComplexTup;\n\t\tEATEST_VERIFY(complexVec.at(4) == defaultComplexTup);\n\t\t\n\t\ttuple<int*, float*, bool*> complexPtrTuple = complexVec.data();\n\t\tEATEST_VERIFY(get<0>(complexPtrTuple) != nullptr);\n\t\tEATEST_VERIFY(get<2>(complexPtrTuple)[2] == complexVec.get<2>()[2]);\n\n\t\ttuple<int&, float&, bool&> complexRefTuple = complexVec.at(2);\n\t\ttuple<int&, float&, bool&> complexRefTupleBracket = complexVec[2];\n\t\ttuple<int&, float&, bool&> complexRefTupleFront = complexVec.front();\n\t\ttuple<int&, float&, bool&> complexRefTupleBack = complexVec.back();\n\t\tEATEST_VERIFY(get<2>(complexRefTuple) == complexVec.get<2>()[2]);\n\t\tEATEST_VERIFY(get<1>(complexRefTupleBracket) == 1.0f);\n\t\tEATEST_VERIFY(get<1>(complexRefTupleFront) == 2.0f);\n\t\tEATEST_VERIFY(get<1>(complexRefTupleBack) == 0.0f);\n\n\t\t// verify the equivalent accessors for the const container exist/compile\n\t\t{\n\t\t\tconst tuple_vector<int, float, bool>& constVec = complexVec;\n\n\t\t\tEATEST_VERIFY(constVec.size() == 5);\n\t\t\tEATEST_VERIFY(constVec.capacity() >= constVec.size());\n\t\t\tEATEST_VERIFY(constVec.empty() == false);\n\t\t\tEATEST_VERIFY(constVec.get<1>() == constVec.get<float>());\n\n\t\t\ttuple<const int*, const float*, const bool*> constPtrTuple = constVec.data();\n\t\t\tEATEST_VERIFY(get<0>(constPtrTuple) != nullptr);\n\t\t\tEATEST_VERIFY(get<2>(constPtrTuple)[2] == constVec.get<2>()[2]);\n\n\t\t\ttuple<const int&, const float&, const bool&> constRefTuple = constVec.at(2);\n\t\t\ttuple<const int&, const float&, const bool&> constRefTupleBracket = constVec[2];\n\t\t\ttuple<const int&, const float&, const bool&> constRefTupleFront = constVec.front();\n\t\t\ttuple<const int&, const float&, const bool&> constRefTupleBack = constVec.back();\n\t\t\tEATEST_VERIFY(get<2>(constRefTuple) == constVec.get<2>()[2]);\n\t\t\tEATEST_VERIFY(get<1>(constRefTupleBracket) == 1.0f);\n\t\t\tEATEST_VERIFY(get<1>(constRefTupleFront) == 2.0f);\n\t\t\tEATEST_VERIFY(get<1>(constRefTupleBack) == 0.0f);\n\n\t\t\t// check that return types of const-version of begin and cbegin (etc) match\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.begin()), decltype(constVec.cbegin())>::value, \"error\");\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.end()), decltype(constVec.cend())>::value, \"error\");\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.rbegin()), decltype(constVec.crbegin())>::value, \"error\");\n\t\t\tstatic_assert(eastl::is_same<decltype(constVec.rend()), decltype(constVec.crend())>::value, \"error\");\n\n\t\t\t// check that return type of non-const version of begin and cbegin (etc) do _not_ match\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.begin()), decltype(complexVec.cbegin())>::value, \"error\");\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.end()), decltype(complexVec.cend())>::value, \"error\");\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.rbegin()), decltype(complexVec.crbegin())>::value, \"error\");\n\t\t\tstatic_assert(!eastl::is_same<decltype(complexVec.rend()), decltype(complexVec.crend())>::value, \"error\");\n\n\t\t}\n\t}\n\n\t// test the memory layouts work for aligned structures\n\t{\n\t\tstruct EA_ALIGN(16) AlignTestVec4\n\t\t{\n\t\t\tfloat a[4];\n\t\t\tAlignTestVec4() : a{1.0f, 2.0f, 3.0f, 4.0f} {}\n\t\t};\n\n\t\tstruct AlignTestByte3\n\t\t{\n\t\t\tchar a[3];\n\t\t\tAlignTestByte3() : a{1, 2, 3} {}\n\t\t};\n\n\t\tstruct EA_ALIGN(8) AlignTestFourByte\n\t\t{\n\t\t\tint a[5];\n\t\t\tAlignTestFourByte() : a{-1, -2, -3, -4, -5} {}\n\t\t};\n\n\t\ttuple_vector<bool, AlignTestVec4, AlignTestByte3, AlignTestFourByte> alignElementVec;\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\t\talignElementVec.push_back();\n\n\t\tEATEST_VERIFY((uintptr_t)alignElementVec.get<AlignTestVec4>() % 16 == 0);\n\t\tEATEST_VERIFY((uintptr_t)alignElementVec.get<AlignTestFourByte>() % 8 == 0);\n\t}\n\n\t// Test resize and various modifications\n\t{\n\t\tTestObject::Reset();\n\n\t\ttuple_vector<bool, TestObject, float> testVec;\n\t\ttypedef tuple_vector<bool, TestObject, float>::size_type tuple_vector_size_type;\n\t\ttestVec.reserve(10);\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\ttestVec.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t}\n\t\ttestVec.pop_back();\n\t\tEATEST_VERIFY(testVec.size() == 9);\n\n\t\t// test resize that does destruction of objects\n\t\ttestVec.resize(5);\n\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 5);\n\t\tEATEST_VERIFY(testVec.capacity() == 10);\n\n\t\t// test resize that does default construction of objects\n\t\ttestVec.resize(10);\n\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 10);\n\t\tEATEST_VERIFY(testVec.capacity() == 10);\n\n\t\t// test resize that does default construction of objects and grows the vector\n\t\ttestVec.resize(15);\n\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 15);\n\t\tEATEST_VERIFY(testVec.capacity() > 10);\n\t\tEATEST_VERIFY(testVec.validate());\n\n\t\t// test resize with args that does destruction of objects\n\t\tauto testVecCapacity = testVec.capacity();\n\t\ttestVec.resize(5, true, TestObject(5), 5.0f);\n\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 5);\n\t\tEATEST_VERIFY(testVec.capacity() == testVecCapacity);\n\n\t\t// test resize with args that does construction of objects\n\t\ttestVec.resize(15, true, TestObject(5), 5.0f);\n\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\tEATEST_VERIFY(TestObject::sTOCount == 15);\n\t\tEATEST_VERIFY(testVec.capacity() == testVecCapacity);\n\n\t\t// test resize with args that does construction of objects and grows the vector\n\t\tauto newTestVecSize = testVecCapacity + 5;\n\t\ttestVec.resize(newTestVecSize, true, TestObject(5), 5.0f);\n\t\tEATEST_VERIFY(testVec.size() == newTestVecSize);\n\t\tEATEST_VERIFY(static_cast<tuple_vector_size_type>(TestObject::sTOCount) == newTestVecSize);\n\t\tEATEST_VERIFY(testVec.capacity() > newTestVecSize);\n\t\tEATEST_VERIFY(testVec.validate());\n\t\tfor (unsigned int i = 5; i < newTestVecSize; ++i)\n\t\t{\n\t\t\tEATEST_VERIFY(testVec.get<0>()[i] == true);\n\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == TestObject(5));\n\t\t\tEATEST_VERIFY(testVec.get<2>()[i] == 5.0f);\n\t\t}\n\n\t\t{\n\t\t\ttuple<bool, TestObject, float> resizeTup(true, TestObject(10), 10.0f);\n\t\t\ttypedef tuple_vector<bool, TestObject, float>::size_type tuple_vector_size_type;\n\n\t\t\t// test resize with tuple that does destruction of objects\n\t\t\ttestVecCapacity = testVec.capacity();\n\t\t\tEATEST_VERIFY(testVecCapacity >= 15); // check for next two resizes to make sure we don't grow vec\n\n\t\t\ttestVec.resize(20, resizeTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 20);\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 20 + 1);\n\t\t\tEATEST_VERIFY(testVec.capacity() == testVecCapacity);\n\n\t\t\t// test resize with tuple that does construction of objects\n\t\t\ttestVec.resize(25, resizeTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 25);\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 25 + 1);\n\t\t\tEATEST_VERIFY(testVec.capacity() == testVecCapacity);\n\n\t\t\t// test resize with tuple that does construction of objects and grows the vector\n\t\t\tnewTestVecSize = testVecCapacity + 5;\n\t\t\ttestVec.resize(newTestVecSize, resizeTup);\n\t\t\tEATEST_VERIFY(testVec.size() == newTestVecSize);\n\t\t\tEATEST_VERIFY(static_cast<tuple_vector_size_type>(TestObject::sTOCount) == newTestVecSize + 1);\n\t\t\tEATEST_VERIFY(testVec.capacity() > newTestVecSize);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 5; i < 20; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(testVec.get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t\tfor (unsigned int i = 20; i < testVecCapacity; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<0>()[i] == get<0>(resizeTup));\n\t\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == get<1>(resizeTup));\n\t\t\t\tEATEST_VERIFY(testVec.get<2>()[i] == get<2>(resizeTup));\n\t\t\t}\n\t\t}\n\n\t\t// test other modifiers\n\t\ttestVec.pop_back();\n\t\tEATEST_VERIFY(testVec.size() == newTestVecSize - 1);\n\t\tEATEST_VERIFY(static_cast<decltype(testVec)::size_type>(TestObject::sTOCount) == newTestVecSize - 1); // down 2 from last sTOCount check - resizeTup dtor and pop_back\n\t\t\n\t\tEATEST_VERIFY(testVec.capacity() > newTestVecSize);\n\t\ttestVec.shrink_to_fit();\n\t\tEATEST_VERIFY(testVec.capacity() == testVec.size());\n\t\tEATEST_VERIFY(testVec.validate());\n\n\t\ttestVec.clear();\n\t\tEATEST_VERIFY(testVec.empty());\n\t\tEATEST_VERIFY(testVec.validate());\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\n\t\ttestVec.shrink_to_fit();\n\t\tEATEST_VERIFY(testVec.capacity() == 0);\n\t\tEATEST_VERIFY(testVec.validate());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test insert\n\t{\n\t\tTestObject::Reset();\n\n\t\t// test insert with n values and lvalue args\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\t\t\tbool boolArg = true;\n\t\t\tTestObject toArg = TestObject(0);\n\t\t\tfloat floatArg = 0.0f;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttoArg = TestObject(3);\n\t\t\tfloatArg = 3.0f;\n\t\t\tauto insertIter = testVec.insert(testVec.begin(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(insertIter == testVec.begin());\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(5);\n\t\t\tfloatArg = 5.0f;\n\t\t\tinsertIter = testVec.insert(testVec.end(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\tEATEST_VERIFY(insertIter == testVec.begin() + 3);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(4);\n\t\t\tfloatArg = 4.0f;\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttoArg = TestObject(6);\n\t\t\tfloatArg = 6.0f;\n\t\t\ttestVec.insert(testVec.end(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttoArg = TestObject(1);\n\t\t\tfloatArg = 1.0f;\n\t\t\ttestVec.insert(testVec.begin(), 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttoArg = TestObject(2);\n\t\t\tfloatArg = 2.0f;\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == TestObject(i / 3 + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with lvalue args\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\t\t\tbool boolArg = true;\n\t\t\tTestObject toArg = TestObject(0);\n\t\t\tfloat floatArg = 0.0f;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttoArg = TestObject(3);\n\t\t\tfloatArg = 3.0f;\n\t\t\ttestVec.insert(testVec.begin(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(5);\n\t\t\tfloatArg = 5.0f;\n\t\t\ttestVec.insert(testVec.end(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttoArg = TestObject(4);\n\t\t\tfloatArg = 4.0f;\n\t\t\ttestVec.insert(testVec.begin() + 1, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttoArg = TestObject(6);\n\t\t\tfloatArg = 6.0f;\n\t\t\ttestVec.insert(testVec.end(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttoArg = TestObject(1);\n\t\t\tfloatArg = 1.0f;\n\t\t\ttestVec.insert(testVec.begin(), boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttoArg = TestObject(2);\n\t\t\tfloatArg = 2.0f;\n\t\t\ttestVec.insert(testVec.begin() + 1, boolArg, toArg, floatArg);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with n and tuple\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\t\t\ttuple<bool, TestObject, float> testTup;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(3), 3.0f);\n\t\t\ttestVec.insert(testVec.begin(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(5), 5.0f);\n\t\t\ttestVec.insert(testVec.end(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(4), 4.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(6), 6.0f);\n\t\t\ttestVec.insert(testVec.end(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(1), 1.0f);\n\t\t\ttestVec.insert(testVec.begin(), 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(2), 2.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, 3, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == TestObject(i / 3 + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with tuple\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\t\t\ttuple<bool, TestObject, float> testTup;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(3), 3.0f);\n\t\t\ttestVec.insert(testVec.begin(), testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(5), 5.0f);\n\t\t\ttestVec.insert(testVec.end(), testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(4), 4.0f);\n\t\t\ttestVec.insert(testVec.begin() + 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(6), 6.0f);\n\t\t\ttestVec.insert(testVec.end(), 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(1), 1.0f);\n\t\t\ttestVec.insert(testVec.begin(), 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(2), 2.0f);\n\t\t\ttestVec.insert(testVec.begin() + 1, 1, testTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with initList\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\t\t\ttuple<bool, TestObject, float> testTup;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(3), 3.0f);\n\t\t\ttestVec.insert(testVec.begin(), { \n\t\t\t\t{true, TestObject(3), 3.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(3), 3.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(5), 5.0f);\n\t\t\ttestVec.insert(testVec.end(), { \n\t\t\t\t{true, TestObject(5), 5.0f}, \n\t\t\t\ttestTup, \n\t\t\t\t{true, TestObject(5), 5.0f} \n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(4), 4.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, {\n\t\t\t\t{true, TestObject(4), 4.0f}, \n\t\t\t\ttestTup, \n\t\t\t\t{true, TestObject(4), 4.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(6), 6.0f);\n\t\t\ttestVec.insert(testVec.end(), { \n\t\t\t\t{true, TestObject(6), 6.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(6), 6.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(1), 1.0f);\n\t\t\ttestVec.insert(testVec.begin(), { \n\t\t\t\t{true, TestObject(1), 1.0f}, \n\t\t\t\ttestTup, \n\t\t\t\t{true, TestObject(1), 1.0f}\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestTup = tuple<bool, TestObject, float>(true, TestObject(2), 2.0f);\n\t\t\ttestVec.insert(testVec.begin() + 3, { \n\t\t\t\t{true, TestObject(2), 2.0f},\n\t\t\t\ttestTup,\n\t\t\t\t{true, TestObject(2), 2.0f\n\t\t\t\t} });\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<1>()[i] == TestObject(i / 3 + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with rvalue args\n\t\t{\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> testVec;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin(), 3, MoveOnlyType(3), TestObject(3));\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.end(), 5, MoveOnlyType(5), TestObject(5));\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin() + 1, 4, MoveOnlyType(4), TestObject(4));\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestVec.insert(testVec.end(), 6, MoveOnlyType(6), TestObject(6));\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin(), 1, MoveOnlyType(1), TestObject(1));\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin() + 1, 2, MoveOnlyType(2), TestObject(2));\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<2>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with rvalue tuple\n\t\t{\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> testVec;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin(), forward_as_tuple(3, MoveOnlyType(3), TestObject(3)));\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.end(), forward_as_tuple(5, MoveOnlyType(5), TestObject(5)));\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin() + 1, forward_as_tuple(4, MoveOnlyType(4), TestObject(4)));\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestVec.insert(testVec.end(), forward_as_tuple(6, MoveOnlyType(6), TestObject(6)));\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin(), forward_as_tuple(1, MoveOnlyType(1), TestObject(1)));\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin() + 1, forward_as_tuple(2, MoveOnlyType(2), TestObject(2)));\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<2>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\n\t\t// test insert with iterator range \n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\t\t\ttestVec.reserve(10);\n\n\t\t\t// test insert on empty vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin(), srcVec.begin() + 6, srcVec.begin() + 9);\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\n\t\t\t// test insert to end of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.end(), srcVec.begin() + 12, srcVec.begin() + 15);\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\n\t\t\t// test insert to middle of vector that doesn't cause growth\n\t\t\ttestVec.insert(testVec.begin() + 3, srcVec.begin() + 9, srcVec.begin() + 12);\n\t\t\tEATEST_VERIFY(testVec.size() == 9);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 10);\n\n\t\t\t// test insert to end of vector that causes growth\n\t\t\ttestVec.insert(testVec.end(), srcVec.begin() + 15, srcVec.begin() + 18);\n\t\t\tEATEST_VERIFY(testVec.size() == 12);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 12);\n\n\t\t\t// test insert to beginning of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin(), srcVec.begin(), srcVec.begin() + 3);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 15);\n\n\t\t\t// test insert to middle of vector that causes growth\n\t\t\ttestVec.insert(testVec.begin() + 3, srcVec.begin() + 3, srcVec.begin() + 6);\n\t\t\tEATEST_VERIFY(testVec.size() == 18);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 18);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test assign\n\t{\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\n\t\t\t// test assign that grows the capacity\n\t\t\ttestVec.assign(20, true, TestObject(1), 1.0f);\n\t\t\tEATEST_VERIFY(testVec.size() == 20);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(1), 1.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 20);\n\n\t\t\t// test assign that shrinks the vector\n\t\t\ttestVec.assign(10, true, TestObject(2), 2.0f);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(2), 2.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10);\n\n\t\t\t// test assign for when there's enough capacity\n\t\t\ttestVec.assign(15, true, TestObject(3), 3.0f);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(3), 3.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15);\n\t\t}\n\n\t\t{\n\t\t\ttuple<bool, TestObject, float> srcTup;\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\n\t\t\t// test assign from tuple that grows the capacity\n\t\t\tsrcTup = make_tuple(true, TestObject(1), 1.0f);\n\t\t\ttestVec.assign(20, srcTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 20);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcTup);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 20 + 1);\n\n\t\t\t// test assign from tuple that shrinks the vector\n\t\t\tsrcTup = make_tuple(true, TestObject(2), 2.0f);\n\t\t\ttestVec.assign(10, srcTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcTup);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10 + 1);\n\n\t\t\t// test assign from tuple for when there's enough capacity\n\t\t\tsrcTup = make_tuple(true, TestObject(3), 3.0f);\n\t\t\ttestVec.assign(15, srcTup);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcTup);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15 + 1);\n\t\t}\n\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\n\t\t\t// test assign from iter range that grows the capacity\n\t\t\ttestVec.assign(srcVec.begin() + 5, srcVec.begin() + 15);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcVec[i+5]);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10 + 20);\n\n\t\t\t// test assign from iter range that shrinks the vector\n\t\t\ttestVec.assign(srcVec.begin() + 2, srcVec.begin() + 7);\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcVec[i + 2]);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 5 + 20);\n\n\t\t\t// test assign from iter range for when there's enough capacity\n\t\t\ttestVec.assign(srcVec.begin() + 5, srcVec.begin() + 15);\n\t\t\tEATEST_VERIFY(testVec.size() == 10);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == srcVec[i + 5]);\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10 + 20);\n\t\t}\n\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\n\t\t\t// test assign from initList that grows the capacity\n\t\t\ttestVec.assign({\n\t\t\t\t{ true, TestObject(1), 1.0f }, \n\t\t\t\t{ true, TestObject(2), 2.0f },\n\t\t\t\t{ true, TestObject(3), 3.0f }\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 1), (float)i + 1.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 3);\n\n\t\t\t// test assign from initList that shrinks the vector\n\t\t\ttestVec.assign({\n\t\t\t\t{ true, TestObject(4), 4.0f }\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 4), (float)i + 4.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 1);\n\n\t\t\t// test assign from initList for when there's enough capacity\n\t\t\ttestVec.assign({\n\t\t\t\t{ true, TestObject(5), 5.0f },\n\t\t\t\t{ true, TestObject(6), 6.0f }\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 5), (float)i + 5.0f));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 2);\n\t\t}\n\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test erase functions\n\t{\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\n\t\t\t// test erase on an iter range\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\tauto eraseIter = testVec.erase(testVec.begin() + 5, testVec.begin() + 10);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 5)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 5), (float)(i + 5)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15 + 20);\n\n\t\t\t// test erase on one position\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase(testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 5)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 1), (float)(i + 1)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\n\t\t\t// test erase_unsorted\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase_unsorted(testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.begin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i != 5)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(19), (float)(19)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\t\t}\n\n\t\t// test erase again but with reverse iterators everywhere\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> srcVec;\n\t\t\tfor (unsigned int i = 0; i < 20; ++i)\n\t\t\t{\n\t\t\t\tsrcVec.push_back(true, TestObject(i), (float)i);\n\t\t\t}\n\t\t\ttuple_vector<bool, TestObject, float> testVec;\n\n\t\t\t// test erase on an iter range\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\tauto eraseIter = testVec.erase(testVec.rbegin() + 5, testVec.rbegin() + 10);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 15);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 10)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 5), (float)(i + 5)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 15 + 20);\n\n\t\t\t// test erase on one position\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase(testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i < 14)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i + 1), (float)(i + 1)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\n\t\t\t// test erase_unsorted\n\t\t\ttestVec.assign(srcVec.begin(), srcVec.end());\n\t\t\teraseIter = testVec.erase_unsorted(testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(eraseIter == testVec.rbegin() + 5);\n\t\t\tEATEST_VERIFY(testVec.size() == 19);\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tif (i != 14)\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(i), (float)i));\n\t\t\t\telse\n\t\t\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(true, TestObject(19), (float)(19)));\n\t\t\t}\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 19 + 20);\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t{\n\t\t// Regression test, make sure we can sort tuple_vectors\n\t\ttuple_vector<int> testVec;\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\ttestVec.push_back(i);\n\t\t}\n\n\t\teastl::sort(testVec.begin(), testVec.end(),\n\t\t            [](auto&& l, auto&& r) { return get<0>(l) > get<0>(r); });\n\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\tint val = 9 - i;\n\t\t\tEATEST_VERIFY(testVec[i] == make_tuple(val));\n\t\t}\n\t}\n\n\t// Test multitude of constructors\n\t{\n\t\tMallocAllocator ma;\n\t\tTestObject::Reset();\n\n\t\t// test ctor via initlist to prime srcVec\n\t\ttuple_vector<bool, TestObject, float> srcVec({\n\t\t\t{ true,  TestObject(0), 0.0f},\n\t\t\t{ false, TestObject(1), 1.0f},\n\t\t\t{ false, TestObject(2), 2.0f},\n\t\t\t{ true,  TestObject(3), 3.0f},\n\t\t\t{ false, TestObject(4), 4.0f},\n\t\t\t{ false, TestObject(5), 5.0f},\n\t\t\t{ true,  TestObject(6), 6.0f},\n\t\t\t{ false, TestObject(7), 7.0f},\n\t\t\t{ false, TestObject(8), 8.0f},\n\t\t\t{ true,  TestObject(9), 9.0f}\n\t\t\t});\n\n\t\t// copy entire tuple_vector in ctor\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> ctorFromConstRef(srcVec);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.get<2>()[i] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// copy entire tuple_vector via assignment\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> ctorFromAssignment;\n\t\t\tctorFromAssignment = srcVec;\n\t\t\tEATEST_VERIFY(ctorFromAssignment.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromAssignment.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.get<2>()[i] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// copy entire tuple_vector via assignment of init-list\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> ctorFromAssignment;\n\t\t\tctorFromAssignment = { \n\t\t\t\t{ true,  TestObject(0), 0.0f},\n\t\t\t\t{ false, TestObject(1), 1.0f},\n\t\t\t\t{ false, TestObject(2), 2.0f},\n\t\t\t\t{ true,  TestObject(3), 3.0f},\n\t\t\t\t{ false, TestObject(4), 4.0f},\n\t\t\t\t{ false, TestObject(5), 5.0f},\n\t\t\t\t{ true,  TestObject(6), 6.0f},\n\t\t\t\t{ false, TestObject(7), 7.0f},\n\t\t\t\t{ false, TestObject(8), 8.0f},\n\t\t\t\t{ true,  TestObject(9), 9.0f}\n\t\t\t};\n\t\t\tEATEST_VERIFY(ctorFromAssignment.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromAssignment.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromAssignment.get<2>()[i] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with iterator range\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> ctorFromIters(srcVec.begin() + 2, srcVec.begin() + 7);\n\t\t\tEATEST_VERIFY(ctorFromIters.size() == 5);\n\t\t\tEATEST_VERIFY(ctorFromIters.validate());\n\t\t\tfor (int i = 2; i < 7; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromIters.get<0>()[i - 2] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromIters.get<1>()[i - 2] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromIters.get<2>()[i - 2] == (float)i);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with initial size\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> ctorFromFill(10);\n\t\t\tEATEST_VERIFY(ctorFromFill.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFill.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFill.get<0>()[i] == false);\n\t\t\t\tEATEST_VERIFY(ctorFromFill.get<1>()[i] == TestObject());\n\t\t\t\tEATEST_VERIFY(ctorFromFill.get<2>()[i] == 0.0f);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with initial size and args\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float> ctorFromFillArgs(10, true, TestObject(5), 5.0f);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector with initial size and tuple\n\t\t{\n\t\t\ttuple<bool, TestObject, float> tup(true, TestObject(5), 5.0f);\n\t\t\ttuple_vector<bool, TestObject, float> ctorFromFillTup(10, tup);\n\t\t\tEATEST_VERIFY(ctorFromFillTup.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFillTup.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFillTup.get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(ctorFromFillTup.get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(ctorFromFillTup.get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_Vector with custom mallocator\n\t\t{\n\t\t\ttuple_vector_alloc<MallocAllocator, bool, TestObject, float> ctorWithAlloc(ma);\n\t\t\ttuple_vector<bool, TestObject, float> ctorDefault;\n\n\t\t\tctorWithAlloc.push_back();\n\t\t\tctorDefault.push_back();\n\n\t\t\tEATEST_VERIFY(ctorWithAlloc == ctorDefault);\n\t\t\tEATEST_VERIFY(ctorWithAlloc.validate());\n\t\t}\n\n\t\t// ctor tuple_vector_alloc with copy (from diff. allocator)\n\t\t{\n\t\t\ttuple_vector_alloc<MallocAllocator, bool, TestObject, float> ctorFromConstRef(srcVec, ma);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromConstRef.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.get<0>()[i] == (i % 3 == 0));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.get<1>()[i] == TestObject(i));\n\t\t\t\tEATEST_VERIFY(ctorFromConstRef.get<2>()[i] == (float)i);\n\t\t\t}\n\t\t\tEATEST_VERIFY(ctorFromConstRef.validate());\n\t\t}\n\n\t\t// ctor tuple_vector with initial size and args\n\t\t{\n\t\t\ttuple_vector_alloc<MallocAllocator, bool, TestObject, float> ctorFromFillArgs(10, true, TestObject(5), 5.0f, ma);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromFillArgs.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.get<0>()[i] == true);\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.get<1>()[i] == TestObject(5));\n\t\t\t\tEATEST_VERIFY(ctorFromFillArgs.get<2>()[i] == 5.0f);\n\t\t\t}\n\t\t}\n\n\t\t// ctor tuple_vector via move\n\t\t{\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> srcMoveVec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tsrcMoveVec.emplace_back(move(i), MoveOnlyType(i), TestObject(i));\n\t\t\t}\n\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> ctorFromMove(move(srcMoveVec));\n\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(srcMoveVec.size() == 0);\n\t\t\tEATEST_VERIFY(srcMoveVec.validate());\n\t\t}\n\n\t\t// ctor tuple_vector via move (from diff. allocator)\n\t\t{\n\t\t\ttuple_vector_alloc<MallocAllocator, int, MoveOnlyType, TestObject> srcMoveVec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tsrcMoveVec.emplace_back(move(i), MoveOnlyType(i), TestObject(i));\n\t\t\t}\n\n\t\t\tMallocAllocator otherMa;\n\t\t\ttuple_vector_alloc<MallocAllocator, int, MoveOnlyType, TestObject> ctorFromMove(move(srcMoveVec), otherMa);\n\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(srcMoveVec.size() == 0);\n\t\t\tEATEST_VERIFY(srcMoveVec.validate());\n\t\t\t\n\t\t\t// bonus test for specifying a custom allocator, but using the same one as above\n\t\t\ttuple_vector_alloc<MallocAllocator, int, MoveOnlyType, TestObject> ctorFromMoveSameAlloc(move(ctorFromMove), otherMa);\n\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.size() == 10);\n\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.validate());\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMoveSameAlloc.get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 0);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t}\n\n\t\t// ctor tuple_vector via move-iters\n\t\t{\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> srcMoveVec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tsrcMoveVec.emplace_back(move(i), MoveOnlyType(i), TestObject(i));\n\t\t\t}\n\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> ctorFromMove(make_move_iterator(srcMoveVec.begin() + 2), make_move_iterator(srcMoveVec.begin() + 7));\n\n\t\t\tEATEST_VERIFY(ctorFromMove.size() == 5);\n\t\t\tEATEST_VERIFY(ctorFromMove.validate());\n\t\t\tfor (int i = 2; i < 7; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<0>()[i-2] == i);\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<1>()[i-2] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(ctorFromMove.get<2>()[i-2] == TestObject(i));\n\t\t\t}\n\t\t\tEATEST_VERIFY(srcMoveVec.size() == 10);\n\t\t\tEATEST_VERIFY(srcMoveVec.validate());\n\t\t\tfor (int i = 0; i < 2; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t\tfor (int i = 2; i < 7; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<0>()[i] == i); // int's just get copied because they're POD\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<1>()[i] == MoveOnlyType(0));\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<2>()[i] == TestObject(0));\n\t\t\t}\n\t\t\tfor (int i = 7; i < 10; ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<0>()[i] == i);\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<1>()[i] == MoveOnlyType(i));\n\t\t\t\tEATEST_VERIFY(srcMoveVec.get<2>()[i] == TestObject(i));\n\t\t\t}\n\t\t}\n\n\t\tsrcVec.clear();\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\n\t\tTestObject::Reset();\n\t}\n\n\t// Test swap\n\t{\n\t\ttuple_vector<int, float, bool> complexVec;\n\t\tcomplexVec.push_back(3, 2.0f, true);\n\t\tcomplexVec.push_back(1, 4.0f, false);\n\t\tcomplexVec.push_back(2, 1.0f, true);\n\t\tcomplexVec.push_back(4, 3.0f, false);\n\n\t\ttuple_vector<int, float, bool> otherComplexVec;\n\t\tcomplexVec.swap(otherComplexVec);\n\n\t\tEATEST_VERIFY(complexVec.size() == 0);\n\t\tEATEST_VERIFY(complexVec.validate());\n\t\tEATEST_VERIFY(otherComplexVec.validate());\n\t\tEATEST_VERIFY(otherComplexVec.get<0>()[0] == 3);\n\t\tEATEST_VERIFY(otherComplexVec.get<float>()[1] == 4.0f);\n\n\t\tcomplexVec.push_back(10, 10.0f, true);\n\t\tswap(complexVec, otherComplexVec);\n\n\t\tEATEST_VERIFY(complexVec.validate());\n\t\tEATEST_VERIFY(*(complexVec.get<0>()) == 3);\n\t\tEATEST_VERIFY(complexVec.get<float>()[1] == 4.0f);\n\n\t\tEATEST_VERIFY(otherComplexVec.validate());\n\t\tEATEST_VERIFY(otherComplexVec.get<float>()[0] == 10.0f);\n\t\tEATEST_VERIFY(otherComplexVec.size() == 1);\n\n\t}\n\n\n\t// Test tuple_Vector in a ranged for, and other large-scale iterator testing\n\t{\n\t\ttuple_vector<int, float, int> tripleElementVec;\n\t\ttripleElementVec.push_back(1, 2.0f, 6);\n\t\ttripleElementVec.push_back(2, 3.0f, 7);\n\t\ttripleElementVec.push_back(3, 4.0f, 8);\n\t\ttripleElementVec.push_back(4, 5.0f, 9);\n\t\ttripleElementVec.push_back(5, 6.0f, 10);\n\n\n\t\t// test copyConstructible, copyAssignable, swappable, prefix inc, !=, reference convertible to value_type (InputIterator!)\n\t\t{\n\t\t\ttuple_vector<int, float, int>::iterator iter = tripleElementVec.begin();\n\t\t\t++iter;\n\t\t\tauto copiedIter(iter);\n\t\t\tEATEST_VERIFY(get<2>(*copiedIter) == 7);\n\t\t\tEATEST_VERIFY(copiedIter == iter);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(copiedIter) != isf_none);\n\n\t\t\t++iter;\n\t\t\tcopiedIter = iter;\n\t\t\tEATEST_VERIFY(get<2>(*copiedIter) == 8);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(copiedIter) != isf_none);\n\n\t\t\t++iter;\n\t\t\tswap(iter, copiedIter);\n\t\t\tEATEST_VERIFY(get<2>(*iter) == 8);\n\t\t\tEATEST_VERIFY(get<2>(*copiedIter) == 9);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(copiedIter) != isf_none);\n\n\t\t\tEATEST_VERIFY(copiedIter != iter);\n\n\t\t\ttuple<const int&, const float&, const int&> ref(*iter);\n\t\t\ttuple<int, float, int> value(*iter);\n\t\t\tEATEST_VERIFY(get<2>(ref) == get<2>(value));\n\t\t}\n\n\t\t// test postfix increment, default constructible (ForwardIterator)\n\t\t{\n\t\t\ttuple_vector<int, float, int>::iterator iter = tripleElementVec.begin();\n\t\t\tauto prefixIter = ++iter;\n\t\t\t\n\t\t\ttuple_vector<int, float, int>::iterator postfixIter;\n\t\t\tpostfixIter = iter++;\n\t\t\tEATEST_VERIFY(prefixIter == postfixIter);\n\t\t\tEATEST_VERIFY(get<2>(*prefixIter) == 7);\n\t\t\tEATEST_VERIFY(get<2>(*iter) == 8);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(prefixIter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(postfixIter) != isf_none);\n\t\t}\n\n\t\t// test prefix decrement and postfix decrement (BidirectionalIterator)\n\t\t{\n\t\t\ttuple_vector<int, float, int>::iterator iter = tripleElementVec.end();\n\t\t\tauto prefixIter = --iter;\n\n\t\t\ttuple_vector<int, float, int>::iterator postfixIter;\n\t\t\tpostfixIter = iter--;\n\t\t\tEATEST_VERIFY(prefixIter == postfixIter);\n\t\t\tEATEST_VERIFY(get<2>(*prefixIter) == 10);\n\t\t\tEATEST_VERIFY(get<2>(*iter) == 9);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(prefixIter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(postfixIter) != isf_none);\n\t\t}\n\n\t\t// test many arithmetic operations (RandomAccessIterator)\n\t\t{\n\t\t\ttuple_vector<int, float, int>::iterator iter = tripleElementVec.begin();\n\t\t\tauto symmetryOne = iter + 2;\n\t\t\tauto symmetryTwo = 2 + iter;\n\t\t\titer += 2;\n\t\t\tEATEST_VERIFY(symmetryOne == symmetryTwo);\n\t\t\tEATEST_VERIFY(symmetryOne == iter);\n\n\t\t\tsymmetryOne = iter - 2;\n\t\t\tsymmetryTwo = 2 - iter;\n\t\t\titer -= 2;\n\t\t\tEATEST_VERIFY(symmetryOne == symmetryTwo);\n\t\t\tEATEST_VERIFY(symmetryOne == iter);\n\n\t\t\titer += 2;\n\t\t\tEATEST_VERIFY(iter - symmetryOne == 2);\n\n\t\t\ttuple<int&, float&, int&> symmetryRef = symmetryOne[2];\n\t\t\tEATEST_VERIFY(get<2>(symmetryRef) == get<2>(*iter));\n\n\t\t\tEATEST_VERIFY(symmetryOne < iter);\n\t\t\tEATEST_VERIFY(iter > symmetryOne);\n\t\t\tEATEST_VERIFY(symmetryOne >= symmetryTwo && iter >= symmetryOne);\n\t\t\tEATEST_VERIFY(symmetryOne <= symmetryTwo && symmetryOne <= iter);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(iter) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(symmetryOne) != isf_none);\n\t\t\tEATEST_VERIFY(tripleElementVec.validate_iterator(symmetryTwo) != isf_none);\n\t\t}\n\n\t\t// test simple iteration, and reverse iteration\n\t\t{\n\t\t\tfloat i = 0;\n\t\t\tint j = 0;\n\t\t\tEATEST_VERIFY(&get<0>(*tripleElementVec.begin()) == tripleElementVec.get<0>());\n\t\t\tEATEST_VERIFY(&get<1>(*tripleElementVec.begin()) == tripleElementVec.get<1>());\n\t\t\tfor (auto iter : tripleElementVec)\n\t\t\t{\n\t\t\t\ti += get<1>(iter);\n\t\t\t\tj += get<2>(iter);\n\t\t\t}\n\t\t\tEATEST_VERIFY(i == 20.0f);\n\t\t\tEATEST_VERIFY(j == 40);\n\n\t\t\tfloat reverse_i = 0;\n\t\t\tint reverse_j = 0;\n\n\t\t\teastl::for_each(tripleElementVec.rbegin(), tripleElementVec.rend(),\n\t\t\t\t[&](const tuple<int, float, int> tup)\n\t\t\t\t{\n\t\t\t\t\treverse_i += get<1>(tup);\n\t\t\t\t\treverse_j += get<2>(tup);\n\t\t\t\t});\n\t\t\tEATEST_VERIFY(i == reverse_i);\n\t\t\tEATEST_VERIFY(j == reverse_j);\n\t\t\tEATEST_VERIFY(get<0>(*tripleElementVec.rbegin()) == 5);\n\t\t}\n\t}\n\n\t// Test move operations\n\t{\n\t\tTestObject::Reset();\n\n\t\t// test emplace \n\t\t{\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> testVec;\n\t\t\ttestVec.reserve(3);\n\n\t\t\t// test emplace on empty vector that doesn't cause growth\n\t\t\ttestVec.emplace(testVec.begin(), 3, MoveOnlyType(3), TestObject(3));\n\t\t\tEATEST_VERIFY(testVec.size() == 1);\n\n\t\t\t// test emplace to end of vector that doesn't cause growth\n\t\t\ttestVec.emplace(testVec.end(), 5, MoveOnlyType(5), TestObject(5));\n\t\t\tEATEST_VERIFY(testVec.size() == 2);\n\n\t\t\t// test emplace to middle of vector that doesn't cause growth\n\t\t\ttestVec.emplace(testVec.begin() + 1, 4, MoveOnlyType(4), TestObject(4));\n\t\t\tEATEST_VERIFY(testVec.size() == 3);\n\t\t\tEATEST_VERIFY(testVec.capacity() == 3);\n\n\t\t\t// test emplace to end of vector that causes growth\n\t\t\ttestVec.emplace(testVec.end(), 6, MoveOnlyType(6), TestObject(6));\n\t\t\tEATEST_VERIFY(testVec.size() == 4);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 4);\n\n\t\t\t// test emplace to beginning of vector that causes growth\n\t\t\ttestVec.emplace(testVec.begin(), 1, MoveOnlyType(1), TestObject(1));\n\t\t\tEATEST_VERIFY(testVec.size() == 5);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 5);\n\n\t\t\t// test emplace to middle of vector that causes growth\n\t\t\ttestVec.emplace(testVec.begin() + 1, 2, MoveOnlyType(2), TestObject(2));\n\t\t\tEATEST_VERIFY(testVec.size() == 6);\n\t\t\ttestVec.shrink_to_fit();\n\t\t\tEATEST_VERIFY(testVec.capacity() == 6);\n\n\t\t\tfor (unsigned int i = 0; i < testVec.size(); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(testVec.get<2>()[i] == TestObject(i + 1));\n\t\t\t}\n\t\t\tEATEST_VERIFY(testVec.validate());\n\t\t}\n\t\n\t\t// test some other miscellania around rvalues, including...\n\t\t// push_back with rvalue args, push_back with rvalue tuple,\n\t\t// emplace_back with args, and emplace_back with tup\n\t\t{\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> v1;\n\t\t\ttuple_vector<int, MoveOnlyType, TestObject> v2;\n\t\t\t// add some data in the vector so we can move it to the other vector.\n\t\t\tv1.reserve(5);\n\t\t\tauto emplacedTup = v1.emplace_back(1, MoveOnlyType(1), TestObject(1));\n\t\t\tEATEST_VERIFY(emplacedTup == v1.back());\n\t\t\tv1.push_back(3, MoveOnlyType(3), TestObject(3));\n\t\t\tv1.emplace_back(forward_as_tuple(5, MoveOnlyType(5), TestObject(5)));\n\t\t\tv1.push_back(forward_as_tuple(6, MoveOnlyType(6), TestObject(6)));\n\t\t\tv1.emplace(v1.begin() + 1, 2, MoveOnlyType(2), TestObject(2));\n\t\t\tv1.emplace(v1.begin() + 3, make_tuple(4, MoveOnlyType(4), TestObject(4)));\n\n\t\t\ttuple<int&, MoveOnlyType&, TestObject&> movedTup = v1.at(0);\n\t\t\tEATEST_VERIFY(v1.validate());\n\t\t\tEATEST_VERIFY(get<0>(movedTup) == 1);\n\t\t\tEATEST_VERIFY(get<0>(*v1.begin()) == 1);\n\n\t\t\tfor (int i = 0; i < static_cast<int>(v1.size()); ++i)\n\t\t\t{\n\t\t\t\tEATEST_VERIFY(v1.get<0>()[i] == i + 1);\n\t\t\t}\n\t\t\tEATEST_VERIFY(!v1.empty() && v2.empty());\n\t\t\tv2 = eastl::move(v1);\n\t\t\tEATEST_VERIFY(v2.validate());\n\t\t\tEATEST_VERIFY(v1.empty() && !v2.empty());\n\t\t\tv1.swap(v2);\n\t\t\tEATEST_VERIFY(v1.validate());\n\t\t\tEATEST_VERIFY(v2.validate());\n\t\t\tEATEST_VERIFY(!v1.empty() && v2.empty());\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test comparisons\n\t{\n\t\tMallocAllocator ma;\n\t\ttuple_vector<bool, TestObject, float> equalsVec1, equalsVec2;\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\tequalsVec1.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t\tequalsVec2.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t}\n\t\tEATEST_VERIFY(equalsVec1 == equalsVec2);\n\n\t\ttuple_vector<bool, TestObject, float> smallSizeVec(5);\n\t\ttuple_vector<bool, TestObject, float> lessThanVec(10);\n\t\ttuple_vector_alloc<MallocAllocator, bool, TestObject, float> greaterThanVec(10, ma);\n\t\tfor (int i = 0; i < 10; ++i)\n\t\t{\n\t\t\tlessThanVec.push_back(i % 3 == 0, TestObject(i), (float)i);\n\t\t\tgreaterThanVec.push_back(i % 3 == 0, TestObject(i * 2), (float)i * 2);\n\t\t}\n\t\tEATEST_VERIFY(equalsVec1 != smallSizeVec);\n\t\tEATEST_VERIFY(equalsVec1 != lessThanVec);\n\t\tEATEST_VERIFY(equalsVec1 != greaterThanVec);\n\t\tEATEST_VERIFY(lessThanVec < greaterThanVec);\n\t\tEATEST_VERIFY(greaterThanVec > lessThanVec);\n\t\tEATEST_VERIFY(lessThanVec <= greaterThanVec);\n\t\tEATEST_VERIFY(equalsVec1 <= equalsVec2);\n\t\tEATEST_VERIFY(equalsVec1 >= equalsVec2);\n\t}\n\n\t// Test partition\n\t{\n\t\t{\n\t\t\ttuple_vector<bool, TestObject, float, MoveOnlyType> vec;\n\t\t\tfor (int i = 0; i < 10; ++i)\n\t\t\t{\n\t\t\t\tvec.push_back(i % 3 == 0, TestObject(i), (float)i, MoveOnlyType(i));\n\t\t\t}\n\n\t\t\teastl::partition(vec.begin(), vec.end(), [](tuple<bool&, TestObject&, float&, MoveOnlyType&> a)\n\t\t\t{ return get<0>(a) == true; });\n\n\t\t\t// partition will split the array into 4 elements where the bool property is true, and 6 where it's false\n\t\t\tfor (int i = 0; i < 4; ++i)\n\t\t\t\tEATEST_VERIFY(vec.get<0>()[i] == true);\n\t\t\tfor (int i = 4; i < 10; ++i)\n\t\t\t\tEATEST_VERIFY(vec.get<0>()[i] == false);\n\n\t\t\tEATEST_VERIFY(vec.validate());\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == 10);\n\t\t}\n\t\tEATEST_VERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// Test allocator manipulation\n\t{\n\t\tInstanceAllocator ia0((uint8_t)0), ia1((uint8_t)1);\n\t\ttuple_vector_alloc<InstanceAllocator, int> vec(ia0);\n\n\t\t// private vector allocator was copied from ia0 and should have matching id\n\t\tEATEST_VERIFY(vec.get_allocator() == ia0);\n\n\t\t// Assigning allocator\n\t\tvec.set_allocator(ia1);\n\t\tEATEST_VERIFY(vec.get_allocator() == ia1);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n"
  },
  {
    "path": "test/source/TestTypeTraits.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/type_traits.h>\n#include <EASTL/vector.h>\n#include <EAStdC/EAAlignment.h>\n#include \"ConceptImpls.h\"\n\n\n\nusing namespace eastl;\n\n\nbool GetType(const true_type&)\n{\n\treturn true;\n}\n\nbool GetType(const false_type&)\n{\n\treturn false;\n}\n\nint GetType(const integral_constant<size_t, (size_t)4>&)\n{\n\treturn 4;\n}\n\nint GetType(const integral_constant<size_t, (size_t)8>&)\n{\n\treturn 8;\n}\n\nint GetType(const integral_constant<size_t, (size_t)16>&)\n{\n\treturn 16;\n}\n\nint GetType(const integral_constant<size_t, (size_t)32>&)\n{\n\treturn 32;\n}\n\n#ifdef _MSC_VER\n\t__declspec(align(32)) class ClassAlign32{ };\n#else\n\tclass ClassAlign32{ } __attribute__((aligned(32)));\n#endif\n\n\nstruct Struct\n{\n\t// Empty\n};\n\nclass Class\n{\n\t// Empty\n};\n\nclass Subclass : public Class\n{\n\t// Empty\n};\n\nclass ClassEmpty\n{\n\t// Empty\n};\n\nclass ClassNonEmpty\n{\npublic:\n\tint x;\n};\n\nenum Enum\n{\n\tkValue1\n};\n\nunion Union\n{\n\tint   x;\n\tshort y;\n};\n\nstruct FinalStruct final\n{\n};\n\nclass FinalClass final\n{\n};\n\n\n\n// Used for union_cast tests below.\n// C++11 allows for PodA/PodB to have a trivial default (i.e. compiler-generated) constructor,\n// but as of this writing (3/2012) most C++ compilers don't have support for this yet.\nstruct PodA{\n\tint mX;\n};\n\nstruct PodB{\n\tint mX;\n};\n\nbool operator ==(const PodA& a1, const PodA& a2) { return (a1.mX == a2.mX); }\n\n\n// std::tr1::is_volatile<T>::value == true if and only if, for a given type T:\n//   * std::tr1::is_scalar<T>::value == true, or\n//   * T is a class or struct that has no user-defined copy assignment operator or destructor, \n//     and T has no non-static data members M for which is_pod<M>::value == false, and no members of reference type, or\n//   * T is the type of an array of objects E for which is_pod<E>::value == true\n// is_pod may only be applied to complete types.\n\nstruct Pod1\n{\n\t// Empty\n};\n\n\nstruct Pod2\n{\n\tint  mX;\n\tPod1 mPod1;\n};\n\nstruct Pod3\n{\n\tPod2 mPod2;\n\tint  mX;\n\tPod1 mPod1;\n};\n\n\nstruct NonPod1\n{\n\tNonPod1(){}\n\tvirtual ~NonPod1(){}\n};\n\nstruct NonPod2\n{\n\tvirtual ~NonPod2(){}\n\tvirtual void Function(){}\n};\n\nstruct HasIncrementOperator { HasIncrementOperator& operator++() { return *this; } };\n\ntemplate <class T>\nusing has_increment_operator_detection = decltype(++eastl::declval<T>());\n\ntemplate<typename, typename = eastl::void_t<>>\nstruct has_increment_operator_using_void_t : eastl::false_type {};\n\ntemplate <typename T>\nstruct has_increment_operator_using_void_t<T, eastl::void_t<has_increment_operator_detection<T>>> : eastl::true_type {};\n\n\n// We use this for the is_copy_constructible test in order to verify that \n// is_copy_constructible in fact returns false for this type and not true.\n// std::is_copy_constructible specification: std::is_constructible<T, const T&>::value is true.\n// Note that the specification refers to const T& and not T&. So we rig our class to \n// accept T& and not const T&. This situation is significant because as of this\n// writing the clang <type_traits> implementation appears to be broken and mis-implements\n// the is_copy_constructible type trait to return true for ConstructibleOnlyWithNonConstReference \n// when in fact it should return false.\nEA_DISABLE_VC_WARNING(4521) // disable warning : \"multiple copy constructors specified\"\nstruct ConstructibleOnlyWithNonConstReference\n{\n\tConstructibleOnlyWithNonConstReference(ConstructibleOnlyWithNonConstReference&) {}\n\n\t#if defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\t\tprivate: ConstructibleOnlyWithNonConstReference() {}\n\t\tprivate: ConstructibleOnlyWithNonConstReference(const ConstructibleOnlyWithNonConstReference&) {}\n\t#else\n\t\tConstructibleOnlyWithNonConstReference() = delete;\n\t\tConstructibleOnlyWithNonConstReference(const ConstructibleOnlyWithNonConstReference&) = delete;\n\t#endif\n};\nEA_RESTORE_VC_WARNING()\n\n#if defined(EA_COMPILER_NO_NOEXCEPT)\n\t//This is needed because VS2013 supports is_nothrow__xxx type traits but doesn't support C++11 noexcept.\n\t//So we use throw() to allow the is_nothrow_xxxx and similiar tests to work in VS2013\n\t#define EASTL_TEST_NOEXCEPT throw()\n#else\n\t#define EASTL_TEST_NOEXCEPT EA_NOEXCEPT\n#endif\n\nstruct ThrowConstructibleTest\n{\n\tThrowConstructibleTest(const int = 0) EASTL_TEST_NOEXCEPT { }\n\tThrowConstructibleTest(const float) EA_NOEXCEPT_IF(false) { }\n};\n\n\n\nstruct NoThrowAssignable { };\n\nstruct ThrowAssignableTest\n{\n\tvoid operator=(const NoThrowAssignable&) EASTL_TEST_NOEXCEPT { }\n\tvoid operator=(const ThrowAssignableTest&) { }\n};\n\n\nstruct NoThrowDestructible\n{\n\t~NoThrowDestructible() EASTL_TEST_NOEXCEPT {}\n};\n\n#if !defined(EA_COMPILER_NO_EXCEPTIONS)\n\tstruct ThrowDestructible\n\t{\n\t\t~ThrowDestructible() noexcept(false) { throw(int()); }\n\t};\n\n\tstruct ThrowDestructibleNoexceptFalse\n\t{\n\t\tvirtual ~ThrowDestructibleNoexceptFalse() EA_NOEXCEPT_IF(false) {  }\n\t};\n#endif\n\n\nstruct HasTrivialConstructor\n{\n\tint x;\n};\n\n\nstruct NoTrivialConstructor\n{\n\tNoTrivialConstructor() { px = &x; }\n\tint  x;\n\tint* px;\n};\n\n\nstruct HasTrivialCopy\n{\n\tvoid Function(){}\n\tint x;\n};\n\n\n#if defined(EA_COMPILER_MSVC) && (_MSC_VER == 1900)\n\t// http://blogs.msdn.com/b/vcblog/archive/2014/06/06/c-14-stl-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1.aspx\n\t// VS2015-preview has a bug regarding C++14 implicit noexcept rules for destructors.  We explicitly define noexcept below for VS2015-preview only.\n\t//\n\t// Re-evaluate when VS2015 RTM has been released.\n\t//\n\tstruct NoTrivialCopy1\n\t{\n\t\tvirtual ~NoTrivialCopy1() EASTL_TEST_NOEXCEPT {} \n\t\tvirtual void Function(){}\n\t};\n#else\n\tstruct NoTrivialCopy1\n\t{\n\t\tvirtual ~NoTrivialCopy1() {}  \n\t\tvirtual void Function(){}\n\t};\n#endif\n\nstruct NonCopyable\n{\n\tNonCopyable() : mX(0) {}\n\tNonCopyable(int x) : mX(x) {}\n\n\tint mX;\n\n\tEA_NON_COPYABLE(NonCopyable)\n};\n\nstruct Polymorphic1\n{\n\tvirtual ~Polymorphic1(){}\n\tvirtual void Function(){}\n};\n\nstruct Polymorphic2 : public Polymorphic1\n{\n\t// Empty\n};\n\nstruct Polymorphic3\n{\n\tvirtual ~Polymorphic3(){}\n\tvirtual void Function() = 0;\n};\n\nstruct NonPolymorphic1\n{\n\tvoid Function(){}\n};\n\n// Disable the following warning:\n//     warning: ‘struct Abstract’ has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]\n// We explicitly want this class not to have a virtual destructor to test our type traits.\nEA_DISABLE_VC_WARNING(4265)\nEA_DISABLE_CLANG_WARNING(-Wnon-virtual-dtor)\nEA_DISABLE_GCC_WARNING(-Wnon-virtual-dtor)\nstruct Abstract\n{\n\tvirtual void Function() = 0;\n};\nEA_RESTORE_GCC_WARNING()\nEA_RESTORE_CLANG_WARNING()\nEA_RESTORE_VC_WARNING()\n\nstruct AbstractWithDtor\n{\n\tvirtual ~AbstractWithDtor(){}\n\tvirtual void Function() = 0;\n};\n\nstruct DeletedDtor\n{\n\t#if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\t\t~DeletedDtor() = delete;\n\t#endif\n};\n\nstruct Assignable\n{\n\tvoid operator=(const Assignable&){}\n\tvoid operator=(const Pod1&){}\n};\n\n\n\n// This class exercises is_convertible for the case that the class has an explicit copy constructor.\nstruct IsConvertibleTest1\n{\n\tIsConvertibleTest1() {}\n\tIsConvertibleTest1(int, int) {}\n\texplicit IsConvertibleTest1(const IsConvertibleTest1&) {}\n\t~IsConvertibleTest1(){}\n};\n\n\n\n// Helpers for enable_if tests\ntemplate<typename T>\ntypename eastl::enable_if<eastl::is_floating_point<T>::value, T>::type EnableIfTestFunction(T) \n\t{ return 999; }\n \ntemplate<typename T>\ntypename eastl::enable_if<eastl::is_integral<T>::value, T>::type EnableIfTestFunction(T) \n\t{ return 888; }\n\ntemplate<typename T>\ntypename eastl::disable_if<eastl::is_signed<T>::value, T>::type EnableIfTestFunction(T) \n\t{ return 777; }\n\n\ntypedef char Array[32];\ntypedef const char ArrayConst[32];\n\n\ntypedef Class& Reference;\ntypedef const Class& ConstReference;\n\n\ntypedef const int ConstInt;\ntypedef int Int;\ntypedef volatile int VolatileInt;\ntypedef const volatile int ConstVolatileInt;\ntypedef int& IntReference;\ntypedef const int& ConstIntReference;                   // Note here that the int is const, not the reference to the int.\ntypedef const volatile int& ConstVolatileIntReference;  // Note here that the int is const, not the reference to the int.\n\n\ntypedef void FunctionVoidVoid();\ntypedef int  FunctionIntVoid();\ntypedef int  FunctionIntFloat(float);\ntypedef void (*FunctionVoidVoidPtr)();\n\nnamespace\n{\n\tconst eastl::string gEmptyStringInstance(\"\");\n\n\tconst eastl::integral_constant<int*, nullptr> gIntNullptrConstant;\n\tstatic_assert(gIntNullptrConstant() == nullptr, \"\");\n}\n\nint TestTypeTraits()\n{\n\tint nErrorCount = 0;\n\n\n\t// static_min / static_max\n\t#if EASTL_TYPE_TRAIT_static_min_CONFORMANCE\n\t\tstatic_assert((static_min<3, 7, 1, 5>::value == 1),  \"static_min failure\");\n\t\tstatic_assert((static_max<3, 7, 1, 5>::value == 7),  \"static_max failure\");\n\t#else\n\t\tstatic_assert((static_min<7, 1>::value == 1),  \"static_min failure\");\n\t\tstatic_assert((static_max<7, 1>::value == 7),  \"static_max failure\");\n\t#endif\n\n\t// enable_if, disable_if.\n\tEATEST_VERIFY((EnableIfTestFunction((double)1.1) == 999));\n\tEATEST_VERIFY((EnableIfTestFunction((int)1) == 888));\n\tEATEST_VERIFY((EnableIfTestFunction((int)-4) == 888));\n\n\n\t// conditional\n\tstatic_assert(sizeof(conditional<true,  int8_t, int16_t>::type) == sizeof(int8_t),  \"conditional failure\");\n\tstatic_assert(sizeof(conditional<false, int8_t, int16_t>::type) == sizeof(int16_t), \"conditional failure\");\n\n\t// bool_constant\n\tstatic_assert(bool_constant<is_same<int, int>::value>::value == true, \"bool_constant failure\");\n\tstatic_assert(bool_constant<is_same<int, short>::value>::value == false, \"bool_constant failure\");\n\tstatic_assert(is_same<bool_constant<false>::type, integral_constant<bool, false>::type>::value, \"bool_constant failure\");\n\n\n\t// type_identity\n\tstatic_assert(sizeof(type_identity<int>::type) == sizeof(int), \"type_identity failure\");\n\tstatic_assert((is_same<int, type_identity<int>::type >::value == true), \"type_identity failure\");\n\tstatic_assert(sizeof(type_identity_t<int>) == sizeof(int), \"type_identity failure\");\n\tstatic_assert((is_same_v<int, type_identity_t<int>> == true), \"type_identity failure\");\n\n\n\n\t// is_void\n\tstatic_assert(is_void<void>::value == true, \"is_void failure\");\n\tstatic_assert(is_void<const void>::value == true, \"is_void failure\");\n\tstatic_assert(is_void<int>::value == false, \"is_void failure\");\n\n\n\t// is_null_pointer\n\t#if defined(EA_COMPILER_CPP11_ENABLED)\n\t\t#if !defined(EA_COMPILER_NO_DECLTYPE) && !defined(_MSC_VER) // VS2012 is broken for just the case of decltype(nullptr).\n\t\t\tstatic_assert(is_null_pointer<decltype(nullptr)>::value == true,  \"is_null_pointer failure\");\n\t\t\tstatic_assert(is_null_pointer<decltype(NULL)>::value    == false, \"is_null_pointer failure\");\n\t\t#endif\n\t\t#if defined(EA_HAVE_nullptr_t_IMPL)\n\t\t\tstatic_assert(is_null_pointer<std::nullptr_t>::value == true,  \"is_null_pointer failure\");  // Can't enable this until we are using an updated <EABase/nullptr.h> that is savvy to C++11 clang (defines nullptr) being used with C++98 GNU libstdc++ (defines std::nullptr_t). \n\t\t#endif\n\t\tstatic_assert(is_null_pointer<void*>::value          == false, \"is_null_pointer failure\");\n\t\tstatic_assert(is_null_pointer<intptr_t>::value       == false, \"is_null_pointer failure\");\n\t#endif\n\n\t// is_integral\n\tstatic_assert(is_integral<int>::value == true, \"is_integral failure\");\n\tEATEST_VERIFY(GetType(is_integral<int>()) == true);\n\n\tstatic_assert(is_integral<const int>::value == true, \"is_integral failure\");\n\tEATEST_VERIFY(GetType(is_integral<const int>()) == true);\n\n\tstatic_assert(is_integral<float>::value == false, \"is_integral failure\");\n\tEATEST_VERIFY(GetType(is_integral<float>()) == false);\n\n\tstatic_assert(is_integral<bool>::value,               \"is_integral failure\");\n\tstatic_assert(is_integral<char8_t>::value,            \"is_integral failure\");\n\tstatic_assert(is_integral<char16_t>::value,           \"is_integral failure\");\n\tstatic_assert(is_integral<char32_t>::value,           \"is_integral failure\");\n\tstatic_assert(is_integral<char>::value,               \"is_integral failure\");\n\tstatic_assert(is_integral<int>::value,                \"is_integral failure\");\n\tstatic_assert(is_integral<long long>::value,          \"is_integral failure\");\n\tstatic_assert(is_integral<long>::value,               \"is_integral failure\");\n\tstatic_assert(is_integral<short>::value,              \"is_integral failure\");\n\tstatic_assert(is_integral<signed char>::value,        \"is_integral failure\");\n\tstatic_assert(is_integral<unsigned char>::value,      \"is_integral failure\");\n\tstatic_assert(is_integral<unsigned int>::value,       \"is_integral failure\");\n\tstatic_assert(is_integral<unsigned long long>::value, \"is_integral failure\");\n\tstatic_assert(is_integral<unsigned long>::value,      \"is_integral failure\");\n\tstatic_assert(is_integral<unsigned short>::value,     \"is_integral failure\");\n#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type which is already handled...\n\tstatic_assert(is_integral<wchar_t>::value,            \"is_integral failure\");\n#endif\n\n\n\t// is_floating_point\n\tstatic_assert(is_floating_point<double>::value == true, \"is_floating_point failure\");\n\tEATEST_VERIFY(GetType(is_floating_point<double>()) == true);\n\n\tstatic_assert(is_floating_point<const double>::value == true, \"is_floating_point failure\");\n\tEATEST_VERIFY(GetType(is_floating_point<const double>()) == true);\n\n\tstatic_assert(is_floating_point<int>::value == false, \"is_floating_point failure\");\n\tEATEST_VERIFY(GetType(is_floating_point<int>()) == false);\n\n\n\t// is_arithmetic\n\tstatic_assert(is_arithmetic<float>::value == true, \"is_arithmetic failure\");\n\tstatic_assert(is_arithmetic_v<float> == true,      \"is_arithmetic failure\");\n\tEATEST_VERIFY(GetType(is_arithmetic<float>()) == true);\n\n\tstatic_assert(is_arithmetic<Class>::value == false, \"is_arithmetic failure\");\n\tstatic_assert(is_arithmetic_v<Class> == false,      \"is_arithmetic failure\");\n\tEATEST_VERIFY(GetType(is_arithmetic<Class>()) == false);\n\n\n\t// is_fundamental\n\tstatic_assert(is_fundamental<void>::value == true, \"is_fundamental failure\");\n\tstatic_assert(is_fundamental_v<void> == true,      \"is_fundamental failure\");\n\tEATEST_VERIFY(GetType(is_fundamental<void>()) == true);\n\n\t#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type which is already handled...\n\t\tstatic_assert(is_fundamental<wchar_t>::value == true, \"is_fundamental failure\");\n\t\tstatic_assert(is_fundamental_v<wchar_t> == true,      \"is_fundamental failure\");\n\t\tEATEST_VERIFY(GetType(is_fundamental<wchar_t>()) == true);\n\t#endif\n\n\tstatic_assert(is_fundamental<Class>::value == false, \"is_fundamental failure\");\n\tstatic_assert(is_fundamental_v<Class> == false,      \"is_fundamental failure\");\n\tEATEST_VERIFY(GetType(is_fundamental<Class>()) == false);\n\n\tstatic_assert(is_fundamental<std::nullptr_t>::value == true, \"is_fundamental failure\");\n\tstatic_assert(is_fundamental_v<std::nullptr_t> == true,      \"is_fundamental failure\");\n\n\n\t// is_array\n\tstatic_assert(is_array<Array>::value == true, \"is_array failure\");\n\tEATEST_VERIFY(GetType(is_array<Array>()) == true);\n\n\tstatic_assert(is_array<ArrayConst>::value == true,   \"is_array failure\");\n\tEATEST_VERIFY(GetType(is_array<ArrayConst>()) == true);\n\n\tstatic_assert(is_array<int[]>::value == true,        \"is_array failure\");\n\n\tstatic_assert(is_array<uint32_t>::value == false,    \"is_array failure\");\n\tEATEST_VERIFY(GetType(is_array<uint32_t>()) == false);\n\n\tstatic_assert(is_array<uint32_t*>::value == false,   \"is_array failure\");\n\tEATEST_VERIFY(GetType(is_array<uint32_t*>()) == false);\n\n\n\t//is_bounded_array\n\tstatic_assert(is_bounded_array<Array>::value == true, \"is_bounded_array failure\");\n\tEATEST_VERIFY(GetType(is_bounded_array<Array>()) == true);\n\n\tstatic_assert(is_bounded_array<ArrayConst>::value == true,   \"is_bounded_array failure\");\n\tEATEST_VERIFY(GetType(is_bounded_array<ArrayConst>()) == true);\n\n\tstatic_assert(is_bounded_array<void>::value == false,\t\t\"is_bounded_array failure\");\n\tstatic_assert(is_bounded_array<PodA>::value == false,\t\t\"is_bounded_array failure\");\n\tstatic_assert(is_bounded_array<int>::value == false,        \"is_bounded_array failure\");\n\tstatic_assert(is_bounded_array<int[32]>::value == true,        \"is_bounded_array failure\");\n\tstatic_assert(is_bounded_array<int[]>::value == false,        \"is_bounded_array failure\");\n\tstatic_assert(is_bounded_array<int[0]>::value == false,\t\t\"is_bounded_array failure\");\n\tstatic_assert(is_bounded_array<void>::value == false,\t\t\"is_bounded_array failure\");\n\n\tstatic_assert(is_bounded_array<uint32_t>::value == false,    \"is_bounded_array failure\");\n\tEATEST_VERIFY(GetType(is_bounded_array<uint32_t>()) == false);\n\n\tstatic_assert(is_bounded_array<uint32_t*>::value == false,   \"is_bounded_array failure\");\n\tEATEST_VERIFY(GetType(is_bounded_array<uint32_t*>()) == false);\n\n\n\t//is_unbounded_array\n\tstatic_assert(is_unbounded_array<Array>::value == false, \"is_unbounded_array failure\");\n\tEATEST_VERIFY(GetType(is_unbounded_array<Array>()) == false);\n\n\tstatic_assert(is_unbounded_array<ArrayConst>::value == false,   \"is_unbounded_array failure\");\n\tEATEST_VERIFY(GetType(is_unbounded_array<ArrayConst>()) == false);\n\n\tstatic_assert(is_unbounded_array<void>::value == false,\t\t\t\"is_unbounded_array failure\");\n\tstatic_assert(is_unbounded_array<PodA>::value == false,\t\t\t\"is_unbounded_array failure\");\n\tstatic_assert(is_unbounded_array<int>::value == false,        \"is_unbounded_array failure\");\n\tstatic_assert(is_unbounded_array<int[32]>::value == false,        \"is_unbounded_array failure\");\n\tstatic_assert(is_unbounded_array<int[]>::value == true,        \"is_unbounded_array failure\");\n\tstatic_assert(is_unbounded_array<int[0]>::value == false,\t\t\"is_unbounded_array failure\");\n\tstatic_assert(is_unbounded_array<void>::value == false,\t\t\t\"is_unbounded_array failure\");\n\n\tstatic_assert(is_unbounded_array<uint32_t>::value == false,    \"is_unbounded_array failure\");\n\tEATEST_VERIFY(GetType(is_unbounded_array<uint32_t>()) == false);\n\n\tstatic_assert(is_unbounded_array<uint32_t*>::value == false,   \"is_unbounded_array failure\");\n\tEATEST_VERIFY(GetType(is_unbounded_array<uint32_t*>()) == false);\n\n\n\n\t// is_reference\n\tstatic_assert(is_reference<Class&>::value == true,        \"is_reference failure\");\n\tEATEST_VERIFY(GetType(is_reference<Class&>()) == true);\n\n\tstatic_assert(is_reference<Class&&>::value == true,        \"is_reference failure\");\n\tEATEST_VERIFY(GetType(is_reference<Class&&>()) == true);\n\n\tstatic_assert(is_reference<const Class&>::value == true,  \"is_reference failure\");\n\tEATEST_VERIFY(GetType(is_reference<const Class&>()) == true);\n\n\tstatic_assert(is_reference<const Class&&>::value == true,  \"is_reference failure\");\n\tEATEST_VERIFY(GetType(is_reference<const Class&&>()) == true);\n\n\tstatic_assert(is_reference<Class>::value == false,        \"is_reference failure\");\n\tEATEST_VERIFY(GetType(is_reference<Class>()) == false);\n\n\tstatic_assert(is_reference<const Class*>::value == false, \"is_reference failure\");\n\tEATEST_VERIFY(GetType(is_reference<const Class*>()) == false);\n\n\n\t// is_member_function_pointer\n\tstatic_assert(is_member_function_pointer<int>::value == false,            \"is_member_function_pointer failure\");\n\tstatic_assert(is_member_function_pointer<int(Class::*)>::value == false,  \"is_member_function_pointer failure\");\n\tstatic_assert(is_member_function_pointer<int(Class::*)()>::value == true, \"is_member_function_pointer failure\");\n\tstatic_assert(is_member_function_pointer<int(Class::*)(...)>::value == true, \"is_member_function_pointer failure\");\n\tstatic_assert(is_member_function_pointer<int(Class::*)() noexcept>::value == true, \"is_member_function_pointer failure\");\n\tstatic_assert(is_member_function_pointer<int(Class::*)() &>::value == true, \"is_member_function_pointer failure\");\n\tstatic_assert(is_member_function_pointer<int(Class::*)() &&>::value == true, \"is_member_function_pointer failure\");\n\n\n\t// is_member_object_pointer\n\tstatic_assert(is_member_object_pointer<int>::value == false,             \"is_member_object_pointer failure\");\n\tstatic_assert(is_member_object_pointer<int(Class::*)>::value == true,    \"is_member_object_pointer failure\");\n\tstatic_assert(is_member_object_pointer<int(Class::*)()>::value == false, \"is_member_object_pointer failure\");\n\n\n\t// is_member_pointer\n\tstatic_assert(is_member_pointer<int>::value == false,            \"is_member_pointer failure\");\n\tstatic_assert(is_member_pointer<int(Class::*)>::value == true,   \"is_member_pointer failure\");\n\tstatic_assert(is_member_pointer<int(Class::*)()>::value == true, \"is_member_pointer failure\");\n\tstatic_assert(is_member_pointer<int(Class::* const)>::value == true, \"is_member_pointer failure\");\n\tstatic_assert(is_member_pointer<int(Class::* volatile)>::value == true, \"is_member_pointer failure\");\n\tstatic_assert(is_member_pointer<int(Class::* const volatile)>::value == true, \"is_member_pointer failure\");\n\n\n\t// is_pointer\n\tstatic_assert(is_pointer<Class*>::value         == true,  \"is_pointer failure\");\n\tstatic_assert(is_pointer<const Class*>::value   == true,  \"is_pointer failure\");\n\tstatic_assert(is_pointer<Class>::value          == false, \"is_pointer failure\");\n\tstatic_assert(is_pointer<const Class&>::value   == false, \"is_pointer failure\");\n\t#if defined(EA_HAVE_nullptr_t_IMPL)\n\t\tstatic_assert(is_pointer<std::nullptr_t>::value == false, \"is_pointer failure\");\n\t#endif\n\n\t// is_enum\n\tstatic_assert(is_enum<Enum>::value == true,            \"is_enum failure \");\n\tstatic_assert(is_enum_v<Enum> == true,                 \"is_enum failure \");\n\tEATEST_VERIFY(GetType(is_enum<Enum>()) == true);\n\n\tstatic_assert(is_enum<const Enum>::value == true,      \"is_enum failure \");\n\tstatic_assert(is_enum_v<const Enum> == true,           \"is_enum failure \");\n\tEATEST_VERIFY(GetType(is_enum<const Enum>()) == true);\n\n\tstatic_assert(is_enum<Enum*>::value == false,          \"is_enum failure \");\n\tstatic_assert(is_enum_v<Enum*> == false,               \"is_enum failure \");\n\tEATEST_VERIFY(GetType(is_enum<Enum*>()) == false);\n\n\tstatic_assert(is_enum<Class>::value == false,          \"is_enum failure \");\n\tstatic_assert(is_enum_v<Class> == false,               \"is_enum failure \");\n\tEATEST_VERIFY(GetType(is_enum<Class>()) == false);\n\n\tstatic_assert(is_enum<Enum&>::value == false,          \"is_enum failure \");\n\tstatic_assert(is_enum_v<Enum&> == false,               \"is_enum failure \");\n\tEATEST_VERIFY(GetType(is_enum<Enum&>()) == false);\n\n\tstatic_assert(is_enum<Enum&&>::value == false,          \"is_enum failure \");\n\tstatic_assert(is_enum_v<Enum&&> == false,               \"is_enum failure \");\n\tEATEST_VERIFY(GetType(is_enum<Enum&&>()) == false);\n\n\n\t// is_union\n\tstatic_assert(is_union<Union>::value == true, \"is_union failure\");\n\tstatic_assert(is_union_v<Union> == true,      \"is_union failure\");\n\tEATEST_VERIFY(GetType(is_union<Union>()) == true);\n\n\tstatic_assert(is_union<int>::value == false, \"is_union failure\");\n\tstatic_assert(is_union_v<int> == false,      \"is_union failure\");\n\tEATEST_VERIFY(GetType(is_union<int>()) == false);\n\n\n\t// is_class\n\tstatic_assert(is_class<Class>::value == true, \"is_class failure\");\n\tEATEST_VERIFY(GetType(is_class<Class>()) == true);\n\n\tstatic_assert(is_class<Struct>::value == true, \"is_class failure\");\n\tEATEST_VERIFY(GetType(is_class<Struct>()) == true);\n\n\tstatic_assert(is_class<Union>::value == false, \"is_class failure\");\n\tEATEST_VERIFY(GetType(is_class<Union>()) == false);\n\n\tstatic_assert(is_class<Enum>::value == false, \"is_class failure\");\n\tEATEST_VERIFY(GetType(is_class<Enum>()) == false);\n\n\tstatic_assert(is_class<int*>::value == false, \"is_class failure\");\n\tEATEST_VERIFY(GetType(is_class<int*>()) == false);\n\n\n\t// is_function\n\tstatic_assert(is_function<void>::value == false,                      \"is_function failure\");\n\tstatic_assert(is_function<FunctionVoidVoid>::value == true,           \"is_function failure\");\n\tstatic_assert(is_function<FunctionVoidVoid&>::value == false,\t\t  \"is_function failure\");\n\tstatic_assert(is_function<FunctionIntVoid>::value == true,            \"is_function failure\");\n\tstatic_assert(is_function<FunctionIntFloat>::value == true,           \"is_function failure\");\n\tstatic_assert(is_function<FunctionVoidVoidPtr>::value == false,       \"is_function failure\");\n\tstatic_assert(is_function<int>::value == false,                       \"is_function failure\");\n\tstatic_assert(is_function<int[3]>::value == false,                    \"is_function failure\");\n\tstatic_assert(is_function<int[]>::value == false,                     \"is_function failure\");\n\tstatic_assert(is_function<Class>::value == false,                     \"is_function failure\");\n\t#if EASTL_TYPE_TRAIT_is_function_CONFORMANCE\n\t\t// typedef int PrintfConst(const char*, ...) const;\n\t\tstatic_assert(is_function<int (const char*, ...)>::value == true, \"is_function failure\");  // This is the signature of printf.\n\t#endif\n\t\t\n\tstatic_assert(is_function<int (float)>::value == true, \"is_function failure\");\n\tstatic_assert(is_function<int (float) const>::value == true, \"is_function failure\");\n\tstatic_assert(is_function<int(float) volatile>::value == true, \"is_function failure\");\n\tstatic_assert(is_function<int(float) const volatile>::value == true, \"is_function failure\");\n\tstatic_assert(is_function<int(float)&>::value == true, \"is_function failure\");\n\tstatic_assert(is_function<int(float)&&>::value == true, \"is_function failure\");\n\tstatic_assert(is_function<int(float) noexcept>::value == true, \"is_function failure\");\n\tstatic_assert(is_function<FunctionIntFloat &>::value == false, \"is_function failure\"); // reference to function, not a l-value reference qualified function\n\tstatic_assert(is_function<FunctionIntFloat &&>::value == false, \"is_function failure\");\n\n\tstatic_assert(is_function_v<void> == false,                           \"is_function failure\");\n\tstatic_assert(is_function_v<FunctionVoidVoid> == true,                \"is_function failure\");\n\tstatic_assert(is_function_v<FunctionVoidVoid&> == false,              \"is_function failure\");\n\tstatic_assert(is_function_v<FunctionIntVoid> == true,                 \"is_function failure\");\n\tstatic_assert(is_function_v<FunctionIntFloat> == true,                \"is_function failure\");\n\tstatic_assert(is_function_v<FunctionVoidVoidPtr> == false,            \"is_function failure\");\n\tstatic_assert(is_function_v<int> == false,                            \"is_function failure\");\n\tstatic_assert(is_function_v<int[3]> == false,                         \"is_function failure\");\n\tstatic_assert(is_function_v<int[]> == false,                          \"is_function failure\");\n\tstatic_assert(is_function_v<Class> == false,                          \"is_function failure\");\n\t#if EASTL_TYPE_TRAIT_is_function_CONFORMANCE\n\t\t// typedef int PrintfConst(const char*, ...) const;\n\t\tstatic_assert(is_function_v<int (const char*, ...)> == true,      \"is_function failure\");  // This is the signature of printf.\n\t#endif\n\n\n\t// is_object\n\tstatic_assert(is_object<int>::value == true,     \"is_object failure\");\n\tEATEST_VERIFY(GetType(is_object<int>()) == true);\n\n\tstatic_assert(is_object<Class>::value == true,   \"is_object failure\");\n\tEATEST_VERIFY(GetType(is_object<Class>()) == true);\n\n\tstatic_assert(is_object<Class*>::value == true,  \"is_object failure\");\n\tEATEST_VERIFY(GetType(is_object<Class*>()) == true);\n\n\tstatic_assert(is_object<Class&>::value == false, \"is_object failure\");\n\tEATEST_VERIFY(GetType(is_object<Class&>()) == false);\n\n\tstatic_assert(is_object<Class&&>::value == false, \"is_object failure\");\n\tEATEST_VERIFY(GetType(is_object<Class&&>()) == false);\n\n\n\t// is_scalar\n\tstatic_assert(is_scalar<int>::value == true,          \"is_scalar failure\");\n\tEATEST_VERIFY(GetType(is_scalar<int>()) == true);\n\n\tstatic_assert(is_scalar<double>::value == true,       \"is_scalar failure\");\n\tEATEST_VERIFY(GetType(is_scalar<double>()) == true);\n\n\tstatic_assert(is_scalar<Enum>::value == true,         \"is_scalar failure\");\n\tEATEST_VERIFY(GetType(is_scalar<Enum>()) == true);\n\n\tstatic_assert(is_scalar<const Class*>::value == true, \"is_scalar failure\");\n\tEATEST_VERIFY(GetType(is_scalar<const Class*>()) == true);\n\n\tstatic_assert(is_scalar<std::nullptr_t>::value == true, \"is_scalar failure\");\n\n\n\t// is_compound\n\tstatic_assert(is_compound<Class>::value == true, \"is_compound failure\");\n\tEATEST_VERIFY(GetType(is_compound<Class>()) == true);\n\n\tstatic_assert(is_compound<const Class&>::value == true, \"is_compound failure\");\n\tEATEST_VERIFY(GetType(is_compound<const Class&>()) == true);\n\n\tstatic_assert(is_compound<int*>::value == true, \"is_compound failure\");\n\tEATEST_VERIFY(GetType(is_compound<int*>()) == true);\n\n\tstatic_assert(is_compound<float>::value == false, \"is_compound failure\");\n\tEATEST_VERIFY(GetType(is_compound<float>()) == false);\n\n\tstatic_assert(is_compound<bool>::value == false, \"is_compound failure\");\n\tEATEST_VERIFY(GetType(is_compound<bool>()) == false);\n\n\n\t// is_const\n\tstatic_assert(is_const<Int>::value == false, \"is_const failure\");\n\tEATEST_VERIFY(GetType(is_const<Int>()) == false);\n\n\tstatic_assert(is_const<ConstInt>::value == true, \"is_const failure\");\n\tEATEST_VERIFY(GetType(is_const<ConstInt>()) == true);\n\n\tstatic_assert(is_const<VolatileInt>::value == false, \"is_const failure\");\n\tEATEST_VERIFY(GetType(is_const<VolatileInt>()) == false);\n\n\tstatic_assert(is_const<ConstVolatileInt>::value == true, \"is_const failure\");\n\tEATEST_VERIFY(GetType(is_const<ConstVolatileInt>()) == true);\n\n\tstatic_assert(is_const<IntReference>::value == false, \"is_const failure\");\n\tEATEST_VERIFY(GetType(is_const<IntReference>()) == false);\n\n\tstatic_assert(is_const<ConstIntReference>::value == false, \"is_const failure\"); // Note here that the int is const, not the reference to the int.\n\tEATEST_VERIFY(GetType(is_const<ConstIntReference>()) == false);\n\n\tstatic_assert(is_const<ConstVolatileIntReference>::value == false, \"is_const failure\"); // Note here that the int is const, not the reference to the int.\n\tEATEST_VERIFY(GetType(is_const<ConstVolatileIntReference>()) == false);\n\n\tstatic_assert(is_const<void() const>::value == false, \"is_const failure\");\n\tEATEST_VERIFY(GetType(is_const<void() const>()) == false);\n\n\t// is_volatile\n\tstatic_assert(is_volatile<Int>::value == false, \"is_volatile failure\");\n\tEATEST_VERIFY(GetType(is_volatile<Int>()) == false);\n\n\tstatic_assert(is_volatile<ConstInt>::value == false, \"is_volatile failure\");\n\tEATEST_VERIFY(GetType(is_volatile<ConstInt>()) == false);\n\n\tstatic_assert(is_volatile<VolatileInt>::value == true, \"is_volatile failure\");\n\tEATEST_VERIFY(GetType(is_volatile<VolatileInt>()) == true);\n\n\tstatic_assert(is_volatile<ConstVolatileInt>::value == true, \"is_volatile failure\");\n\tEATEST_VERIFY(GetType(is_volatile<ConstVolatileInt>()) == true);\n\n\tstatic_assert(is_volatile<IntReference>::value == false, \"is_volatile failure\");\n\tEATEST_VERIFY(GetType(is_volatile<IntReference>()) == false);\n\n\tstatic_assert(is_volatile<ConstIntReference>::value == false, \"is_volatile failure\");\n\tEATEST_VERIFY(GetType(is_volatile<ConstIntReference>()) == false);\n\n\tstatic_assert(is_volatile<ConstVolatileIntReference>::value == false, \"is_volatile failure\"); // Note here that the int is volatile, not the reference to the int.\n\tEATEST_VERIFY(GetType(is_volatile<ConstVolatileIntReference>()) == false);\n\n\tstatic_assert(is_volatile<void() const>::value == false, \"is_volatile failure\");\n\tEATEST_VERIFY(GetType(is_volatile<void() const>()) == false);\n\n\n\t// underlying_type and to_underlying\n\t#if EASTL_TYPE_TRAIT_underlying_type_CONFORMANCE && !defined(EA_COMPILER_NO_STRONGLY_TYPED_ENUMS) // If we can execute this test...\n\t\tenum UnderlyingTypeTest : uint16_t { firstVal = 0, secondVal = 1 };\n\t\t\n\t\tconstexpr bool isUnderlyingTypeCorrect = is_same_v<underlying_type_t<UnderlyingTypeTest>, uint16_t>;\n\t\tstatic_assert(isUnderlyingTypeCorrect, \"Wrong type for underlying_type_t.\");\n\t\tEATEST_VERIFY(isUnderlyingTypeCorrect);\n\t\t\n\t\tauto v1 = to_underlying(UnderlyingTypeTest::firstVal); \n\t\tauto v2 = to_underlying(UnderlyingTypeTest::secondVal); \n\n\t\tconstexpr bool isToUnderlyingReturnTypeCorrect = is_same_v<decltype(v1), uint16_t>;\n\t\tstatic_assert(isToUnderlyingReturnTypeCorrect, \"Wrong return type for to_underlying.\");\n\t\tEATEST_VERIFY(isToUnderlyingReturnTypeCorrect);\n\n\t\tEATEST_VERIFY(v1 == 0 && v2 == 1);\n\t#endif\n\n\n\t// is_trivial\n\t// is_trivially_copyable\n\t// is_trivially_default_constructible\n\t#if EASTL_TYPE_TRAIT_is_trivial_CONFORMANCE\n\t\tstatic_assert(is_trivial<Pod1>::value == true, \"is_trivial failure\");\n\t\tstatic_assert(is_trivial<NonPod1>::value == false, \"is_trivial failure\");\n\t#endif\n\n\n\t// is_pod\n\tstatic_assert(is_pod<Pod1>::value == true, \"is_pod failure\");\n\tEATEST_VERIFY(GetType(is_pod<Pod1>()) == true);\n\n\tstatic_assert(is_pod<Pod2>::value == true, \"is_pod failure\");\n\tEATEST_VERIFY(GetType(is_pod<Pod2>()) == true);\n\n\tstatic_assert(is_pod<Pod3>::value == true, \"is_pod failure\");\n\tEATEST_VERIFY(GetType(is_pod<Pod3>()) == true);\n\n\tstatic_assert(is_pod<float>::value == true, \"is_pod failure\");\n\tEATEST_VERIFY(GetType(is_pod<float>()) == true);\n\n\tstatic_assert(is_pod<Pod1*>::value == true, \"is_pod failure\");\n\tEATEST_VERIFY(GetType(is_pod<Pod1*>()) == true);\n\n\tstatic_assert(is_pod<NonPod1>::value == false, \"is_pod failure\");\n\tEATEST_VERIFY(GetType(is_pod<NonPod1>()) == false);\n\n\tstatic_assert(is_pod<NonPod2>::value == false, \"is_pod failure\");\n\tEATEST_VERIFY(GetType(is_pod<NonPod2>()) == false);\n\n\n\t// is_standard_layout\n\tstatic_assert(is_standard_layout<Pod1>::value == true, \"is_standard_layout<Pod1> failure\");\n\tstatic_assert(is_standard_layout_v<Pod1> == true,      \"is_standard_layout<Pod1> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<Pod1>()) == true);\n\n\tstatic_assert(is_standard_layout<Pod2>::value == true, \"is_standard_layout<Pod2> failure\");\n\tstatic_assert(is_standard_layout_v<Pod2> == true,      \"is_standard_layout<Pod2> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<Pod2>()) == true);\n\n\tstatic_assert(is_standard_layout<Pod3>::value == true, \"is_standard_layout<Pod3> failure\");\n\tstatic_assert(is_standard_layout_v<Pod3> == true,      \"is_standard_layout<Pod3> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<Pod3>()) == true);\n\n\tstatic_assert(is_standard_layout<float>::value == true, \"is_standard_layout<float> failure\");\n\tstatic_assert(is_standard_layout_v<float> == true,      \"is_standard_layout<float> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<float>()) == true);\n\n\tstatic_assert(is_standard_layout<Pod1*>::value == true, \"is_standard_layout<Pod1*> failure\");\n\tstatic_assert(is_standard_layout_v<Pod1*> == true,      \"is_standard_layout<Pod1*> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<Pod1*>()) == true);\n\n\tstatic_assert(is_standard_layout<NonPod1>::value == false, \"is_standard_layout<NonPod1> failure\");\n\tstatic_assert(is_standard_layout_v<NonPod1> == false,      \"is_standard_layout<NonPod1> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<NonPod1>()) == false);\n\n\tstatic_assert(is_standard_layout<NonPod2>::value == false, \"is_standard_layout<NonPod2> failure\");\n\tstatic_assert(is_standard_layout_v<NonPod2> == false,      \"is_standard_layout<NonPod2> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<NonPod2>()) == false);\n\n\tstatic_assert(is_standard_layout<HasTrivialConstructor>::value == true, \"is_standard_layout<HasTrivialConstructor> failure\");\n\tstatic_assert(is_standard_layout_v<HasTrivialConstructor> == true,      \"is_standard_layout<HasTrivialConstructor> failure\");\n\tEATEST_VERIFY(GetType(is_standard_layout<HasTrivialConstructor>()) == true);\n\n\tstatic_assert(is_standard_layout<NoTrivialConstructor>::value == true, \"is_standard_layout<NoTrivialConstructor> failure\");        // A key difference between a POD and Standard Layout is that the latter is true if there is a constructor.\n\tstatic_assert(is_standard_layout_v<NoTrivialConstructor> == true, \"is_standard_layout<NoTrivialConstructor> failure\");        // A key difference between a POD and Standard Layout is that the latter is true if there is a constructor.\n\tEATEST_VERIFY(GetType(is_standard_layout<NoTrivialConstructor>()) == true);\n\n\n\t// is_empty\n\tstatic_assert(is_empty<ClassEmpty>::value == true,  \"is_empty failure\");\n\tEATEST_VERIFY(GetType(is_empty<ClassEmpty>()) == true);\n\n\tstatic_assert(is_empty<ClassNonEmpty>::value == false,  \"is_empty failure\");\n\tEATEST_VERIFY(GetType(is_empty<ClassNonEmpty>()) == false);\n\n\tstatic_assert(is_empty<int>::value == false,  \"is_empty failure\");\n\tEATEST_VERIFY(GetType(is_empty<int>()) == false);\n\n\tstatic_assert(is_empty<Enum>::value == false,  \"is_empty failure\");\n\tEATEST_VERIFY(GetType(is_empty<Enum>()) == false);\n\n\n\t// is_polymorphic\n\tstatic_assert(is_polymorphic<Polymorphic1>::value == true,  \"is_polymorphic failure\");\n\tEATEST_VERIFY(GetType(is_polymorphic<Polymorphic1>()) == true);\n\n\tstatic_assert(is_polymorphic<Polymorphic2>::value == true,  \"is_polymorphic failure\");\n\tEATEST_VERIFY(GetType(is_polymorphic<Polymorphic2>()) == true);\n\n\tstatic_assert(is_polymorphic<Polymorphic3>::value == true,  \"is_polymorphic failure\");\n\tEATEST_VERIFY(GetType(is_polymorphic<Polymorphic3>()) == true);\n\n\tstatic_assert(is_polymorphic<NonPolymorphic1>::value == false,  \"is_polymorphic failure\");\n\tEATEST_VERIFY(GetType(is_polymorphic<NonPolymorphic1>()) == false);\n\n\tstatic_assert(is_polymorphic<int>::value == false,  \"is_polymorphic failure\");\n\tEATEST_VERIFY(GetType(is_polymorphic<int>()) == false);\n\n\tstatic_assert(is_polymorphic<Polymorphic1*>::value == false,  \"is_polymorphic failure\");\n\tEATEST_VERIFY(GetType(is_polymorphic<Polymorphic1*>()) == false);\n\n\n\t// is_signed\n\tstatic_assert(is_signed<int>::value == true,                \"is_signed failure \");\n\tstatic_assert(is_signed_v<int> == true,                     \"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<int>()) == true);\n\n\tstatic_assert(is_signed<const int64_t>::value == true,      \"is_signed failure \");\n\tstatic_assert(is_signed_v<const int64_t> == true,           \"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<const int64_t>()) == true);\n\n\tstatic_assert(is_signed<uint32_t>::value == false,          \"is_signed failure \");\n\tstatic_assert(is_signed_v<uint32_t> == false,               \"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<uint32_t>()) == false);\n\n\tstatic_assert(is_signed<bool>::value == false,              \"is_signed failure \");\n\tstatic_assert(is_signed_v<bool> == false,                   \"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<bool>()) == false);\n\n\tstatic_assert(is_signed<float>::value == true,              \"is_signed failure \");\n\tstatic_assert(is_signed_v<float> == true,                   \"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<float>()) == true);\n\n\tstatic_assert(is_signed<double>::value == true,             \"is_signed failure \");\n\tstatic_assert(is_signed_v<double> == true,                  \"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<double>()) == true);\n\t\n\tstatic_assert(is_signed<char16_t>::value == false,\t\t\t\"is_signed failure \");\n\tstatic_assert(is_signed_v<char16_t> == false,\t\t\t\t\"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<char16_t>()) == false);\n\n\tstatic_assert(is_signed<char32_t>::value == false,\t\t\t\"is_signed failure \");\n\tstatic_assert(is_signed_v<char32_t> == false,\t\t\t\t\"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<char32_t>()) == false);\n\n#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\tstatic_assert(is_signed<__int128_t>::value == true,\t\t\t\"is_signed failure \");\n\tstatic_assert(is_signed_v<__int128_t> == true,\t\t\t\t\"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<__int128_t>()) == true);\n\n\tstatic_assert(is_signed<__uint128_t>::value == false,\t\t\"is_signed failure \");\n\tstatic_assert(is_signed_v<__uint128_t> == false,\t\t\t\"is_signed failure \");\n\tEATEST_VERIFY(GetType(is_signed<__uint128_t>()) == false);\n#endif\n\n\t// is_unsigned\n\tstatic_assert(is_unsigned<unsigned int>::value == true,        \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<unsigned int> == true,             \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<unsigned int>()) == true);\n\n\tstatic_assert(is_unsigned<const uint64_t>::value == true,      \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<const uint64_t> == true,           \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<const uint64_t>()) == true);\n\n\tstatic_assert(is_unsigned<int32_t>::value == false,            \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<int32_t> == false,                 \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<int32_t>()) == false);\n\n\tstatic_assert(is_unsigned<bool>::value == true,                \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<bool> == true,                     \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<bool>()) == true);\n\n\tstatic_assert(is_unsigned<float>::value == false,              \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<float> == false,                   \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<float>()) == false);\n\n\tstatic_assert(is_unsigned<double>::value == false,             \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<double> == false,                  \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<double>()) == false);\n\t\n\tstatic_assert(is_unsigned<char16_t>::value == true,\t\t\t   \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<char16_t> == true,\t\t\t\t   \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<char16_t>()) == true);\n\n\tstatic_assert(is_unsigned<char32_t>::value == true,\t\t\t   \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<char32_t> == true,\t\t\t\t   \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<char32_t>()) == true);\n\n#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\tstatic_assert(is_unsigned<__int128_t>::value == false,\t\t   \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<__int128_t> == false,\t\t\t   \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<__int128_t>()) == false);\n\n\tstatic_assert(is_unsigned<__uint128_t>::value == true,\t\t   \"is_unsigned failure \");\n\tstatic_assert(is_unsigned_v<__uint128_t> == true,\t\t\t   \"is_unsigned failure \");\n\tEATEST_VERIFY(GetType(is_unsigned<__uint128_t>()) == true);\n#endif\n\n\n\t// is_lvalue_reference\n\tstatic_assert((is_lvalue_reference<Class>::value == false),   \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference<Class&>::value == true),   \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference<Class&&>::value == false), \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference<int>::value == false),     \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference<int&>::value == true),     \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference<int&&>::value == false),   \"is_lvalue_reference failure\");\n\n\tstatic_assert((is_lvalue_reference_v<Class> == false),        \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference_v<Class&> == true),        \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference_v<Class&&> == false),      \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference_v<int> == false),          \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference_v<int&> == true),          \"is_lvalue_reference failure\");\n\tstatic_assert((is_lvalue_reference_v<int&&> == false),        \"is_lvalue_reference failure\");\n\n\n\t// is_rvalue_reference\n\tstatic_assert((is_rvalue_reference<Class>::value == false),  \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference<Class&>::value == false), \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference<Class&&>::value == true), \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference<int>::value == false),    \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference<int&>::value == false),   \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference<int&&>::value == true),   \"is_rvalue_reference failure\");\n\n\tstatic_assert((is_rvalue_reference_v<Class> == false),  \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference_v<Class&> == false), \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference_v<Class&&> == true), \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference_v<int> == false),    \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference_v<int&> == false),   \"is_rvalue_reference failure\");\n\tstatic_assert((is_rvalue_reference_v<int&&> == true),   \"is_rvalue_reference failure\");\n\n\n\t// is_assignable\n\t// See the documentation for is_assignable to understand the results below are as they are.\n\tstatic_assert((eastl::is_assignable<int&, int>::value              == true),   \"is_assignable failure\");\n\tstatic_assert((eastl::is_assignable<const int&, int>::value        == false),  \"is_assignable failure\");\n\tstatic_assert((eastl::is_assignable<char*, int*>::value            == false),  \"is_assignable failure\");\n\tstatic_assert((eastl::is_assignable<char*, const char*>::value     == false),  \"is_assignable failure\");\n\tstatic_assert((eastl::is_assignable<PodA, PodB*>::value            == false),  \"is_assignable failure\");\n\tstatic_assert((eastl::is_assignable<Assignable, Pod2>::value       == false),  \"is_assignable failure\");\n\n\t#if EASTL_TYPE_TRAIT_is_assignable_CONFORMANCE\n\t\t// These might not succeed unless the implementation is conforming.\n\t\tstatic_assert((eastl::is_assignable<Assignable, Assignable>::value == true),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<Assignable, Pod1>::value       == true),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<PodA&, PodA>::value            == true),  \"is_assignable failure\");\n\n\t\t// These cannot succeed unless the implementation is conforming.\n\t\tstatic_assert((eastl::is_assignable<void, void>::value             == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<int, int>::value               == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<int, const int>::value         == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<const int, int>::value         == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<int, int&>::value              == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<int64_t, int8_t>::value        == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<bool, bool>::value             == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<char*, char*>::value           == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<int, float>::value             == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<const char*, char*>::value     == false),  \"is_assignable failure\");\n\t\tstatic_assert((eastl::is_assignable<int[], int[]>::value           == false),  \"is_assignable failure\");\n\t#endif\n\n\n\t// is_copy_assignable\n\tstatic_assert((eastl::is_copy_assignable<int&>::value              == true),   \"is_copy_assignable failure\");\n\tstatic_assert((eastl::is_copy_assignable<char>::value              == true),   \"is_copy_assignable failure\");\n\n\t#if EASTL_TYPE_TRAIT_is_assignable_CONFORMANCE\n\t\t// These might not succeed unless the implementation is conforming.\n\t\tstatic_assert((eastl::is_copy_assignable<Assignable>::value    == true),  \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<Assignable>::value    == true),  \"is_copy_assignable failure\");\n\n\t\t// These cannot succeed unless the implementation is conforming.\n\t\tstatic_assert((eastl::is_copy_assignable<char*>::value         == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<PodA>::value          == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<Assignable>::value    == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<void>::value          == false),  \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<int>::value           == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<const int>::value     == false),  \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<int64_t>::value       == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<bool>::value          == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<char*>::value         == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<const char*>::value   == true),   \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<int[3]>::value        == false),  \"is_copy_assignable failure\");\n\t\tstatic_assert((eastl::is_copy_assignable<int[]>::value         == false),  \"is_copy_assignable failure\");\n\t#endif\n\n\n\t// is_trivially_assignable\n\tstatic_assert((eastl::is_trivially_assignable<int&, int>::value              == true),   \"is_trivially_assignable failure\");\n\tstatic_assert((eastl::is_trivially_assignable<char*, int*>::value            == false),  \"is_trivially_assignable failure\");\n\tstatic_assert((eastl::is_trivially_assignable<char*, const char*>::value     == false),  \"is_trivially_assignable failure\");\n\tstatic_assert((eastl::is_trivially_assignable<PodA, PodB*>::value            == false),  \"is_trivially_assignable failure\");\n\tstatic_assert((eastl::is_trivially_assignable<Assignable, Assignable>::value == false),  \"is_trivially_assignable failure\"); // False because not trivial.\n\tstatic_assert((eastl::is_trivially_assignable<Assignable, Pod1>::value       == false),  \"is_trivially_assignable failure\"); // False because not trivial.\n\tstatic_assert((eastl::is_trivially_assignable<Assignable, Pod2>::value == false),        \"is_trivially_assignable failure\");\n\n\t// is_nothrow_assignable\n\tstatic_assert((is_nothrow_assignable<void, void>::value          == false),  \"is_nothrow_assignable failure\");\n\tstatic_assert((is_nothrow_assignable<int32_t, int32_t>::value    == false),  \"is_nothrow_assignable failure\");    // See is_assignable for why this is so.\n\tstatic_assert((is_nothrow_assignable<int32_t&, int32_t>::value   == true),   \"is_nothrow_assignable failure\");\n\tstatic_assert((is_nothrow_assignable<int32_t, int8_t>::value     == false),  \"is_nothrow_assignable failure\");\n\t#if EASTL_TYPE_TRAIT_is_nothrow_assignable_CONFORMANCE\n\t\tstatic_assert((is_nothrow_assignable<int32_t&, int8_t>::value    == true),   \"is_nothrow_assignable failure\");\n\t\tstatic_assert((is_nothrow_assignable<NoThrowAssignable,   NoThrowAssignable>::value   == true),  \"is_nothrow_assignable failure\");\n\t\tstatic_assert((is_nothrow_assignable<ThrowAssignableTest, NoThrowAssignable>::value   == true),  \"is_nothrow_assignable failure\");\n\t\tstatic_assert((is_nothrow_assignable<ThrowAssignableTest, ThrowAssignableTest>::value == false), \"is_nothrow_assignable failure\");\n\t#endif\n\n\n\t// is_trivially_copyable\n\tstatic_assert(is_trivially_copyable<void>::value           == false,  \"is_trivially_copyable failure\");\n\tEATEST_VERIFY(GetType(is_trivially_copyable<void>())\t   == false);\n\tstatic_assert(is_trivially_copyable<int>::value            == true,   \"is_trivially_copyable failure\");\n\tstatic_assert(is_trivially_copyable<int*>::value           == true,   \"is_trivially_copyable failure\");\n\tstatic_assert(is_trivially_copyable<int[]>::value          == true,   \"is_trivially_copyable failure\");\n\tstatic_assert(is_trivially_copyable<int[4]>::value         == true,   \"is_trivially_copyable failure\");\n\t#if EASTL_TYPE_TRAIT_is_trivially_copyable_CONFORMANCE\n\t\tstatic_assert(is_trivially_copyable<NonPod1>::value        == false,  \"is_trivially_copyable failure\");\n\t\tstatic_assert(is_trivially_copyable<NoTrivialCopy1>::value == false,  \"is_trivially_copyable failure\");\n\t\tstatic_assert(is_trivially_copyable<PodA>::value           == true,   \"is_trivially_copyable failure\");\n\t#endif\n\n\t{  // user reported regression\n\t\tstruct Foo\n\t\t{\n\t\t\tint a;\n\t\t\tFoo(int i) : a(i) {}\n\t\t\tFoo(Foo&& other) : a(other.a) { other.a = 0; }\n\n\t\t\tFoo(const Foo&) = delete;\n\t\t\tFoo& operator=(const Foo&) = delete;\n\t\t};\n\n\t\tstatic_assert(!eastl::is_trivially_copyable<Foo>::value, \"is_trivially_copyable failure\");\n\t}\n\n\n\t// is_trivially_copy_assignable\n\t{\n\t\tstatic_assert(is_trivially_copy_assignable<int>::value == true, \"is_trivially_copy_assignable failure\");\n\t\tstatic_assert(is_trivially_copy_assignable<char*>::value == true,       \"is_trivially_copy_assignable failure\");\n\t\tstatic_assert(is_trivially_copy_assignable<const char*>::value == true, \"is_trivially_copy_assignable failure\");\n\t\tstatic_assert(is_trivially_copy_assignable<NoTrivialCopy1>::value == false, \"is_trivially_copy_assignable failure\");\n\n\t#ifdef INTENTIONALLY_DISABLED\n\t\t// These tests currently fail on clang, but they would pass using the std::is_trivially_copy_assignable trait.  We should\n\t\t// determine if our implementation is correct, or if clang is actually incorrect.\n\t\tstatic_assert(is_trivially_copy_assignable<const int>::value == true, \"is_trivially_copy_assignable failure\");\n\t\tstatic_assert(is_trivially_copy_assignable<const PodA>::value == true, \"is_trivially_copy_assignable failure\");\n\t\tstatic_assert(is_trivially_copy_assignable<PodA>::value == true, \"is_trivially_copy_assignable failure\");\n\t#endif\n\t}\n\t// is_trivially_default_constructible\n\t// To do.\n\n\n\t// is_trivial\n\t// To do.\n\n\n\t// is_constructible\n\tstatic_assert(is_constructible<void>::value           == false,  \"is_constructible failure\");\n\tstatic_assert(is_constructible<const void>::value     == false,  \"is_constructible failure\");\n\tstatic_assert(is_constructible<int>::value            == true,   \"is_constructible failure\");\n\tstatic_assert(is_constructible<int&>::value           == false,  \"is_constructible failure\");\n\tstatic_assert(is_constructible<int&&>::value          == false,  \"is_constructible failure\");\n\tstatic_assert(is_constructible<int*>::value           == true,   \"is_constructible failure\");\n\tstatic_assert(is_constructible<int[]>::value          == false,  \"is_constructible failure\");\n\tstatic_assert(is_constructible<int[4]>::value         == true,   \"is_constructible failure\");\n\tstatic_assert(is_constructible<NonPod1>::value        == true,  \" is_constructible failure\");\n\tstatic_assert(is_constructible<NoTrivialCopy1>::value == true,   \"is_constructible failure\");\n\tstatic_assert(is_constructible<PodA>::value           == true,   \"is_constructible failure\");\n\tstatic_assert(is_constructible<Abstract>::value       == false,  \"is_constructible failure\");\n\tstatic_assert(is_constructible<NonCopyable>::value       == true,  \"is_constructible failure\");\n\t#if EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE\n\t\tstatic_assert((is_constructible<int, const int>::value                   == true),   \"is_constructible failure\");\n\t\tstatic_assert((is_constructible<char*, const char*>::value               == false),  \"is_constructible failure\");\n\t\tstatic_assert((is_constructible<char*, char* const>::value               == true),   \"is_constructible failure\");\n\t\tstatic_assert((is_constructible<ThrowConstructibleTest, int>::value      == true),   \"is_constructible failure\");\n\t\tstatic_assert((is_constructible<ThrowConstructibleTest, float>::value    == true),   \"is_constructible failure\");\n\t#endif\n\n\n\t// is_trivially_constructible\n\t// Need double parentheses because some older compilers need static_assert implemented as a macro.\n\tstatic_assert((is_trivially_constructible<void>::value                     == false),  \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<void, void>::value               == false),  \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<void, int>::value                == false),  \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int>::value                      == true),   \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int, int>::value                 == true),   \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int, Abstract>::value            == false),  \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int*>::value                     == true),   \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int[]>::value                    == false),  \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int[], int[]>::value             == false),  \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int[4]>::value                   == true),   \"is_trivially_constructible failure\");\n\tstatic_assert((is_trivially_constructible<int[4], int[]>::value            == false),  \"is_trivially_constructible failure\");\n\t#if EASTL_TYPE_TRAIT_is_trivially_constructible_CONFORMANCE\n\t\tstatic_assert((is_trivially_constructible<NoTrivialCopy1>::value       == false),  \"is_trivially_constructible failure\");\n\t\tstatic_assert((is_trivially_constructible<PodA>::value                 == true),   \"is_trivially_constructible failure\");\n\t\tstatic_assert((is_trivially_constructible<PodA, PodA>::value           == true),   \"is_trivially_constructible failure\");\n\t\tstatic_assert((is_trivially_constructible<Abstract>::value             == false),  \"is_trivially_constructible failure\");\n\t\tstatic_assert((is_trivially_constructible<NonPod1>::value              == false),  \"is_trivially_constructible failure\");\n\t\tstatic_assert((is_trivially_constructible<NoTrivialConstructor>::value == false),  \"is_trivially_constructible failure\");\n\t#endif\n\n\n\t// is_nothrow_constructible\n\tstatic_assert((is_nothrow_constructible<void>::value           == false),  \"is_nothrow_constructible failure\");\n\tstatic_assert((is_nothrow_constructible<int>::value            == true),   \"is_nothrow_constructible failure\");\n\tstatic_assert((is_nothrow_constructible<int*>::value           == true),   \"is_nothrow_constructible failure\");\n\tstatic_assert((is_nothrow_constructible<int[4]>::value         == true),   \"is_nothrow_constructible failure\");\n\t#if EASTL_TYPE_TRAIT_is_nothrow_constructible_CONFORMANCE\n\t\tstatic_assert((is_nothrow_constructible<int[]>::value                            == false),  \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<Abstract>::value                         == false),  \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<int, const int>::value                   == true),   \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<char*, const char*>::value               == false),  \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<char*, char* const>::value               == true),   \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<NonPod1>::value                          == false),  \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<PodA>::value                             == true),   \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<ThrowConstructibleTest, int>::value      == true),   \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<ThrowConstructibleTest, float>::value    == false),  \"is_nothrow_constructible failure\");\n\t\tstatic_assert((is_nothrow_constructible<NoTrivialCopy1>::value                   == true),   \"is_nothrow_constructible failure\");  //True because it's a compiler-generated constructor.\n\t#endif\n\n\n\t// is_nothrow_move_constructible\n#if !defined(EA_PLATFORM_MICROSOFT) \n\tstatic_assert((is_nothrow_move_constructible<void>::value                  == false),    \"is_nothrow_move_constructible failure\");\n\tstatic_assert((is_nothrow_move_constructible<int>::value                   == true),     \"is_nothrow_move_constructible failure\");\n\tstatic_assert((is_nothrow_move_constructible<int*>::value                  == true),     \"is_nothrow_move_constructible failure\");\n\tstatic_assert((is_nothrow_move_constructible<const int*>::value            == true),     \"is_nothrow_move_constructible failure\");\n\tstatic_assert((is_nothrow_move_constructible<int&>::value                  == true),     \"is_nothrow_move_constructible failure\");\n\tstatic_assert((is_nothrow_move_constructible<double>::value                == true),     \"is_nothrow_move_constructible failure\");\n\tstatic_assert((is_nothrow_move_constructible<ClassEmpty>::value            == true),     \"is_nothrow_move_constructible failure\");\n#endif\n\n\n\t// is_copy_constructible\n\tstatic_assert((is_copy_constructible<void>::value                                       == false),  \"is_copy_constructible failure\");\n\t#if EASTL_TYPE_TRAIT_is_copy_constructible_CONFORMANCE\n\t\tstatic_assert((is_copy_constructible<int>::value                                    == true),   \"is_copy_constructible failure\");\n\t\tstatic_assert((is_copy_constructible<char*>::value                                  == true),   \"is_copy_constructible failure\");\n\t\tstatic_assert((is_copy_constructible<int&>::value                                   == true),   \"is_copy_constructible failure\"); // As of this writing, GCC's libstdc++ reports true for this. I'm trying to find what's correct.\n\t\tstatic_assert((is_copy_constructible<const int>::value                              == true),   \"is_copy_constructible failure\");\n\t\tstatic_assert((is_copy_constructible<HasTrivialCopy>::value                         == true),   \"is_copy_constructible failure\");\n\n\t\t#if !defined(EA_COMPILER_EDG) && !defined(EA_COMPILER_MSVC) // EDG (and only EDG) is generating warnings about the decltype expression referencing a deleted constructor. This seems like a bug, though we need to verify.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// EA_COMPILER_MSVC is disabled because VS2013 fails this test and it may be that EASTL_TYPE_TRAIT_is_copy_constructible_CONFORMANCE should really be 0 for VS2013.\n\t\t\tstatic_assert((is_copy_constructible<ConstructibleOnlyWithNonConstReference>::value == false),  \"is_copy_constructible failure\");\n\t\t#endif\n\t#endif\n\n\n\t// is_destructible\n\tstatic_assert(is_destructible<int>::value              == true,  \"is_destructible failure\");\n\tstatic_assert(is_destructible<int&>::value             == true,  \"is_destructible failure\");\n\tstatic_assert(is_destructible<int&&>::value            == true,  \"is_destructible failure\");\n\tstatic_assert(is_destructible<char>::value             == true,  \"is_destructible failure\");\n\tstatic_assert(is_destructible<char*>::value            == true,  \"is_destructible failure\");\n\tstatic_assert(is_destructible<PodA>::value             == true,  \"is_destructible failure\");\n\tstatic_assert(is_destructible<void>::value             == false, \"is_destructible failure\");\n\tstatic_assert(is_destructible<int[3]>::value           == true,  \"is_destructible failure\");\n\tstatic_assert(is_destructible<int[]>::value            == false, \"is_destructible failure\"); // You can't call operator delete on this class.\n\tstatic_assert(is_destructible<Abstract>::value         == true, \"is_destructible failure\");\n\tstatic_assert(is_destructible<AbstractWithDtor>::value == true, \"is_destructible failure\");\n\t#if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\t\tstatic_assert(is_destructible<DeletedDtor>::value  == false, \"is_destructible failure\"); // You can't call operator delete on this class.\n\t#endif\n\tstatic_assert(is_destructible<NonPod2>::value          == true,  \"is_destructible failure\");\n\n\n\t// is_trivially_destructible\n\tstatic_assert(is_trivially_destructible<int>::value                  == true,  \"is_trivially_destructible failure\");\n\tstatic_assert(is_trivially_destructible<int&>::value                 == true,  \"is_trivially_destructible failure\");\n\tstatic_assert(is_trivially_destructible<int&&>::value                == true,  \"is_trivially_destructible failure\");\n\tstatic_assert(is_trivially_destructible<char>::value                 == true,  \"is_trivially_destructible failure\");\n\tstatic_assert(is_trivially_destructible<char*>::value                == true,  \"is_trivially_destructible failure\");\n\tstatic_assert(is_trivially_destructible<void>::value                 == false, \"is_trivially_destructible failure\");\n\t#if EASTL_TYPE_TRAIT_is_trivially_destructible_CONFORMANCE\n\t\tstatic_assert(is_trivially_destructible<PodA>::value             == true,  \"is_trivially_destructible failure\");\n\t\tstatic_assert(is_trivially_destructible<int[3]>::value           == true,  \"is_trivially_destructible failure\");\n\t\tstatic_assert(is_trivially_destructible<int[]>::value            == false, \"is_trivially_destructible failure\");\n\t\tstatic_assert(is_trivially_destructible<Abstract>::value         == true, \"is_trivially_destructible failure\");\n\t\tstatic_assert(is_trivially_destructible<AbstractWithDtor>::value == false, \"is_trivially_destructible failure\"); // Having a user-defined destructor make it non-trivial.\n\t#if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\t\tstatic_assert(is_trivially_destructible<DeletedDtor>::value      == false, \"is_trivially_destructible failure\");\n\t#endif\n\t\tstatic_assert(is_trivially_destructible<NonPod2>::value          == false, \"is_trivially_destructible failure\");    // This case differs from is_destructible, because we have a declared destructor.\n\t#endif\n\n\n\t// is_nothrow_destructible\n\tstatic_assert(is_nothrow_destructible<int>::value                      == true,  \"is_nothrow_destructible failure\");\n\tstatic_assert(is_nothrow_destructible<int&>::value                     == true,  \"is_nothrow_destructible failure\");\n\tstatic_assert(is_nothrow_destructible<int&&>::value                    == true,  \"is_nothrow_destructible failure\");\n\tstatic_assert(is_nothrow_destructible<void>::value                     == false, \"is_nothrow_destructible failure\");\n\tstatic_assert(is_nothrow_destructible<Abstract>::value         \t       == true, \"is_nothrow_destructible failure\");\n\tstatic_assert(is_nothrow_destructible<AbstractWithDtor>::value         == true, \"is_nothrow_destructible failure\");\n\t#if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)\n\t\tstatic_assert(is_nothrow_destructible<DeletedDtor>::value          == false, \"is_nothrow_destructible failure\"); // You can't call operator delete on this class.\n\t#endif\n\t#if EASTL_TYPE_TRAIT_is_nothrow_destructible_CONFORMANCE\n\t\tstatic_assert(is_nothrow_destructible<NonPod2>::value              == true,  \"is_nothrow_destructible failure\"); // NonPod2 is nothrow destructible because it has an empty destructor (makes no calls) which has no exception specification. Thus its exception specification defaults to noexcept(true) [C++11 Standard, 15.4 paragraph 14]\n\t\tstatic_assert(is_nothrow_destructible<NoThrowDestructible>::value  == true,  \"is_nothrow_destructible failure\");\n\t#endif\n\t#if EASTL_TYPE_TRAIT_is_nothrow_destructible_CONFORMANCE && !defined(EA_COMPILER_NO_EXCEPTIONS)\n\t\tstatic_assert(is_nothrow_destructible<ThrowDestructible>::value               == false, \"is_nothrow_destructible failure\");\n\t\tstatic_assert(is_nothrow_destructible<ThrowDestructibleNoexceptFalse>::value  == false, \"is_nothrow_destructible failure\");\n\t#endif\n\n\n\t// alignment_of\n\t#if !defined(EA_ABI_ARM_APPLE) // Apple on ARM (i.e. iPhone/iPad) doesn't align 8 byte types on 8 byte boundaries, and the hardware allows it.\n\t\tstatic_assert(alignment_of<uint64_t>::value == 8, \"alignment_of failure\");\n\t\tEATEST_VERIFY(GetType(alignment_of<uint64_t>()) == 8);\n\t#endif\n\n\tstatic_assert(alignment_of<ClassAlign32>::value == 32, \"alignment_of failure\");\n\tEATEST_VERIFY(GetType(alignment_of<ClassAlign32>()) == 32);\n\n\n\t// common_type\n\tstatic_assert((is_same<common_type<NonPod2*>::type, NonPod2*>::value), \"common_type failure\");\n\tstatic_assert((is_same<common_type<int>::type, int>::value), \"common_type failure\");\n\tstatic_assert((is_same<common_type<void, void>::type, void>::value), \"common_type failure\");\n\tstatic_assert((is_same<common_type<int, int>::type, int>::value), \"common_type failure\");\n\n\n\t// rank\n\tstatic_assert(rank<int[1][2][3][4][5][6]>::value == 6, \"rank failure\");\n\tstatic_assert(rank<int[][1][2]>::value == 3,           \"rank failure\");\n\tstatic_assert(rank<int>::value == 0,                   \"rank failure\");\n\tstatic_assert(rank<void>::value == 0,                  \"rank failure\");\n\n\tstatic_assert(rank_v<int[1][2][3][4][5][6]> == 6,      \"rank failure\");\n\tstatic_assert(rank_v<int[][1][2]> == 3,                \"rank failure\");\n\tstatic_assert(rank_v<int> == 0,                        \"rank failure\");\n\tstatic_assert(rank_v<void> == 0,                       \"rank failure\");\n\n\n\n\t// extent\n\tstatic_assert((extent<int>         ::value == 0), \"extent failure\");\n\tstatic_assert((extent<int[2]>      ::value == 2), \"extent failure\");\n\tstatic_assert((extent<int[2][4]>   ::value == 2), \"extent failure\");\n\tstatic_assert((extent<int[]>       ::value == 0), \"extent failure\");\n\tstatic_assert((extent<int[][4]>    ::value == 0), \"extent failure\");\n\tstatic_assert((extent<int, 1>      ::value == 0), \"extent failure\");\n\tstatic_assert((extent<int[2], 1>   ::value == 0), \"extent failure\");\n\tstatic_assert((extent<int[2][4], 1>::value == 4), \"extent failure\");\n\tstatic_assert((extent<int[][4], 1> ::value == 4), \"extent failure\");\n\n\tstatic_assert((extent_v<int>          == 0),      \"extent failure\");\n\tstatic_assert((extent_v<int[2]>       == 2),      \"extent failure\");\n\tstatic_assert((extent_v<int[2][4]>    == 2),      \"extent failure\");\n\tstatic_assert((extent_v<int[]>        == 0),      \"extent failure\");\n\tstatic_assert((extent_v<int[][4]>     == 0),      \"extent failure\");\n\tstatic_assert((extent_v<int, 1>       == 0),      \"extent failure\");\n\tstatic_assert((extent_v<int[2], 1>    == 0),      \"extent failure\");\n\tstatic_assert((extent_v<int[2][4], 1> == 4),      \"extent failure\");\n\tstatic_assert((extent_v<int[][4], 1>  == 4),      \"extent failure\");\n\n\n\n\t// is_aligned\n\tstatic_assert(is_aligned<uint8_t>::value == false,  \"is_aligned failure\");\n\tEATEST_VERIFY(GetType(is_aligned<uint8_t>()) == false);\n\n\tstatic_assert(is_aligned<uint16_t>::value == false,  \"is_aligned failure\");\n\tEATEST_VERIFY(GetType(is_aligned<uint16_t>()) == false);\n\n\tstatic_assert(is_aligned<uint32_t>::value == false,  \"is_aligned failure\");\n\tEATEST_VERIFY(GetType(is_aligned<uint32_t>()) == false);\n\n\tstatic_assert(is_aligned<uint64_t>::value == false,  \"is_aligned failure\");\n\tEATEST_VERIFY(GetType(is_aligned<uint64_t>()) == false);\n\n\tstatic_assert(is_aligned<uint64_t>::value == false,  \"is_aligned failure\");\n\tEATEST_VERIFY(GetType(is_aligned<uint64_t>()) == false);\n\n\t{ // alignment tests\n\t\tstatic_assert(is_aligned<Align16>::value, \"is_aligned failure\");\n\t\tEATEST_VERIFY(GetType(is_aligned<Align16>()));\n\n\n\t\tstatic_assert(is_aligned<Align32>::value, \"is_aligned failure\");\n\t\tEATEST_VERIFY(GetType(is_aligned<Align32>()));\n\n\t\tstatic_assert(is_aligned<Align64>::value, \"is_aligned failure\");\n\t\tEATEST_VERIFY(GetType(is_aligned<Align64>()));\n\t}\n\n\n\t// is_same\n\tstatic_assert((is_same<uint32_t, uint32_t>::value  == true),  \"is_same failure\");\n\tstatic_assert((is_same<void, void>::value          == true),  \"is_same failure\");\n\tstatic_assert((is_same<void*, void*>::value        == true),  \"is_same failure\");\n\tstatic_assert((is_same<uint64_t, uint64_t>::value  == true),  \"is_same failure\");\n\tstatic_assert((is_same<Class, Class>::value        == true),  \"is_same failure\");\n\tstatic_assert((is_same<uint64_t, uint32_t>::value  == false), \"is_same failure\");\n\tstatic_assert((is_same<Class, ClassAlign32>::value == false), \"is_same failure\");\n\n\tstatic_assert((is_same_v<uint32_t, uint32_t>  == true),       \"is_same_v failure\");\n\tstatic_assert((is_same_v<void, void>          == true),       \"is_same_v failure\");\n\tstatic_assert((is_same_v<void*, void*>        == true),       \"is_same_v failure\");\n\tstatic_assert((is_same_v<uint64_t, uint64_t>  == true),       \"is_same_v failure\");\n\tstatic_assert((is_same_v<Class, Class>        == true),       \"is_same_v failure\");\n\tstatic_assert((is_same_v<uint64_t, uint32_t>  == false),      \"is_same_v failure\");\n\tstatic_assert((is_same_v<Class, ClassAlign32> == false),      \"is_same_v failure\");\n\n\n\n\t// is_convertible\n\tstatic_assert((is_convertible<uint16_t,  uint32_t>::value     == true),     \"is_convertible failure\");\n\tstatic_assert((is_convertible<int32_t,   int16_t>::value      == true),     \"is_convertible failure\");  // This is a conversion from 32 bits down to 16 bits. All compilers natively report that this is true. However, VC++ generates warnings for actual such conversions.\n\tstatic_assert((is_convertible<Subclass,  Class>::value        == true),     \"is_convertible failure\");\n\tstatic_assert((is_convertible<Subclass*, Class*>::value       == true),     \"is_convertible failure\");\n\tstatic_assert((is_convertible<Subclass&, const Class&>::value == true),     \"is_convertible failure\");\n\tstatic_assert((is_convertible<int,       Class>::value        == false),    \"is_convertible failure\");\n\tstatic_assert((is_convertible<NonPod1,   NonPod1>::value      == true),     \"is_convertible failure\");\n\tstatic_assert((is_convertible<NonPod1,   NonPod2>::value      == false),    \"is_convertible failure\");\n\t#if EASTL_TYPE_TRAIT_is_convertible_CONFORMANCE // This causes compile failures.\n\tstatic_assert((is_convertible<IsConvertibleTest1, IsConvertibleTest1>::value == false),    \"is_convertible failure\");\n\t#endif\n\n\n\t// make_signed\n\t// make_unsigned\n\t{\n\t\t// Test declarations\n\t\teastl::make_signed<int8_t>::type i8 = -1;\n\t\tEATEST_VERIFY(i8 == -1);\n\t\teastl::make_unsigned<uint8_t>::type u8 = 0xff;\n\t\tEATEST_VERIFY(u8 == 0xff);\n\n\t\teastl::make_signed<int16_t>::type i16 = -1;\n\t\tEATEST_VERIFY(i16 == -1);\n\t\teastl::make_unsigned<uint16_t>::type u16 = 0xffff;\n\t\tEATEST_VERIFY(u16 == 0xffff);\n\n\t\teastl::make_signed<int32_t>::type i32 = -1;\n\t\tEATEST_VERIFY(i32 == -1);\n\t\teastl::make_unsigned<uint32_t>::type u32 = 0xffffffff;\n\t\tEATEST_VERIFY(u32 == 0xffffffff);\n\n\t\teastl::make_signed<int64_t>::type i64 = -1;\n\t\tEATEST_VERIFY(i64 == -1);\n\t\teastl::make_unsigned<uint64_t>::type u64 = UINT64_C(0xffffffffffffffff);\n\t\tEATEST_VERIFY(u64 == UINT64_C(0xffffffffffffffff));\n\n\t\t// Test conversions via static_cast:\n\t\tu8 = static_cast<eastl::make_unsigned<uint8_t>::type>(i8);\n\t\tEATEST_VERIFY(u8 == 0xff);\n\t\ti8 = static_cast<eastl::make_signed<int8_t>::type>(u8);\n\t\tEATEST_VERIFY(i8 == -1);\n\n\t\tu16 = static_cast<eastl::make_unsigned<uint16_t>::type>(i16);\n\t\tEATEST_VERIFY(u16 == 0xffff);\n\t\ti16 = static_cast<eastl::make_signed<int16_t>::type>(u16);\n\t\tEATEST_VERIFY(i16 == -1);\n\n\t\tu32 = static_cast<eastl::make_unsigned<uint32_t>::type>(i32);\n\t\tEATEST_VERIFY(u32 == 0xffffffff);\n\t\ti32 = static_cast<eastl::make_signed<int32_t>::type>(u32);\n\t\tEATEST_VERIFY(i32 == -1);\n\n\t\tu64 = static_cast<eastl::make_unsigned<uint64_t>::type>(i64);\n\t\tEATEST_VERIFY(u64 == UINT64_C(0xffffffffffffffff));\n\t\ti64 = static_cast<eastl::make_signed<int64_t>::type>(u64);\n\t\tEATEST_VERIFY(i64 == -1);\n\n\n\t\tstatic_assert(eastl::is_same_v<signed char, eastl::make_signed<unsigned char>::type>);\n\t\tstatic_assert(eastl::is_same_v<short, eastl::make_signed<unsigned short>::type>);\n\t\tstatic_assert(eastl::is_same_v<int, eastl::make_signed<unsigned int>::type>);\n\t\tstatic_assert(eastl::is_same_v<long, eastl::make_signed<unsigned long>::type>);\n\t\tstatic_assert(eastl::is_same_v<long long, eastl::make_signed<unsigned long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<const signed char, eastl::make_signed<const unsigned char>::type>);\n\t\tstatic_assert(eastl::is_same_v<const short, eastl::make_signed<const unsigned short>::type>);\n\t\tstatic_assert(eastl::is_same_v<const int, eastl::make_signed<const unsigned int>::type>);\n\t\tstatic_assert(eastl::is_same_v<const long, eastl::make_signed<const unsigned long>::type>);\n\t\tstatic_assert(eastl::is_same_v<const long long, eastl::make_signed<const unsigned long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<volatile signed char, eastl::make_signed<volatile unsigned char>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile short, eastl::make_signed<volatile unsigned short>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile int, eastl::make_signed<volatile unsigned int>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile long, eastl::make_signed<volatile unsigned long>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile long long, eastl::make_signed<volatile unsigned long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<const volatile signed char, eastl::make_signed<const volatile unsigned char>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile short, eastl::make_signed<const volatile unsigned short>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile int, eastl::make_signed<const volatile unsigned int>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile long, eastl::make_signed<const volatile unsigned long>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile long long, eastl::make_signed<const volatile unsigned long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<unsigned char, eastl::make_unsigned<signed char>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned short, eastl::make_unsigned<short>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned int, eastl::make_unsigned<int>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned long, eastl::make_unsigned<long>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned long long, eastl::make_unsigned<long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<const unsigned char, eastl::make_unsigned<const signed char>::type>);\n\t\tstatic_assert(eastl::is_same_v<const unsigned short, eastl::make_unsigned<const short>::type>);\n\t\tstatic_assert(eastl::is_same_v<const unsigned int, eastl::make_unsigned<const int>::type>);\n\t\tstatic_assert(eastl::is_same_v<const unsigned long, eastl::make_unsigned<const long>::type>);\n\t\tstatic_assert(eastl::is_same_v<const unsigned long long, eastl::make_unsigned<const long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<volatile unsigned char, eastl::make_unsigned<volatile signed char>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile unsigned short, eastl::make_unsigned<volatile short>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile unsigned int, eastl::make_unsigned<volatile int>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile unsigned long, eastl::make_unsigned<volatile long>::type>);\n\t\tstatic_assert(eastl::is_same_v<volatile unsigned long long, eastl::make_unsigned<volatile long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<const volatile unsigned char, eastl::make_unsigned<const volatile signed char>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile unsigned short, eastl::make_unsigned<const volatile short>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile unsigned int, eastl::make_unsigned<const volatile int>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile unsigned long, eastl::make_unsigned<const volatile long>::type>);\n\t\tstatic_assert(eastl::is_same_v<const volatile unsigned long long, eastl::make_unsigned<const volatile long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<signed char, eastl::make_signed<signed char>::type>);\n\t\tstatic_assert(eastl::is_same_v<short, eastl::make_signed<signed short>::type>);\n\t\tstatic_assert(eastl::is_same_v<int, eastl::make_signed<signed int>::type>);\n\t\tstatic_assert(eastl::is_same_v<long, eastl::make_signed<signed long>::type>);\n\t\tstatic_assert(eastl::is_same_v<long long, eastl::make_signed<signed long long>::type>);\n\n\t\tstatic_assert(eastl::is_same_v<unsigned char, eastl::make_unsigned<unsigned char>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned short, eastl::make_unsigned<unsigned short>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned int, eastl::make_unsigned<unsigned int>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned long, eastl::make_unsigned<unsigned long>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned long long, eastl::make_unsigned<unsigned long long>::type>);\n\n\t\t#if EASTL_GCC_STYLE_INT128_SUPPORTED\n\t\t\tstatic_assert(eastl::is_same_v<__uint128_t, eastl::make_unsigned<__int128_t>::type>);\n\t\t\tstatic_assert(eastl::is_same_v<__uint128_t, eastl::make_unsigned<__uint128_t>::type>);\n\n\t\t\tstatic_assert(eastl::is_same_v<__int128_t, eastl::make_signed<__int128_t>::type>);\n\t\t\tstatic_assert(eastl::is_same_v<__int128_t, eastl::make_signed<__uint128_t>::type>);\n\t\t#endif\n\n\t\t// Char tests\n\t\tstatic_assert(sizeof(char) == sizeof(eastl::make_signed<char>::type));\n\t\tstatic_assert(sizeof(wchar_t) == sizeof(eastl::make_signed<wchar_t>::type));\n\t\tstatic_assert(sizeof(char8_t) == sizeof(eastl::make_signed<char8_t>::type));\n\t\tstatic_assert(sizeof(char16_t) == sizeof(eastl::make_signed<char16_t>::type));\n\t\tstatic_assert(sizeof(char32_t) == sizeof(eastl::make_signed<char32_t>::type));\n\t\tstatic_assert(sizeof(char) == sizeof(eastl::make_unsigned<char>::type));\n\t\tstatic_assert(sizeof(wchar_t) == sizeof(eastl::make_unsigned<wchar_t>::type));\n\t\tstatic_assert(sizeof(char8_t) == sizeof(eastl::make_unsigned<char8_t>::type));\n\t\tstatic_assert(sizeof(char16_t) == sizeof(eastl::make_unsigned<char16_t>::type));\n\t\tstatic_assert(sizeof(char32_t) == sizeof(eastl::make_unsigned<char32_t>::type));\n\n\t\tstatic_assert(eastl::is_same_v<signed char, eastl::make_signed<char8_t>::type>);\n\t\tstatic_assert(eastl::is_same_v<unsigned char, eastl::make_unsigned<char8_t>::type>);\n\n\t\t// Enum tests\n\t\tenum EnumUCharSize : unsigned char\t\t{};\n\t\tenum EnumUShortSize : unsigned short\t{};\n\t\tenum EnumUIntSize : unsigned int\t\t{};\n\t\tenum EnumULongSize : unsigned long {};\n\t\tenum EnumULongLongSize : unsigned long long\t\t{};\n\n\t\tstatic_assert(eastl::is_signed_v<eastl::make_signed<EnumUCharSize>::type>);\n\t\tstatic_assert(eastl::is_signed_v<eastl::make_signed<EnumUShortSize>::type>);\n\t\tstatic_assert(eastl::is_signed_v<eastl::make_signed<EnumUIntSize>::type>);\n\t\tstatic_assert(eastl::is_signed_v<eastl::make_signed<EnumULongSize>::type>);\n\t\tstatic_assert(eastl::is_signed_v<eastl::make_signed<EnumULongLongSize>::type>);\n\t\tstatic_assert(sizeof(EnumUCharSize) == sizeof(eastl::make_signed<EnumUCharSize>::type));\n\t\tstatic_assert(sizeof(EnumUShortSize) == sizeof(eastl::make_signed<EnumUShortSize>::type));\n\t\tstatic_assert(sizeof(EnumUIntSize) == sizeof(eastl::make_signed<EnumUIntSize>::type));\n\t\tstatic_assert(sizeof(EnumULongSize) == sizeof(eastl::make_signed<EnumULongSize>::type));\n\t\tstatic_assert(sizeof(EnumULongLongSize) == sizeof(eastl::make_signed<EnumULongLongSize>::type));\n\n\t\tenum EnumCharSize : signed char\t{};\n\t\tenum EnumShortSize : short\t\t{};\n\t\tenum EnumIntSize : int\t\t\t{};\n\t\tenum EnumLongSize : long\t\t\t{};\n\t\tenum EnumLongLongSize : long long\t{};\n\n\t\tstatic_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumCharSize>::type>);\n\t\tstatic_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumShortSize>::type>);\n\t\tstatic_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumIntSize>::type>);\n\t\tstatic_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumLongSize>::type>);\n\t\tstatic_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumLongLongSize>::type>);\n\t\tstatic_assert(sizeof(EnumCharSize) == sizeof(eastl::make_unsigned<EnumCharSize>::type));\n\t\tstatic_assert(sizeof(EnumShortSize) == sizeof(eastl::make_unsigned<EnumShortSize>::type));\n\t\tstatic_assert(sizeof(EnumIntSize) == sizeof(eastl::make_unsigned<EnumIntSize>::type));\n\t\tstatic_assert(sizeof(EnumLongSize) == sizeof(eastl::make_unsigned<EnumLongSize>::type));\n\t\tstatic_assert(sizeof(EnumLongLongSize) == sizeof(eastl::make_unsigned<EnumLongLongSize>::type));\n\t}\n\n\t// remove_const\n\t// remove_volatile\n\t// remove_cv\n\t{\n\t\t// To do: Make more thorough tests verifying this. Such tests will probably involve template metaprogramming.\n\t\tremove_const<const int32_t>::type i32 = 47;\n\t\tEATEST_VERIFY(++i32 == 48);\n\n\t\tremove_volatile<volatile int16_t>::type i16 = 47;\n\t\tEATEST_VERIFY(++i16 == 48);\n\n\t\tremove_cv<const volatile int32_t>::type i64 = 47;\n\t\tEATEST_VERIFY(++i64 == 48);\n\n\t\t//static_assert(is_same<std::remove_cv<int (int, ...)>::type , std::remove_cv<int (int, ...) const>::type>::value, \"remove_cv failure\");\n\t}\n\n\t// remove_cvref\n\t{\n\t\tstatic_assert(is_same_v<remove_cvref_t<int>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int&>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int&&>, int>, \"remove_cvref failure\");\n\n\t\tstatic_assert(is_same_v<remove_cvref_t<const int>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<const int&>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<const int&&>, int>, \"remove_cvref failure\");\n\n\t\tstatic_assert(is_same_v<remove_cvref_t<volatile int>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<volatile int&>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<volatile int&&>, int>, \"remove_cvref failure\");\n\n\t\tstatic_assert(is_same_v<remove_cvref_t<const volatile int>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<const volatile int&>, int>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<const volatile int&&>, int>, \"remove_cvref failure\");\n\n\t\t// test pointer types\n\t\tstatic_assert(is_same_v<remove_cvref_t<int*>, int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int*&>, int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int*&&>, int*>, \"remove_cvref failure\");\n\n\t\tstatic_assert(is_same_v<remove_cvref_t<const int*>, const int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<const int*&>, const int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<const int*&&>, const int*>, \"remove_cvref failure\");\n\n\t\tstatic_assert(is_same_v<remove_cvref_t<int* const>, int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int* const&>, int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int* const&&>, int*>, \"remove_cvref failure\");\n\n\t\tstatic_assert(is_same_v<remove_cvref_t<int* const volatile>, int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int* const volatile&>, int*>, \"remove_cvref failure\");\n\t\tstatic_assert(is_same_v<remove_cvref_t<int* const volatile&&>, int*>, \"remove_cvref failure\");\n\t}\n\n\n\t// add_const\n\t// add_volatile\n\t// add_cv\n\t{\n\t\t// To do: Make more thorough tests verifying this. Such tests will probably involve template metaprogramming.\n\t\teastl::add_const<int32_t>::type i32 = 47;\n\t\tEATEST_VERIFY(i32 == 47);\n\n\t\t// C++20 deprecated a lot of volatile operations\n\t\teastl::add_volatile<int16_t>::type i16 = 47;\n\t\tEATEST_VERIFY(i16 + 1 == 48);\n\n\t\teastl::add_cv<int32_t>::type i64 = 47;\n\t\tEATEST_VERIFY(i64 == 47);\n\t}\n\n\n\t// as_const\n\t{\n\t\t{\n\t\t\tint i = 42;\t\n\t\t\tstatic_assert(eastl::is_same<decltype(eastl::as_const(i)), const int&>::value, \"expecting a 'const T&' return type\");\n\t\t\tEATEST_VERIFY(eastl::as_const(i) == 42);\n\t\t}\n\n\t\t{\n\t\t\teastl::string str = \"Electronic Arts\";\n\t\t\tstatic_assert(eastl::is_same<decltype(eastl::as_const(str)), const eastl::string&>::value, \"expecting a 'const T&' return type\");\n\t\t\tEATEST_VERIFY(eastl::as_const(str) == \"Electronic Arts\");\n\t\t}\n\t}\n\n\n\t// remove_reference\n\t// remove_pointer\n\t// add_pointer\n\t// remove_extent\n\t// remove_all_extents\n\t{\n\t\tint x = 18;\n\n\t\teastl::remove_reference<int&>::type xValue;\n\t\txValue = 3;\n\t\tEATEST_VERIFY(xValue == 3);\n\n\t\teastl::add_pointer<int>::type xPtr = &x;\n\t\t*xPtr = 19;\n\t\tEATEST_VERIFY(x == 19);\n\n\t\teastl::remove_pointer<int*>::type yValue;\n\t\tyValue = 3;\n\t\tEATEST_VERIFY(yValue == 3);\n\n\t\t// ref to T\n\t\t//   -> T*\n\t\tstatic_assert(is_same_v<add_pointer_t<int&>, int*>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<int(&)()>, int(*)()>, \"add_pointer failure\");\n\n\t\t// object type (a (possibly cv-qualified) type other than function type, reference type or void), or\n\t\t// a function type that is not cv- or ref-qualified, or a (possibly cv-qualified) void type\n\t\t//   -> T*\n\t\tstatic_assert(is_same_v<add_pointer_t<int>, int*>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<int*>, int**>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<int()>, int(*)()>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<void>, void*>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<const void>, const void*>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<volatile void>, volatile void*>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<const volatile void>, const volatile void*>, \"add_pointer failure\");\n\n\t\t// otherwise (cv- or ref-qualified function type)\n\t\t//   -> T\n\t\tstatic_assert(is_same_v<add_pointer_t<int() const>, int() const>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<int() volatile>, int() volatile>, \"add_pointer failure\");\n\t\tstatic_assert(is_same_v<add_pointer_t<int() const volatile>, int() const volatile>, \"add_pointer failure\");\n\n\t\t// remove_extent\n\t\t// If T is an array of some type X, provides the member typedef type equal to X, otherwise \n\t\t// type is T. Note that if T is a multidimensional array, only the first dimension is removed. \n\t\ttypedef int IntArray1[37];\n\t\ttypedef eastl::remove_extent<IntArray1>::type Int;\n\t\tstatic_assert((eastl::is_same<Int, int>::value == true), \"remove_extent/is_same failure\");\n\n\t\t// remove_all_extents\n\t\ttypedef int IntArray2[37][54];\n\t\ttypedef eastl::remove_all_extents<IntArray2>::type Int2;\n\t\tstatic_assert((eastl::is_same<Int2, int>::value == true), \"remove_all_extents/is_same failure\");\n\t}\n\n\t// add_lvalue_reference\n\t{\n\t\t// function type with no cv- or ref-qualifier\n\t\t//   -> T&\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<void()>, void(&)()>, \"add_lvalue_reference failure\");\n\n\t\t// object type (a (possibly cv-qualified) type other than function type, reference type or void)\n\t\t//   -> T&\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<int>, int&>, \"add_lvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<const int>, const int&>, \"add_lvalue_reference failure\");\n\n\t\t// if T is an rvalue reference (to some type U)\n\t\t//   -> U&\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<int&&>, int&>, \"add_lvalue_reference failure\");\n\n\t\t// otherwise (cv- or ref-qualified function type, or reference type, or (possibly cv-qualified) void)\n\t\t//   -> T\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<void() const>, void() const>, \"add_lvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<void()&>, void()&>, \"add_lvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<void()&&>, void()&&>, \"add_lvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<int&>, int&>, \"add_lvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<const int&>, const int&>, \"add_lvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<void>, void>, \"add_lvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_lvalue_reference_t<const void>, const void>, \"add_lvalue_reference failure\");\n\t}\n\n\t// add_rvalue_reference\n\t{\n\t\t// function type with no cv- or ref-qualifier\n\t\t//   -> T&&\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<void()>, void(&&)()>, \"add_rvalue_reference failure\");\n\n\t\t// object type (a (possibly cv-qualified) type other than function type, reference type or void)\n\t\t//   -> T&&\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<int>, int&&>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<const int>, const int&&>, \"add_rvalue_reference failure\");\n\n\t\t// otherwise (cv- or ref-qualified function type, or reference type, or (possibly cv-qualified) void)\n\t\t//   -> T\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<void() const>, void() const>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<void()&>, void()&>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<void()&&>, void()&&>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<int&>, int&>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<int&&>, int&&>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<const int&>, const int&>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<void>, void>, \"add_rvalue_reference failure\");\n\t\tstatic_assert(is_same_v<add_rvalue_reference_t<const void>, const void>, \"add_rvalue_reference failure\");\n\t}\n\n\n\t// decay\n\t{ \n\t\tstatic_assert((eastl::is_same<uint32_t,          eastl::decay<uint32_t>::type>::value                    == true), \"is_same failure\");\n\t\tstatic_assert((eastl::is_same<uint32_t,          eastl::decay<const uint32_t>::type>::value              == true), \"is_same failure\");\n\t\tstatic_assert((eastl::is_same<uint32_t,          eastl::decay<volatile uint32_t>::type>::value           == true), \"is_same failure\");\n\t\tstatic_assert((eastl::is_same<uint32_t,          eastl::decay<uint32_t&>::type>::value                   == true), \"is_same failure\");\n\t\tstatic_assert((eastl::is_same<uint32_t,          eastl::decay<const uint32_t&>::type>::value             == true), \"is_same failure\");\n\t\tstatic_assert((eastl::is_same<uint32_t,          eastl::decay<const volatile uint32_t&>::type>::value    == true), \"is_same failure\");\n\t  #if !EASTL_NO_RVALUE_REFERENCES\n\t\tstatic_assert((eastl::is_same<uint32_t,          eastl::decay<uint32_t&&>::type>::value                  == true), \"is_same failure\");\n\t  #endif\n\t\tstatic_assert((eastl::is_same<uint32_t*,         eastl::decay<uint32_t[3]>::type>::value                 == true), \"is_same failure\");\n\t\tstatic_assert((eastl::is_same<uint32_t(*)(char), eastl::decay<uint32_t(char)>::type>::value              == true), \"is_same failure\");\n\t}\n\n\n\t// aligned_storage\n\t// Some compilers don't support or ignore alignment specifications for stack variables, \n\t// so we limit our testing to compilers that are known to support it.\n\t#if (EA_ALIGN_MAX_AUTOMATIC >= 64) && defined(EA_PLATFORM_DESKTOP) // Actually there are additional compilers that support alignment of stack-based variables, most significantly clang, GCC 4.4+, and probably others.\n\t{\n\t\t// Test the creation of a single aligned value.\n\t\tconst size_t     kArraySize = 100;\n\t\tconst size_t     kExpectedAlignment = 64;\n\t\ttypedef uint16_t Type;\n\n\t\teastl::aligned_storage<sizeof(Type), kExpectedAlignment>::type data;\n\t\tType* value = new(&data) Type;\n\t\t*value = 37;\n\t\tEATEST_VERIFY_F((EA::StdC::GetAlignment(value) >= kExpectedAlignment) && (*value == 37), \n\t\t\t\t\t\t \"eastl::aligned_storage failure: Expected: %u, Actual: %u\", (unsigned)kExpectedAlignment, (unsigned)EA::StdC::GetAlignment(value));\n\n\t\t// Create an array of 100 values aligned.\n\t\teastl::aligned_storage<sizeof(Type), kExpectedAlignment>::type dataArray[kArraySize];\n\t\tType* valueArray = new(dataArray) Type[kArraySize];\n\t\tvalueArray[0] = 37;\n\t\tEATEST_VERIFY_F((EA::StdC::GetAlignment(valueArray) >= kExpectedAlignment) && (valueArray[0] == 37), \n\t\t\t\t\t\t \"eastl::aligned_storage failure: Expected: %u, Actual: %u\", (unsigned)kExpectedAlignment, (unsigned)EA::StdC::GetAlignment(valueArray));\n\t}\n\t{\n\t\t// Test the creation of a single aligned value.\n\t\tconst size_t     kArraySize = 17;\n\t\tconst size_t     kExpectedAlignment = 128;\n\t\ttypedef uint8_t  Type;\n\n\t\teastl::aligned_storage<sizeof(Type), kExpectedAlignment>::type data;\n\t\tType* value = new(&data) Type;\n\t\t*value = 37;\n\t\tEATEST_VERIFY_F((EA::StdC::GetAlignment(value) >= kExpectedAlignment) && (*value == 37), \n\t\t\t\t\t\t \"eastl::aligned_storage failure: Expected: %u, Actual: %u\", (unsigned)kExpectedAlignment, (unsigned)EA::StdC::GetAlignment(value));\n\n\t\t// Create an array of 100 values aligned.\n\t\teastl::aligned_storage<sizeof(Type), kExpectedAlignment>::type dataArray[kArraySize];\n\t\tType* valueArray = new(dataArray) Type[kArraySize];\n\t\tvalueArray[0] = 37;\n\t\tEATEST_VERIFY_F((EA::StdC::GetAlignment(valueArray) >= kExpectedAlignment) && (valueArray[0] == 37), \n\t\t\t\t\t\t \"eastl::aligned_storage failure: Expected: %u, Actual: %u\", (unsigned)kExpectedAlignment, (unsigned)EA::StdC::GetAlignment(valueArray));\n\t}\n\t{\n\t\t// Test the creation of a single aligned value.\n\t\tconst size_t     kArraySize = 27;\n\t\tconst size_t     kExpectedAlignment = 256;\n\t\ttypedef uint32_t Type;\n\n\t\teastl::aligned_storage<sizeof(Type), kExpectedAlignment>::type data;\n\t\tType* value = new(&data) Type;\n\t\t*value = 37;\n\t\tEATEST_VERIFY_F((EA::StdC::GetAlignment(value) >= kExpectedAlignment) && (*value == 37), \n\t\t\t\t\t\t \"eastl::aligned_storage failure: Expected: %u, Actual: %u\", (unsigned)kExpectedAlignment, (unsigned)EA::StdC::GetAlignment(value));\n\n\t\t// Create an array of 100 values aligned.\n\t\teastl::aligned_storage<sizeof(Type), kExpectedAlignment>::type dataArray[kArraySize];\n\t\tType* valueArray = new(dataArray) Type[kArraySize];\n\t\tvalueArray[0] = 37;\n\t\tEATEST_VERIFY_F((EA::StdC::GetAlignment(valueArray) >= kExpectedAlignment) && (valueArray[0] == 37), \n\t\t\t\t\t\t \"eastl::aligned_storage failure: Expected: %u, Actual: %u\", (unsigned)kExpectedAlignment, (unsigned)EA::StdC::GetAlignment(valueArray));\n\t}\n\t#endif\n\n\n\t// aligned_union\n\t// Some compilers don't support or ignore alignment specifications for stack variables, \n\t// so we limit our testing to compilers that are known to support it.\n\t{\n\t\tunion AlignedUnion\n\t\t{\n\t\t\tchar  c;\n\t\t\tint   i;\n\t\t\tfloat f;\n\t\t\tchar  a[32];\n\t\n\t\t\tAlignedUnion(float fValue) : f(fValue) {}\n\t\t};\n\t\n\t\ttypedef aligned_union<sizeof(AlignedUnion), char, int, float>::type AlignedUnionStorage;\n\n\t\tstatic_assert((EA_ALIGN_OF(AlignedUnionStorage) >= EA_ALIGN_OF(float)) && (EA_ALIGN_OF(AlignedUnionStorage) <= EA_ALIGN_OF(double)), \"aligned_union failure\");\n\t\tstatic_assert(sizeof(AlignedUnionStorage) >= sizeof(AlignedUnion), \"aligned_union failure\");\n\n\t\tAlignedUnionStorage alignedUnionStorage; // Since we know that our alignment is a simple value <= default alignment, we can just declare an object here and it will work with all compilers, including those that are limited in the stack alignments they support.\n\t\tAlignedUnion*       pAlignedUnion = new (&alignedUnionStorage) AlignedUnion(21.4f);\n\t\tEATEST_VERIFY(pAlignedUnion->f == 21.4f);\n\t\tpAlignedUnion->i = 37;\n\t\tEATEST_VERIFY(pAlignedUnion->i == 37);\n\t}\n\n\n\t// union_cast\n\t{\n\t\tfloat    f32    = -1234.f;\n\t\tuint32_t n32    = union_cast<uint32_t>(f32);\n\t\tfloat    f32New = union_cast<float>(n32);\n\t\tEATEST_VERIFY(f32 == f32New);\n\n\t\tdouble   f64    = -1234.0;\n\t\tuint64_t n64    = union_cast<uint64_t>(f64);\n\t\tdouble   f64New = union_cast<double>(n64);\n\t\tEATEST_VERIFY(f64 == f64New);\n\n\t\tPodA a    = { -1234 };\n\t\tPodB b    = union_cast<PodB>(a);\n\t\tPodA aNew = union_cast<PodA>(b);\n\t\tEATEST_VERIFY(a == aNew);\n\n\t\tPodA*  pA    = new PodA;\n\t\tPodB*  pB    = union_cast<PodB*>(pA);\n\t\tPodA*  pANew = union_cast<PodA*>(pB);\n\t\tEATEST_VERIFY(pA == pANew);\n\t\tdelete pA;\n\t}\n\n\t// void_t\n\t{\n\t\t{\n\t\t\tstatic_assert(is_same<void_t<void>, void>::value, \"void_t failure\");\n\t\t\tstatic_assert(is_same<void_t<int>, void>::value, \"void_t failure\");\n\t\t\tstatic_assert(is_same<void_t<short>, void>::value, \"void_t failure\");\n\t\t\tstatic_assert(is_same<void_t<long>, void>::value, \"void_t failure\");\n\t\t\tstatic_assert(is_same<void_t<long long>, void>::value, \"void_t failure\");\n\t\t\tstatic_assert(is_same<void_t<ClassEmpty>, void>::value, \"void_t failure\");\n\t\t\tstatic_assert(is_same<void_t<ClassNonEmpty>, void>::value, \"void_t failure\");\n\t\t\tstatic_assert(is_same<void_t<vector<int>>, void>::value, \"void_t failure\");\n\t\t}\n\n\t\t// new sfinae mechansim test \n\t\t{\n\t\t\tstatic_assert(has_increment_operator_using_void_t<HasIncrementOperator>::value, \"void_t sfinae failure\");\n\t\t\tstatic_assert(!has_increment_operator_using_void_t<ClassEmpty>::value, \"void_t sfinae failure\");\n\t\t}\n\t}\n\n\t// detected idiom\n\t{\n\t\tstatic_assert(is_detected<has_increment_operator_detection, HasIncrementOperator>::value, \"is_detected failure.\");\n\t\tstatic_assert(!is_detected<has_increment_operator_detection, ClassEmpty>::value, \"is_detected failure.\");\n\n\t\tstatic_assert(is_same<detected_t<has_increment_operator_detection, HasIncrementOperator>, HasIncrementOperator&>::value, \"is_detected_t failure.\");\n\t\tstatic_assert(is_same<detected_t<has_increment_operator_detection, ClassEmpty>, nonesuch>::value, \"is_detected_t failure.\");\n\n\t\tusing detected_or_positive_result = detected_or<float, has_increment_operator_detection, HasIncrementOperator>;\n\t\tusing detected_or_negative_result = detected_or<float, has_increment_operator_detection, ClassEmpty>;\n\t\tstatic_assert(detected_or_positive_result::value_t::value, \"detected_or failure.\");\n\t\tstatic_assert(!detected_or_negative_result::value_t::value, \"detected_or failure.\");\n\t\tstatic_assert(is_same<detected_or_positive_result::type, HasIncrementOperator&>::value, \"detected_or failure.\");\n\t\tstatic_assert(is_same<detected_or_negative_result::type, float>::value, \"detected_or failure.\");\n\n\t\tstatic_assert(is_same<detected_or_t<float, has_increment_operator_detection, HasIncrementOperator>, HasIncrementOperator&>::value, \"detected_or_t failure.\");\n\t\tstatic_assert(is_same<detected_or_t<float, has_increment_operator_detection, ClassEmpty>, float>::value, \"detected_or_t failure.\");\n\n\t\tstatic_assert(is_detected_exact<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>::value, \"is_detected_exact failure.\");\n\t\tstatic_assert(!is_detected_exact<float, has_increment_operator_detection, HasIncrementOperator>::value, \"is_detected_exact failure.\");\n\t\tstatic_assert(is_detected_exact<nonesuch, has_increment_operator_detection, ClassEmpty>::value, \"is_detected_exact failure.\");\n\t\tstatic_assert(!is_detected_exact<float, has_increment_operator_detection, ClassEmpty>::value, \"is_detected_exact failure.\");\n\n\t\tstatic_assert(is_detected_convertible<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>::value, \"is_detected_convertible failure.\");\n\t\tstatic_assert(is_detected_convertible<HasIncrementOperator, has_increment_operator_detection, HasIncrementOperator>::value, \"is_detected_convertible failure.\");\n\t\tstatic_assert(!is_detected_convertible<float, has_increment_operator_detection, HasIncrementOperator>::value, \"is_detected_convertible failure.\");\n\t\tstatic_assert(!is_detected_convertible<nonesuch, has_increment_operator_detection, ClassEmpty>::value, \"is_detected_convertible failure.\");\n\t\tstatic_assert(!is_detected_convertible<float, has_increment_operator_detection, ClassEmpty>::value, \"is_detected_convertible failure.\");\n\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\tstatic_assert(is_detected_v<has_increment_operator_detection, HasIncrementOperator>, \"is_detected_v failure.\");\n\t\tstatic_assert(!is_detected_v<has_increment_operator_detection, ClassEmpty>, \"is_detected_v failure.\");\n\n\t\tstatic_assert(is_detected_exact_v<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>, \"is_detected_exact_v failure.\");\n\t\tstatic_assert(!is_detected_exact_v<float, has_increment_operator_detection, HasIncrementOperator>, \"is_detected_exact_v failure.\");\n\t\tstatic_assert(is_detected_exact_v<nonesuch, has_increment_operator_detection, ClassEmpty>, \"is_detected_exact_v failure.\");\n\t\tstatic_assert(!is_detected_exact_v<float, has_increment_operator_detection, ClassEmpty>, \"is_detected_exact_v failure.\");\n\n\t\tstatic_assert(is_detected_convertible_v<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>, \"is_detected_convertible_v failure.\");\n\t\tstatic_assert(is_detected_convertible_v<HasIncrementOperator, has_increment_operator_detection, HasIncrementOperator>, \"is_detected_convertible_v failure.\");\n\t\tstatic_assert(!is_detected_convertible_v<float, has_increment_operator_detection, HasIncrementOperator>, \"is_detected_convertible_v failure.\");\n\t\tstatic_assert(!is_detected_convertible_v<nonesuch, has_increment_operator_detection, ClassEmpty>, \"is_detected_convertible_v failure.\");\n\t\tstatic_assert(!is_detected_convertible_v<float, has_increment_operator_detection, ClassEmpty>, \"is_detected_convertible_v failure.\");\n\t#endif\n\t}\n\n\t// conjunction\n\t{\n\t\tstatic_assert( conjunction<>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<false_type>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<false_type, false_type>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<false_type, false_type, false_type>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<false_type, false_type, false_type, true_type>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<false_type, false_type, true_type, true_type>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<false_type, true_type, true_type, true_type>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<true_type, true_type, true_type, true_type, false_type>::value, \"conjunction failure\");\n\t\tstatic_assert(!conjunction<true_type, false_type, true_type, true_type, true_type>::value, \"conjunction failure\");\n\t\tstatic_assert( conjunction<true_type, true_type, true_type, true_type, true_type>::value, \"conjunction failure\");\n\t\tstatic_assert( conjunction<true_type, true_type, true_type, true_type>::value, \"conjunction failure\");\n\t\tstatic_assert( conjunction<true_type, true_type, true_type>::value, \"conjunction failure\");\n\t\tstatic_assert( conjunction<true_type>::value, \"conjunction failure\");\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\tstatic_assert( conjunction_v<>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<false_type>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<false_type, false_type>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<false_type, false_type, false_type>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<false_type, false_type, false_type, true_type>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<false_type, false_type, true_type, true_type>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<false_type, true_type, true_type, true_type>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<true_type, true_type, true_type, true_type, false_type>, \"conjunction failure\");\n\t\tstatic_assert(!conjunction_v<true_type, false_type, true_type, true_type, true_type>, \"conjunction failure\");\n\t\tstatic_assert( conjunction_v<true_type, true_type, true_type, true_type, true_type>, \"conjunction failure\");\n\t\tstatic_assert( conjunction_v<true_type, true_type, true_type, true_type>, \"conjunction failure\");\n\t\tstatic_assert( conjunction_v<true_type, true_type, true_type>, \"conjunction failure\");\n\t\tstatic_assert( conjunction_v<true_type>, \"conjunction failure\");\n\t#endif\n\t}\n\t\n\t// disjunction\n\t{\n\t\tstatic_assert(!disjunction<>::value, \"disjunction failure\");\n\t\tstatic_assert(!disjunction<false_type>::value, \"disjunction failure\");\n\t\tstatic_assert(!disjunction<false_type, false_type>::value, \"disjunction failure\");\n\t\tstatic_assert(!disjunction<false_type, false_type, false_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<false_type, false_type, false_type, true_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<false_type, false_type, true_type, true_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<false_type, true_type, true_type, true_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<true_type, true_type, true_type, true_type, false_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<true_type, false_type, true_type, true_type, true_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<true_type, true_type, true_type, true_type, true_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<true_type, true_type, true_type, true_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<true_type, true_type, true_type>::value, \"disjunction failure\");\n\t\tstatic_assert( disjunction<true_type>::value, \"disjunction failure\");\n\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\tstatic_assert(!disjunction_v<>, \"disjunction failure\");\n\t\tstatic_assert(!disjunction_v<false_type>, \"disjunction failure\");\n\t\tstatic_assert(!disjunction_v<false_type, false_type>, \"disjunction failure\");\n\t\tstatic_assert(!disjunction_v<false_type, false_type, false_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<false_type, false_type, false_type, true_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<false_type, false_type, true_type, true_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<false_type, true_type, true_type, true_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<true_type, true_type, true_type, true_type, false_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<true_type, false_type, true_type, true_type, true_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<true_type, true_type, true_type, true_type, true_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<true_type, true_type, true_type, true_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<true_type, true_type, true_type>, \"disjunction failure\");\n\t\tstatic_assert( disjunction_v<true_type>, \"disjunction failure\");\n\t#endif\n\t}\n\n\t// negation\n\t{\n\t\tstatic_assert( negation<false_type>::value, \"negation failure\");\n\t\tstatic_assert(!negation<true_type>::value, \"negation failure\");\n\n\t\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\t\tstatic_assert( negation_v<false_type>, \"negation failure\");\n\t\t\tstatic_assert(!negation_v<true_type>, \"negation failure\");\n\t\t#endif\n\t}\n\n\t// has_unique_object_representations\n\t{\n\t\tstatic_assert( has_unique_object_representations<bool>::value,               \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<char16_t>::value,           \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<char32_t>::value,           \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<char>::value,               \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<int>::value,                \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<long long>::value,          \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<long>::value,               \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<short>::value,              \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<signed char>::value,        \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<unsigned char>::value,      \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<unsigned int>::value,       \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<unsigned long long>::value, \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<unsigned long>::value,      \"has_unique_object_representations failure\");\n\t\tstatic_assert( has_unique_object_representations<unsigned short>::value,     \"has_unique_object_representations failure\");\n\t\tstatic_assert(!has_unique_object_representations<void>::value,               \"has_unique_object_representations failure\");\n#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type which is already handled...\n\t\tstatic_assert( has_unique_object_representations<wchar_t>::value,            \"has_unique_object_representations failure\");\n#endif\n\n\t#if EASTL_TYPE_TRAIT_has_unique_object_representations_CONFORMANCE\n\t\t{\n\t\t\tstruct packed_type { int a; };\n\t\t\tstatic_assert( has_unique_object_representations<packed_type>::value, \"has_unique_object_representations failure\");\n\n\t\t\tstruct padded_type { int a; char b; int c; };\n\t\t\tstatic_assert(!has_unique_object_representations<padded_type>::value, \"has_unique_object_representations failure\");\n\t\t}\n\t#endif\n\t}\n\t\n\t// is_final\n\t{\n\t#if (EA_COMPILER_HAS_FEATURE(is_final))\n\t\tstatic_assert(std::is_final<FinalStruct>::value == eastl::is_final<FinalStruct>::value,  \"final struct not correctly detected\");\n\t\tstatic_assert(std::is_final<FinalClass>::value  == eastl::is_final<FinalClass>::value,   \"final class not correctly detected\");\n\t\tstatic_assert(std::is_final<Enum>::value        == eastl::is_final<Enum>::value,         \"enum not correctly detected\");\n\t\tstatic_assert(std::is_final<int>::value         == eastl::is_final<int>::value,          \"int not correctly detected\");\n\t\tstatic_assert(std::is_final<Struct>::value      == eastl::is_final<Struct>::value,       \"non-final struct not correctly detected\");\n\t\tstatic_assert(std::is_final<Class>::value       == eastl::is_final<Class>::value,        \"non-final class not correctly detected\");\n    #endif\n\n\t// endian (big-endian and little; no mixed-endian/middle-endian)\n\tstatic_assert(eastl::endian::big != eastl::endian::little, \"little-endian and big-endian are not the same\");\n\tstatic_assert(eastl::endian::native == eastl::endian::big || eastl::endian::native == eastl::endian::little, \"native may be little endian or big endian\");\n\tstatic_assert(!(eastl::endian::native == eastl::endian::big && eastl::endian::native == eastl::endian::little), \"native cannot be both big and little endian\");\n\n\t#ifdef EA_SYSTEM_LITTLE_ENDIAN\n\t\tstatic_assert(eastl::endian::native == eastl::endian::little,  \"must be little endian\");\n\t\tstatic_assert(eastl::endian::native != eastl::endian::big,     \"must not be big endian\");\n\t#else\n\t\tstatic_assert(eastl::endian::native != eastl::endian::little,  \"must not be little endian\");\n\t\tstatic_assert(eastl::endian::native == eastl::endian::big,     \"must be big endian\");\n\t#endif\n\t}\n\n\t// has_equality\n\t{\n\t\tstatic_assert( has_equality_v<int>, \"has_equality failure\");\n\t\tstatic_assert( has_equality_v<short>, \"has_equality failure\");\n\t\tstatic_assert( has_equality_v<long>, \"has_equality failure\");\n\t\tstatic_assert( has_equality_v<long long>, \"has_equality failure\");\n\t\tstatic_assert( has_equality_v<TestObject>, \"has_equality failure\");\n\t\tstatic_assert(!has_equality_v<MissingEquality>, \"has_equality failure\");\n\t}\n\n\t// is_aggregate\n\t#if EASTL_TYPE_TRAIT_is_aggregate_CONFORMANCE\n\t{\n\t\tstatic_assert(!is_aggregate_v<int>, \"is_aggregate failure\");\n\t\tstatic_assert( is_aggregate_v<int[]>, \"is_aggregate failure\");\n\n\t\t{\n\t\t\tstruct Aggregrate {};\n\t\t\tstatic_assert(is_aggregate_v<Aggregrate>, \"is_aggregate failure\");\n\t\t}\n\n\t\t{\n\t\t\tstruct NotAggregrate { NotAggregrate() {} }; // user provided ctor\n\t\t\tstatic_assert(!is_aggregate_v<NotAggregrate>, \"is_aggregate failure\");\n\t\t}\n\n\t\t#if defined(EA_COMPILER_CPP11_ENABLED) && !defined(EA_COMPILER_CPP14_ENABLED)\n\t\t// See https://en.cppreference.com/w/cpp/language/aggregate_initialization\n\t\t// In C++11 the requirement was added to aggregate types that no default member initializers exist,\n\t\t// however this requirement was removed in C++14.\n\t\t{\n\t\t\tstruct NotAggregrate { int data = 42; }; // default member initializer \n\t\t\tstatic_assert(!is_aggregate_v<NotAggregrate>, \"is_aggregate failure\");\n\t\t}\n\t\t#endif\n\n\t\t{\n\t\t\tstruct NotAggregrate { virtual void foo() {} }; // virtual member function\n\t\t\tstatic_assert(!is_aggregate_v<NotAggregrate>, \"is_aggregate failure\");\n\t\t}\n\t}\n\t#endif\n\n\t// is_complete_type\n\t{\n\t\tstruct Foo\n\t\t{\n\t\t\tint x;\n\t\t};\n\n\t\tstruct FooEmpty\n\t\t{\n\t\t};\n\n\t\tstruct Bar;\n\n\t\tvoid FooFunc();\n\n\t\tstatic_assert(eastl::internal::is_complete_type_v<Foo>, \"is_complete_type failure\");\n\t\tstatic_assert(eastl::internal::is_complete_type_v<FooEmpty>, \"is_complete_type failure\");\n\t\tstatic_assert(!eastl::internal::is_complete_type_v<Bar>, \"is_complete_type failure\");\n\t\tstatic_assert(!eastl::internal::is_complete_type_v<void>, \"is_complete_type failure\");\n\t\tstatic_assert(!eastl::internal::is_complete_type_v<volatile void>, \"is_complete_type failure\");\n\t\tstatic_assert(!eastl::internal::is_complete_type_v<const void>, \"is_complete_type failure\");\n\t\tstatic_assert(!eastl::internal::is_complete_type_v<const volatile void>, \"is_complete_type failure\");\n\t\tstatic_assert(eastl::internal::is_complete_type_v<decltype(FooFunc)>, \"is_complete_type failure\");\n\t}\n\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestUtility.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/utility.h>\n#include <EAStdC/EAString.h>\n\nstruct BasicObject\n{\n\tint mX;\n\tBasicObject(int x) : mX(x) {}\n};\n\ninline bool operator==(const BasicObject& t1, const BasicObject& t2) { return t1.mX == t2.mX; }\n\ninline bool operator<(const BasicObject& t1, const BasicObject& t2) { return t1.mX < t2.mX; }\n\nstatic_assert(eastl::is_trivially_copyable_v<eastl::pair<int, int>>, \"EASTL extension, pair is trivially copyable.\");\nstatic_assert(eastl::is_trivially_copyable_v<eastl::pair<float, int>>, \"EASTL extension, pair is trivially copyable.\");\nstatic_assert(eastl::is_trivially_copyable_v<eastl::pair<int, float>>, \"EASTL extension, pair is trivially copyable.\");\n\n///////////////////////////////////////////////////////////////////////////////\n// TestUtilityPair\n//\nstatic int TestUtilityPair()\n{\n\tusing namespace eastl;\n\n\tint nErrorCount = 0;\n\n\t{\n\t\tint _0 = 0, _2 = 2, _3 = 3;\n\t\tfloat _1f = 1.f;\n\n\t\t// pair();\n\t\tpair<int, float> ifPair1;\n\t\tEATEST_VERIFY((ifPair1.first == 0) && (ifPair1.second == 0.f));\n\n\t\t// pair(const T1& x, const T2& y);\n\t\tpair<int, float> ifPair2(_0, _1f);\n\t\tEATEST_VERIFY((ifPair2.first == 0) && (ifPair2.second == 1.f));\n\n\t\t// template <typename U, typename V>\n\t\t// pair(U&& u, V&& v);\n\t\tpair<int, float> ifPair3(int(0), float(1.f));\n\t\tEATEST_VERIFY((ifPair3.first == 0) && (ifPair3.second == 1.f));\n\n\t\t// template <typename U>\n\t\t// pair(U&& x, const T2& y);\n\t\tconst float fConst1 = 1.f;\n\t\tpair<int, float> ifPair4(int(0), fConst1);\n\t\tEATEST_VERIFY((ifPair4.first == 0) && (ifPair4.second == 1.f));\n\n\t\t// template <typename V>\n\t\t// pair(const T1& x, V&& y);\n\t\tconst int intConst0 = 0;\n\t\tpair<int, float> ifPair5(intConst0, float(1.f));\n\t\tEATEST_VERIFY((ifPair5.first == 0) && (ifPair5.second == 1.f));\n\n\t\tpair<const int, const int> constIntPair(_2, _3);\n\t\tEATEST_VERIFY((constIntPair.first == 2) && (constIntPair.second == 3));\n\n\t\t// pair(const pair&) = default;\n\t\tpair<int, float> ifPair2Copy(ifPair2);\n\t\tEATEST_VERIFY((ifPair2Copy.first == 0) && (ifPair2Copy.second == 1.f));\n\n\t\tpair<const int, const int> constIntPairCopy(constIntPair);\n\t\tEATEST_VERIFY((constIntPairCopy.first == 2) && (constIntPairCopy.second == 3));\n\n\t\t// template<typename U, typename V>\n\t\t// pair(const pair<U, V>& p);\n\t\tpair<long, double> idPair2(ifPair2);\n\t\tEATEST_VERIFY((idPair2.first == 0) && (idPair2.second == 1.0));\n\n\t\t// invoke the explicit TestObject constructor:\n\t\t// explicit TestObject(int x = 0, bool bThrowOnCopy = false)\n\t\tpair<TestObject, int> tiPair1(0, 4);\n\n\t\t// pair(pair&& p);\n\n\t\t// template<typename U, typename V>\n\t\t// pair(pair<U, V>&& p);\n\n\t\t// pair& operator=(const pair& p);\n\n\t\t// template<typename U, typename V>\n\t\t// pair& operator=(const pair<U, V>& p);\n\n\t\t// pair& operator=(pair&& p);\n\n\t\t// template<typename U, typename V>\n\t\t// pair& operator=(pair<U, V>&& p);\n\n\t\t// void swap(pair& p);\n\n\t\t// use_self, use_first, use_second\n\t\tuse_self<pair<int, float> > usIFPair;\n\t\tuse_first<pair<int, float> > u1IFPair;\n\t\tuse_second<pair<int, float> > u2IFPair;\n\n\t\tifPair2 = usIFPair(ifPair2);\n\t\tEATEST_VERIFY((ifPair2.first == 0) && (ifPair2.second == 1));\n\n\t\tint first = u1IFPair(ifPair2);\n\t\tEATEST_VERIFY(first == 0);\n\n\t\tfloat second = u2IFPair(ifPair2);\n\t\tEATEST_VERIFY(second == 1);\n\n\t\t// make_pair\n\t\tpair<int, float> p1 = make_pair(int(0), float(1));\n\t\tEATEST_VERIFY((p1.first == 0) && (p1.second == 1.f));\n\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED() // make_pair_ref: was declared deprecated\n\t\tpair<int, float> p2 = make_pair_ref(int(0), float(1));\n\t\tEATEST_VERIFY((p2.first == 0) && (p2.second == 1.f));\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED() // make_pair_ref: was declared deprecated\n\n\t\tpair<const char*, int> p3 = eastl::make_pair(\"a\", 1);\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p3.first, \"a\") == 0) && (p3.second == 1));\n\n\t\tpair<const char*, int> p4 = eastl::make_pair(\"a\", 1);\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p4.first, \"a\") == 0) && (p4.second == 1));\n\n\t\tpair<int, const char*> p5 = eastl::make_pair(1, \"b\");\n\t\tEATEST_VERIFY((p5.first == 1) && (EA::StdC::Strcmp(p5.second, \"b\") == 0));\n\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t\tpair<int, int> p6 = eastl::make_pair(1, 2);\n\t\tpair<int, int> p7 = eastl::make_pair(2, 1);\n\t\tpair<int, int> p8 = eastl::make_pair(7, 8);\n\t\tpair<int, int> p9 = eastl::make_pair(10, 1);\n\n\t\tEATEST_VERIFY( (p6 <=> p7) != 0);\n\t\tEATEST_VERIFY( (p6 <=> p6) == 0);\n\t\tEATEST_VERIFY( (p7 <=> p8) < 0);\n\t\tEATEST_VERIFY( (p7 <=> p8) <= 0);\n\t\tEATEST_VERIFY( (p9 <=> p8) > 0);\n\t\tEATEST_VERIFY( (p9 <=> p8) >= 0);\n#endif\n\n#if !defined(EA_COMPILER_NO_AUTO)\n\t\tauto p60 = eastl::make_pair(\"a\", \"b\");  // Different strings of same length of 1.\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p60.first, \"a\") == 0) && (EA::StdC::Strcmp(p60.second, \"b\") == 0));\n\n\t\tauto p61 = eastl::make_pair(\"ab\", \"cd\");  // Different strings of same length > 1.\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p61.first, \"ab\") == 0) && (EA::StdC::Strcmp(p61.second, \"cd\") == 0));\n\n\t\tauto p62 = eastl::make_pair(\"abc\", \"bcdef\");  // Different strings of different length.\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p62.first, \"abc\") == 0) && (EA::StdC::Strcmp(p62.second, \"bcdef\") == 0));\n\n\t\tchar strA[] = \"a\";\n\t\tauto p70 = eastl::make_pair(strA, strA);\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p70.first, \"a\") == 0) && (EA::StdC::Strcmp(p70.second, \"a\") == 0));\n\n\t\tchar strBC[] = \"bc\";\n\t\tauto p71 = eastl::make_pair(strA, strBC);\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p71.first, \"a\") == 0) && (EA::StdC::Strcmp(p71.second, \"bc\") == 0));\n\n\t\tconst char cstrA[] = \"a\";\n\t\tauto p80 = eastl::make_pair(cstrA, cstrA);\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p80.first, \"a\") == 0) && (EA::StdC::Strcmp(p80.second, \"a\") == 0));\n\n\t\tconst char cstrBC[] = \"bc\";\n\t\tauto p81 = eastl::make_pair(cstrA, cstrBC);\n\t\tEATEST_VERIFY((EA::StdC::Strcmp(p81.first, \"a\") == 0) && (EA::StdC::Strcmp(p81.second, \"bc\") == 0));\n#endif\n\t}\n\n#if EASTL_TUPLE_ENABLED\n\t// get<I>(pair&)\n\t// get<T>(pair&)\n\t// get<T, U>(pair&)\n\t{\n\t\tpair<int, float> p{2, 3.3f};\n\t\tEATEST_VERIFY(get<0>(p) == 2);\n\t\tEATEST_VERIFY(get<1>(p) == 3.3f);\n\n\t\tEATEST_VERIFY(get<int>(p) == 2);\n\t\tEATEST_VERIFY(get<float>(p) == 3.3f);\n\t\tEATEST_VERIFY((get<int, float>(p) == 2));\n\t\tEATEST_VERIFY((get<float, int>(p) == 3.3f));\n\n\t\tget<int>(p) = 3;\n\t\tEATEST_VERIFY(p.first == 3);\n\t\tget<float>(p) = 4.0f;\n\t\tEATEST_VERIFY(p.second == 4.0f);\n\n\t\t// no matching overload, index is not in range.\n\t\t// get<2>(p);\n\t}\n\n\t// get<I>(const pair&)\n\t// get<T>(const pair&)\n\t// get<T, U>(const pair&)\n\t{\n\t\tconst pair<int, float> p{ 2, 3.3f };\n\t\tEATEST_VERIFY(get<0>(p) == 2);\n\t\tEATEST_VERIFY(get<1>(p) == 3.3f);\n\n\t\tEATEST_VERIFY(get<int>(p) == 2);\n\t\tEATEST_VERIFY(get<float>(p) == 3.3f);\n\t\tEATEST_VERIFY((get<int, float>(p) == 2));\n\t\tEATEST_VERIFY((get<float, int>(p) == 3.3f));\n\n\t\t// cannot assign to a const&.\n\t\t// get<int>(p) = 3;\n\t\t// get<float>(p) = 4.0f;\n\t}\n\n\t// get<I>(pair&&)\n\t// get<T>(pair&&)\n\t// get<T, U>(pair&&)\n\t{\n\t\tEATEST_VERIFY(get<0>(pair<int, MoveOnlyType>{ 2, MoveOnlyType(3) }) == 2);\n\t\tMoveOnlyType mo = get<1>(pair<int, MoveOnlyType>{ 2, MoveOnlyType(3) });\n\t\tEATEST_VERIFY(mo == MoveOnlyType(3));\n\n\t\tEATEST_VERIFY(get<int>(pair<int, MoveOnlyType>{ 2, MoveOnlyType(3) }) == 2);\n\t\tEATEST_VERIFY(get<MoveOnlyType>(pair<int, MoveOnlyType>{ 2, MoveOnlyType(3) }) == MoveOnlyType(3));\n\t\tEATEST_VERIFY((get<int, MoveOnlyType>(pair<int, MoveOnlyType>{ 2, MoveOnlyType(3) }) == 2));\n\t\tEATEST_VERIFY((get<MoveOnlyType, int>(pair<int, MoveOnlyType>{ 2, MoveOnlyType(3) }) == MoveOnlyType(3)));\n\t}\n\n\t// get<I>(const pair&&)\n\t// get<T>(const pair&&)\n\t// get<T, U>(const pair&&)\n\t{\n\t\tusing pair_type = const pair<int, MoveOnlyType>;\n\t\tEATEST_VERIFY(get<0>(pair_type{ 2, MoveOnlyType(3) }) == 2);\n\t\tEATEST_VERIFY(get<1>(pair_type{ 2, MoveOnlyType(3) }) == MoveOnlyType(3));\n\n\t\tEATEST_VERIFY(get<int>(pair_type{ 2, MoveOnlyType(3) }) == 2);\n\t\tEATEST_VERIFY(get<MoveOnlyType>(pair_type{ 2, MoveOnlyType(3) }) == MoveOnlyType(3));\n\t\tEATEST_VERIFY((get<int, MoveOnlyType>(pair_type{ 2, MoveOnlyType(3) }) == 2));\n\t\tEATEST_VERIFY((get<MoveOnlyType, int>(pair_type{ 2, MoveOnlyType(3) }) == MoveOnlyType(3)));\n\t}\n\n\t// get(pair<T, T>)\n\t{\n\t\tpair<int, int> p{ 1, 2 };\n\t\tEATEST_VERIFY(get<0>(p) == 1);\n\t\tEATEST_VERIFY(get<1>(p) == 2);\n\n\t\tget<0>(p) = 3;\n\t\tEATEST_VERIFY(p.first == 3);\n\t\tget<1>(p) = 4;\n\t\tEATEST_VERIFY(p.second == 4);\n\n\t\t// no matching overload, ambiguous which element.\n\t\t// get<int>(p)\n\t}\n\n\t// get<I>(pair) and get<T>(pair) are constexpr\n\t{\n\t\tconstexpr pair<int, float> cp{ 1, 2.0f };\n\t\tconstexpr int ci = get<0>(cp);\n\t\tconstexpr float cf = get<float>(cp);\n\t\tstatic_assert(ci == 1, \"unexpected return from get<I>(pair)\");\n\t\tstatic_assert(cf == 2.0f, \"unexpected return from get<T>(pair)\");\n\t}\n\n\n#endif\n\n\t{\n// One-off tests and regressions\n\n#if EASTL_PAIR_CONFORMANCE  // See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#811\n\t\tpair<char*, char*> zeroLiteralPair(0, 0);\n\t\tEATEST_VERIFY((zeroLiteralPair.first == NULL) && (zeroLiteralPair.second == NULL));\n#endif\n\n\t\t// template<typename U>\n\t\t// pair(U&& x, const T2& y)\n\t\ttypedef eastl::pair<uint16_t, const char8_t*> LCIDMapping;\n\t\tLCIDMapping lcidMappingArray[1] = {LCIDMapping(0x0036, EA_CHAR8(\"af\"))};  // Note that 0x0036 is of type int.\n\t\tEATEST_VERIFY((lcidMappingArray[0].first == 0x0036));\n\n\t\t// template<typename V>\n\t\t// pair(const T1& x, V&& y)\n\t\ttypedef eastl::pair<const char8_t*, uint16_t> LCIDMapping2;\n\t\tLCIDMapping2 lcidMapping2Array[1] = {LCIDMapping2(EA_CHAR8(\"af\"), 0x0036)};\n\t\tEATEST_VERIFY((lcidMapping2Array[0].second == 0x0036));\n\n// The following code was giving an EDG compiler:\n//       error 145: a value of type \"int\" cannot be used to initialize\n//       an entity of type \"void *\" second(eastl::forward<V>(v)) {}\n// template <typename U, typename V>\n// pair(U&& u, V&& v);\n#if EASTL_PAIR_CONFORMANCE\n\t\ttypedef eastl::pair<float*, void*> TestPair1;\n\t\tfloat fOne = 1.f;\n\t\tTestPair1 testPair1(&fOne, NULL);\n\t\tEATEST_VERIFY(*testPair1.first == 1.f);\n#endif\n\t}\n\n#ifndef EA_COMPILER_NO_STRUCTURED_BINDING\n\t// pair structured bindings test \n\t{\n\t\teastl::pair<int, int> t = {1,2};\n\t\tauto [x,y] = t;\n\t\tEATEST_VERIFY(x == 1);\n\t\tEATEST_VERIFY(y == 2);\n\t}\n\n\t{\n\t\tauto t = eastl::make_pair(1, 2);\n\t\tauto [x,y] = t;\n\t\tEATEST_VERIFY(x == 1);\n\t\tEATEST_VERIFY(y == 2);\n\t}\n\n\t{ // reported user-regression structured binding unpacking for iterators\n\t\teastl::vector<int> v = {1,2,3,4,5,6};\n\t\tauto t = eastl::make_pair(v.begin(), v.end() - 1);\n\t\tauto [x,y] = t;\n\t\tEATEST_VERIFY(*x == 1);\n\t\tEATEST_VERIFY(*y == 6);\n\t}\n\n\t{ // reported user-regression structured binding unpacking for iterators\n\t\teastl::vector<int> v = {1,2,3,4,5,6};\n\t\tauto t = eastl::make_pair(v.begin(), v.end());\n\t\tauto [x,y] = t;\n\t\tEATEST_VERIFY(*x == 1);\n\t\tEA_UNUSED(y);\n\t}\n\n\t{ // reported user-regression for const structured binding unpacking for iterators\n\t\teastl::vector<int> v = {1,2,3,4,5,6};\n\t\tconst auto [x,y] = eastl::make_pair(v.begin(), v.end());;\n\t\tEATEST_VERIFY(*x == 1);\n\t\tEA_UNUSED(y);\n\t}\n#endif\n\n\treturn nErrorCount;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// TestUtilityRelops\n//\nstatic int TestUtilityRelops()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tusing namespace eastl::rel_ops;  // Defines default versions of operators !=, <, >, <=, >= based on == and <.\n\n\t\tBasicObject bo1(1), bo2(2);\n\n\t\tEATEST_VERIFY(!(bo1 == bo2));\n\t\tEATEST_VERIFY((bo1 != bo2));\n\t\tEATEST_VERIFY((bo1 < bo2));\n\t\tEATEST_VERIFY(!(bo1 > bo2));\n\t\tEATEST_VERIFY((bo1 <= bo2));\n\t\tEATEST_VERIFY(!(bo1 >= bo2));\n\t}\n\n\treturn nErrorCount;\n}\n\n// ThrowSwappable\nstruct ThrowSwappable\n{\n};\n\nvoid swap(ThrowSwappable& x, ThrowSwappable& y) EA_NOEXCEPT_IF(false)\n{\n\tThrowSwappable temp(x);\n\tx = y;\n\ty = temp;\n\n#if EASTL_EXCEPTIONS_ENABLED\n\tthrow int();\n#endif\n}\n\n#if EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE\n// NoThrowSwappable\nstruct NoThrowSwappable\n{\n};\n\nvoid swap(NoThrowSwappable& x, NoThrowSwappable& y) EA_NOEXCEPT_IF(true)\n{\n\tNoThrowSwappable temp(x);\n\tx = y;\n\ty = temp;\n}\n#endif\n\nstruct Swappable1 {};\nstruct Swappable2 {};\nstruct Swappable3 {};\nvoid swap(Swappable1&, Swappable2&) {} \nvoid swap(Swappable2&, Swappable1&) {} \nvoid swap(Swappable1&, Swappable3&) {} // intentionally missing 'swap(Swappable3, Swappable1)'\n\n\nstatic int TestUtilitySwap()\n{\n\tint nErrorCount = 0;\n\n// is_swappable\n// is_nothrow_swappable\n#if EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE\n\tstatic_assert((eastl::is_swappable<int>::value == true), \"is_swappable failure\");\n\tstatic_assert((eastl::is_swappable<eastl::vector<int> >::value == true), \"is_swappable failure\");\n\tstatic_assert((eastl::is_swappable<ThrowSwappable>::value == true), \"is_swappable failure\");\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\tstatic_assert((eastl::is_swappable_v<int> == true), \"is_swappable failure\");\n\t\tstatic_assert((eastl::is_swappable_v<eastl::vector<int> > == true), \"is_swappable failure\");\n\t\tstatic_assert((eastl::is_swappable_v<ThrowSwappable> == true), \"is_swappable failure\");\n\t#endif\n// Need to come up with a class that's not swappable. How do we do that, given the universal swap template?  \n// static_assert((eastl::is_swappable<?>::value  == false), \"is_swappable failure\");\n#endif\n\n#if EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE\n\tstatic_assert((eastl::is_nothrow_swappable<int>::value == true), \"is_nothrow_swappable failure\");  // There currently isn't any specialization for swap of scalar types that's nothrow.\n\tstatic_assert((eastl::is_nothrow_swappable<eastl::vector<int> >::value == false), \"is_nothrow_swappable failure\");\n\tstatic_assert((eastl::is_nothrow_swappable<ThrowSwappable>::value == false), \"is_nothrow_swappable failure\");\n\tstatic_assert((eastl::is_nothrow_swappable<NoThrowSwappable>::value == true), \"is_nothrow_swappable failure\");\n\t#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\tstatic_assert((eastl::is_nothrow_swappable_v<int> == true), \"is_nothrow_swappable failure\");  // There currently isn't any specialization for swap of scalar types that's nothrow.\n\t\tstatic_assert((eastl::is_nothrow_swappable_v<eastl::vector<int>> == false), \"is_nothrow_swappable failure\");\n\t\tstatic_assert((eastl::is_nothrow_swappable_v<ThrowSwappable> == false), \"is_nothrow_swappable failure\");\n\t\tstatic_assert((eastl::is_nothrow_swappable_v<NoThrowSwappable> == true), \"is_nothrow_swappable failure\");\n\t#endif\n#endif\n\n#if EASTL_VARIADIC_TEMPLATES_ENABLED\n// is_swappable_with\n// is_nothrow_swappable_with\n\tstatic_assert(eastl::is_swappable_with<int&, int&>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<int, int>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<int&, int>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<int, int&>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<int, short>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<int, long>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<int, eastl::vector<int>>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<void, void>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<int, void>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<void, int>::value, \"is_swappable_with failure\");\n\tstatic_assert(!eastl::is_swappable_with<ThrowSwappable, ThrowSwappable>::value, \"is_swappable_with failure\");\n\tstatic_assert(eastl::is_swappable_with<ThrowSwappable&, ThrowSwappable&>::value, \"is_swappable_with failure\");\n\tstatic_assert(eastl::is_swappable_with<Swappable1&, Swappable1&>::value, \"is_swappable_with failure\");\n\tstatic_assert(eastl::is_swappable_with<Swappable1&, Swappable2&>::value, \"is_swappable_with failure\");\n\tstatic_assert(eastl::is_swappable_with<Swappable2&, Swappable1&>::value, \"is_swappable_with failure\");\n\n    #if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\tstatic_assert(eastl::is_swappable_with_v<int&, int&>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_swappable_with_v<int, int>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_swappable_with_v<int&, int>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_swappable_with_v<int, int&>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_swappable_with_v<int, short>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_swappable_with_v<int, long>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_swappable_with_v<int, eastl::vector<int>>, \"is_swappable_with_v failure\");\n\t    static_assert(!eastl::is_swappable_with_v<void, void>, \"is_swappable_with_v failure\");\n\t    static_assert(!eastl::is_swappable_with_v<int, void>, \"is_swappable_with_v failure\");\n\t    static_assert(!eastl::is_swappable_with_v<void, int>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_swappable_with_v<ThrowSwappable, ThrowSwappable>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(eastl::is_swappable_with_v<ThrowSwappable&, ThrowSwappable&>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(eastl::is_swappable_with_v<Swappable1&, Swappable1&>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(eastl::is_swappable_with_v<Swappable1&, Swappable2&>, \"is_swappable_with_v failure\");\n\t\tstatic_assert(eastl::is_swappable_with_v<Swappable2&, Swappable1&>, \"is_swappable_with_v failure\");\n    #endif // EASTL_VARIABLE_TEMPLATES_ENABLED\n\n#if EASTL_TYPE_TRAIT_is_nothrow_swappable_with_CONFORMANCE\n\tstatic_assert(eastl::is_nothrow_swappable_with<int&, int&>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<int, int>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<int&, int>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<int, int&>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<int, short>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<int, long>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<int, eastl::vector<int>>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<void, void>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<int, void>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<void, int>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<ThrowSwappable, ThrowSwappable>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<ThrowSwappable&, ThrowSwappable&>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(!eastl::is_nothrow_swappable_with<NoThrowSwappable, NoThrowSwappable>::value, \"is_nothrow_swappable_with failure\");\n\tstatic_assert(eastl::is_nothrow_swappable_with<NoThrowSwappable&, NoThrowSwappable&>::value, \"is_nothrow_swappable_with failure\");\n\n    #if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t\tstatic_assert(eastl::is_nothrow_swappable_with_v<int&, int&>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<int, int>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<int&, int>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<int, int&>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<int, short>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<int, long>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<int, eastl::vector<int>>, \"is_nothrow_swappable_with_v failure\");\n\t    static_assert(!eastl::is_nothrow_swappable_with_v<void, void>, \"is_nothrow_swappable_with_v failure\");\n\t    static_assert(!eastl::is_nothrow_swappable_with_v<int, void>, \"is_nothrow_swappable_with_v failure\");\n\t    static_assert(!eastl::is_nothrow_swappable_with_v<void, int>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<ThrowSwappable, ThrowSwappable>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<ThrowSwappable&, ThrowSwappable&>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(!eastl::is_nothrow_swappable_with_v<NoThrowSwappable, NoThrowSwappable>, \"is_nothrow_swappable_with_v failure\");\n\t\tstatic_assert(eastl::is_nothrow_swappable_with_v<NoThrowSwappable&, NoThrowSwappable&>, \"is_nothrow_swappable_with_v failure\");\n    #endif // EASTL_VARIABLE_TEMPLATES_ENABLED\n#endif\n#endif // EASTL_VARIADIC_TEMPLATES_ENABLED\n\n\treturn nErrorCount;\n}\n\n#if !defined(EA_COMPILER_NO_NOEXCEPT)\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Warning C4626 warns against an implicitly deleted move assignment operator.\n// This warning was disabled by default in VS2013. It was enabled by default in\n// VS2015.  Since the the tests below are explicitly testing move construction\n// of the various classes explicitly deleting the move assignment to remove the\n// warning is safe. \n//\n// https://msdn.microsoft.com/en-us/library/23k5d385.aspx\n\nstruct noexcept_move_copy\n{\n\tbool mStatus;\n\n\tnoexcept_move_copy() : mStatus(true) {}\n\n\tnoexcept_move_copy(const noexcept_move_copy&) = default;\n\n\tnoexcept_move_copy(noexcept_move_copy&& r) noexcept { r.mStatus = false; }\n\n\tnoexcept_move_copy& operator=(const noexcept_move_copy&) = delete;  // required as VS2015 enabled C4626 by default.\n};\n\nstruct noexcept_move_no_copy\n{\n\tbool mStatus;\n\n\tnoexcept_move_no_copy() : mStatus(true) {}\n\n\tnoexcept_move_no_copy(const noexcept_move_no_copy&) = delete;\n\n\tnoexcept_move_no_copy(noexcept_move_no_copy&& r) noexcept { r.mStatus = false; };\n\n\tnoexcept_move_no_copy& operator=(const noexcept_move_no_copy&) = delete;  // required as VS2015 enabled C4626 by default.\n};\n\nstruct except_move_copy\n{\n\tbool mStatus;\n\n\texcept_move_copy() : mStatus(true) {}\n\n\texcept_move_copy(const except_move_copy&) = default;\n\n\texcept_move_copy(except_move_copy&& r) noexcept(false) { r.mStatus = false; };\n\n\texcept_move_copy& operator=(const except_move_copy&) = delete;  // required as VS2015 enabled C4626 by default.\n};\n\nstruct except_move_no_copy\n{\n\tbool mStatus;\n\n\texcept_move_no_copy() : mStatus(true) {}\n\n\texcept_move_no_copy(const except_move_no_copy&) = delete;\n\n\texcept_move_no_copy(except_move_no_copy&& r) noexcept(false) { r.mStatus = false; };\n\n\texcept_move_no_copy& operator=(const except_move_no_copy&) = delete;  // required as VS2015 enabled C4626 by default.\n};\n#endif\n\nstatic int TestUtilityMove()\n{\n\tint nErrorCount = 0;\n\n// move_if_noexcept\n#if !defined(EA_COMPILER_NO_NOEXCEPT)\n\tnoexcept_move_copy nemcA;\n\tnoexcept_move_copy nemcB =\n\t\teastl::move_if_noexcept(nemcA);  // nemcB should be constructed via noexcept_move_copy(noexcept_move_copy&&)\n\tEATEST_VERIFY(nemcA.mStatus == false);\n\tEA_UNUSED(nemcB);\n\n\tnoexcept_move_no_copy nemncA;\n\tnoexcept_move_no_copy nemncB = eastl::move_if_noexcept(\n\t\tnemncA);  // nemncB should be constructed via noexcept_move_no_copy(noexcept_move_no_copy&&)\n\tEATEST_VERIFY(nemncA.mStatus == false);\n\tEA_UNUSED(nemncB);\n\n\texcept_move_copy emcA;\n\texcept_move_copy emcB = eastl::move_if_noexcept(\n\t\temcA);  // emcB should be constructed via except_move_copy(const except_move_copy&) if exceptions are enabled.\n#if EASTL_EXCEPTIONS_ENABLED\n\tEATEST_VERIFY(emcA.mStatus == true);\n#else\n\tEATEST_VERIFY(emcA.mStatus == false);\n#endif\n\tEA_UNUSED(emcB);\n\n\texcept_move_no_copy emncA;\n\texcept_move_no_copy emncB =\n\t\teastl::move_if_noexcept(emncA);  // emncB should be constructed via except_move_no_copy(except_move_no_copy&&)\n\tEATEST_VERIFY(emncA.mStatus == false);\n\tEA_UNUSED(emncB);\n#endif\n\n\treturn nErrorCount;\n}\n\nstatic int TestUtilityIntegerSequence()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n#if EASTL_VARIADIC_TEMPLATES_ENABLED\n\t\n\tEATEST_VERIFY((integer_sequence<int, 0, 1, 2, 3, 4>::size() == 5));\n\tEATEST_VERIFY((make_integer_sequence<int, 5>::size() == 5));\n\tstatic_assert(is_same<make_integer_sequence<int, 5>, integer_sequence<int, 0, 1, 2, 3, 4>>::value);\n\n\tEATEST_VERIFY((index_sequence<0, 1, 2, 3, 4>::size() == 5));\n\tEATEST_VERIFY((make_index_sequence<5>::size() == 5));\n\tstatic_assert(is_same<make_index_sequence<5>, index_sequence<0, 1, 2, 3, 4>>::value);\n\tstatic_assert(is_same<make_index_sequence<5>, integer_sequence<size_t, 0, 1, 2, 3, 4>>::value);\n#endif  // EASTL_VARIADIC_TEMPLATES_ENABLED\n\n\treturn nErrorCount;\n}\n\nstatic int TestUtilityExchange()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tint a = 0;\n\t\tauto r = eastl::exchange(a, 1);\n\n\t\tEATEST_VERIFY(r == 0);\n\t\tEATEST_VERIFY(a == 1);\n\t}\n\n\t{\n\t\tint a = 0;\n\t\tauto r = eastl::exchange(a, 1.78);\n\n\t\tEATEST_VERIFY(r == 0);\n\t\tEATEST_VERIFY(a == 1);\n\t}\n\n\t{\n\t\tint a = 0;\n\t\tauto r = eastl::exchange(a, 1.78f);\n\n\t\tEATEST_VERIFY(r == 0);\n\t\tEATEST_VERIFY(a == 1);\n\t}\n\n\t{\n\t\tint a = 0, b = 1;\n\t\tauto r = eastl::exchange(a, b);\n\n\t\tEATEST_VERIFY(r == 0);\n\t\tEATEST_VERIFY(a == 1);\n\t\tEATEST_VERIFY(b == 1);\n\t}\n\n\t{\n\t\tbool b = true;\n\n\t\tauto r = eastl::exchange(b, true);\n\t\tEATEST_VERIFY(r);\n\n\t\tr = eastl::exchange(b, false);\n\t\tEATEST_VERIFY(r);\n\t\tEATEST_VERIFY(!b);\n\n\t\tr = eastl::exchange(b, true);\n\t\tEATEST_VERIFY(!r);\n\t\tEATEST_VERIFY(b);\n\t}\n\n\t{\n\t\tTestObject::Reset();\n\n\t\tTestObject a(42);\n\t\tauto r = eastl::exchange(a, TestObject(24));\n\n\t\tEATEST_VERIFY(r.mX == 42);\n\t\tEATEST_VERIFY(a.mX == 24);\n\t}\n\n\t{\n\t\tconst char* const pElectronicArts = \"Electronic Arts\";\n\t\tconst char* const pEAVancouver = \"EA Vancouver\";\n\n\t\teastl::string a(pElectronicArts);\n\t\tauto r = eastl::exchange(a, pEAVancouver);\n\n\t\tEATEST_VERIFY(r == pElectronicArts);\n\t\tEATEST_VERIFY(a == pEAVancouver);\n\n\t\tr = eastl::exchange(a, \"EA Standard Template Library\");\n\t\tEATEST_VERIFY(a == \"EA Standard Template Library\");\n\t}\n\n\t// Construct pair using single move constructor\n\t{\n\t\tstruct TestPairSingleMoveConstructor\n\t\t{\n\t\t\tvoid test(int&& val)\n\t\t\t{\n\t\t\t\teastl::pair<int,int> p(eastl::pair_first_construct, eastl::move(val));\n\t\t\t}\n\t\t};\n\n\t\tint i1 = 1;\n\t\tTestPairSingleMoveConstructor test;\n\t\ttest.test(eastl::move(i1));\n\t}\n\n\t// User reported regression where via reference collapsing, we see the same single element ctor defined twice.\n\t//\n\t// T = const U&\n\t// pair(const T&) -> pair(const const U& &) -> pair(const U&)\n\t// pair(T&&)      -> pair(const U& &&)      -> pair(const U&)\n\t{\n\t\tstruct FooType {};\n\n\t\tusing VectorOfPairWithReference = eastl::vector<eastl::pair<const FooType&, float>>;\n\n\t\tVectorOfPairWithReference v;\n\t}\n\n\treturn nErrorCount;\n}\n\n#if defined(EA_COMPILER_CPP17_ENABLED)\ntemplate <typename T>\nstatic int TestCmpCommon()\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::cmp_equal(T(0), T(0)));\n\tEATEST_VERIFY(eastl::cmp_equal(T(1), T(1)));\n\tEATEST_VERIFY(eastl::cmp_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));\n\tEATEST_VERIFY(eastl::cmp_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(!eastl::cmp_equal(T(0), T(1)));\n\tEATEST_VERIFY(!eastl::cmp_equal(T(1), T(0)));\n\tif (eastl::is_signed_v<T>)\n\t{\n\t\tEATEST_VERIFY(eastl::cmp_equal(T(-1), T(-1)));\n\t\tEATEST_VERIFY(!eastl::cmp_equal(T(-1), T(-2)));\n\t\tEATEST_VERIFY(!eastl::cmp_equal(T(-2), T(-1)));\n\t}\n\n\tEATEST_VERIFY(eastl::cmp_not_equal(T(1), T(0)));\n\tEATEST_VERIFY(eastl::cmp_not_equal(T(0), T(1)));\n\tEATEST_VERIFY(eastl::cmp_not_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(eastl::cmp_not_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));\n\tif (eastl::is_signed_v<T>)\n\t{\n\t\tEATEST_VERIFY(!eastl::cmp_not_equal(T(-1), T(-1)));\n\t\tEATEST_VERIFY(eastl::cmp_not_equal(T(-1), T(-2)));\n\t\tEATEST_VERIFY(eastl::cmp_not_equal(T(-2), T(-1)));\n\t}\n\n\tEATEST_VERIFY(eastl::cmp_less(T(0), T(1)));\n\tEATEST_VERIFY(eastl::cmp_less(T(5), T(10)));\n\tEATEST_VERIFY(!eastl::cmp_less(T(0), T(0)));\n\tEATEST_VERIFY(!eastl::cmp_less(T(1), T(0)));\n\tEATEST_VERIFY(eastl::cmp_less(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(!eastl::cmp_less(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));\n\tEATEST_VERIFY(!eastl::cmp_less(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(!eastl::cmp_less(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));\n\tif (eastl::is_signed_v<T>)\n\t{\n\t\tEATEST_VERIFY(!eastl::cmp_less(T(-1), T(-1)));\n\t\tEATEST_VERIFY(!eastl::cmp_less(T(-1), T(-2)));\n\t\tEATEST_VERIFY(eastl::cmp_less(T(-2), T(-1)));\n\t}\n\n\tEATEST_VERIFY(eastl::cmp_less_equal(T(0), T(1)));\n\tEATEST_VERIFY(eastl::cmp_less_equal(T(5), T(10)));\n\tEATEST_VERIFY(eastl::cmp_less_equal(T(0), T(0)));\n\tEATEST_VERIFY(eastl::cmp_less_equal(T(1), T(1)));\n\tEATEST_VERIFY(!eastl::cmp_less_equal(T(1), T(0)));\n\tEATEST_VERIFY(eastl::cmp_less_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(eastl::cmp_less_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));\n\tEATEST_VERIFY(eastl::cmp_less_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(!eastl::cmp_less_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));\n\tif (eastl::is_signed_v<T>)\n\t{\n\t\tEATEST_VERIFY(eastl::cmp_less_equal(T(-1), T(-1)));\n\t\tEATEST_VERIFY(!eastl::cmp_less_equal(T(-1), T(-2)));\n\t\tEATEST_VERIFY(eastl::cmp_less_equal(T(-2), T(-1)));\n\t}\n\n\tEATEST_VERIFY(eastl::cmp_greater(T(1), T(0)));\n\tEATEST_VERIFY(eastl::cmp_greater(T(10), T(5)));\n\tEATEST_VERIFY(!eastl::cmp_greater(T(0), T(0)));\n\tEATEST_VERIFY(!eastl::cmp_greater(T(0), T(1)));\n\tEATEST_VERIFY(eastl::cmp_greater(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));\n\tEATEST_VERIFY(!eastl::cmp_greater(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));\n\tEATEST_VERIFY(!eastl::cmp_greater(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(!eastl::cmp_greater(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));\n\tif (eastl::is_signed_v<T>)\n\t{\n\t\tEATEST_VERIFY(!eastl::cmp_greater(T(-1), T(-1)));\n\t\tEATEST_VERIFY(eastl::cmp_greater(T(-1), T(-2)));\n\t\tEATEST_VERIFY(!eastl::cmp_greater(T(-2), T(-1)));\n\t}\n\n\tEATEST_VERIFY(eastl::cmp_greater_equal(T(1), T(0)));\n\tEATEST_VERIFY(eastl::cmp_greater_equal(T(10), T(5)));\n\tEATEST_VERIFY(eastl::cmp_greater_equal(T(0), T(0)));\n\tEATEST_VERIFY(!eastl::cmp_greater_equal(T(0), T(1)));\n\tEATEST_VERIFY(eastl::cmp_greater_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));\n\tEATEST_VERIFY(eastl::cmp_greater_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));\n\tEATEST_VERIFY(eastl::cmp_greater_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));\n\tEATEST_VERIFY(!eastl::cmp_greater_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));\n\tif (eastl::is_signed_v<T>)\n\t{\n\t\tEATEST_VERIFY(eastl::cmp_greater_equal(T(-1), T(-1)));\n\t\tEATEST_VERIFY(eastl::cmp_greater_equal(T(-1), T(-2)));\n\t\tEATEST_VERIFY(!eastl::cmp_greater_equal(T(-2), T(-1)));\n\t}\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T, typename U>\nstatic int TestUtilityCmpEql(const T x, const U y)\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::cmp_equal(T(x), U(y)));\n\tEATEST_VERIFY(eastl::cmp_equal(U(y), T(x)));\n\tEATEST_VERIFY(!eastl::cmp_not_equal(T(x), U(y)));\n\tEATEST_VERIFY(!eastl::cmp_not_equal(U(y), T(x)));\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T, typename U>\nstatic int TestUtilityCmpLess(const T x, const U y)\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::cmp_less(T(x), U(y)));\n\tEATEST_VERIFY(!eastl::cmp_less(U(y), T(x)));\n\n\tEATEST_VERIFY(!eastl::cmp_greater_equal(T(x), U(y)));\n\tEATEST_VERIFY(eastl::cmp_greater_equal(U(y), T(x)));\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T, typename U>\nstatic int TestUtilityCmpGreater(const T x, const U y)\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::cmp_greater(T(x), U(y)));\n\tEATEST_VERIFY(!eastl::cmp_greater(U(y), T(x)));\n\n\tEATEST_VERIFY(!eastl::cmp_less_equal(T(x), U(y)));\n\tEATEST_VERIFY(eastl::cmp_less_equal(U(y), T(x)));\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T, typename U>\nstatic int TestUtilityCmpLessEq(const T x, const U y)\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::cmp_less_equal(T(x), U(y)));\n\tEATEST_VERIFY(eastl::cmp_less(T(x), U(y)) || eastl::cmp_equal(T(x), U(y)));\n\n\tEATEST_VERIFY(eastl::cmp_greater_equal(U(y), T(x)));\n\n\treturn nErrorCount;\n}\n\ntemplate <typename T, typename U>\nstatic int TestUtilityCmpGreaterEq(const T x, const U y)\n{\n\tint nErrorCount = 0;\n\n\tEATEST_VERIFY(eastl::cmp_greater_equal(T(x), U(y)));\n\tEATEST_VERIFY(eastl::cmp_greater(T(x), U(y)) || eastl::cmp_equal(T(x), U(y)));\n\n\tEATEST_VERIFY(eastl::cmp_less_equal(U(y), T(x)));\n\n\treturn nErrorCount;\n}\n\nstatic int TestUtilityIntegralComp()\n{\n\tint nErrorCount = 0;\n\n\t// Test integral comparisons among same types\n\tnErrorCount += TestCmpCommon<int>();\n\tnErrorCount += TestCmpCommon<short>();\n\tnErrorCount += TestCmpCommon<long>();\n\tnErrorCount += TestCmpCommon<long long>();\n\n\tnErrorCount += TestCmpCommon<unsigned int>();\n\tnErrorCount += TestCmpCommon<unsigned short>();\n\tnErrorCount += TestCmpCommon<unsigned long>();\n\tnErrorCount += TestCmpCommon<unsigned long long>();\n\n\t//\n\t// Test integral comparison among different types\n\t//\n\t// we're now using integer-suffixes because Clang on\n\t// unix was failing to construct integer types with a\n\t// space in them, like 'unsigned long', e.g.\n\t// \n\t//    TestUilityCmpLess(4, unsigned long(4))\n\t// \n\t// \n\t// Integer literal suffixes:\n\t// \n\t//    u/U   : unsigned (`unsigned int` by default)\n\t// \n\t//    l/L   : long\n\t//    ll/LL : long long\n\t//    z/Z   : (c++23) the signed version of size_t\n\t//    uz/UZ : (c++23) size_t\n\t//\n\t// unsignedness & the width suffixes can be combined together.\n\t// thus `2ull` is an unsigned long long (of value 2). because\n\t// there's no ordering for u vs ll, we can also write the\n\t// equivalent `2llu`, or `2ULL`\n\t// \n\t// NOTE: integer literals that are too large to fit into the\n\t//       requested type will be promoted a little bit to a\n\t//       \"sensible\" (post c++11) higher category. so the\n\t//       following:\n\t// \n\t//           235763456234623452345L\n\t//\n\t//       is way to large to fit into `L` (long int), and so\n\t//       and so will be interpreted as a `long long int` literal.\n\t// \n\t// DOUBLE NOTE: the above promotion rules are expanded a bit for\n\t//              binary, hexadecimal, or octal literals. basically\n\t//              they can be unsigned sometimes. this is why\n\t//              compilers give you a warning when you mess this up.\n\t// \n\t// the more you know!!\n\t// \n\t// \n\t// Further reading\n\t//     https://en.cppreference.com/w/cpp/language/integer_literal\n\t//\n\tnErrorCount += TestUtilityCmpEql(0, short(0));\n\tnErrorCount += TestUtilityCmpEql(short(2), 2l);\n\tnErrorCount += TestUtilityCmpEql(short(3), 3ul);\n\tnErrorCount += TestUtilityCmpEql(-5, -5ll);\n\tnErrorCount += TestUtilityCmpEql(short(-100), -100ll);\n\tnErrorCount += TestUtilityCmpEql(100u, 100l);\n\tnErrorCount += TestUtilityCmpEql(100ull, 100);\n\n\tnErrorCount += TestUtilityCmpLess(0, 1ll);\n\tnErrorCount += TestUtilityCmpLess(-1, 1ul);\n\tnErrorCount += TestUtilityCmpLess(short(-100), 100ll);\n\tnErrorCount += TestUtilityCmpLess(eastl::numeric_limits<long>::min(), short(0));\n\tnErrorCount += TestUtilityCmpLess(short(0), eastl::numeric_limits<int>::max());\n\tnErrorCount += TestUtilityCmpLess(eastl::numeric_limits<unsigned short>::min(), eastl::numeric_limits<int>::max());\n\tnErrorCount += TestUtilityCmpLess(eastl::numeric_limits<short>::max(), eastl::numeric_limits<long>::max());\n\tnErrorCount += TestUtilityCmpLess(eastl::numeric_limits<int>::max(), eastl::numeric_limits<long long>::max());\n\tnErrorCount += TestUtilityCmpLess(-100, 0u);\n\tnErrorCount += TestUtilityCmpLess(eastl::numeric_limits<int>::min(), eastl::numeric_limits<unsigned int>::min());\n\n\tnErrorCount += TestUtilityCmpGreater(1, short(0));\n\tnErrorCount += TestUtilityCmpGreater(1ul, -1);\n\tnErrorCount += TestUtilityCmpGreater(100ull, short(-100));\n\tnErrorCount += TestUtilityCmpGreater(short(0), eastl::numeric_limits<short>::min());\n\tnErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<long>::max(), (unsigned short)5);\n\tnErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<long>::max(), eastl::numeric_limits<int>::min());\n\tnErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<int>::max(), eastl::numeric_limits<short>::max());\n\tnErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<long long>::max(), eastl::numeric_limits<int>::max());\n\tnErrorCount += TestUtilityCmpGreater(0u, -100);\n\tnErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<unsigned int>::min(), eastl::numeric_limits<int>::min());\n\n\tnErrorCount += TestUtilityCmpLessEq(0, short(1));\n\tnErrorCount += TestUtilityCmpLessEq(-1, -1ll);\n\tnErrorCount += TestUtilityCmpLessEq(short(-100), 100ull);\n\tnErrorCount += TestUtilityCmpLessEq(short(-100), -100ll);\n\tnErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::min(), short(0));\n\tnErrorCount += TestUtilityCmpLessEq(short(0), eastl::numeric_limits<int>::max());\n\tnErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<short>::min(), eastl::numeric_limits<short>::min());\n\tnErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<int>::max());\n\tnErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<long long>::max());\n\tnErrorCount += TestUtilityCmpLessEq(50, 50u);\n\tnErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::min(), eastl::numeric_limits<unsigned int>::min());\n\n\tnErrorCount += TestUtilityCmpGreaterEq(1, short(1));\n\tnErrorCount += TestUtilityCmpGreaterEq(-1ll, -1);\n\tnErrorCount += TestUtilityCmpGreaterEq(-100ll, short(-100));\n\tnErrorCount += TestUtilityCmpGreaterEq(short(0), 0l);\n\tnErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<long>::max(), eastl::numeric_limits<long>::max());\n\tnErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<short>::min());\n\tnErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<short>::max());\n\tnErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<long long>::max(), eastl::numeric_limits<int>::max());\n\tnErrorCount += TestUtilityCmpGreaterEq(0u, 0);\n\tnErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<unsigned int>::min(), eastl::numeric_limits<int>::min());\n\n\t// Test in_range\n\tEATEST_VERIFY(eastl::in_range<int>(0));\n\tEATEST_VERIFY(eastl::in_range<int>(eastl::numeric_limits<int>::min()));\n\tEATEST_VERIFY(eastl::in_range<int>(eastl::numeric_limits<int>::max()));\n\tEATEST_VERIFY(eastl::in_range<unsigned int>(0));\n\tEATEST_VERIFY(eastl::in_range<unsigned int>(eastl::numeric_limits<unsigned int>::min()));\n\tEATEST_VERIFY(eastl::in_range<unsigned int>(eastl::numeric_limits<unsigned int>::max()));\n\tEATEST_VERIFY(!eastl::in_range<unsigned int>(-1));\n\tEATEST_VERIFY(!eastl::in_range<int>(eastl::numeric_limits<unsigned int>::max()));\n\tEATEST_VERIFY(!eastl::in_range<unsigned int>(eastl::numeric_limits<int>::min()));\n\n\tEATEST_VERIFY(eastl::in_range<short>(100));\n\tEATEST_VERIFY(eastl::in_range<short>(eastl::numeric_limits<short>::min()));\n\tEATEST_VERIFY(eastl::in_range<short>(eastl::numeric_limits<short>::max()));\n\tEATEST_VERIFY(eastl::in_range<unsigned short>(100));\n\tEATEST_VERIFY(eastl::in_range<unsigned short>(eastl::numeric_limits<unsigned short>::min()));\n\tEATEST_VERIFY(eastl::in_range<unsigned short>(eastl::numeric_limits<unsigned short>::max()));\n\tEATEST_VERIFY(!eastl::in_range<unsigned short>(-1));\n\tEATEST_VERIFY(!eastl::in_range<short>(eastl::numeric_limits<unsigned int>::max()));\n\tEATEST_VERIFY(!eastl::in_range<unsigned short>(eastl::numeric_limits<int>::min()));\n\n\tEATEST_VERIFY(eastl::in_range<long>(50));\n\tEATEST_VERIFY(eastl::in_range<long>(eastl::numeric_limits<long>::min()));\n\tEATEST_VERIFY(eastl::in_range<long>(eastl::numeric_limits<long>::max()));\n\tEATEST_VERIFY(eastl::in_range<unsigned long>(50));\n\tEATEST_VERIFY(eastl::in_range<unsigned long>(eastl::numeric_limits<unsigned long>::min()));\n\tEATEST_VERIFY(eastl::in_range<unsigned long>(eastl::numeric_limits<unsigned long>::max()));\n\tEATEST_VERIFY(!eastl::in_range<unsigned long>(-1));\n\tEATEST_VERIFY(eastl::in_range<long>(eastl::numeric_limits<unsigned int>::max()) == (sizeof(unsigned int) < sizeof(long)));\n\tEATEST_VERIFY(!eastl::in_range<unsigned long>(eastl::numeric_limits<int>::min()));\n\n\treturn nErrorCount;\n}\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n// TestUtility\n//\nint TestUtility()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestUtilityPair();\n\tnErrorCount += TestUtilityRelops();\n\tnErrorCount += TestUtilitySwap();\n\tnErrorCount += TestUtilityMove();\n\tnErrorCount += TestUtilityIntegerSequence();\n\tnErrorCount += TestUtilityExchange();\n#if defined(EA_COMPILER_CPP17_ENABLED)\n\tnErrorCount += TestUtilityIntegralComp();\n#endif\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestVariant.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EASTL/string.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/sort.h>\n#include <EASTL/bonus/overloaded.h>\n\n// 4512/4626 - 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.\nEA_DISABLE_VC_WARNING(4512 4626);\n\n#ifdef EA_COMPILER_CPP14_ENABLED\n#include \"ConceptImpls.h\"\n#include <EASTL/variant.h>\n\n\n#if EASTL_EXCEPTIONS_ENABLED\n\n// Intentionally Non-Trivial.\n// There are optimizations we can make in variant if the types are trivial that we don't currently do but can do.\ntemplate <typename T>\nstruct valueless_struct\n{\n\tvalueless_struct() {}\n\n\tvalueless_struct(const valueless_struct&) {}\n\n\t~valueless_struct() {}\n\n\tstruct exception_tag {};\n\n\toperator T() const { throw exception_tag{}; }\n};\n\n#endif\n\n\nint TestVariantAlternative()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\t{\n\t\tusing v_t = variant<int>;\n\t\tstatic_assert(is_same_v<variant_alternative_t<0, v_t>, int>, \"error variant_alternative\");\n\t}\n\t{\n\t\tusing v_t = variant<int, long, short, char>;\n\n\t\tstatic_assert(is_same_v<variant_alternative_t<0, v_t>, int>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<1, v_t>, long>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<2, v_t>, short>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<3, v_t>, char>, \"error variant_alternative\");\n\t}\n\t{\n\t\tstruct custom_type1 {};\n\t\tstruct custom_type2 {};\n\t\tstruct custom_type3 {};\n\n\t\tusing v_t = variant<int, long, short, char, size_t, unsigned, signed, custom_type1, custom_type2, custom_type3>;\n\n\t\tstatic_assert(is_same_v<variant_alternative_t<5, v_t>, unsigned>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<6, v_t>, signed>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<7, v_t>, custom_type1>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<8, v_t>, custom_type2>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<9, v_t>, custom_type3>, \"error variant_alternative\");\n\t}\n\t// cv-qualifier tests\n\t{\n\t\tusing v_t = variant<int, const int, volatile int, const volatile int>;\n\n\t\tstatic_assert(is_same_v<variant_alternative_t<0, v_t>, int>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<1, v_t>, const int>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<2, v_t>, volatile int>, \"error variant_alternative\");\n\t\tstatic_assert(is_same_v<variant_alternative_t<3, v_t>, const volatile int>, \"error variant_alternative\");\n\t}\n\treturn nErrorCount;\n}\n\nint TestVariantSize()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\tstatic_assert(variant_size<variant<int>>() == 1, \"error variant_size\");\n\tstatic_assert(variant_size<variant<int, int>>() == 2, \"error variant_size\");\n\tstatic_assert(variant_size<variant<int, int, int, int>>() == 4, \"error variant_size\");\n\tstatic_assert(variant_size<variant<const int>>() == 1, \"error variant_size\");\n\tstatic_assert(variant_size<variant<volatile int>>() == 1, \"error variant_size\");\n\tstatic_assert(variant_size<variant<const volatile int>>() == 1, \"error variant_size\");\n\n\tstatic_assert(variant_size_v<variant<int>> == 1, \"error variant_size\");\n\tstatic_assert(variant_size_v<variant<int, int>> == 2, \"error variant_size\");\n\tstatic_assert(variant_size_v<variant<int, int, int, int>> == 4, \"error variant_size\");\n\tstatic_assert(variant_size_v<variant<const int>> == 1, \"error variant_size\");\n\tstatic_assert(variant_size_v<variant<volatile int>> == 1, \"error variant_size\");\n\tstatic_assert(variant_size_v<variant<const volatile int>> == 1, \"error variant_size\");\n\n\tstatic_assert(variant_size_v<variant<int, int>> == 2, \"error variant_size_v\");\n\tstatic_assert(variant_size_v<variant<volatile int, const int>> == 2, \"error variant_size_v\");\n\tstatic_assert(variant_size_v<variant<volatile int, const int, const volatile int>> == 3, \"error variant_size_v\");\n\n\treturn nErrorCount;\n}\n\ntemplate<class T>\nconstexpr bool has_default_hash_v = eastl::internal::is_hasher_for_v<eastl::hash<T>, T>;\n\nint TestVariantHash()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{ hash<monostate> h; EA_UNUSED(h); }\n\n\t// basic hash example - discriminates between values.\n\t{\n\t\tusing variant_type = variant<int, unsigned int>;\n\t\thash<variant_type> hasher;\n\t\tVERIFY(hasher(variant_type{ in_place_index<0>, 10 }) != hasher(variant_type{ in_place_index<1>, 20 }));\n\t}\n\n\t// hash<variant> should hash the index so that it can distinguish between non-unique alternative types.\n\t{\n\t\tusing variant_type = variant<int, int>;\n\t\thash<variant_type> hasher;\n\t\tVERIFY(hasher(variant_type{ in_place_index<0>, 10 }) != hasher(variant_type{ in_place_index<1>, 10 }));\n\t}\n\n\tstruct no_hash {};\n\n\tstatic_assert(has_default_hash_v<monostate>, \"hashable\");\n\tstatic_assert(!has_default_hash_v<no_hash>, \"!hashable\");\n\n\tstatic_assert(has_default_hash_v<variant<monostate>>, \"hashable\");\n\tstatic_assert(has_default_hash_v<variant<monostate, monostate>>, \"hashable\");\n\tstatic_assert(has_default_hash_v<variant<const monostate, monostate>>, \"hashable\");\n\tstatic_assert(has_default_hash_v<variant<monostate, const monostate>>, \"hashable\");\n\n\tstatic_assert(!has_default_hash_v<variant<no_hash>>, \"!hashable\");\n\tstatic_assert(!has_default_hash_v<variant<no_hash, monostate>>, \"!hashable\");\n\tstatic_assert(!has_default_hash_v<variant<monostate, no_hash>>, \"!hashable\");\n\n\treturn nErrorCount;\n}\n\nint TestVariantBasic()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{ VERIFY(variant_npos == size_t(-1)); }\n\n\t// variant used to:\n\t//  - internally store a pointer.\n\t//  - use a minimum of 16 bytes for its internal buffer for the alternative storage.\n\t// both of these overheads have been removed.\n\tstatic_assert(sizeof(variant<int>) <= 2 * sizeof(size_t), \"size\");\n\n\t{ variant<int> v;                                                         EA_UNUSED(v); }\n\t{ variant<int, short> v;                                                  EA_UNUSED(v); }\n\t{ variant<int, short, float> v;                                           EA_UNUSED(v); }\n\t{ variant<int, short, float, char> v;                                     EA_UNUSED(v); }\n\t{ variant<int, short, float, char, long> v;                               EA_UNUSED(v); }\n\t{ variant<int, short, float, char, long, long long> v;                    EA_UNUSED(v); }\n\t{ variant<int, short, float, char, long, long long, double> v;            EA_UNUSED(v); }\n\n\t{ variant<monostate> v;                                                   EA_UNUSED(v); }\n\t{ variant<monostate, NotDefaultConstructible> v;                          EA_UNUSED(v); }\n\t{ variant<int, NotDefaultConstructible> v;                                EA_UNUSED(v); }\n\n\t{\n\t\tstruct MyObj\n\t\t{\n\t\t\tMyObj() : i(1337) {}\n\t\t\t~MyObj() {}\n\n\t\t\tint i;\n\t\t};\n\n\t\tstruct MyObj2\n\t\t{\n\t\t\tMyObj2(int& ii) : i(ii) {}\n\t\t\t~MyObj2() {}\n\n\t\t\tMyObj2& operator=(const MyObj2&) = delete;\n\n\t\t\tint& i;\n\t\t};\n\n\t\tstatic_assert(!eastl::is_trivially_destructible_v<MyObj>, \"MyObj can't be trivially destructible\");\n\t\tstatic_assert(!eastl::is_trivially_destructible_v<MyObj2>, \"MyObj2 can't be trivially destructible\");\n\t\tstatic_assert(eastl::is_copy_constructible_v<MyObj>, \"MyObj can be copy constructed\");\n\t\tstatic_assert(eastl::is_copy_constructible_v<MyObj2>, \"MyObj2 can't be copy constructed\");\n\t\tstatic_assert(eastl::is_copy_assignable_v<MyObj>, \"MyObj can be copy assigned\");\n\t\tstatic_assert(!eastl::is_copy_assignable_v<MyObj2>, \"MyObj2 can't be copy assigned\");\n\n\t\t{\n\t\t\teastl::variant<MyObj, MyObj2> myVar;\n\t\t\tVERIFY(get<MyObj>(myVar).i == 1337);\n\t\t}\n\n\t\t{\n\t\t\teastl::variant<MyObj, MyObj2> myVar = MyObj();\n\t\t\tVERIFY(get<MyObj>(myVar).i == 1337);\n\t\t}\n\n\t\t{\n\t\t\tint i = 42;\n\t\t\teastl::variant<MyObj, MyObj2> myVar = MyObj2(i);\n\t\t\tVERIFY(get<MyObj2>(myVar).i == 42);\n\t\t}\n\n\t\t{\n\t\t\tauto m = MyObj();\n\t\t\tm.i = 2000;\n\n\t\t\teastl::variant<MyObj, MyObj2> myVar = m;\n\t\t\tVERIFY(get<MyObj>(myVar).i == 2000);\n\t\t}\n\t}\n\n\t{ variant<int, int> v;                                                    EA_UNUSED(v); }\n\t{ variant<const short, volatile short, const volatile short> v;           EA_UNUSED(v); }\n\t{ variant<int, int, const short, volatile short, const volatile short> v; EA_UNUSED(v); }\n\n\t{\n\t\t// verify constructors and destructors are called\n\t\t{\n\t\t\tvariant<TestObject> v = TestObject(1337);\n\t\t\tVERIFY((get<TestObject>(v)).mX == 1337);\n\n\t\t\tvariant<TestObject> vCopy = v;\n\t\t\tVERIFY((get<TestObject>(vCopy)).mX == 1337);\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t{\n\t\tvariant<string> v;\n\t\tVERIFY(*(get_if<string>(&v)) == \"\");\n\t\tVERIFY(get_if<string>(&v)->empty());\n\t\tVERIFY(get_if<string>(&v)->length() == 0);\n\t\tVERIFY(get_if<string>(&v)->size() == 0);\n\n\t\t*(get_if<string>(&v)) += 'a';\n\t\tVERIFY(*(get_if<string>(&v)) == \"a\");\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantGet()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tconst char* strValue = \"canada\";\n\t\tusing v_t = variant<int, string>;\n\t\t{\n\t\t\tv_t v;\n\t\t\tv = 42;\n\t\t\tVERIFY(v.index() == 0);\n\t\t\tVERIFY(*get_if<int>(&v) == 42);\n\t\t\tVERIFY(get<int>(v) == 42);\n\t\t\tVERIFY( holds_alternative<int>(v));\n\t\t\tVERIFY(!holds_alternative<string>(v));\n\t\t}\n\t\t{\n\t\t\tv_t v;\n\t\t\tv = strValue;\n\t\t\tVERIFY(v.index() == 1);\n\t\t\tVERIFY(*get_if<string>(&v) == strValue);\n\t\t\tVERIFY(get<string>(v) == strValue);\n\t\t\tVERIFY(!holds_alternative<int>(v));\n\t\t\tVERIFY(holds_alternative<string>(v));\n\t\t\tVERIFY(get<string>(move(v)) == strValue);\n\t\t}\n\t\t{\n\t\t\tv_t v;\n\t\t\tv = 42;\n\t\t\tVERIFY(v.index() == 0);\n\t\t\tVERIFY(*get_if<0>(&v) == 42);\n\t\t\tVERIFY(get<0>(v) == 42);\n\t\t\tVERIFY( holds_alternative<int>(v));\n\t\t\tVERIFY(!holds_alternative<string>(v));\n\t\t}\n\t\t{\n\t\t\t v_t v;\n\t\t\t v = strValue;\n\t\t\t VERIFY(v.index() == 1);\n\t\t\t VERIFY(*get_if<1>(&v) == strValue);\n\t\t\t VERIFY(get<1>(v) == strValue);\n\t\t\t VERIFY(!holds_alternative<int>(v));\n\t\t\t VERIFY( holds_alternative<string>(v));\n\t\t}\n\t\t{\n\t\t\t v_t v;\n\t\t\t v = strValue;\n\t\t\t VERIFY(v.index() == 1);\n\t\t\t VERIFY(*get_if<1>(&v) == strValue);\n\t\t\t VERIFY(get_if<0>(&v) == nullptr);\n\t\t}\n\t\t{\n\t\t\t VERIFY(get_if<0>((v_t*)nullptr) == nullptr);\n\t\t\t VERIFY(get_if<1>((v_t*)nullptr) == nullptr);\n\t\t}\n\t\t{\n#if EASTL_EXCEPTIONS_ENABLED\n\t\t\tv_t v;\n\t\t\tv = strValue;\n\t\t\tEATEST_VERIFY_THROW(get<0>(v));\n\t\t\tEATEST_VERIFY_THROW(get<int>(v));\n\t\t\tauto* str = get_if<1>(&v);\n\t\t\tVERIFY(str && *str == strValue);\n#endif\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantHoldsAlternative()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\t{\n\t\t\tusing v_t = variant<int, short>;  // default construct first type\n\t\t\tv_t v;\n\n\t\t\t// no matching overload, type is not an alternative.\n\t\t\t// holds_alternative<long>(v);\n\t\t\t// holds_alternative<string>(v);\n\t\t\tVERIFY( holds_alternative<int>(v));    // variant does hold an int, because its a default constructible first parameter\n\t\t\tVERIFY(!holds_alternative<short>(v));  // variant does not hold a short\n\t\t}\n\n\t\t{\n\t\t\tusing v_t = variant<monostate, int, short>;  // default construct monostate\n\t\t\tv_t v;\n\n\t\t\t// no matching overload, type is not an alternative.\n\t\t\t// holds_alternative<long>(v);\n\t\t\t// holds_alternative<string>(v);\n\t\t\tVERIFY(!holds_alternative<int>(v));    // variant does not hold an int \n\t\t\tVERIFY(!holds_alternative<short>(v));  // variant does not hold a short\n\t\t}\n\n\t\t{\n\t\t\tusing v_t = variant<monostate, int>;\n\n\t\t\t{\n\t\t\t\tv_t v;\n\t\t\t\tVERIFY(!holds_alternative<int>(v));   // variant does not hold an int\n\n\t\t\t\tv = 42;\n\t\t\t\tVERIFY(holds_alternative<int>(v));\t// variant does hold an int\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tv_t v1, v2;\n\t\t\t\tVERIFY(!holds_alternative<int>(v1));\n\t\t\t\tVERIFY(!holds_alternative<int>(v2));\n\n\t\t\t\tv1 = 42;\n\t\t\t\tVERIFY(holds_alternative<int>(v1));\n\t\t\t\tVERIFY(!holds_alternative<int>(v2));\n\n\t\t\t\teastl::swap(v1, v2);\n\t\t\t\tVERIFY(!holds_alternative<int>(v1));\n\t\t\t\tVERIFY(holds_alternative<int>(v2));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantValuelessByException()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\t{\n\t\t\tusing v_t = variant<int, short>;\n\t\t\tstatic_assert(eastl::is_default_constructible_v<v_t>, \"valueless_by_exception error\");\n\n\t\t\tv_t v;\n\t\t\tVERIFY(!v.valueless_by_exception());\n\n\t\t\tv = 42;\n\t\t\tVERIFY(!v.valueless_by_exception());\n\t\t}\n\n\t\t{\n\t\t\tusing v_t = variant<monostate, int>;\n\t\t\tstatic_assert(eastl::is_default_constructible_v<v_t>, \"valueless_by_exception error\");\n\n\t\t\tv_t v1, v2;\n\t\t\tVERIFY(!v1.valueless_by_exception());\n\t\t\tVERIFY(!v2.valueless_by_exception());\n\n\t\t\tv1 = 42;\n\t\t\tVERIFY(!v1.valueless_by_exception());\n\t\t\tVERIFY(!v2.valueless_by_exception());\n\n\t\t\teastl::swap(v1, v2);\n\t\t\tVERIFY(!v1.valueless_by_exception());\n\t\t\tVERIFY(!v2.valueless_by_exception());\n\n\t\t\tv1 = v2;\n\t\t\tVERIFY(!v1.valueless_by_exception());\n\t\t\tVERIFY(!v2.valueless_by_exception());\n\t\t}\n\n\t\t{\n\t\t\tstruct NotDefaultConstructibleButHasConversionCtor\n\t\t\t{\n\t\t\t\tNotDefaultConstructibleButHasConversionCtor() = delete;\n\t\t\t\tNotDefaultConstructibleButHasConversionCtor(int) {}\n\t\t\t};\n\t\t\tstatic_assert(!eastl::is_default_constructible<NotDefaultConstructibleButHasConversionCtor>::value, \"valueless_by_exception error\");\n\n\t\t\tusing v_t = variant<NotDefaultConstructibleButHasConversionCtor>;\n\t\t\tv_t v(42);\n\t\t\tstatic_assert(!eastl::is_default_constructible_v<v_t>, \"valueless_by_exception error\");\n\t\t\tVERIFY(!v.valueless_by_exception());\n\t\t}\n\n\t\t{\n\t\t\tstruct NotDefaultConstructible\n\t\t\t{\n\t\t\t\tNotDefaultConstructible() = delete;\n\t\t\t\texplicit NotDefaultConstructible(int) {}\n\t\t\t};\n\t\t\tstatic_assert(!eastl::is_default_constructible<NotDefaultConstructible>::value, \"is_default_constructible\");\n\n\t\t\tusing v_t = variant<float, NotDefaultConstructible>;\n\t\t\tv_t v;\n\t\t\tstatic_assert(eastl::is_default_constructible_v<v_t>, \"is_default_constructible\");\n\t\t\tVERIFY(!v.valueless_by_exception());\n\t\t}\n\n\t\t// TODO(rparolin):  review exception safety for variant types \n\t\t//\n\t\t// {\n\t\t// #if EASTL_EXCEPTIONS_ENABLED\n\t\t//     struct DefaultConstructibleButThrows\n\t\t//     {\n\t\t//         DefaultConstructibleButThrows() {}\n\t\t//         ~DefaultConstructibleButThrows() {}\n\t\t//\n\t\t//         DefaultConstructibleButThrows(DefaultConstructibleButThrows&&) { throw 42; }\n\t\t//         DefaultConstructibleButThrows(const DefaultConstructibleButThrows&) { throw 42; }\n\t\t//         DefaultConstructibleButThrows& operator=(const DefaultConstructibleButThrows&) { throw 42; }\n\t\t//         DefaultConstructibleButThrows& operator=(DefaultConstructibleButThrows&&) { throw 42; }\n\t\t//     };\n\t\t//\n\t\t//     using v_t = variant<DefaultConstructibleButThrows>;\n\t\t//\n\t\t//     v_t v1;\n\t\t//     VERIFY(!v1.valueless_by_exception());\n\t\t//\n\t\t//     try\n\t\t//     {\n\t\t//         v1 = DefaultConstructibleButThrows();\n\t\t//     }\n\t\t//     catch (...)\n\t\t//     {\n\t\t//         VERIFY(v1.valueless_by_exception());\n\t\t//     }\n\t\t// #endif\n\t\t// }\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantCopyAndMove()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tusing v_t = variant<int, short, char>;\n\n\t\tv_t v1 = 42;\n\t\tv_t v2 = v1;\n\n\t\tVERIFY(get<int>(v2) == get<int>(v1));\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantEmplace()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tvariant<int> v;\n\t\tv.emplace<int>(42);\n\t\tVERIFY(get<int>(v) == 42);\n\t}\n\t{\n\t\tvariant<int> v;\n\t\tv.emplace<0>(42);\n\t\tVERIFY(get<0>(v) == 42);\n\t}\n\n\t{\n\t\tvariant<int, short, long> v;\n\n\t\tv.emplace<0>(42);\n\t\tVERIFY(get<0>(v) == 42);\n\n\t\tv.emplace<1>(short(43));\n\t\tVERIFY(get<1>(v) == short(43));\n\n\t\tv.emplace<2>(44L);\n\t\tVERIFY(get<2>(v) == 44L);\n\t}\n\t{\n\t\tvariant<int, short, long> v;\n\n\t\tv.emplace<int>(42);\n\t\tVERIFY(get<int>(v) == 42);\n\n\t\tv.emplace<short>(short(43));\n\t\tVERIFY(get<short>(v) == short(43));\n\n\t\tv.emplace<long>(44L);\n\t\tVERIFY(get<long>(v) == 44L);\n\t}\n\n\t{\n\t\t{\n\t\t\tvariant<TestObject> v;\n\t\t\tv.emplace<0>(1337);\n\t\t\tVERIFY(get<0>(v).mX == 1337);\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t{\n\t\t{\n\t\t\tvariant<int, TestObject> v;\n\n\t\t\tv.emplace<int>(42);\n\t\t\tVERIFY(get<int>(v) == 42);\n\n\t\t\tv.emplace<TestObject>(1337);\n\t\t\tVERIFY(get<TestObject>(v).mX == 1337);\n\n\t\t\tv.emplace<TestObject>(1338, 42, 3);\n\t\t\tVERIFY(get<TestObject>(v).mX == 1338 + 42 + 3);\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\t// emplace<T>() is invalid if T matches more than one of the variant's alternative types,\n\t// but emplace<I>() is fine.\n\t{\n\t\tvariant<int, int> v;\n\n\t\tv.emplace<0>(42);\n\t\tVERIFY(get<0>(v) == 42);\n\n\t\tv.emplace<1>(1337);\n\t\tVERIFY(get<1>(v) == 1337);\n\t}\n\n\t{\n\t\t{\n\t\t\tstruct r {\n\t\t\t\tr() = default;\n\t\t\t\tr(int x) : mX(x) {}\n\t\t\t\tint mX;\n\t\t\t};\n\n\t\t\tvariant<int, r> v;\n\n\t\t\tv.emplace<0>(42);\n\t\t\tVERIFY(get<0>(v) == 42);\n\n\t\t\tv.emplace<1>(1337);\n\t\t\tVERIFY(get<1>(v).mX == 1337);\n\t\t}\n\t}\n\n\t{\n\t\tstruct r {\n\t\t\tr() = default;\n\t\t\tr(int a, int b, int c, int d) : a(a), b(b), c(c), d(d) {}\n\t\t\tr(std::initializer_list<int> l)\n\t\t\t{\n\t\t\t\tauto it = l.begin();\n\n\t\t\t\ta = *it++;\n\t\t\t\tb = *it++;\n\t\t\t\tc = *it++;\n\t\t\t\td = *it++;\n\t\t\t}\n\t\t\tint a, b, c, d;\n\t\t};\n\n\t\tr aa{1,2,3,4};\n\t\tVERIFY(aa.a == 1);\n\t\tVERIFY(aa.b == 2);\n\t\tVERIFY(aa.c == 3);\n\t\tVERIFY(aa.d == 4);\n\n\t\tvariant<r> v;\n\t\tv.emplace<0>(std::initializer_list<int>{1,2,3,4});\n\n\t\tVERIFY(get<r>(v).a == 1);\n\t\tVERIFY(get<r>(v).b == 2);\n\t\tVERIFY(get<r>(v).c == 3);\n\t\tVERIFY(get<r>(v).d == 4);\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantSwap()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tvariant<int, float> v1 = 42;\n\t\tvariant<int, float> v2 = 24;\n\n\t\tv1.swap(v2);\n\n\t\tVERIFY(get<int>(v1) == 24); \n\t\tVERIFY(get<int>(v2) == 42);\n\n\t\tv1.swap(v2);\n\n\t\tVERIFY(get<int>(v1) == 42); \n\t\tVERIFY(get<int>(v2) == 24);\n\t}\n\n\t{\n\t\t variant<string> v1 = \"Hello\";\n\t\t variant<string> v2 = \"World\";\n\n\t\t VERIFY(get<string>(v1) == \"Hello\"); \n\t\t VERIFY(get<string>(v2) == \"World\");\n\n\t\t v1.swap(v2);\n\n\t\t VERIFY(get<string>(v1) == \"World\");\n\t\t VERIFY(get<string>(v2) == \"Hello\"); \n\t}\n\n\t{\n\t\tvariant<TestObject> v1{ in_place_type<TestObject>, 1337 };\n\t\tvariant<TestObject> v2{ in_place_type<TestObject>, 9001 };\n\n\t\tswap(v1, v2); // same alternative types; calls swap(TestObject&, TestObject&);\n\n\t\tVERIFY(get<TestObject>(v1).mX == 9001);\n\t\tVERIFY(get<TestObject>(v2).mX == 1337);\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT) // This test fails in previous EASTL versions.\n\t\tVERIFY(TestObject::sTOSwapCount == 1);\n#endif\n\t\tVERIFY(TestObject::sTODefaultCtorCount == 2);\n\t\tVERIFY(TestObject::sTOCopyCtorCount == 0);\n\t}\n\tVERIFY(TestObject::Reset());\n\n\t{\n\t\tvariant<int, TestObject> v1{ in_place_type<int>, 1337 };\n\t\tvariant<int, TestObject> v2{ in_place_type<TestObject>, 9001 };\n\n\t\tswap(v1, v2); // differing alternative types; swaps by move construction (no assignments).\n\n\t\tVERIFY(get<TestObject>(v1).mX == 9001);\n\t\tVERIFY(get<int>(v2) == 1337);\n\t\tVERIFY(TestObject::sTOSwapCount == 0);\n\t\tVERIFY(TestObject::sTODefaultCtorCount == 1);\n\t\tVERIFY(TestObject::sTOCopyCtorCount == 0);\n\t\tVERIFY(TestObject::sTOMoveCtorCount >= 1);\n\t\tVERIFY(TestObject::sTOCopyAssignCount == 0);\n\t\tVERIFY(TestObject::sTOMoveAssignCount == 0);\n\t}\n\tVERIFY(TestObject::Reset());\n\n\treturn nErrorCount;\n}\n\nint TestVariantRelOps()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tvariant<int, float> v1 = 42;\n\t\tvariant<int, float> v2 = 24;\n\t\tvariant<int, float> v1e = v1;\n\n\t\tVERIFY(v1 == v1e);\n\t\tVERIFY(v1 != v2);\n\t\tVERIFY(v1 > v2);\n\t\tVERIFY(v2 < v1);\n\t}\n\n\t{\n\t\tvector<variant<int, string>> v = {{1}, {3}, {7}, {4}, {0}, {5}, {2}, {6}, {8}};\n\t\teastl::sort(v.begin(), v.end());\n\t\tVERIFY(eastl::is_sorted(v.begin(), v.end()));\n\t}\n\n\treturn nErrorCount;\n}\n\n\nint TestVariantInplaceCtors()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tvariant<int, int> v(in_place_index<0>, 42);\n\t\tVERIFY(get<0>(v) == 42);\n\t\tVERIFY(v.index() == 0);\n\t}\n\n\t{\n\t\tvariant<int, int> v(in_place_index<1>, 42);\n\t\tVERIFY(get<1>(v) == 42);\n\t\tVERIFY(v.index() == 1);\n\t}\n\n\t{\n\t\tvariant<int, string> v(in_place_type<int>, 42);\n\t\tVERIFY(get<0>(v) == 42);\n\t\tVERIFY(v.index() == 0);\n\t}\n\n\t{\n\t\tvariant<int, string> v(in_place_type<string>, \"hello\");\n\t\tVERIFY(get<1>(v) == \"hello\");\n\t\tVERIFY(v.index() == 1);\n\t}\n\n\treturn nErrorCount;\n}\n\n// Many Compilers are smart and will fully inline the visitor in our unittests,\n// Thereby not actually testing the recursive call.\nEA_NO_INLINE int TestVariantVisitNoInline(const eastl::variant<int, bool, unsigned>& v)\n{\n\tint nErrorCount = 0;\n\n\tbool bVisited = false;\n\n\tstruct MyVisitor\n\t{\n\t\tMyVisitor() = delete;\n\t\tMyVisitor(bool& visited) : mVisited(visited) {};\n\n\t\tvoid operator()(int) { mVisited = true; }\n\t\tvoid operator()(bool) { mVisited = true; }\n\t\tvoid operator()(unsigned) { mVisited = true; }\n\n\t\tbool& mVisited;\n\t};\n\n\teastl::visit(MyVisitor(bVisited), v);\n\n\tEATEST_VERIFY(bVisited);\n\n\treturn nErrorCount;\n}\n\nEA_NO_INLINE int TestVariantVisit2NoInline(const eastl::variant<int, bool>& v0, const eastl::variant<int, bool>& v1)\n{\n\tint nErrorCount = 0;\n\n\tbool bVisited = false;\n\n\tstruct MyVisitor\n\t{\n\t\tMyVisitor() = delete;\n\t\tMyVisitor(bool& visited) : mVisited(visited) {};\n\n\t\tvoid operator()(int, int) { mVisited = true; }\n\t\tvoid operator()(bool, int) { mVisited = true; }\n\t\tvoid operator()(int, bool) { mVisited = true; }\n\t\tvoid operator()(bool, bool) { mVisited = true; }\n\n\t\tbool& mVisited;\n\t};\n\n\teastl::visit(MyVisitor(bVisited), v0, v1);\n\n\tEATEST_VERIFY(bVisited);\n\n\treturn nErrorCount;\n}\n\nEA_NO_INLINE int TestVariantVisit3tNoInline(const eastl::variant<int, bool>& v0, const eastl::variant<int, bool>& v1, const eastl::variant<int, bool>& v2)\n{\n\tint nErrorCount = 0;\n\n\tbool bVisited = false;\n\n\tstruct MyVisitor\n\t{\n\t\tMyVisitor() = delete;\n\t\tMyVisitor(bool& visited) : mVisited(visited) {};\n\n\t\tvoid operator()(int, int, int) { mVisited = true; }\n\t\tvoid operator()(bool, int, int) { mVisited = true; }\n\t\tvoid operator()(int, bool, int) { mVisited = true; }\n\t\tvoid operator()(bool, bool, int) { mVisited = true; }\n\n\t\tvoid operator()(int, int, bool) { mVisited = true; }\n\t\tvoid operator()(bool, int, bool) { mVisited = true; }\n\t\tvoid operator()(int, bool, bool) { mVisited = true; }\n\t\tvoid operator()(bool, bool, bool) { mVisited = true; }\n\n\t\tbool& mVisited;\n\t};\n\n\teastl::visit(MyVisitor(bVisited), v0, v1, v2);\n\n\tEATEST_VERIFY(bVisited);\n\n\treturn nErrorCount;\n}\n\nint TestVariantVisitorOverloaded()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\tusing v_t = variant<int, string, double, long>;\n\tv_t arr[] = {42, \"jean\", 42.0, 42L};\n\tv_t v{42.0};\n\n\n\t#ifdef __cpp_deduction_guides\n\t{\n\t\tint count = 0;\n\n\t\tfor (auto& e : arr)\n\t\t{\n\t\t\teastl::visit(\n\t\t\t\toverloaded{\n\t\t\t\t\t[&](int)    { count++; },\n\t\t\t\t\t[&](string) { count++; },\n\t\t\t\t\t[&](double) { count++; },\n\t\t\t   \t\t[&](long)   { count++; }},\n\t\t\t\te\n\t\t\t);\n\t\t}\n\n\t\tVERIFY(count == EAArrayCount(arr));\n\t}\n\n\t{\n\t\tdouble visitedValue = 0.0f;\n\n\t\teastl::visit(\n\t\t\toverloaded{\n\t\t\t\t[](int)    { },\n\t\t\t\t[](string) { },\n\t\t\t\t[&](double d) { visitedValue = d; },\n\t\t\t\t[](long)   { }},\n\t\t\tv\n\t\t);\n\n\t\tVERIFY(visitedValue == 42.0f);\n\t}\n\n\t#endif\n\n\t{\n\t\tint count = 0;\n\n\t\tfor (auto& e : arr)\n\t\t{\n\t\t\teastl::visit(\n\t\t\t\teastl::make_overloaded(\n\t\t\t\t\t[&](int)    { count++; },\n\t\t\t\t\t[&](string) { count++; },\n\t\t\t\t\t[&](double) { count++; },\n\t\t\t\t\t[&](long)   { count++; }), \n\t\t\t\te\n\t\t\t);\n\t\t}\n\n\t\tVERIFY(count == EAArrayCount(arr));\n\t}\n\n\t{\n\t\tdouble visitedValue = 0.0f;\n\n\t\teastl::visit(\n\t\t\teastl::make_overloaded(\n\t\t\t\t[](int)    { },\n\t\t\t\t[](string) { },\n\t\t\t\t[&](double d) { visitedValue = d; },\n\t\t\t\t[](long)   { }),\n\t\t\tv\n\t\t);\n\n\t\tVERIFY(visitedValue == 42.0f);\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantVisitor()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\tusing v_t = variant<int, string, double, long>;\n\n\t{\n\t\tv_t arr[] = {42, \"hello\", 42.0, 42L};\n\n\t\tint count = 0;\n\t\tfor (auto& e : arr)\n\t\t{\n\t\t\teastl::visit([&](auto){ count++; }, e);\n\t\t}\n\n\t\tVERIFY(count == EAArrayCount(arr));\n\n\t\tcount = 0;\n\t\tfor (auto& e : arr)\n\t\t{\n\t\t\teastl::visit<void>([&](auto){ count++; }, e);\n\t\t}\n\n\t\tVERIFY(count == EAArrayCount(arr));\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tvariant<int, long, string> v = 42;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tvoid operator()(int)      { bVisited = true; };\n\t\t\tvoid operator()(long)     { };\n\t\t\tvoid operator()(string)   { };\n\t\t\tvoid operator()(unsigned) { }; // not in variant\n\t\t};\n\n\t\tvisit(MyVisitor{}, v);\n\t\tVERIFY(bVisited);\n\n\t\tbVisited = false;\n\n\t\tvisit<void>(MyVisitor{}, v);\n\t\tVERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tvariant<int, bool, unsigned> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tbool& operator()(int) { return bVisited; }\n\t\t\tbool& operator()(bool) { return bVisited; }\n\t\t\tbool& operator()(unsigned) { return bVisited; }\n\t\t};\n\n\t\tbool& ret = visit(MyVisitor{}, v);\n\t\tret = true;\n\t\tVERIFY(bVisited);\n\n\t\tbVisited = false;\n\t\tbool& ret2 = visit<bool&>(MyVisitor{}, v);\n\t\tret2 = true;\n\t\tVERIFY(bVisited);\n\t}\n\n\t{\n\t\tvariant<int, bool, unsigned> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tvoid operator()(int& i) { i = 2; }\n\t\t\tvoid operator()(bool&) {}\n\t\t\tvoid operator()(unsigned&) {}\n\t\t};\n\n\t\tvisit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(get<0>(v) == (int)2);\n\n\t\tv = (int)1;\n\t\tvisit<void>(MyVisitor{}, v);\n\t\tEATEST_VERIFY(get<0>(v) == (int)2);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tvariant<int, bool, unsigned> v =(int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tvoid operator()(const int&) { bVisited = true; }\n\t\t\tvoid operator()(const bool&) {}\n\t\t\tvoid operator()(const unsigned&) {}\n\t\t};\n\n\t\tvisit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\n\t\tbVisited = false;\n\t\tvisit<void>(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tconst variant<int, bool, unsigned> v =(int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tvoid operator()(const int&) { bVisited = true; }\n\t\t\tvoid operator()(const bool&) {}\n\t\t\tvoid operator()(const unsigned&) {}\n\t\t};\n\n\t\tvisit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\n\t\tbVisited = false;\n\t\tvisit<void>(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tvoid operator()(int&&) { bVisited = true; }\n\t\t\tvoid operator()(bool&&) {}\n\t\t\tvoid operator()(unsigned&&) {}\n\t\t};\n\n\t\tvisit(MyVisitor{}, variant<int, bool, unsigned>{(int)1});\n\t\tEATEST_VERIFY(bVisited);\n\n\t\tvisit<void>(MyVisitor{}, variant<int, bool, unsigned>{(int)1});\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tvariant<int, bool, unsigned> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tbool&& operator()(int) { return eastl::move(bVisited); }\n\t\t\tbool&& operator()(bool) { return eastl::move(bVisited); }\n\t\t\tbool&& operator()(unsigned) { return eastl::move(bVisited); }\n\t\t};\n\n\t\tbool&& ret = visit(MyVisitor{}, v);\n\t\tret = true;\n\t\tVERIFY(bVisited);\n\n\t\tbVisited = false;\n\t\tbool&& ret2 = visit<bool&&>(MyVisitor{}, v);\n\t\tret2 = true;\n\t\tVERIFY(bVisited);\n\t}\n\n\t{\n\t\tvariant<int, bool, unsigned> v = (int)1;\n\n\t\tTestVariantVisitNoInline(v);\n\t\tv = (bool)true;\n\t\tTestVariantVisitNoInline(v);\n\t\tv = (int)3;\n\t\tTestVariantVisitNoInline(v);\n\t}\n\n\t{\n\t\tvariant<int, bool> v0 = (int)1;\n\t\tvariant<int, bool> v1 = (bool)true;\n\n\t\tTestVariantVisit2NoInline(v0, v1);\n\t\tv0 = (bool)false;\n\t\tTestVariantVisit2NoInline(v0, v1);\n\t\tv1 = (int)2;\n\t\tTestVariantVisit2NoInline(v0, v1);\n\t}\n\n\t{\n\t\tvariant<int, bool> v0 = (int)1;\n\t\tvariant<int, bool> v1 = (int)2;\n\t\tvariant<int, bool> v2 = (int)3;\n\n\t\tTestVariantVisit3tNoInline(v0, v1, v2);\n\t\tv2 = (bool)false;\n\t\tTestVariantVisit3tNoInline(v0, v1, v2);\n\t\tv0 = (bool)true;\n\t\tTestVariantVisit3tNoInline(v0, v1, v2);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tvariant<int, string> i = 42;\n\t\tvariant<int, string> s = \"hello\";\n\n\t\tstruct MultipleVisitor\n\t\t{\n\t\t\tMultipleVisitor& operator()(int, int)       { return *this; }\n\t\t\tMultipleVisitor& operator()(int, string)    { bVisited = true; return *this; }\n\t\t\tMultipleVisitor& operator()(string, int)    { return *this; }\n\t\t\tMultipleVisitor& operator()(string, string) { return *this; }\n\t\t};\n\n\t\tMultipleVisitor& ret = visit(MultipleVisitor{}, i, s);\n\t\tEA_UNUSED(ret);\n\t\tVERIFY(bVisited);\n\n\t\tMultipleVisitor& ret2 = visit<MultipleVisitor&>(MultipleVisitor{}, i, s);\n\t\tEA_UNUSED(ret2);\n\t\tVERIFY(bVisited);\n\t}\n\n\t{\n\t\tbool bVisited = false;\n\n\t\tvariant<int, bool> v0 = 0;\n\t\tvariant<int, bool> v1 = 1;\n\n\t\tstruct MultipleVisitor\n\t\t{\n\t\t\tMultipleVisitor() = delete;\n\t\t\tMultipleVisitor(bool& visited) : mVisited(visited) {};\n\n\t\t\tvoid operator()(int, int) { mVisited = true; }\n\t\t\tvoid operator()(int, bool) {}\n\t\t\tvoid operator()(bool, int) {}\n\t\t\tvoid operator()(bool, bool) {}\n\n\t\t\tbool& mVisited;\n\t\t};\n\n\t\tvisit(MultipleVisitor(bVisited), v0, v1);\n\t\tEATEST_VERIFY(bVisited);\n\n\t\tbVisited = false;\n\t\tvisit<void>(MultipleVisitor(bVisited), v0, v1);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tvariant<int, string> v = 42;\n\n\t\tstruct ModifyingVisitor\n\t\t{\n\t\t\tvoid operator()(int &i) { i += 1; }\n\t\t\tvoid operator()(string &s) { s += \"hello\"; }\n\t\t};\n\n\t\tvisit(ModifyingVisitor{}, v);\n\t\tVERIFY(get<0>(v) == 43);\n\t}\n\n\t{\n\t\tvariant<int, string> v = 42;\n\n\t\tstruct ReturningVisitor\n\t\t{\n\t\t\tint operator()(int i) {return i;}\n\t\t\tint operator()(string s) {return 0;}\n\t\t};\n\n\t\tVERIFY(visit(ReturningVisitor{}, v) == 42);\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantVisitorReturn()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\teastl::variant<int, bool> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tbool operator()(int) { bVisited = true; return true; }\n\t\t\tbool operator()(bool) { return false; }\n\t\t};\n\n\t\teastl::visit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t\tbVisited = false;\n\t\teastl::visit<void>(MyVisitor{}, v); // using the C++20 overload with explicit return type\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\teastl::variant<int, bool> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tbool operator()(int) { bVisited = true; return true; }\n\t\t\tbool operator()(bool) { return false; }\n\t\t};\n\n\t\teastl::visit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t\tbVisited = false;\n\t\teastl::visit<const void>(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\teastl::variant<int, bool> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tbool operator()(int) { bVisited = true; return true; }\n\t\t\tbool operator()(bool) { return false; }\n\t\t};\n\n\t\teastl::visit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t\tbVisited = false;\n\t\teastl::visit<void>(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\teastl::variant<int, bool> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tbool operator()(int) { bVisited = true; return true; }\n\t\t\tbool operator()(bool) { return false; }\n\t\t};\n\n\t\teastl::visit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t\tbVisited = false;\n\t\teastl::visit<const void>(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\teastl::variant<int, bool> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tbool operator()(int) { bVisited = true; return true; }\n\t\t\tbool operator()(bool) { return false; }\n\t\t};\n\n\t\tbool ret = eastl::visit(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t\tEATEST_VERIFY(ret);\n\t\tbVisited = false;\n\t\tint int_ret = eastl::visit<int>(MyVisitor{}, v);\n\t\tEATEST_VERIFY(bVisited);\n\t\tEATEST_VERIFY(int_ret);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\tstruct A {};\n\t\tstruct B : public A {};\n\t\tstruct C : public A {};\n\n\t\teastl::variant<int, bool> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tB operator()(int) { bVisited = true; return B{}; }\n\t\t\tC operator()(bool) { return C{}; }\n\t\t};\n\n\t\t// ambiguity requires specifying the visit return type:\n\t\tA ret = eastl::visit<A>(MyVisitor{}, v);\n\t\tEA_UNUSED(ret);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\t{\n\t\tstatic bool bVisited = false;\n\n\t\teastl::variant<int, bool> v = (int)1;\n\n\t\tstruct MyVisitor\n\t\t{\n\t\t\tMyVisitor operator()(int) { bVisited = true; return MyVisitor{}; }\n\t\t\tMyVisitor operator()(bool) { return MyVisitor{}; }\n\t\t};\n\n\t\t// specifying the return type with visit<MyVisitor>() would result in overload ambiguity. could be either:\n\t\t// visit<MyVisitor, variant<int, bool>>()\t\t\t\t\t[ie. Visitor, Variants...]\n\t\t// visit<MyVisitor, MyVisitor, variant<int, bool>>()\t\t[ie. Return, Visitor, Variants...]\n\t\t// calling without explicit template parameters uses the first overload.\n\t\tMyVisitor ret = eastl::visit(MyVisitor{}, v);\n\t\tEA_UNUSED(ret);\n\t\tEATEST_VERIFY(bVisited);\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantVisitBase()\n{\n\tint nErrorCount = 0;\n\n\tstruct Base { virtual ~Base() = default; };\n\tstruct Derived : public Base {};\n\n\tstruct MyVisitor\n\t{\n\t\tint operator()(const Base&) { return 1; }\n\t\tint operator()(int) { return 2; }\n\t\tint operator()(const eastl::string&) { return 3; }\n\t};\n\n\teastl::variant<Derived, int, eastl::string> v;\n\n\tv.emplace<Derived>();\n\tEATEST_VERIFY(eastl::visit(MyVisitor{}, v) == 1);\n\n\tv.emplace<int>();\n\tEATEST_VERIFY(eastl::visit(MyVisitor{}, v) == 2);\n\n\tv.emplace<eastl::string>(\"my string\");\n\tEATEST_VERIFY(eastl::visit(MyVisitor{}, v) == 3);\n\n\treturn nErrorCount;\n}\n\nint TestVariantAssignment()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tvariant<int, TestObject> v = TestObject(1337);\n\t\tVERIFY(get<TestObject>(v).mX == 1337);\n\t\tTestObject::Reset();\n\n\t\tv.operator=(42);                         // ensure assignment-operator is called\n\t\tVERIFY(TestObject::sTODtorCount == 1);   // verify TestObject dtor is called.\n\t\tVERIFY(get<int>(v) == 42);\n\t\tTestObject::Reset();\n\t}\n\n\t{\n\t\tvariant<int, ImplicitlyConvertible> v(ImplicitlyConvertible{});\n\t\tv = ImplicitlyConvertible::implicit; // converting assignment; calls ImplicitlyConvertible move assignment\n\t\tVERIFY(v.index() == 1);\n\t\tVERIFY(ImplicitlyConvertible::sDefaultCtorCount == 1);\n\t\tVERIFY(ImplicitlyConvertible::sConvertCtorCount == 1);\n\t\tVERIFY(ImplicitlyConvertible::sCopyAssignCount == 0);\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT) // This test fails in previous EASTL versions.\n\t\tVERIFY(ImplicitlyConvertible::sMoveAssignCount == 1);\n#endif\n\t\tImplicitlyConvertible::Reset();\n\t}\n\n\t{\n\t\tvariant<int, ImplicitlyConvertible> v(0); // starts as an int\n\t\tv = ImplicitlyConvertible::implicit; // converting assignment; calls ImplicitlyConvertible converting constructor\n\t\tVERIFY(v.index() == 1);\n\t\tVERIFY(ImplicitlyConvertible::sDefaultCtorCount == 0);\n\t\tVERIFY(ImplicitlyConvertible::sConvertCtorCount == 1);\n\t\tVERIFY(ImplicitlyConvertible::sCopyAssignCount == 0); // should be emplaced\n\t\tVERIFY(ImplicitlyConvertible::sMoveAssignCount == 0); // should be emplaced\n\t\tImplicitlyConvertible::Reset();\n\t}\n\n\treturn nErrorCount;\n}\n\n\nint TestVariantMoveOnly()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tvariant<int, MoveOnlyType> v = MoveOnlyType(1337);\n\t\tVERIFY(get<MoveOnlyType>(v).mVal == 1337);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n//compilation test related to PR #315: converting constructor and assignment operator compilation error\nvoid TestCompilation(const double e) { eastl::variant<double> v{e}; }\n\n\n\nint TestVariantUserRegressionCopyMoveAssignmentOperatorLeak()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\t{\n\t\t\teastl::variant<TestObject> v = TestObject(1337);\n\t\t\tVERIFY(eastl::get<TestObject>(v).mX == 1337);\n\t\t\teastl::variant<TestObject> v2 = TestObject(1338);\n\t\t\tVERIFY(eastl::get<TestObject>(v2).mX == 1338);\n\t\t\tv.operator=(v2);\n\t\t\tVERIFY(eastl::get<TestObject>(v).mX == 1338);\n\t\t\tVERIFY(eastl::get<TestObject>(v2).mX == 1338);\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_OCT) // This test fails in previous EASTL versions.\n\t\t\tVERIFY(TestObject::sTOCopyAssignCount == 1);\n#endif\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\t{\n\t\t{\n\t\t\teastl::variant<TestObject> v = TestObject(1337);\n\t\t\tVERIFY(eastl::get<TestObject>(v).mX == 1337);\n\t\t\teastl::variant<TestObject> v2 = TestObject(1338);\n\t\t\tVERIFY(eastl::get<TestObject>(v2).mX == 1338);\n\t\t\tv.operator=(eastl::move(v2));\n\t\t\tVERIFY(eastl::get<TestObject>(v).mX == 1338);\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\t{\n\t\t{\n\t\t\teastl::variant<TestObject> v = TestObject(1337);\n\t\t\tVERIFY(eastl::get<TestObject>(v).mX == 1337);\n\t\t\tv = {};\n\t\t\tVERIFY(eastl::get<TestObject>(v).mX == 0);\n\t\t}\n\t\tVERIFY(TestObject::IsClear());\n\t\tTestObject::Reset();\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantRelationalOperators()\n{\n\tint nErrorCount = 0;\n\n\tusing VariantNoThrow = eastl::variant<int, bool, float>;\n\n\t// Equality\n\t{\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ true };\n\n\t\t\tEATEST_VERIFY((v1 == v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 == v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)0 };\n\n\t\t\tEATEST_VERIFY((v1 == v2) == false);\n\t\t}\n\t}\n\n\t// Inequality\n\t{\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ true };\n\n\t\t\tEATEST_VERIFY((v1 != v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 != v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)0 };\n\n\t\t\tEATEST_VERIFY((v1 != v2) == true);\n\t\t}\n\t}\n\n\t// Less Than\n\t{\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ true };\n\n\t\t\tEATEST_VERIFY((v1 < v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ true };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 < v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 < v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)0 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 < v2) == true);\n\t\t}\n\t}\n\n\t// Greater Than\n\t{\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ true };\n\n\t\t\tEATEST_VERIFY((v1 > v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ true };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 > v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 > v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)0 };\n\n\t\t\tEATEST_VERIFY((v1 > v2) == true);\n\t\t}\n\t}\n\n\t// Less Equal\n\t{\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ true };\n\n\t\t\tEATEST_VERIFY((v1 <= v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ true };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 <= v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 <= v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)0 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 <= v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)0 };\n\n\t\t\tEATEST_VERIFY((v1 <= v2) == false);\n\t\t}\n\t}\n\n\t// Greater Equal\n\t{\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ true };\n\n\t\t\tEATEST_VERIFY((v1 >= v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ true };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 >= v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 >= v2) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)0 };\n\t\t\tVariantNoThrow v2{ (int)1 };\n\n\t\t\tEATEST_VERIFY((v1 >= v2) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantNoThrow v1{ (int)1 };\n\t\t\tVariantNoThrow v2{ (int)0 };\n\n\t\t\tEATEST_VERIFY((v1 >= v2) == true);\n\t\t}\n\t}\n\n#if EASTL_EXCEPTIONS_ENABLED\n\n\tusing VariantThrow = eastl::variant<int, bool, float>;\n\n\tauto make_variant_valueless = [](VariantThrow& v)\n\t\t\t\t\t\t\t\t  {\n\t\t\t\t\t\t\t\t\t  try\n\t\t\t\t\t\t\t\t\t  {\n\t\t\t\t\t\t\t\t\t\t  v.emplace<0>(valueless_struct<int>{});\n\t\t\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t\t\t  catch(const typename valueless_struct<int>::exception_tag &)\n\t\t\t\t\t\t\t\t\t  {\n\t\t\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t\t  };\n\n\t// Equality\n\t{\n\t\t{\n\t\t\tVariantThrow v0{ (int)0 };\n\t\t\tVariantThrow v1{ (int)1 };\n\n\t\t\tmake_variant_valueless(v0);\n\t\t\tmake_variant_valueless(v1);\n\n\t\t\tEATEST_VERIFY((v0 == v1) == true);\n\t\t}\n\t}\n\n\t// Inequality\n\t{\n\t\t{\n\t\t\tVariantThrow v0{ (int)0 };\n\t\t\tVariantThrow v1{ (int)1 };\n\n\t\t\tmake_variant_valueless(v0);\n\t\t\tmake_variant_valueless(v1);\n\n\t\t\tEATEST_VERIFY((v0 != v1) == false);\n\t\t}\n\t}\n\n\t// Less Than\n\t{\n\t\t{\n\t\t\tVariantThrow v0{ (int)0 };\n\t\t\tVariantThrow v1{ (int)1 };\n\n\t\t\tmake_variant_valueless(v0);\n\n\t\t\tEATEST_VERIFY((v0 < v1) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantThrow v0{ (int)0 };\n\t\t\tVariantThrow v1{ (int)1 };\n\n\t\t\tmake_variant_valueless(v1);\n\n\t\t\tEATEST_VERIFY((v0 < v1) == false);\n\t\t}\n\t}\n\n\t// Greater Than\n\t{\n\t\t{\n\t\t\tVariantThrow v0{ (int)1 };\n\t\t\tVariantThrow v1{ (int)0 };\n\n\t\t\tmake_variant_valueless(v0);\n\n\t\t\tEATEST_VERIFY((v0 > v1) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantThrow v0{ (int)1 };\n\t\t\tVariantThrow v1{ (int)0 };\n\n\t\t\tmake_variant_valueless(v1);\n\n\t\t\tEATEST_VERIFY((v0 > v1) == true);\n\t\t}\n\t}\n\n\t// Less Equal\n\t{\n\t\t{\n\t\t\tVariantThrow v0{ (int)1 };\n\t\t\tVariantThrow v1{ (int)1 };\n\n\t\t\tmake_variant_valueless(v0);\n\n\t\t\tEATEST_VERIFY((v0 <= v1) == true);\n\t\t}\n\n\t\t{\n\t\t\tVariantThrow v0{ (int)1 };\n\t\t\tVariantThrow v1{ (int)0 };\n\n\t\t\tmake_variant_valueless(v1);\n\n\t\t\tEATEST_VERIFY((v0 <= v1) == false);\n\t\t}\n\t}\n\n\t// Greater Equal\n\t{\n\t\t{\n\t\t\tVariantThrow v0{ (int)1 };\n\t\t\tVariantThrow v1{ (int)1 };\n\n\t\t\tmake_variant_valueless(v0);\n\n\t\t\tEATEST_VERIFY((v0 >= v1) == false);\n\t\t}\n\n\t\t{\n\t\t\tVariantThrow v0{ (int)1 };\n\t\t\tVariantThrow v1{ (int)0 };\n\n\t\t\tmake_variant_valueless(v1);\n\n\t\t\tEATEST_VERIFY((v0 >= v1) == true);\n\t\t}\n\t}\n\n\t// get()\n\t{\n\t\tVariantThrow v1{ (int)1 };\n\t\tEATEST_VERIFY_THROW(eastl::get<bool>(v1));\n\n\t\tVariantThrow v2{ (int)1 };\n\t\tEATEST_VERIFY_THROW(eastl::get<1>(v2));\n\t}\n\n#endif\n\n\treturn nErrorCount;\n}\n\n\nint TestVariantUserRegressionIncompleteType()\n{\n\tusing namespace eastl;\n\tint nErrorCount = 0;\n\n\t{\n\t\tstruct B;\n\n\t\tstruct A\n\t\t{\n\t\t\tvector<variant<B>> v;\n\t\t};\n\n\t\tstruct B\n\t\t{\n\t\t\tvector<variant<A>> v;\n\t\t};\n\t}\n\n\treturn nErrorCount;\n}\n\n#define EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Type, VarName)\t\t\t\\\n\tbool operator==(const Type & rhs) const { return VarName == rhs.VarName; } \\\n\tbool operator!=(const Type & rhs) const { return VarName != rhs.VarName; } \\\n\tbool operator<(const Type & rhs) const { return VarName < rhs.VarName; } \\\n\tbool operator>(const Type & rhs) const { return VarName > rhs.VarName; } \\\n\tbool operator<=(const Type & rhs) const { return VarName <= rhs.VarName; } \\\n\tbool operator>=(const Type & rhs) const { return VarName >= rhs.VarName; }\n\nint TestBigVariantComparison()\n{\n\tint nErrorCount = 0;\n\n\tstruct A;\n\tstruct B;\n\tstruct C;\n\tstruct D;\n\tstruct E;\n\tstruct F;\n\tstruct G;\n\tstruct H;\n\tstruct I;\n\tstruct J;\n\tstruct K;\n\tstruct L;\n\tstruct M;\n\tstruct N;\n\tstruct O;\n\tstruct P;\n\tstruct Q;\n\tstruct R;\n\tstruct S;\n\tstruct T;\n\tstruct U;\n\tstruct V;\n\tstruct W;\n\tstruct X;\n\tstruct Y;\n\tstruct Z;\n\n\tusing BigVariant = eastl::variant<A, B, C, D, E, F, G, H, I, J, K, L, M, N,\n\t\t\t\t\t\t\t\t\t  O, P, Q, R, S, T, U, V, W, X, Y, Z>;\n\n\tstruct A { int a; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(A, a) };\n\tstruct B { int b; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(B, b) };\n\tstruct C { int c; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(C, c) };\n\tstruct D { int d; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(D, d) };\n\tstruct E { int e; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(E, e) };\n\tstruct F { int f; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(F, f) };\n\tstruct G { int g; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(G, g) };\n\tstruct H { int h; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(H, h) };\n\tstruct I { int i; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(I, i) };\n\tstruct J { int j; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(J, j) };\n\tstruct K { int k; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(K, k) };\n\tstruct L { int l; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(L, l) };\n\tstruct M { int m; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(M, m) };\n\tstruct N { int n; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(N, n) };\n\tstruct O { int o; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(O, o) };\n\tstruct P { int p; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(P, p) };\n\tstruct Q { int q; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Q, q) };\n\tstruct R { int r; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(R, r) };\n\tstruct S { int s; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(S, s) };\n\tstruct T { int t; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(T, t) };\n\tstruct U { int u; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(U, u) };\n\tstruct V { int v; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(V, v) };\n\tstruct W { int w; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(W, w) };\n\tstruct X { int x; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(X, x) };\n\tstruct Y { int y; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Y, y) };\n\tstruct Z { int z; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Z, z) };\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ A{1} };\n\n\t\tVERIFY(v0 != v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ A{1} };\n\n\t\tVERIFY(v0 < v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ A{0} };\n\n\t\tVERIFY(v0 == v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{1} };\n\t\tBigVariant v1{ A{0} };\n\n\t\tVERIFY(v0 > v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ A{1} };\n\n\t\tVERIFY(v0 <= v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ A{0} };\n\n\t\tVERIFY(v0 <= v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ A{0} };\n\n\t\tVERIFY(v0 >= v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{1} };\n\t\tBigVariant v1{ A{0} };\n\n\t\tVERIFY(v0 >= v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ B{0} };\n\n\t\tVERIFY(v0 != v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ B{0} };\n\n\t\tVERIFY(v0 < v1);\n\t}\n\n\t{\n\t\tBigVariant v0{ A{0} };\n\t\tBigVariant v1{ B{0} };\n\n\t\tVERIFY(v1 > v0);\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariantGeneratingComparisonOverloads();\n\n// test special member functions are enabled/disabled based on the contained types.\nint TestSpecialMembersDisabled()\n{\n\tint nErrorCount = 0;\n\n\tusing namespace eastl;\n\n\t// test copy construction\n\t// copy constructor is not enabled unless Ts are copy constructible.\n\t// copy constructor is trivial if Ts are trivially copy constructible.\n\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(!is_copy_constructible_v<variant<NoCopyMove>>, \"!copy constructible\");\n\t\tstatic_assert(!is_copy_constructible_v<variant<MoveOnlyType>>, \"!copy constructible\");\n\t\tstatic_assert(!is_copy_constructible_v<variant<MoveOnlyTypeDefaultCtor>>, \"!copy constructible\");\n#endif\n\n\t\tstatic_assert(is_copy_constructible_v<variant<NonTriviallyCopyable>>, \"copy constructible\");\n\t\tstatic_assert(!is_trivially_copy_constructible_v<variant<NonTriviallyCopyable>>, \"!trivially copy constructible\");\n\t\tstatic_assert(is_copy_constructible_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"copy constructible\");\n\t\tstatic_assert(!is_trivially_copy_constructible_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"!trivially copy constructible\");\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(is_trivially_copy_constructible_v<variant<TriviallyCopyableWithCopy>>, \"trivially copy constructible\");\n\t\tstatic_assert(is_trivially_copy_constructible_v<variant<TriviallyCopyableWithCopy, TriviallyCopyableWithCopy>>, \"trivially copy constructible\");\n\t\tstatic_assert(is_trivially_copy_constructible_v<variant<TriviallyCopyableWithCopyCtor>>, \"trivially copy constructible\");\n\t\tstatic_assert(is_trivially_copy_constructible_v<variant<TriviallyCopyableWithCopyCtor, TriviallyCopyableWithCopyCtor>>, \"trivially copy constructible\");\n\n\t\t// trivially copy constructible types, but with a copy constructor deleted\n\t\tstatic_assert(!is_copy_constructible_v<variant<TriviallyCopyableWithMove>>, \"!copy constructible\");\n\t\tstatic_assert(!is_copy_constructible_v<variant<TriviallyCopyableWithCopyAssign>>, \"!copy constructible\");\n\t\tstatic_assert(!is_copy_constructible_v<variant<TriviallyCopyableWithMoveCtor>>, \"!copy constructible\");\n\t\tstatic_assert(!is_copy_constructible_v<variant<TriviallyCopyableWithMoveAssign>>, \"!copy constructible\");\n#endif\n\t}\n\n\t// test move construction\n\t// copy constructor is not enabled unless Ts are *nothrow* move constructible.\n\t// move constructor is trivial if Ts are trivially move constructible.\n\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(!is_move_constructible_v<variant<NoCopyMove>>, \"!move constructible\");\n#endif\n\n\t\tstatic_assert(is_move_constructible_v<variant<MoveOnlyType>>, \"move constructible\");\n\t\tstatic_assert(!is_trivially_move_constructible_v<variant<MoveOnlyType>>, \"!trivially move constructible\");\n\t\tstatic_assert(is_move_constructible_v<variant<MoveOnlyTypeDefaultCtor>>, \"move constructible\");\n\t\tstatic_assert(!is_trivially_move_constructible_v<variant<MoveOnlyTypeDefaultCtor>>, \"!trivially move constructible\");\n\n\t\tstatic_assert(is_move_constructible_v<variant<NonTriviallyCopyable>>, \"move constructible\");\n\t\tstatic_assert(!is_trivially_move_constructible_v<variant<NonTriviallyCopyable>>, \"!trivially move constructible\");\n\t\tstatic_assert(is_move_constructible_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"move constructible\");\n\t\tstatic_assert(!is_trivially_move_constructible_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"!trivially move constructible\");\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(is_trivially_move_constructible_v<variant<TriviallyCopyableWithMove>>, \"trivially move constructible\");\n\t\tstatic_assert(is_trivially_move_constructible_v<variant<TriviallyCopyableWithMove, TriviallyCopyableWithMove>>, \"trivially move constructible\");\n\t\tstatic_assert(is_trivially_move_constructible_v<variant<TriviallyCopyableWithMoveCtor>>, \"trivially move constructible\");\n\t\tstatic_assert(is_trivially_move_constructible_v<variant<TriviallyCopyableWithMoveCtor, TriviallyCopyableWithMoveCtor>>, \"trivially move constructible\");\n\n\t\t// trivially move constructible types, but with a move constructor deleted\n\t\tstatic_assert(!is_move_constructible_v<variant<TriviallyCopyableWithCopyAssign>>, \"!move constructible\");\n\t\tstatic_assert(!is_move_constructible_v<variant<TriviallyCopyableWithMoveAssign>>, \"!move constructible\");\n\n\t\t// move constructor is deleted, but type trait passes because copy constructor exists\n\t\tstatic_assert(is_trivially_copy_constructible_v<variant<TriviallyCopyableWithCopy>>, \"trivially copy constructible\");\n\t\tstatic_assert(is_trivially_move_constructible_v<variant<TriviallyCopyableWithCopy>>, \"trivially move constructible\");\n\t\tstatic_assert(is_trivially_copy_constructible_v<variant<TriviallyCopyableWithCopyCtor>>, \"trivially copy constructible\");\n\t\tstatic_assert(is_trivially_move_constructible_v<variant<TriviallyCopyableWithCopyCtor>>, \"trivially move constructible\");\n#endif\n\t}\n\n\t// test copy assignment\n\t// copy assignment is not enabled unless Ts are both copy constructible and assignable.\n\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(!is_copy_assignable_v<variant<NoCopyMove>>, \"!copy assignable\");\n\t\tstatic_assert(!is_copy_assignable_v<variant<MoveOnlyType>>, \"!copy assignable\");\n\t\tstatic_assert(!is_copy_assignable_v<variant<MoveOnlyTypeDefaultCtor>>, \"!copy assignable\");\n#endif\n\n\t\tstatic_assert(is_copy_assignable_v<variant<NonTriviallyCopyable>>, \"copy assignable\");\n\t\tstatic_assert(!is_trivially_copy_assignable_v<variant<NonTriviallyCopyable>>, \"!trivially copy assignable\");\n\t\tstatic_assert(is_copy_assignable_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"copy assignable\");\n\t\tstatic_assert(!is_trivially_copy_assignable_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"!trivially copy assignable\");\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(is_trivially_copy_assignable_v<variant<TriviallyCopyableWithCopy>>, \"trivially copy assignable\");\n\t\tstatic_assert(is_trivially_copy_assignable_v<variant<TriviallyCopyableWithCopy, TriviallyCopyableWithCopy>>, \"trivially copy assignable\");\n\n\t\t// types that are missing either a copy constructor or copy assignment.\n\t\tstatic_assert(!is_copy_assignable_v<variant<TriviallyCopyableWithCopyCtor>>, \"!copy assignable\");\n\t\tstatic_assert(!is_copy_assignable_v<variant<TriviallyCopyableWithCopyAssign>>, \"!copy assignable\");\n\t\tstatic_assert(!is_copy_assignable_v<variant<TriviallyCopyableWithMove>>, \"!copy assignable\");\n\t\tstatic_assert(!is_copy_assignable_v<variant<TriviallyCopyableWithMoveCtor>>, \"!copy assignable\");\n\t\tstatic_assert(!is_copy_assignable_v<variant<TriviallyCopyableWithMoveAssign>>, \"!copy assignable\");\n#endif\n\t}\n\n\t// test move assignment\n\t// move assignment is not enabled unless Ts are both move constructible and assignable.\n\t{\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(!is_move_assignable_v<variant<NoCopyMove>>, \"!move assignable\");\n#endif\n\n\t\tstatic_assert(is_move_assignable_v<variant<MoveOnlyType>>, \"move assignable\");\n\t\tstatic_assert(!is_trivially_move_assignable_v<variant<MoveOnlyType>>, \"!trivially move assignable\");\n\t\tstatic_assert(is_move_assignable_v<variant<MoveOnlyTypeDefaultCtor>>, \"move assignable\");\n\t\tstatic_assert(!is_trivially_move_assignable_v<variant<MoveOnlyTypeDefaultCtor>>, \"!trivially move assignable\");\n\n\t\tstatic_assert(is_move_assignable_v<variant<NonTriviallyCopyable>>, \"move assignable\"); // invokes copy assignment. therefore true.\n\t\tstatic_assert(!is_trivially_move_assignable_v<variant<NonTriviallyCopyable>>, \"!trivially move assignable\");\n\t\tstatic_assert(is_move_assignable_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"move assignable\");\n\t\tstatic_assert(!is_trivially_move_assignable_v<variant<NonTriviallyCopyable, NonTriviallyCopyable>>, \"!trivially move assignable\");\n\n#if EA_IS_ENABLED(EA_DEPRECATIONS_FOR_2025_APRIL)\n\t\tstatic_assert(is_trivially_move_assignable_v<variant<TriviallyCopyableWithCopy>>, \"trivially move assignable\");\n\t\tstatic_assert(is_trivially_move_assignable_v<variant<TriviallyCopyableWithCopy, TriviallyCopyableWithCopy>>, \"trivially move assignable\");\n\t\tstatic_assert(is_trivially_move_assignable_v<variant<TriviallyCopyableWithMove>>, \"move assignable\");\n\t\tstatic_assert(is_trivially_move_assignable_v<variant<TriviallyCopyableWithMove, TriviallyCopyableWithMove>>, \"trivially move assignable\");\n\t\t\n\t\t// types that are missing either a move constructor or move assignment.\n\t\tstatic_assert(!is_move_assignable_v<variant<TriviallyCopyableWithCopyCtor>>, \"!move assignable\");\n\t\tstatic_assert(!is_move_assignable_v<variant<TriviallyCopyableWithCopyAssign>>, \"!move assignable\");\n\t\tstatic_assert(!is_move_assignable_v<variant<TriviallyCopyableWithMoveCtor>>, \"!move assignable\");\n\t\tstatic_assert(!is_move_assignable_v<variant<TriviallyCopyableWithMoveAssign>>, \"!move assignable\");\n#endif\n\t}\n\n\treturn nErrorCount;\n}\n\nint TestVariant()\n{\n\tint nErrorCount = 0;\n\n\tnErrorCount += TestVariantBasic();\n\tnErrorCount += TestVariantSize();\n\tnErrorCount += TestVariantAlternative();\n\tnErrorCount += TestVariantValuelessByException();\n\tnErrorCount += TestVariantGet();\n\tnErrorCount += TestVariantHoldsAlternative();\n\tnErrorCount += TestVariantHash();\n\tnErrorCount += TestVariantCopyAndMove();\n\tnErrorCount += TestVariantSwap();\n\tnErrorCount += TestVariantEmplace();\n\tnErrorCount += TestVariantRelOps();\n\tnErrorCount += TestVariantInplaceCtors();\n\tnErrorCount += TestVariantVisitorOverloaded();\n\tnErrorCount += TestVariantVisitor();\n\tnErrorCount += TestVariantVisitorReturn();\n\tnErrorCount += TestVariantVisitBase();\n\tnErrorCount += TestVariantAssignment();\n\tnErrorCount += TestVariantMoveOnly();\n\tnErrorCount += TestVariantUserRegressionCopyMoveAssignmentOperatorLeak();\n\tnErrorCount += TestVariantUserRegressionIncompleteType();\n\tnErrorCount += TestVariantGeneratingComparisonOverloads();\n\tnErrorCount += TestBigVariantComparison();\n\tnErrorCount += TestVariantRelationalOperators();\n\tnErrorCount += TestSpecialMembersDisabled();\n\n\treturn nErrorCount;\n}\n#else\n\tint TestVariant() { return 0; }\n#endif\n\nEA_RESTORE_VC_WARNING();\n"
  },
  {
    "path": "test/source/TestVariant2.cpp",
    "content": "/**\n * NOTE:\n *\n * DO NOT INCLUDE EATest/EATest.h or ANY OTHER HEADER\n * There is a bug in MSVC whereby pushing/poping all warnings from a header does not reenable all warnings\n * in the TU that included the header.\n * For example C4805 will not reenabled.\n */\n\n#include <EASTL/variant.h>\n\nint TestVariantGeneratingComparisonOverloads()\n{\n\tint nErrorCount = 0;\n\n\t{\n\t\teastl::variant<int, float, bool> a;\n\t\teastl::variant<int, float, bool> b;\n\n\t\tauto r = a == b;\n\n\t\tnErrorCount += !r;\n\t}\n\n\t{\n\t\teastl::variant<int, float, bool> a;\n\t\teastl::variant<int, float, bool> b;\n\n\t\tbool r = (a == b);\n\n\t\tnErrorCount += !r;\n\t}\n\n\t// A variant is permitted to hold the same type more than once, and to hold differently cv-qualified versions of the same type.\n\n\t{\n\t\teastl::variant<int, int, int> a;\n\t\teastl::variant<int, int, int> b;\n\n\t\tbool r = (a == b);\n\n\t\tnErrorCount += !r;\n\t}\n\n\t{\n\t\teastl::variant<signed int, unsigned int> a;\n\t\teastl::variant<signed int, unsigned int> b;\n\n\t\tbool r = (a == b);\n\n\t\tnErrorCount += !r;\n\t}\n\n\t{\n\t\teastl::variant<int, bool> a;\n\t\teastl::variant<int, bool> b;\n\n\t\tbool r = (a == b);\n\n\t\tnErrorCount += !r;\n\t}\n\n\t{\n\t\teastl::variant<volatile int, int, const int, const volatile int> a;\n\t\teastl::variant<volatile int, int, const int, const volatile int> b;\n\n\t\tbool r = (a == b);\n\n\t\tnErrorCount += !r;\n\t}\n\n\t{\n\t\teastl::variant<volatile int, int, const int, const volatile int, bool> a;\n\t\teastl::variant<volatile int, int, const int, const volatile int, bool> b;\n\n\t\tbool r = (a == b);\n\n\t\tnErrorCount += !r;\n\t}\n\n\treturn nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestVector.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n#include \"EASTLTest.h\"\n#include <EASTL/vector.h>\n#include <EASTL/string.h>\n#include <EASTL/deque.h>\n#include <EASTL/list.h>\n#include <EASTL/slist.h>\n#include <EASTL/algorithm.h>\n#include <EASTL/utility.h>\n#include <EASTL/allocator_malloc.h>\n#include <EASTL/unique_ptr.h>\n\n#include \"ConceptImpls.h\"\n\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <vector>\n\t#include <string>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::vector<bool>;\ntemplate class eastl::vector<int>;\ntemplate class eastl::vector<Align64>;\ntemplate class eastl::vector<TestObject>;\n\n\n// This tests \"uninitialized_fill\" usage in vector when T has a user provided\n// address-of operator overload.  In these situations, EASTL containers must use\n// the standard utility \"eastl::addressof(T)\" which is designed to by-pass user\n// provided address-of operator overloads.\n// \n// Previously written as: \n// \tfor(; first != last; ++first, ++currentDest)\n// \t\t::new((void*)&*currentDest) value_type(*first); // & not guaranteed to be a pointer\n//\n// Bypasses user 'addressof' operators:\n// \tfor(; n > 0; --n, ++currentDest)\n// \t\t::new(eastl::addressof(*currentDest)) value_type(value);  // guaranteed to be a pointer\n//\nstruct AddressOfOperatorResult {};\nstruct HasAddressOfOperator \n{\n\t// problematic 'addressof' operator that doesn't return a pointer type\n    AddressOfOperatorResult operator&() const { return {}; }\n\tbool operator==(const HasAddressOfOperator&) const { return false; }\n};\ntemplate class eastl::vector<HasAddressOfOperator>;  // force compile all functions of vector\n\n\n\n// Test compiler issue that appeared in VS2012 relating to kAlignment\nstruct StructWithContainerOfStructs\n{\n\teastl::vector<StructWithContainerOfStructs> children;\n};\n\n\t\t// This relatively complex test is to prevent a regression on VS2013.  The data types have what may appear to be\n\t\t// strange names (for test code) because the code is based on a test case extracted from the Frostbite codebase.\n\t\t// This test is actually invalid and should be removed as const data memebers are problematic for STL container\n\t\t// implementations. (ie.  they prevent constructors from being generated).\nnamespace\n{\n\t\t\tEA_DISABLE_VC_WARNING(4512) // disable warning : \"assignment operator could not be generated\"\n#if (defined(_MSC_VER) && (_MSC_VER >= 1900))  // VS2015-preview and later.\n\t\t\tEA_DISABLE_VC_WARNING(5025) // disable warning : \"move assignment operator could not be generated\"\n\t\t\tEA_DISABLE_VC_WARNING(4626) // disable warning : \"assignment operator was implicitly defined as deleted\"\n\t\t\tEA_DISABLE_VC_WARNING(5027) // disable warning : \"move assignment operator was implicitly defined as deleted\"\n#endif\nstruct ScenarioRefEntry\n{\n\tScenarioRefEntry(const eastl::string& contextDatabase) : ContextDatabase(contextDatabase) {}\n\n\tstruct RowEntry\n\t{\n\t\tRowEntry(int levelId, int sceneId, int actorId, int partId, const eastl::string& controller)\n\t\t\t: LevelId(levelId), SceneId(sceneId), ActorId(actorId), PartId(partId), Controller(controller)\n\t\t{\n\t\t}\n\n\t\tint LevelId;\n\t\tint SceneId;\n\t\tint ActorId;\n\t\tint PartId;\n\t\tconst eastl::string& Controller;\n\t};\n\tconst eastl::string& ContextDatabase;  // note:  const class members prohibits move semantics\n\ttypedef eastl::vector<RowEntry> RowData;\n\tRowData Rows;\n};\ntypedef eastl::vector<ScenarioRefEntry> ScenarRefData;\nstruct AntMetaDataRecord\n{\n\tScenarRefData ScenarioRefs;\n};\ntypedef eastl::vector<AntMetaDataRecord> MetadataRecords;\n\nstruct StructWithConstInt\n{\n\tStructWithConstInt(const int& _i) : i(_i) {}\n\tconst int i;\n};\n\nstruct StructWithConstRefToInt\n{\n\tStructWithConstRefToInt(const int& _i) : i(_i) {}\n\tconst int& i;\n};\n#if (defined(_MSC_VER) && (_MSC_VER >= 1900))  // VS2015-preview and later.\n\tEA_RESTORE_VC_WARNING() // disable warning 5025:  \"move assignment operator could not be generated\"\n\tEA_RESTORE_VC_WARNING() // disable warning 4626:  \"assignment operator was implicitly defined as deleted\"\n\tEA_RESTORE_VC_WARNING() // disable warning 5027:  \"move assignment operator was implicitly defined as deleted\"\n#endif\nEA_RESTORE_VC_WARNING()\n}\n\nstruct ItemWithConst\n{\n\tItemWithConst& operator=(const ItemWithConst&);\n\npublic:\n\tItemWithConst(int _i) : i(_i) {}\n\tItemWithConst(const ItemWithConst& x) : i(x.i) {}\n\tconst int i;\n};\n\nstruct testmovable\n{\n\tEA_NON_COPYABLE(testmovable)\npublic:\n\ttestmovable() EA_NOEXCEPT {}\n\n\ttestmovable(testmovable&&) EA_NOEXCEPT {}\n\n\ttestmovable& operator=(testmovable&&) EA_NOEXCEPT { return *this; }\n};\n\nstruct TestMoveAssignToSelf\n{\n\tTestMoveAssignToSelf() EA_NOEXCEPT : mMovedToSelf(false)      {}\n\tTestMoveAssignToSelf(const TestMoveAssignToSelf& other)       { mMovedToSelf = other.mMovedToSelf; }\n\tTestMoveAssignToSelf& operator=(TestMoveAssignToSelf&&)       { mMovedToSelf = true; return *this; }\n\tTestMoveAssignToSelf& operator=(const TestMoveAssignToSelf&) = delete;\n\n\tbool mMovedToSelf;\n};\n\n#if EASTL_VARIABLE_TEMPLATES_ENABLED\n\t/// custom type-trait which checks if a type is comparable via the <operator.\n\ttemplate <class, class = eastl::void_t<>>\n\tstruct is_less_comparable : eastl::false_type { };\n\ttemplate <class T>\n\tstruct is_less_comparable<T, eastl::void_t<decltype(eastl::declval<T>() < eastl::declval<T>())>> : eastl::true_type { };\n#else\n\t// bypass the test since the compiler doesn't support variable templates.\n\ttemplate <class> struct is_less_comparable : eastl::false_type { };\n#endif\n\n\nint TestVector()\n{\n\tint nErrorCount = 0;\n\teastl_size_t i;\n\n\tTestObject::Reset();\n\n\t{\n\t\tMetadataRecords mMetadataRecords;\n\t\tAntMetaDataRecord r, s;\n\t\tmMetadataRecords.push_back(r);\n\t\tmMetadataRecords.push_back(s);\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// explicit vector();\n\t\tvector<int> intArray1;\n\t\tvector<TestObject> toArray1;\n\t\tvector<list<TestObject> > toListArray1;\n\n\t\tEATEST_VERIFY(intArray1.validate());\n\t\tEATEST_VERIFY(intArray1.empty());\n\t\tEATEST_VERIFY(toArray1.validate());\n\t\tEATEST_VERIFY(toArray1.empty());\n\t\tEATEST_VERIFY(toListArray1.validate());\n\t\tEATEST_VERIFY(toListArray1.empty());\n\n\t\t// explicit vector(const allocator_type& allocator);\n\t\tMallocAllocator::reset_all();\n\t\tMallocAllocator ma;\n\t\tvector<int, MallocAllocator> intArray6(ma);\n\t\tvector<TestObject, MallocAllocator> toArray6(ma);\n\t\tvector<list<TestObject>, MallocAllocator> toListArray6(ma);\n\t\tintArray6.resize(1);\n\t\ttoArray6.resize(1);\n\t\ttoListArray6.resize(1);\n\t\tEATEST_VERIFY(MallocAllocator::mAllocCountAll == 3);\n\n\t\t// explicit vector(size_type n, const allocator_type& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR)\n\t\tvector<int> intArray2(10);\n\t\tvector<TestObject> toArray2(10);\n\t\tvector<list<TestObject> > toListArray2(10);\n\n\t\tEATEST_VERIFY(intArray2.validate());\n\t\tEATEST_VERIFY(intArray2.size() == 10);\n\t\tEATEST_VERIFY(toArray2.validate());\n\t\tEATEST_VERIFY(toArray2.size() == 10);\n\t\tEATEST_VERIFY(toListArray2.validate());\n\t\tEATEST_VERIFY(toListArray2.size() == 10);\n\n\t\t// vector(size_type n, const value_type& value, const allocator_type& allocator =\n\t\t// EASTL_VECTOR_DEFAULT_ALLOCATOR)\n\t\tvector<int> intArray3(10, 7);\n\t\tvector<TestObject> toArray3(10, TestObject(7));\n\t\tvector<list<TestObject> > toListArray3(10, list<TestObject>(7));\n\n\t\tEATEST_VERIFY(intArray3.validate());\n\t\tEATEST_VERIFY(intArray3.size() == 10);\n\t\tEATEST_VERIFY(intArray3[5] == 7);\n\t\tEATEST_VERIFY(toArray3.validate());\n\t\tEATEST_VERIFY(toArray3[5] == TestObject(7));\n\t\tEATEST_VERIFY(toListArray3.validate());\n\t\tEATEST_VERIFY(toListArray3[5] == list<TestObject>(7));\n\n\t\t// vector(const vector& x)\n\t\tvector<int> intArray4(intArray2);\n\t\tvector<TestObject> toArray4(toArray2);\n\t\tvector<list<TestObject> > toListArray4(toListArray2);\n\n\t\tEATEST_VERIFY(intArray4.validate());\n\t\tEATEST_VERIFY(intArray4 == intArray2);\n\t\tEATEST_VERIFY(toArray4.validate());\n\t\tEATEST_VERIFY(toArray4 == toArray2);\n\t\tEATEST_VERIFY(intArray4.validate());\n\t\tEATEST_VERIFY(toListArray4 == toListArray2);\n\n\t\t// vector(const this_type& x, const allocator_type& allocator)\n\t\tMallocAllocator::reset_all();\n\t\tvector<int, MallocAllocator> intArray7(intArray6, ma);\n\t\tvector<TestObject, MallocAllocator> toArray7(toArray6, ma);\n\t\tvector<list<TestObject>, MallocAllocator> toListArray7(toListArray6, ma);\n\t\tEATEST_VERIFY(MallocAllocator::mAllocCountAll == 3);\n\n\t\t// vector(InputIterator first, InputIterator last)\n\t\tdeque<int> intDeque(3);\n\t\tdeque<TestObject> toDeque(3);\n\t\tdeque<list<TestObject> > toListDeque(3);\n\n\t\tvector<int> intArray5(intDeque.begin(), intDeque.end());\n\t\tvector<TestObject> toArray5(toDeque.begin(), toDeque.end());\n\t\tvector<list<TestObject> > toListArray5(toListDeque.begin(), toListDeque.end());\n\n\t\t// vector(std::initializer_list<T> ilist, const Allocator& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR);\n\t\t{\n#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t\teastl::vector<float> floatVector{0, 1, 2, 3};\n\n\t\t\tEATEST_VERIFY(floatVector.size() == 4);\n\t\t\tEATEST_VERIFY((floatVector[0] == 0) && (floatVector[3] == 3));\n#endif\n\t\t}\n\n\t\t// vector& operator=(const vector& x);\n\t\tintArray3 = intArray4;\n\t\ttoArray3 = toArray4;\n\t\ttoListArray3 = toListArray4;\n\n\t\tEATEST_VERIFY(intArray3.validate());\n\t\tEATEST_VERIFY(intArray3 == intArray4);\n\t\tEATEST_VERIFY(toArray3.validate());\n\t\tEATEST_VERIFY(toArray3 == toArray4);\n\t\tEATEST_VERIFY(intArray3.validate());\n\t\tEATEST_VERIFY(toListArray3 == toListArray4);\n\n// this_type& operator=(std::initializer_list<T> ilist);\n#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\tintArray3 = {0, 1, 2, 3};\n\t\tEATEST_VERIFY((intArray3.size() == 4) && (intArray3[0] == 0) && (intArray3[3] == 3));\n#endif\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// vector(this_type&& x)\n\t\t// vector(this_type&& x, const Allocator& allocator)\n\t\t// this_type& operator=(this_type&& x)\n\n\t\tvector<TestObject> vector3TO33(3, TestObject(33));\n\t\tvector<TestObject> toVectorA(eastl::move(vector3TO33));\n\t\tEATEST_VERIFY((toVectorA.size() == 3) && (toVectorA.front().mX == 33) && (vector3TO33.size() == 0));\n\n\t\t// The following is not as strong a test of this ctor as it could be. A stronger test would be to use\n\t\t// IntanceAllocator with different instances.\n\t\tvector<TestObject, MallocAllocator> vector4TO44(4, TestObject(44));\n\t\tvector<TestObject, MallocAllocator> toVectorB(eastl::move(vector4TO44), MallocAllocator());\n\t\tEATEST_VERIFY((toVectorB.size() == 4) && (toVectorB.front().mX == 44) && (vector4TO44.size() == 0));\n\n\t\tvector<TestObject, MallocAllocator> vector5TO55(5, TestObject(55));\n\t\ttoVectorB = eastl::move(vector5TO55);\n\t\tEATEST_VERIFY((toVectorB.size() == 5) && (toVectorB.front().mX == 55) && (vector5TO55.size() == 0));\n\n\t\t// Should be able to emplace_back an item with const members (non-copyable)\n\t\teastl::vector<ItemWithConst> myVec2;\n\t\tItemWithConst& ref = myVec2.emplace_back(42);\n\t\tEATEST_VERIFY(myVec2.back().i == 42);\n\t\tEATEST_VERIFY(ref.i == 42);\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// pointer         data();\n\t\t// const_pointer   data() const;\n\t\t// reference       front();\n\t\t// const_reference front() const;\n\t\t// reference       back();\n\t\t// const_reference back() const;\n\n\t\tvector<int> intArray(10, 7);\n\t\tintArray[0] = 10;\n\t\tintArray[1] = 11;\n\t\tintArray[2] = 12;\n\n\t\tEATEST_VERIFY(intArray.data() == &intArray[0]);\n\t\tEATEST_VERIFY(*intArray.data() == 10);\n\t\tEATEST_VERIFY(intArray.front() == 10);\n\t\tEATEST_VERIFY(intArray.back() == 7);\n\n\t\tconst vector<TestObject> toArrayC(10, TestObject(7));\n\n\t\tEATEST_VERIFY(toArrayC.data() == &toArrayC[0]);\n\t\tEATEST_VERIFY(*toArrayC.data() == TestObject(7));\n\t\tEATEST_VERIFY(toArrayC.front() == TestObject(7));\n\t\tEATEST_VERIFY(toArrayC.back() == TestObject(7));\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// iterator               begin();\n\t\t// const_iterator         begin() const;\n\t\t// iterator               end();\n\t\t// const_iterator         end() const;\n\t\t// reverse_iterator       rbegin();\n\t\t// const_reverse_iterator rbegin() const;\n\t\t// reverse_iterator       rend();\n\t\t// const_reverse_iterator rend() const;\n\n\t\tvector<int> intArray(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintArray[i] = (int)i;\n\n\t\ti = 0;\n\t\tfor (vector<int>::iterator it = intArray.begin(); it != intArray.end(); ++it, ++i)\n\t\t\tEATEST_VERIFY(*it == (int)i);\n\n\t\ti = intArray.size() - 1;\n\t\tfor (vector<int>::reverse_iterator itr = intArray.rbegin(); itr != intArray.rend(); ++itr, --i)\n\t\t\tEATEST_VERIFY(*itr == (int)i);\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// void    swap(vector& x);\n\t\t// void    assign(size_type n, const value_type& value);\n\t\t// void    assign(InputIterator first, InputIterator last);\n\n\t\tconst int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};\n\t\tconst int B[] = {99, 99, 99, 99, 99};\n\t\tconst size_t N = sizeof(A) / sizeof(int);\n\t\tconst size_t M = sizeof(B) / sizeof(int);\n\n\t\t// assign from pointer range\n\t\tvector<int> v3;\n\t\tv3.assign(A, A + N);\n\t\tEATEST_VERIFY(equal(v3.begin(), v3.end(), A));\n\t\tEATEST_VERIFY(v3.size() == N);\n\n\t\t// assign from iterator range\n\t\tvector<int> v4;\n\t\tv4.assign(v3.begin(), v3.end());\n\t\tEATEST_VERIFY(equal(v4.begin(), v4.end(), A));\n\t\tEATEST_VERIFY(equal(A, A + N, v4.begin()));\n\n\t\t// assign from initializer range with resize\n\t\tv4.assign(M, 99);\n\t\tEATEST_VERIFY(equal(v4.begin(), v4.end(), B));\n\t\tEATEST_VERIFY(equal(B, B + M, v4.begin()));\n\t\tEATEST_VERIFY((v4.size() == M) && (M != N));\n\n#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t// void assign(std::initializer_list<T> ilist);\n\t\tv4.assign({0, 1, 2, 3});\n\t\tEATEST_VERIFY(v4.size() == 4);\n\t\tEATEST_VERIFY((v4[0] == 0) && (v4[3] == 3));\n#endif\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// reference       operator[](size_type n);\n\t\t// const_reference operator[](size_type n) const;\n\t\t// reference       at(size_type n);\n\t\t// const_reference at(size_type n) const;\n\n\t\tvector<int> intArray(5);\n\t\tEATEST_VERIFY(intArray[3] == 0);\n\t\tEATEST_VERIFY(intArray.at(3) == 0);\n\n\t\tvector<TestObject> toArray(5);\n\t\tEATEST_VERIFY(toArray[3] == TestObject(0));\n\t\tEATEST_VERIFY(toArray.at(3) == TestObject(0));\n\n#if EASTL_EXCEPTIONS_ENABLED\n\t\tvector<TestObject> vec01(5);\n\n\t\ttry\n\t\t{\n\t\t\tTestObject& r01 = vec01.at(6);\n\t\t\tEATEST_VERIFY(!(r01 == TestObject(0)));  // Should not get here, as exception thrown.\n\t\t}\n\t\tcatch (std::out_of_range&) { EATEST_VERIFY(true); }\n\t\tcatch (...) { EATEST_VERIFY(false); }\n#endif\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// void push_back(const value_type& value);\n\t\t// void push_back();\n\t\t// void pop_back();\n\t\t// void push_back(T&& value);\n\n\t\tvector<int> intArray(6);\n\t\tfor (i = 0; i < 6; i++)\n\t\t\tintArray[i] = (int)i;\n\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 6);\n\t\tEATEST_VERIFY(intArray[5] == 5);\n\n\t\tfor (i = 0; i < 40; i++)\n\t\t{\n\t\t\tint& ref = intArray.push_back();\n\t\t\tEATEST_VERIFY(&ref == &intArray.back());\n\t\t\tref = 98;\n\t\t}\n\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 46);\n\t\tEATEST_VERIFY(intArray[45] == 98);\n\n\t\tfor (i = 0; i < 40; i++)\n\t\t\tintArray.push_back(99);\n\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 86);\n\t\tEATEST_VERIFY(intArray[85] == 99);\n\n\t\tfor (i = 0; i < 30; i++)\n\t\t\tintArray.pop_back();\n\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 56);\n\t\tEATEST_VERIFY(intArray[5] == 5);\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// void* push_back_uninitialized();\n\n\t\tint64_t toCount0 = TestObject::sTOCount;\n\n\t\tvector<TestObject> vTO;\n\t\tEATEST_VERIFY(TestObject::sTOCount == toCount0);\n\n\t\tfor (i = 0; i < 25; i++)\n\t\t{\n\t\t\tvoid* pTO = vTO.push_back_uninitialized();\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == (toCount0 + static_cast<int64_t>(i)));\n\n\t\t\tnew (pTO) TestObject((int)i);\n\t\t\tEATEST_VERIFY(TestObject::sTOCount == (toCount0 + static_cast<int64_t>(i) + 1));\n\t\t\tEATEST_VERIFY(vTO.back().mX == (int)i);\n\t\t\tEATEST_VERIFY(vTO.validate());\n\t\t}\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// template<class... Args>\n\t\t// iterator emplace(const_iterator position, Args&&... args);\n\n\t\t// template<class... Args>\n\t\t// void emplace_back(Args&&... args);\n\n\t\t// iterator insert(const_iterator position, value_type&& value);\n\t\t// void push_back(value_type&& value);\n\n\t\tTestObject::Reset();\n\n\t\tvector<TestObject> toVectorA;\n\n\t\tTestObject& ref = toVectorA.emplace_back(2, 3, 4);\n\t\tEATEST_VERIFY((toVectorA.size() == 1) && (toVectorA.back().mX == (2 + 3 + 4)) &&\n\t\t\t\t\t  (TestObject::sTOCtorCount == 1));\n\t\tEATEST_VERIFY(ref.mX == (2 + 3 + 4));\n\n\t\ttoVectorA.emplace(toVectorA.begin(), 3, 4, 5);\n\t\tEATEST_VERIFY((toVectorA.size() == 2) && (toVectorA.front().mX == (3 + 4 + 5)) &&\n\t\t\t\t\t  (TestObject::sTOCtorCount == 3));  // 3 because the original count of 1, plus the existing vector\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t // element will be moved, plus the one being emplaced.\n\n\t\tTestObject::Reset();\n\n\t\t// void push_back(T&& x);\n\t\t// iterator insert(const_iterator position, T&& x);\n\n\t\tvector<TestObject> toVectorC;\n\n\t\ttoVectorC.push_back(TestObject(2, 3, 4));\n\t\tEATEST_VERIFY((toVectorC.size() == 1) && (toVectorC.back().mX == (2 + 3 + 4)) &&\n\t\t\t\t\t  (TestObject::sTOMoveCtorCount == 1));\n\n\t\ttoVectorC.insert(toVectorC.begin(), TestObject(3, 4, 5));\n\t\tEATEST_VERIFY((toVectorC.size() == 2) && (toVectorC.front().mX == (3 + 4 + 5)) &&\n\t\t\t\t\t  (TestObject::sTOMoveCtorCount == 3));  // 3 because the original count of 1, plus the existing\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t // vector element will be moved, plus the one being\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t // emplaced.\n\t}\n\n\t// We don't check for TestObject::IsClear because we messed with state above and don't currently have a matching set\n\t// of ctors and dtors.\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// iterator erase(iterator position);\n\t\t// iterator erase(iterator first, iterator last);\n\t\t// iterator erase_unsorted(iterator position);\n\t\t// iterator erase_first(const T& pos);\n\t\t// iterator erase_first_unsorted(const T& pos);\n\t\t// iterator erase_last(const T& pos);\n\t\t// iterator erase_last_unsorted(const T& pos);\n\t\t// void     clear();\n\n\t\tvector<int> intArray(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintArray[i] = (int)i;\n\n\t\t// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19\n\n\t\tintArray.erase(intArray.begin() +\n\t\t\t\t\t   10);  // Becomes: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 19);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[10] == 11);\n\t\tEATEST_VERIFY(intArray[18] == 19);\n\n\t\tintArray.erase(intArray.begin() + 10,\n\t\t\t\t\t   intArray.begin() + 15);  // Becomes: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 14);\n\t\tEATEST_VERIFY(intArray[9] == 9);\n\t\tEATEST_VERIFY(intArray[13] == 19);\n\n\t\tintArray.erase(intArray.begin() + 1, intArray.begin() + 5);  // Becomes: 0, 5, 6, 7, 8, 9, 16, 17, 18, 19\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 10);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 5);\n\t\tEATEST_VERIFY(intArray[9] == 19);\n\n\t\tintArray.erase(intArray.begin() + 7, intArray.begin() + 10);  // Becomes: 0, 5, 6, 7, 8, 9, 16\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 7);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 5);\n\t\tEATEST_VERIFY(intArray[6] == 16);\n\n\t\tintArray.clear();\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.empty());\n\t\tEATEST_VERIFY(intArray.size() == 0);\n\n\t\tvector<TestObject> toArray(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\ttoArray[i] = TestObject((int)i);\n\n\t\ttoArray.erase(toArray.begin() + 10);\n\t\tEATEST_VERIFY(toArray.validate());\n\t\tEATEST_VERIFY(toArray.size() == 19);\n\t\tEATEST_VERIFY(toArray[10] == TestObject(11));\n\n\t\ttoArray.erase(toArray.begin() + 10, toArray.begin() + 15);\n\t\tEATEST_VERIFY(toArray.validate());\n\t\tEATEST_VERIFY(toArray.size() == 14);\n\t\tEATEST_VERIFY(toArray[10] == TestObject(16));\n\n\t\ttoArray.clear();\n\t\tEATEST_VERIFY(toArray.validate());\n\t\tEATEST_VERIFY(toArray.empty());\n\t\tEATEST_VERIFY(toArray.size() == 0);\n\n\t\t// iterator erase_unsorted(iterator position);\n\t\tintArray.resize(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintArray[i] = (int)i;\n\n\t\tintArray.erase_unsorted(intArray.begin() + 0);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 19);\n\t\tEATEST_VERIFY(intArray[0] == 19);\n\t\tEATEST_VERIFY(intArray[1] == 1);\n\t\tEATEST_VERIFY(intArray[18] == 18);\n\n\t\tintArray.erase_unsorted(intArray.begin() + 10);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 18);\n\t\tEATEST_VERIFY(intArray[0] == 19);\n\t\tEATEST_VERIFY(intArray[10] == 18);\n\t\tEATEST_VERIFY(intArray[17] == 17);\n\n\t\tintArray.erase_unsorted(intArray.begin() + 17);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 17);\n\t\tEATEST_VERIFY(intArray[0] == 19);\n\t\tEATEST_VERIFY(intArray[10] == 18);\n\t\tEATEST_VERIFY(intArray[16] == 16);\n\n\t\t// iterator erase_first(iterator position);\n\t\tintArray.resize(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintArray[i] = (int)i % 3; // (i.e. 0,1,2,0,1,2...)\n\n\t\tintArray.erase_first(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 19);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 2);\n\t\tEATEST_VERIFY(intArray[2] == 0);\n\t\tEATEST_VERIFY(intArray[3] == 1);\n\t\tEATEST_VERIFY(intArray[18] == 1);\n\n\t\tintArray.erase_first(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 18);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 2);\n\t\tEATEST_VERIFY(intArray[2] == 0);\n\t\tEATEST_VERIFY(intArray[3] == 2);\n\t\tEATEST_VERIFY(intArray[17] == 1);\n\n\t\tintArray.erase_first(0);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 17);\n\t\tEATEST_VERIFY(intArray[0] == 2);\n\t\tEATEST_VERIFY(intArray[1] == 0);\n\t\tEATEST_VERIFY(intArray[2] == 2);\n\t\tEATEST_VERIFY(intArray[3] == 0);\n\t\tEATEST_VERIFY(intArray[16] == 1);\n\n\t\t// iterator erase_first_unsorted(const T& val);\n\t\tintArray.resize(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintArray[i] = (int) i/2; // every two values are the same (i.e. 0,0,1,1,2,2,3,3...)\n\n\t\tintArray.erase_first_unsorted(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 19);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 0);\n\t\tEATEST_VERIFY(intArray[2] == 9);\n\t\tEATEST_VERIFY(intArray[3] == 1);\n\t\tEATEST_VERIFY(intArray[18] == 9);\n\n\t\tintArray.erase_first_unsorted(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 18);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 0);\n\t\tEATEST_VERIFY(intArray[2] == 9);\n\t\tEATEST_VERIFY(intArray[3] == 9);\n\t\tEATEST_VERIFY(intArray[17] == 8);\n\n\t\tintArray.erase_first_unsorted(0);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 17);\n\t\tEATEST_VERIFY(intArray[0] == 8);\n\t\tEATEST_VERIFY(intArray[1] == 0);\n\t\tEATEST_VERIFY(intArray[2] == 9);\n\t\tEATEST_VERIFY(intArray[3] == 9);\n\t\tEATEST_VERIFY(intArray[16] == 8);\n\n\t\t// iterator erase_last(const T& val);\n\t\tintArray.resize(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintArray[i] = (int)i % 3; // (i.e. 0,1,2,0,1,2...)\n\n\t\tintArray.erase_last(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 19);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 1);\n\t\tEATEST_VERIFY(intArray[2] == 2);\n\t\tEATEST_VERIFY(intArray[3] == 0);\n\t\tEATEST_VERIFY(intArray[15] == 0);\n\t\tEATEST_VERIFY(intArray[16] == 1);\n\t\tEATEST_VERIFY(intArray[17] == 2);\n\t\tEATEST_VERIFY(intArray[18] == 0);\n\n\t\tintArray.erase_last(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 18);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 1);\n\t\tEATEST_VERIFY(intArray[2] == 2);\n\t\tEATEST_VERIFY(intArray[3] == 0);\n\t\tEATEST_VERIFY(intArray[14] == 2);\n\t\tEATEST_VERIFY(intArray[15] == 0);\n\t\tEATEST_VERIFY(intArray[16] == 2);\n\t\tEATEST_VERIFY(intArray[17] == 0);\n\n\t\tintArray.erase_last(0);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 17);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 1);\n\t\tEATEST_VERIFY(intArray[2] == 2);\n\t\tEATEST_VERIFY(intArray[3] == 0);\n\t\tEATEST_VERIFY(intArray[13] == 1);\n\t\tEATEST_VERIFY(intArray[14] == 2);\n\t\tEATEST_VERIFY(intArray[15] == 0);\n\t\tEATEST_VERIFY(intArray[16] == 2);\n\n\t\t// iterator erase_last_unsorted(const T& val);\n\t\tintArray.resize(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintArray[i] = (int)i / 2; // every two values are the same (i.e. 0,0,1,1,2,2,3,3...)\n\n\t\tintArray.erase_last_unsorted(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 19);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 0);\n\t\tEATEST_VERIFY(intArray[2] == 1);\n\t\tEATEST_VERIFY(intArray[3] == 9);\n\t\tEATEST_VERIFY(intArray[18] == 9);\n\n\t\tintArray.erase_last_unsorted(1);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 18);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 0);\n\t\tEATEST_VERIFY(intArray[2] == 9);\n\t\tEATEST_VERIFY(intArray[3] == 9);\n\t\tEATEST_VERIFY(intArray[17] == 8);\n\n\t\tintArray.erase_last_unsorted(0);\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY(intArray.size() == 17);\n\t\tEATEST_VERIFY(intArray[0] == 0);\n\t\tEATEST_VERIFY(intArray[1] == 8);\n\t\tEATEST_VERIFY(intArray[2] == 9);\n\t\tEATEST_VERIFY(intArray[3] == 9);\n\t\tEATEST_VERIFY(intArray[16] == 8);\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// iterator erase(reverse_iterator position);\n\t\t// iterator erase(reverse_iterator first, reverse_iterator last);\n\t\t// iterator erase_unsorted(reverse_iterator position);\n\n\t\tvector<int> intVector;\n\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintVector.push_back((int)i);\n\t\tEATEST_VERIFY((intVector.size() == 20) && (intVector[0] == 0) && (intVector[19] == 19));\n\n\t\tvector<int>::reverse_iterator r2A = intVector.rbegin();\n\t\tvector<int>::reverse_iterator r2B = r2A + 3;\n\t\tintVector.erase(r2A, r2B);\n\t\tEATEST_VERIFY((intVector.size() == 17));\n\t\tEATEST_VERIFY((intVector[0] == 0));\n\t\tEATEST_VERIFY((intVector[16] == 16));\n\n\t\tr2B = intVector.rend();\n\t\tr2A = r2B - 3;\n\t\tintVector.erase(r2A, r2B);\n\t\tEATEST_VERIFY((intVector.size() == 14));\n\t\tEATEST_VERIFY((intVector[0] == 3));\n\t\tEATEST_VERIFY((intVector[13] == 16));\n\n\t\tr2B = intVector.rend() - 1;\n\t\tintVector.erase(r2B);\n\t\tEATEST_VERIFY((intVector.size() == 13));\n\t\tEATEST_VERIFY((intVector[0] == 4));\n\t\tEATEST_VERIFY((intVector[12] == 16));\n\n\t\tr2B = intVector.rbegin();\n\t\tintVector.erase(r2B);\n\t\tEATEST_VERIFY((intVector.size() == 12));\n\t\tEATEST_VERIFY((intVector[0] == 4));\n\t\tEATEST_VERIFY((intVector[11] == 15));\n\n\t\tr2A = intVector.rbegin();\n\t\tr2B = intVector.rend();\n\t\tintVector.erase(r2A, r2B);\n\t\tEATEST_VERIFY(intVector.size() == 0);\n\n\t\t// iterator erase_unsorted(iterator position);\n\t\tintVector.resize(20);\n\t\tfor (i = 0; i < 20; i++)\n\t\t\tintVector[i] = (int)i;\n\n\t\tintVector.erase_unsorted(intVector.rbegin() + 0);\n\t\tEATEST_VERIFY(intVector.validate());\n\t\tEATEST_VERIFY(intVector.size() == 19);\n\t\tEATEST_VERIFY(intVector[0] == 0);\n\t\tEATEST_VERIFY(intVector[10] == 10);\n\t\tEATEST_VERIFY(intVector[18] == 18);\n\n\t\tintVector.erase_unsorted(intVector.rbegin() + 10);\n\t\tEATEST_VERIFY(intVector.validate());\n\t\tEATEST_VERIFY(intVector.size() == 18);\n\t\tEATEST_VERIFY(intVector[0] == 0);\n\t\tEATEST_VERIFY(intVector[8] == 18);\n\t\tEATEST_VERIFY(intVector[17] == 17);\n\n\t\tintVector.erase_unsorted(intVector.rbegin() + 17);\n\t\tEATEST_VERIFY(intVector.validate());\n\t\tEATEST_VERIFY(intVector.size() == 17);\n\t\tEATEST_VERIFY(intVector[0] == 17);\n\t\tEATEST_VERIFY(intVector[8] == 18);\n\t\tEATEST_VERIFY(intVector[16] == 16);\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\tconst int valueToRemove = 44;\n\t\tint testValues[] = {42, 43, 44, 45, 46, 47};\n\n\t\teastl::vector<eastl::unique_ptr<int>> v; \n\t\t\n\t\tfor(auto& te : testValues)\n\t\t\tv.push_back(eastl::make_unique<int>(te));\n\n\t\t// remove 'valueToRemove' from the container\n\t\tauto iterToRemove = eastl::find_if(v.begin(), v.end(), [&](eastl::unique_ptr<int>& e)\n\t\t                                   { return *e == valueToRemove; });\n\t\tv.erase_unsorted(iterToRemove); \n\t\tEATEST_VERIFY(v.size() == 5);\n\n\t\t// verify 'valueToRemove' is no longer in the container\n\t\tEATEST_VERIFY(eastl::find_if(v.begin(), v.end(), [&](eastl::unique_ptr<int>& e)\n\t\t                             { return *e == valueToRemove; }) == v.end());\n\n\t\t// verify all other expected values are in the container\n\t\tfor (auto& te : testValues)\n\t\t{\n\t\t\tif (te == valueToRemove)\n\t\t\t\tcontinue;\n\n\t\t\tEATEST_VERIFY(eastl::find_if(v.begin(), v.end(), [&](eastl::unique_ptr<int>& e)\n\t\t\t                             { return *e == te; }) != v.end());\n\t\t}\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// iterator insert(iterator position, const value_type& value);\n\t\t// iterator insert(iterator position, size_type n, const value_type& value);\n\t\t// iterator insert(iterator position, InputIterator first, InputIterator last);\n\t\t// iterator insert(const_iterator position, std::initializer_list<T> ilist);\n\n\t\tvector<int> v(7, 13);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector\", 13, 13, 13, 13, 13, 13, 13, -1));\n\n\t\t// insert at end of size and capacity.\n\t\tv.insert(v.end(), 99);\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 13, 13, 13, 13, 13, 13, 99, -1));\n\n\t\t// insert at end of size.\n\t\tv.reserve(30);\n\t\tv.insert(v.end(), 999);\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(\n\t\t\tVerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 13, 13, 13, 13, 13, 13, 99, 999, -1));\n\n\t\t// Insert in middle.\n\t\tvector<int>::iterator it = v.begin() + 7;\n\t\tit = v.insert(it, 49);\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(\n\t\t\tVerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 13, 13, 13, 13, 13, 13, 49, 99, 999, -1));\n\n\t\t// Insert multiple copies\n\t\tit = v.insert(v.begin() + 5, 3, 42);\n        EATEST_VERIFY(it == v.begin() + 5);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 13, 13, 13, 13, 42, 42, 42, 13, 13,\n\t\t\t\t\t\t\t\t\t 49, 99, 999, -1));\n\n        // Insert multiple copies with count == 0\n        vector<int>::iterator at = v.end();\n        it = v.insert(at, 0, 666);\n        EATEST_VERIFY(it == at);\n        EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 13, 13, 13, 13, 42, 42, 42, 13, 13,\n                                     49, 99, 999, -1));\n\t\t// Insert iterator range\n\t\tconst int data[] = {2, 3, 4, 5};\n\t\tit = v.insert(v.begin() + 1, data, data + 4);\n        EATEST_VERIFY(it == v.begin() + 1);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,\n\t\t\t\t\t\t\t\t\t 42, 13, 13, 49, 99, 999, -1));\n\n        // Insert empty iterator range\n        at = v.begin() + 1;\n\t\tit = v.insert(at, data + 4, data + 4);\n        EATEST_VERIFY(it == at);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,\n\t\t\t\t\t\t\t\t\t 42, 13, 13, 49, 99, 999, -1));\n\n\t\t// Insert with reallocation\n\t\tit = v.insert(v.end() - 3, 6, 17);\n        EATEST_VERIFY(it == v.end() - (3 + 6));\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,\n\t\t\t\t\t\t\t\t\t 42, 13, 13, 17, 17, 17, 17, 17, 17, 49, 99, 999, -1));\n\n\t\t// Single insert with reallocation\n\t\tvector<int> v2;\n\t\tv2.reserve(100);\n\t\tv2.insert(v2.begin(), 100, 17);\n\t\tEATEST_VERIFY(v2.size() == 100);\n\t\tEATEST_VERIFY(v2[0] == 17);\n\t\tv2.insert(v2.begin() + 50, 42);\n\t\tEATEST_VERIFY(v2.size() == 101);\n\t\tEATEST_VERIFY(v2[50] == 42);\n\n\t\t// Test insertion of values that come from within the vector.\n\t\tv.insert(v.end() - 3, v.end() - 5, v.end());\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,\n\t\t\t\t\t\t\t\t\t 42, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 49, 99, 999, 49, 99, 999, -1));\n\n\t\tv.insert(v.end() - 3, v.back());\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,\n\t\t\t\t\t\t\t\t\t 42, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 49, 99, 999, 999, 49, 99, 999, -1));\n\n\t\tv.insert(v.end() - 3, 2, v[v.size() - 3]);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.insert\", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,\n\t\t\t\t\t\t\t\t\t 42, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 49, 99, 999, 999, 49, 49, 49, 99, 999,\n\t\t\t\t\t\t\t\t\t -1));\n\n#if !defined(EASTL_STD_ITERATOR_CATEGORY_ENABLED) && !defined(EA_COMPILER_NO_STANDARD_CPP_LIBRARY)\n\t\t// std::vector / eastl::vector\n\t\tstd::vector<TestObject> stdV(10);\n\t\teastl::vector<TestObject> eastlV(10);\n\n\t\teastlV.insert(eastlV.end(), stdV.begin(), stdV.end());\n\t\tstdV.insert(stdV.end(), eastlV.begin(), eastlV.end());\n\n\t\tEATEST_VERIFY(eastlV.size() == 20);\n\t\tEATEST_VERIFY(stdV.size() == 30);\n\n\t\t// std::string / eastl::vector\n\t\tstd::string stdString(\"blah\");\n\t\teastl::vector<char8_t> eastlVString;\n\n\t\teastlVString.assign(stdString.begin(), stdString.end());\n#endif\n\n// iterator insert(const_iterator position, std::initializer_list<T> ilist);\n#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)\n\t\t// iterator insert(const_iterator position, std::initializer_list<T> ilist);\n\t\teastl::vector<float> floatVector;\n\n\t\tfloatVector.insert(floatVector.end(), {0, 1, 2, 3});\n\t\tEATEST_VERIFY(floatVector.size() == 4);\n\t\tEATEST_VERIFY((floatVector[0] == 0) && (floatVector[3] == 3));\n#endif\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{\n\t\t// Test insert move objects\n\t\teastl::vector<TestObject> toVector1;\n\t\ttoVector1.reserve(20);\n\t\tfor(int idx = 0; idx < 2; ++idx)\n\t\t\ttoVector1.push_back(TestObject(idx));\n\n\t\teastl::vector<TestObject> toVector2;\n\t\tfor(int idx = 0; idx < 3; ++idx)\n\t\t\ttoVector2.push_back(TestObject(10 + idx));\n\n\t\t// Insert more objects than the existing number using insert with iterator\n\t\tTestObject::Reset();\n        eastl::vector<TestObject>::iterator it;\n\t\tit = toVector1.insert(toVector1.begin(), toVector2.begin(), toVector2.end());\n        EATEST_VERIFY(it == toVector1.begin());\n\t\tEATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), \"vector.insert\", 10, 11, 12, 0, 1, -1));\n\t\tEATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 2 &&\n\t\t\t\t\t  TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 3); // Move 2 existing elements and copy the 3 inserted\n\n\t\teastl::vector<TestObject> toVector3;\n\t\ttoVector3.push_back(TestObject(20));\n\n\t\t// Insert less objects than the existing number using insert with iterator\n\t\tTestObject::Reset();\n\t\tit = toVector1.insert(toVector1.begin(), toVector3.begin(), toVector3.end());\n\t\tEATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), \"vector.insert\", 20, 10, 11, 12, 0, 1, -1));\n        EATEST_VERIFY(it == toVector1.begin());\n\t\tEATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 5 &&\n\t\t\t\t\t  TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 1); // Move 5 existing elements and copy the 1 inserted\n\n\t\t// Insert more objects than the existing number using insert without iterator\n\t\tTestObject::Reset();\n\t\tit = toVector1.insert(toVector1.begin(), 1, TestObject(17));\n        EATEST_VERIFY(it == toVector1.begin());\n\t\tEATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), \"vector.insert\", 17, 20, 10, 11, 12, 0, 1, -1));\n\t\tEATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 6 &&\n\t\t\t\t\t  TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 2); // Move 6 existing element and copy the 1 inserted +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   // the temporary one inside the function\n\n\t\t// Insert less objects than the existing number using insert without iterator\n\t\tTestObject::Reset();\n\t\tit = toVector1.insert(toVector1.begin(), 10, TestObject(18));\n        EATEST_VERIFY(it == toVector1.begin());\n\t\tEATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), \"vector.insert\", 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 20, 10, 11, 12, 0, 1, -1));\n\t\tEATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 7 &&\n\t\t\t\t\t  TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 11); // Move 7 existing element and copy the 10 inserted +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// the temporary one inside the function\n\t}\n\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// reserve / resize / capacity / clear\n\t\tvector<int> v(10, 17);\n\t\tv.reserve(20);\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v.size() == 10);\n\t\tEATEST_VERIFY(v.capacity() == 20);\n\n\t\tv.resize(7);  // Shrink\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v.capacity() == 20);\n\n\t\tv.resize(17);  // Grow without reallocation\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v.capacity() == 20);\n\n\t\tv.resize(42);  // Grow with reallocation\n\t\tvector<int>::size_type c = v.capacity();\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v[41] == 0);\n\t\tEATEST_VERIFY(c >= 42);\n\n\t\tv.resize(44, 19);  // Grow with reallocation\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v[43] == 19);\n\n\t\tc = v.capacity();\n\t\tv.clear();\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v.empty());\n\t\tEATEST_VERIFY(v.capacity() == c);\n\n\t\t// How to shrink a vector's capacity to be equal to its size.\n\t\tvector<int>(v).swap(v);\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v.empty());\n\t\tEATEST_VERIFY(v.capacity() == v.size());\n\n\t\t// How to completely clear a vector (size = 0, capacity = 0, no allocation).\n\t\tvector<int>().swap(v);\n\t\tEATEST_VERIFY(v.validate());\n\t\tEATEST_VERIFY(v.empty());\n\t\tEATEST_VERIFY(v.capacity() == 0);\n\t}\n\n\t{  // set_capacity / reset\n\t\tusing namespace eastl;\n\n\t\tconst int intArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};\n\t\tconst size_t kIntArraySize = sizeof(intArray) / sizeof(int);\n\n\t\tvector<int> v(30);\n\t\tEATEST_VERIFY(v.capacity() >= 30);\n\n\t\tv.assign(intArray, intArray + kIntArraySize);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.assign\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n\t\t\t\t\t\t\t\t\t 13, 14, 15, 16, 17, -1));\n\n\t\t// set_capacity\n\t\tv.set_capacity();\n\t\tEATEST_VERIFY(v.capacity() == v.size());\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.set_capacity\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\n\t\t\t\t\t\t\t\t\t 11, 12, 13, 14, 15, 16, 17, -1));\n\n\t\tv.set_capacity(0);\n\t\tEATEST_VERIFY(v.size() == 0);\n\t\tEATEST_VERIFY(v.data() == NULL);\n\t\tEATEST_VERIFY(v.capacity() == v.size());\n\n\t\t// Test set_capacity doing a realloc of non-scalar class types.\n\t\teastl::vector<TestObject> toArray;\n\t\ttoArray.resize(16);\n\t\ttoArray.set_capacity(64);\n\t\tEATEST_VERIFY(v.validate());\n\n\t\t// reset_lose_memory\n\t\tint* const pData = v.data();\n\t\tvector<int>::size_type n = v.size();\n\t\tvector<int>::allocator_type& allocator = v.get_allocator();\n\t\tv.reset_lose_memory();\n\t\tallocator.deallocate(pData, n);\n\t\tEATEST_VERIFY(v.capacity() == 0);\n\t\tEATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), \"vector.reset\", -1));\n\n\t\t// Test set_capacity make a move when reducing size\n\t\tvector<TestObject> toArray2(10, TestObject(7));\n\t\tTestObject::Reset();\n\t\ttoArray2.set_capacity(5);\n\t\tEATEST_VERIFY(TestObject::sTOMoveCtorCount == 5 &&\n\t\t\t\t\t  TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 0); // Move the 5 existing elements, no copy\n\t\tEATEST_VERIFY(VerifySequence(toArray2.begin(), toArray2.end(), int(), \"vector.set_capacity\", 7, 7, 7, 7, 7, -1));\n\t}\n\n\tTestObject::Reset();\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// Regression for user-reported possible bug.\n\t\t{\n\t\t\tMallocAllocator::reset_all();\n\n\t\t\teastl::vector<int, MallocAllocator> v;\n\t\t\tv.reserve(32);  // does allocation\n\n\t\t\tv.push_back(37);  // may reallocate if we do enough of these to exceed 32\n\t\t\tv.erase(v.begin());\n\n\t\t\tv.set_capacity(0);\n\n\t\t\t// Verify that all memory is freed by the set_capacity function.\n\t\t\tEATEST_VERIFY((MallocAllocator::mAllocCountAll > 0) &&\n\t\t\t\t\t\t  (MallocAllocator::mAllocCountAll == MallocAllocator::mFreeCountAll));\n\n\t\t\tMallocAllocator::reset_all();\n\t\t}\n\n\t\t{\n\t\t\tMallocAllocator::reset_all();\n\n\t\t\teastl::vector<int, MallocAllocator> v;\n\t\t\tv.reserve(32);  // does allocation\n\n\t\t\tfor (int j = 0; j < 40; j++)\n\t\t\t\tv.push_back(37);  // may reallocate if we do enough of these to exceed 32\n\t\t\tfor (int k = 0; k < 40; k++)\n\t\t\t\tv.erase(v.begin());\n\n\t\t\tv.set_capacity(0);\n\n\t\t\t// Verify that all memory is freed by the set_capacity function.\n\t\t\tEATEST_VERIFY((MallocAllocator::mAllocCountAll > 0) &&\n\t\t\t\t\t\t  (MallocAllocator::mAllocCountAll == MallocAllocator::mFreeCountAll));\n\n\t\t\tMallocAllocator::reset_all();\n\t\t}\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// bool validate() const;\n\t\t// bool validate_iterator(const_iterator i) const;\n\n\t\tvector<int> intArray(20);\n\n\t\tEATEST_VERIFY(intArray.validate());\n\t\tEATEST_VERIFY((intArray.validate_iterator(intArray.begin()) & (isf_valid | isf_can_dereference)) != 0);\n\t\tEATEST_VERIFY(intArray.validate_iterator(NULL) == isf_none);\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// global operators (==, !=, <, etc.)\n\t\tvector<int> intArray1(10);\n\t\tvector<int> intArray2(10);\n\n\t\tfor (i = 0; i < intArray1.size(); i++)\n\t\t{\n\t\t\tintArray1[i] = (int)i;  // Make intArray1 equal to intArray2.\n\t\t\tintArray2[i] = (int)i;\n\t\t}\n\n\t\tEATEST_VERIFY((intArray1 == intArray2));\n\t\tEATEST_VERIFY(!(intArray1 != intArray2));\n\t\tEATEST_VERIFY((intArray1 <= intArray2));\n\t\tEATEST_VERIFY((intArray1 >= intArray2));\n\t\tEATEST_VERIFY(!(intArray1 < intArray2));\n\t\tEATEST_VERIFY(!(intArray1 > intArray2));\n\n\t\tintArray1.push_back(100);  // Make intArray1 less than intArray2.\n\t\tintArray2.push_back(101);\n\n\t\tEATEST_VERIFY(!(intArray1 == intArray2));\n\t\tEATEST_VERIFY((intArray1 != intArray2));\n\t\tEATEST_VERIFY((intArray1 <= intArray2));\n\t\tEATEST_VERIFY(!(intArray1 >= intArray2));\n\t\tEATEST_VERIFY((intArray1 < intArray2));\n\t\tEATEST_VERIFY(!(intArray1 > intArray2));\n\t}\n\n\t// three way comparison operator\n#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)\n\t{\n\t\tusing namespace eastl;\n\n\t\tvector<int> intArray1(10);\n\t\tvector<int> intArray2(10);\n\n\t\tfor (i = 0; i < intArray1.size(); i++)\n\t\t{\n\t\t    intArray1[i] = (int)i; // Make intArray1 equal to intArray2.\n\t\t    intArray2[i] = (int)i;\n\t\t}\n\n\t\t// Verify equality between intArray1 and intArray2\n\t\tEATEST_VERIFY((intArray1 <=> intArray2) == 0);\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) != 0));\n\t\tEATEST_VERIFY((intArray1 <=> intArray2) <= 0);\n\t\tEATEST_VERIFY((intArray1 <=> intArray2) >= 0);\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) < 0));\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) > 0));\n\n\t\tintArray1.push_back(100); // Make intArray1 less than intArray2.\n\t\tintArray2.push_back(101);\n\n\t\t// Verify intArray1 < intArray2\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) == 0));\n\t\tEATEST_VERIFY((intArray1 <=> intArray2) != 0);\n\t\tEATEST_VERIFY((intArray1 <=> intArray2) <= 0);\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) >= 0));\n\t\tEATEST_VERIFY(((intArray1 <=> intArray2) < 0));\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) > 0));\n\n\t\tfor (i = 0; i < 3; i++) // Make the length of intArray2 less than intArray1\n\t\t\tintArray2.pop_back();\n\n\t\t// Verify intArray2.size() < intArray1.size() and intArray2 is a subset of intArray1\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) == 0));\n\t\tEATEST_VERIFY((intArray1 <=> intArray2) != 0);\n\t\tEATEST_VERIFY((intArray1 <=> intArray2) >= 0);\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) <= 0));\n\t\tEATEST_VERIFY(((intArray1 <=> intArray2) > 0));\n\t\tEATEST_VERIFY(!((intArray1 <=> intArray2) < 0));\n\t}\n\n\t{\n\t\tusing namespace eastl;\n\n\t\tvector<int> intArray1 = {1, 2, 3, 4, 5, 6, 7};\n\t\tvector<int> intArray2 = {7, 6, 5, 4, 3, 2, 1};\n\t\tvector<int> intArray3 = {1, 2, 3, 4};\n\n\t\tstruct weak_ordering_vector\n\t\t{\n\t\t    vector<int> vec;\n\t\t    inline std::weak_ordering operator<=>(const weak_ordering_vector& b) const { return vec <=> b.vec; }\n\t\t};\n\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray1}, weak_ordering_vector{intArray2}) == std::weak_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray3}, weak_ordering_vector{intArray1}) == std::weak_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray2}, weak_ordering_vector{intArray1}) == std::weak_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray2}, weak_ordering_vector{intArray3}) == std::weak_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray1}, weak_ordering_vector{intArray1}) == std::weak_ordering::equivalent);\n\n\t\tstruct strong_ordering_vector\n\t\t{\n\t\t    vector<int> vec;\n\t\t    inline std::strong_ordering operator<=>(const strong_ordering_vector& b) const { return vec <=> b.vec; }\n\t\t};\n\n\t\tEATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray1}, strong_ordering_vector{intArray2}) == std::strong_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray3}, strong_ordering_vector{intArray1}) == std::strong_ordering::less);\n\t\tEATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray2}, strong_ordering_vector{intArray1}) == std::strong_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray2}, strong_ordering_vector{intArray3}) == std::strong_ordering::greater);\n\t\tEATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray1}, strong_ordering_vector{intArray1}) == std::strong_ordering::equal);\n\t}\n#endif\n\n\t{\n\t\tusing namespace eastl;\n\n\t\t// Test vector<Align64>\n\n\t\t// Aligned objects should be CustomAllocator instead of the default, because the\n\t\t// EASTL default might be unable to do aligned allocations, but CustomAllocator always can.\n\t\tvector<Align64, CustomAllocator> vA64(10);\n\n\t\tvA64.resize(2);\n\t\tEATEST_VERIFY(vA64.size() == 2);\n\n\t\tvA64.push_back(Align64());\n\t\tEATEST_VERIFY(vA64.size() == 3);\n\n\t\tvA64.resize(0);\n\t\tEATEST_VERIFY(vA64.size() == 0);\n\n\t\tvA64.insert(vA64.begin(), Align64());\n\t\tEATEST_VERIFY(vA64.size() == 1);\n\n\t\tvA64.resize(20);\n\t\tEATEST_VERIFY(vA64.size() == 20);\n\t}\n\n\t{\n\t\t// Misc additional tests\n\n\t\teastl::vector<int> empty1;\n\t\tEATEST_VERIFY(empty1.data() == NULL);\n\t\tEATEST_VERIFY(empty1.size() == 0);\n\t\tEATEST_VERIFY(empty1.capacity() == 0);\n\n\t\teastl::vector<int> empty2 = empty1;\n\t\tEATEST_VERIFY(empty2.data() == NULL);\n\t\tEATEST_VERIFY(empty2.size() == 0);\n\t\tEATEST_VERIFY(empty2.capacity() == 0);\n\t}\n\n\t{  // Test whose purpose is to see if calling vector::size() in a const loop results in the compiler optimizing the\n\t\t// size() call to outside the loop.\n\t\teastl::vector<TestObject> toArray;\n\n\t\ttoArray.resize(7);\n\n\t\tfor (i = 0; i < toArray.size(); i++)\n\t\t{\n\t\t\tTestObject& to = toArray[i];\n\n\t\t\tif (to.mX == 99999)\n\t\t\t\tto.mX++;\n\t\t}\n\t}\n\n\t{  // Test assign from iterator type.\n\t\tTestObject to;\n\t\teastl::vector<TestObject> toTest;\n\n\t\t// InputIterator\n\t\tdemoted_iterator<TestObject*, eastl::forward_iterator_tag> toInput(&to);\n\t\ttoTest.assign(toInput, toInput);\n\n\t\t// ForwardIterator\n\t\teastl::slist<TestObject> toSList;\n\t\ttoTest.assign(toSList.begin(), toSList.end());\n\n\t\t// BidirectionalIterator\n\t\teastl::list<TestObject> toList;\n\t\ttoTest.assign(toList.begin(), toList.end());\n\n\t\t// RandomAccessIterator\n\t\teastl::deque<TestObject> toDeque;\n\t\ttoTest.assign(toDeque.begin(), toDeque.end());\n\n\t\t// ContiguousIterator    (note: as of this writing, vector doesn't actually use contiguous_iterator_tag)\n\t\teastl::vector<TestObject> toArray;\n\t\ttoTest.assign(toArray.begin(), toArray.end());\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{  // Test user report that they think they saw code like this leak memory.\n\t\teastl::vector<int> intTest;\n\n\t\tintTest.push_back(1);\n\t\tintTest = eastl::vector<int>();\n\n\t\teastl::vector<TestObject> toTest;\n\n\t\ttoTest.push_back(TestObject(1));\n\t\ttoTest = eastl::vector<TestObject>();\n\t}\n\n\tEATEST_VERIFY(TestObject::IsClear());\n\tTestObject::Reset();\n\n\t{  // Regression to verify that const vector works.\n\t\tconst eastl::vector<int> constIntVector1;\n\t\tEATEST_VERIFY(constIntVector1.empty());\n\n\t\tint intArray[3] = {37, 38, 39};\n\t\tconst eastl::vector<int> constIntVector2(intArray, intArray + 3);\n\t\tEATEST_VERIFY(constIntVector2.size() == 3);\n\n\t\tconst eastl::vector<int> constIntVector3(4, 37);\n\t\tEATEST_VERIFY(constIntVector3.size() == 4);\n\n\t\tconst eastl::vector<int> constIntVector4;\n\t\tconst eastl::vector<int> constIntVector5 = constIntVector4;\n\t}\n\n\t{  // Regression to verify that a bug fix for a vector optimization works.\n\t\teastl::vector<int> intVector1;\n\t\tintVector1.reserve(128);\n\t\tintVector1.resize(128, 37);\n\t\tintVector1.push_back(intVector1.front());\n\t\tEATEST_VERIFY(intVector1.back() == 37);\n\n\t\teastl::vector<int> intVector2;\n\t\tintVector2.reserve(1024);\n\t\tintVector2.resize(1024, 37);\n\t\tintVector2.resize(2048, intVector2.front());\n\t\tEATEST_VERIFY(intVector2.back() == 37);\n\t}\n\n\t{  // C++11 Range\n// EABase 2.00.34+ has EA_COMPILER_NO_RANGE_BASED_FOR_LOOP, which we can check instead.\n#if (defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1700)) ||                                        \\\n\t(defined(__clang__) && (EA_COMPILER_VERSION >= 300) && (__cplusplus >= 201103L)) ||            \\\n\t(defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \\\n\t(__cplusplus >= 201103L)\n\n\t\teastl::vector<float> floatVector;\n\n\t\tfloatVector.push_back(0.0);\n\t\tfloatVector.push_back(1.0);\n\n\t\tfor (auto& f : floatVector)\n\t\t\tf += 1.0;\n\n\t\tEATEST_VERIFY(floatVector.back() == 2.0);\n#endif\n\t}\n\n\t{\n// C++11 cbegin, cend, crbegin, crend\n#if !defined(EA_COMPILER_NO_AUTO)\n\t\t// float vector\n\t\teastl::vector<float> floatVector;\n\n\t\tauto cb = floatVector.cbegin();\n\t\tauto ce = floatVector.cend();\n\t\tauto crb = floatVector.crbegin();\n\t\tauto cre = floatVector.crend();\n\n\t\tEATEST_VERIFY(eastl::distance(cb, ce) == 0);\n\t\tEATEST_VERIFY(eastl::distance(crb, cre) == 0);\n\n\t\t// const float vector\n\t\tconst eastl::vector<float> cFloatVector;\n\n\t\tauto ccb = cFloatVector.cbegin();\n\t\tauto cce = cFloatVector.cend();\n\t\tauto ccrb = cFloatVector.crbegin();\n\t\tauto ccre = cFloatVector.crend();\n\n\t\tEATEST_VERIFY(eastl::distance(ccb, cce) == 0);\n\t\tEATEST_VERIFY(eastl::distance(ccrb, ccre) == 0);\n\n#endif\n\t}\n\n\t{\n\t\t// Regression for failure in DoRealloc's use of uninitialize_move.\n\t\tusing namespace eastl;\n\n\t\tconst eastl::string str0 = \"TestString0\";\n\t\tvector<eastl::string> v(1, str0);\n\t\tvector<eastl::string> v_copy;\n\n\t\t// Test operator=\n\t\tv_copy = v;\n\t\tEATEST_VERIFY_MSG(v_copy.size() == 1, \"vector string8 copy size\");\n\t\tEATEST_VERIFY_MSG(eastl::find(v_copy.begin(), v_copy.end(), str0) != v_copy.end(), \"vector copy string8\");\n\t\tEATEST_VERIFY_MSG(v.size() == 1, \"vector string8 copy size\");\n\t\tEATEST_VERIFY_MSG(eastl::find(v.begin(), v.end(), str0) != v.end(), \"vector copy string8\");\n\n\t\t// Test assign.\n\t\tv.clear();\n\t\tv.push_back(str0);\n\t\tv_copy.assign(v.begin(), v.end());\n\t\tEATEST_VERIFY_MSG(v_copy.size() == 1, \"vector string8 copy size\");\n\t\tEATEST_VERIFY_MSG(eastl::find(v_copy.begin(), v_copy.end(), str0) != v_copy.end(), \"vector copy string8\");\n\t\tEATEST_VERIFY_MSG(v.size() == 1, \"vector string8 copy size\");\n\t\tEATEST_VERIFY_MSG(eastl::find(v.begin(), v.end(), str0) != v.end(), \"vector copy string8\");\n\t}\n\n\t{\n\t\t// Regression of vector::operator= for the case of EASTL_ALLOCATOR_COPY_ENABLED=1\n\t\t// For this test we need to use InstanceAllocator to create two containers of the same\n\t\t// type but with different and unequal allocator instances. The bug was that when\n\t\t// EASTL_ALLOCATOR_COPY_ENABLED was enabled operator=(this_type& x) assigned x.mAllocator\n\t\t// to this and then proceeded to assign member elements from x to this. That's invalid\n\t\t// because the existing elements of this were allocated by a different allocator and\n\t\t// will be freed in the future with the allocator copied from x.\n\t\t// The test below should work for the case of EASTL_ALLOCATOR_COPY_ENABLED == 0 or 1.\n\t\t{\n\t\t\tInstanceAllocator ia0((uint8_t)0);\n\t\t\tInstanceAllocator ia1((uint8_t)1);\n\n\t\t\teastl::vector<int, InstanceAllocator> v0((eastl_size_t)1, (int)0, ia0);\n\t\t\teastl::vector<int, InstanceAllocator> v1((eastl_size_t)1, (int)1, ia1);\n\n\t\t\tEATEST_VERIFY((v0.front() == 0) && (v1.front() == 1));\n\t\t\tEATEST_VERIFY(v0.get_allocator() != v1.get_allocator());\n\t\t\tv0 = v1;\n\t\t\tEATEST_VERIFY((v0.front() == 1) && (v1.front() == 1));\n\t\t\tEATEST_VERIFY(InstanceAllocator::mMismatchCount == 0);\n\t\t\tEATEST_VERIFY(v0.validate());\n\t\t\tEATEST_VERIFY(v1.validate());\n\t\t\tbool allocatorsEqual = (v0.get_allocator() == v1.get_allocator());\n\t\t\tEATEST_VERIFY(allocatorsEqual == (bool)EASTL_ALLOCATOR_COPY_ENABLED);\n\n\t\t\t// destroying containers to invoke InstanceAllocator::deallocate() checks\n\t\t}\n\n\t\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t\t                  \"Container elements should be deallocated by the allocator that allocated it.\");\n\t}\n\n\t{\n\t\t// Test shrink_to_fit\n\t\teastl::vector<int> v;\n\t\tEATEST_VERIFY(v.capacity() == 0);\n\t\tv.resize(100);\n\t\tEATEST_VERIFY(v.capacity() == 100);\n\t\tv.clear();\n\t\tEATEST_VERIFY(v.capacity() == 100);\n\t\tv.shrink_to_fit();\n\t\tEATEST_VERIFY(v.capacity() == 0);\n\t}\n\n\t{\n\t\t// Regression for compilation errors found and fixed when integrating into Frostbite.\n\t\tint j = 7;\n\n\t\teastl::vector<StructWithConstInt> v1;\n\t\tv1.push_back(StructWithConstInt(j));\n\n\t\teastl::vector<StructWithConstRefToInt> v2;\n\t\tv2.push_back(StructWithConstRefToInt(j));\n\t}\n\n\t{\n\t\t// Regression for issue with vector containing non-copyable values reported by user\n\t\teastl::vector<testmovable> moveablevec;\n\t\ttestmovable moveable;\n\t\tmoveablevec.insert(moveablevec.end(), eastl::move(moveable));\n\t}\n\n\t{\n\t\t// Calling erase of empty range should not call a move assignment to self\n\t\teastl::vector<TestMoveAssignToSelf> v1;\n\t\tv1.push_back(TestMoveAssignToSelf());\n\t\tEATEST_VERIFY(!v1[0].mMovedToSelf);\n\t\tv1.erase(v1.begin(), v1.begin());\n\t\tEATEST_VERIFY(!v1[0].mMovedToSelf);\n\t}\n\n#if defined(EASTL_TEST_CONCEPT_IMPLS)\n\t{\n\t\t// vector default constructor should require no more than Destructible\n\t\teastl::vector<Destructible> v1;\n\t\tEATEST_VERIFY(v1.empty());\n\n\t\t// some basic vector operations (data(), capacity(), size(), empty(), clear(), erase()) should impose no\n\t\t// requirements beyond Destructible\n\t\tEATEST_VERIFY(v1.empty());\n\t\tEATEST_VERIFY(v1.size() == 0);\n\t\tEATEST_VERIFY(v1.capacity() == 0);\n\t\tEATEST_VERIFY(eastl::distance(v1.data(), v1.data() + v1.size()) == 0);\n\t\tv1.clear();\n\t}\n\n\t{\n\t\t// vector default constructor should work with DefaultConstructible T\n\t\teastl::vector<DefaultConstructible> v1;\n\t\tEATEST_VERIFY(v1.empty());\n\t}\n\n\t{\n\t\t// vector constructor that takes an initial size should only require DefaultConstructible T\n\t\teastl::vector<DefaultConstructible> v2(2);\n\t\tEATEST_VERIFY(v2.size() == 2 && v2[0].value == v2[1].value &&\n\t\t\t\t\t  v2[0].value == DefaultConstructible::defaultValue);\n\t}\n\n\t{\n\t\t// vector constructor taking an initial size and a value should only require CopyConstructible\n\t\teastl::vector<CopyConstructible> v3(2, CopyConstructible::Create());\n\t\tEATEST_VERIFY(v3.size() == 2 && v3[0].value == v3[1].value && v3[0].value == CopyConstructible::defaultValue);\n\n\t\t// vector constructor taking a pair of iterators should work for CopyConstructible\n\t\teastl::vector<CopyConstructible> v4(cbegin(v3), cend(v3));\n\t\tEATEST_VERIFY(v4.size() == 2 && v4[0].value == v4[1].value && v4[0].value == CopyConstructible::defaultValue);\n\t}\n\n\t{\n\t\t// vector::reserve() should only require MoveInsertible\n\t\teastl::vector<MoveConstructible> v5;\n\t\tv5.reserve(2);\n\t\tv5.push_back(MoveConstructible::Create());\n\t\tv5.push_back(MoveConstructible::Create());\n\t\tEATEST_VERIFY(v5.size() == 2 && v5[0].value == v5[1].value && v5[0].value == MoveConstructible::defaultValue);\n\t\tv5.pop_back();\n\n\t\t// vector::shrink_to_fit() should only require MoveInsertible\n\t\tv5.shrink_to_fit();\n\t\tEATEST_VERIFY(v5.size() == 1 && v5.capacity() == 1 && v5[0].value == MoveConstructible::defaultValue);\n\t}\n\n\t{\n\t\t// vector constructor taking a pair of iterators should only require MoveConstructible\n\t\tMoveConstructible moveConstructibleArray[] = {MoveConstructible::Create()};\n\t\teastl::vector<MoveConstructible> v7(\n\t\t\teastl::move_iterator<MoveConstructible*>(eastl::begin(moveConstructibleArray)),\n\t\t\teastl::move_iterator<MoveConstructible*>(eastl::end(moveConstructibleArray)));\n\t\tEATEST_VERIFY(v7.size() == 1 && v7[0].value == MoveConstructible::defaultValue);\n\t}\n\n\t{\n\t\t// vector::swap() should only require Destructible. We also test with DefaultConstructible as it gives us a\n\t\t// testable result.\n\n\t\teastl::vector<Destructible> v4, v5;\n\t\teastl::swap(v4, v5);\n\t\tEATEST_VERIFY(v4.empty() && v5.empty());\n\n\t\teastl::vector<DefaultConstructible> v6(1), v7(2);\n\t\teastl::swap(v6, v7);\n\t\tEATEST_VERIFY(v6.size() == 2 && v7.size() == 1);\n\t}\n\n\t{\n\t\t// vector::resize() should only require MoveInsertable and DefaultInsertable\n\t\teastl::vector<MoveAndDefaultConstructible> v8;\n\t\tv8.resize(2);\n\t\tEATEST_VERIFY(v8.size() == 2 && v8[0].value == v8[1].value && v8[0].value ==\n\t\tMoveAndDefaultConstructible::defaultValue);\n\t}\n\n\t{\n\t\teastl::vector<MoveAssignable> v1;\n\t\t// vector::insert(pos, rv) should only require MoveAssignable\n\t\tv1.insert(begin(v1), MoveAssignable::Create());\n\t\tEATEST_VERIFY(v1.size() == 1 && v1.front().value == MoveAssignable::defaultValue);\n\t\t// vector::erase(pos) should only require MoveAssignable\n\t\tv1.erase(begin(v1));\n\t\tEATEST_VERIFY(v1.empty());\n\t}\n#endif // EASTL_TEST_CONCEPT_IMPLS\n\n\t{\n\t\t// validates our vector implementation does not use 'operator<' on input iterators during vector construction.\n\t\t//\n\t\tstruct container_value_type { int data; };\n\t\tstruct container_with_custom_iterator\n\t\t{\n\t\t\tstruct iterator\n\t\t\t{\n\t\t\t\ttypedef eastl::input_iterator_tag iterator_category;\n\t\t\t\ttypedef int value_type;\n\t\t\t\ttypedef ptrdiff_t difference_type;\n\t\t\t\ttypedef int* pointer;\n\t\t\t\ttypedef int& reference;\n\n\t\t\t\tbool operator!=(const iterator&) const { return false; }\n\t\t\t\titerator& operator++()                 { return *this; }\n\t\t\t\titerator operator++(int)               { return *this; }\n\t\t\t\tcontainer_value_type operator*()       { return {};    }\n\t\t\t};\n\n\t\t\tcontainer_with_custom_iterator() EA_NOEXCEPT {}\n\n\t\t\titerator begin() const { return {}; }\n\t\t\titerator end() const   { return {}; }\n\t\t\tbool empty() const     { return false; }\n\n\t\tprivate:\n\t\t\teastl::vector<container_value_type> m_vector;\n\t\t};\n\n\t\tstatic_assert(!is_less_comparable<container_with_custom_iterator::iterator>::value, \"type cannot support comparison by '<' for this test\");\n\t\tcontainer_with_custom_iterator ci;\n\t\teastl::vector<container_value_type> v2(ci.begin(), ci.end()); \n\t}\n\n\t// If the legacy code path is enabled we cannot handle non-copyable types\n\t#ifndef EASTL_VECTOR_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR \n\t\t// unique_ptr tests\n\t\t{\n\t\t\t// Simple move-assignment test to prevent regressions where eastl::vector utilizes operations on T that are not necessary.\n\t\t\t{\n\t\t\t\teastl::vector<eastl::unique_ptr<int>> v1;\n\t\t\t\teastl::vector<eastl::unique_ptr<int>> v2;\n\t\t\t\tv2 = eastl::move(v1);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t// This test verifies that eastl::vector can handle the move-assignment case where its utilizes two\n\t\t\t\t// different allocator instances that do not compare equal.  An example of an allocator that compares equal\n\t\t\t\t// but isn't the same object instance is an allocator that shares the same memory allocation mechanism (eg.\n\t\t\t\t// malloc).  The memory allocated from one instance can be freed by another instance in the case where\n\t\t\t\t// allocators compare equal.  This test is verifying functionality in the opposite case where allocators\n\t\t\t\t// instances do not compare equal and must clean up its own allocated memory.\n\t\t\t\t{\n\t\t\t\t\tInstanceAllocator a1(uint8_t(0)), a2(uint8_t(1));\n\t\t\t\t\teastl::vector<eastl::unique_ptr<int>, InstanceAllocator> v1(a1);\n\t\t\t\t\teastl::vector<eastl::unique_ptr<int>, InstanceAllocator> v2(a2);\n\n\t\t\t\t\tVERIFY(v1.get_allocator() != v2.get_allocator());\n\n\t\t\t\t\t// add some data in the vector so we can move it to the other vector.\n\t\t\t\t\tv1.push_back(nullptr);\n\t\t\t\t\tv1.push_back(nullptr);\n\t\t\t\t\tv1.push_back(nullptr);\n\t\t\t\t\tv1.push_back(nullptr);\n\n\t\t\t\t\tVERIFY(!v1.empty() && v2.empty());\n\t\t\t\t\tv2 = eastl::move(v1);\n\t\t\t\t\tVERIFY(v1.empty() && !v2.empty());\n\t\t\t\t\tv1.swap(v2); \n\t\t\t\t\tVERIFY(!v1.empty() && v2.empty());\n\n\t\t\t\t\t// destroying containers to invoke InstanceAllocator::deallocate() checks\n\t\t\t\t}\n\n\t\t\t\tEATEST_VERIFY_MSG(InstanceAllocator::reset_all(),\n\t                              \"Container elements should be deallocated by the allocator that allocated it.\");\n\t\t\t}\n\t\t}\n\t#endif\n\n\t{\n\t\t// CustomAllocator has no data members which reduces the size of an eastl::vector via the empty base class optimization.\n\t\ttypedef eastl::vector<int, CustomAllocator> EboVector;\n\t\tstatic_assert(sizeof(EboVector) == 3 * sizeof(void*), \"\");\n\t}\n\n\t// eastl::erase / eastl::erase_if tests\n\t{\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n\t\t\tauto numErased = eastl::erase(v, 5);\n\t\t\tVERIFY((v == eastl::vector<int> {1, 2, 3, 4, 6, 7, 8, 9}));\n\t\t\tVERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(v, 2);\n\t\t\tVERIFY((v == eastl::vector<int> {1, 3, 4, 6, 7, 8, 9}));\n\t\t\tVERIFY(numErased == 1);\n\n\t\t\tnumErased = eastl::erase(v, 9);\n\t\t\tVERIFY((v == eastl::vector<int> {1, 3, 4, 6, 7, 8}));\n\t\t\tVERIFY(numErased == 1);\n\t\t}\n\n\t\t{\n\t\t\teastl::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tauto numErased = eastl::erase_if(v, [](auto i) { return i % 2 == 0; });\n\t\t\tVERIFY((v == eastl::vector<int>{1, 3, 5, 7, 9}));\n\t\t\tVERIFY(numErased == 4);\n\t\t}\n\t}\n\n\t// Tests for erase_unordered\n\t{\n\t\t{\n\t\t\teastl::vector<int> vec = {0, 1, 2, 3};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 1);\n\t\t\tEATEST_VERIFY(numErased == 1);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 3, 2}, \"erase_unordered\") );\n\t\t}\n\t\t{\n\t\t\teastl::vector<int> vec = {};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 42);\n\t\t\tEATEST_VERIFY(numErased == 0);\n\t\t\tEATEST_VERIFY(vec.size() == 0);\n\t\t}\n\t\t// The following test checks that the correct implementation is called for vector by checking the order\n\t\t// of the remaining values. It is not a strict requirement that they have this order but it\n\t\t// is expected to be the result based on that it minimizes the amount of work.\n\t\t{\n\t\t\teastl::vector<int> vec = {0, 1, 2, 3, 1, 5, 6, 1, 8, 9};\n\t\t\tauto numErased = eastl::erase_unsorted(vec, 1);\n\t\t\tEATEST_VERIFY(numErased == 3);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 9, 2, 3, 8, 5, 6}, \"erase_unordered\") );\n\t\t}\n\t}\n\n\t// Tests for erase_unordered_if\n\t{\n\t\t{\n\t\t\teastl::vector<int> vec = {0, 1, 2, 3};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 2);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 2}, \"erase_unordered_if\") );\n\t\t}\n\t\t{\n\t\t\teastl::vector<int> vec = {};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 0);\n\t\t\tEATEST_VERIFY(vec.size() == 0);\n\t\t}\n\t\t// The following test checks that the correct implementation is called for vector by checking the order\n\t\t// of the remaining values. It is not a strict requirement that they have this order but it\n\t\t// is expected to be the result based on that it minimizes the amount of work.\n\t\t{\n\t\t\teastl::vector<int> vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\t\t\tauto numErased = eastl::erase_unsorted_if(vec, [](const int& v) { return v % 2 == 1; });\n\t\t\tEATEST_VERIFY(numErased == 5);\n\t\t\tEATEST_VERIFY(VerifySequence(vec, {0, 8, 2, 6, 4}, \"erase_unordered_if\") );\n\t\t}\n\t}\n\n// This test takes a while to run and even longer in debug builds, so for now we only do it in\n// on demand, you can define EASTL_TEST_VERY_BIG_VECTORS to enable the test.\n// This test will crash if the platform cannot allocate enough memory.\n#if defined(EASTL_TEST_VERY_BIG_VECTORS)\n    // Test we support very large vectors.\n    {\n\t    {\n\t\t    const uint32_t kMax = eastl::numeric_limits<uint32_t>::max();\n\t\t    eastl::vector<uint32_t> v;\n\t\t    v.reserve(kMax/2+1); // avoid some reallocations, but test that push_back() won't cause vector::GetNewCapacity() to overflow when we exceed the capacity.\n\t\t    for (uint32_t index{0}; index < kMax; ++index)\n\t\t    {\n\t\t\t    v.push_back(index);\n\t\t    }\n\t\t    EATEST_VERIFY(v.size() == kMax);\n\t\t    for (uint32_t index{0}; index < kMax; ++index)\n\t\t    {\n\t\t\t    EATEST_VERIFY(v[index] == index);\n\t\t    }\n\t    }\n\t    {\n\t\t\tconst uint32_t kMaxForPushBack = eastl::numeric_limits<uint32_t>::max();\n\t\t    eastl::vector<uint32_t> v;\n\t\t    for (uint32_t index{0}; index < kMaxForPushBack; ++index)\n\t\t    {\n\t\t\t    // Do it the \"slow growth\" way, i.e. without reserve()\n\t\t\t    v.push_back(index);\n\t\t    }\n\t\t    EATEST_VERIFY(v.size() == kMaxForPushBack);\n\t\t    for (uint32_t index{0}; index < kMaxForPushBack; ++index)\n\t\t    {\n\t\t\t    EATEST_VERIFY(v[index] == index);\n\t\t    }\n\t    }\n    }\n#endif\n\n    // test emplace() with an element from the vector.\n    {\n\t    const char* const str = \"example\";\n\t    eastl::vector<eastl::string> v;\n\t    v.push_back(str);\n\t    EATEST_VERIFY(v.size() == v.capacity()); // emplace() will cause existing elements to be moved.\n\t    v.emplace(v.end(), v.back());\n\n\t    VerifySequence(v, {str, str}, \"emplace() must be able to push elements from self.\");\n    }\n\n    // test push_back() with an element from the vector.\n    {\n\t    const char* const str = \"example\";\n\t    eastl::vector<eastl::string> v;\n\t    v.push_back(str);\n\t    EATEST_VERIFY(v.size() == v.capacity()); // push_back() will cause existing elements to be moved.\n\t    v.push_back(v.back());\n\n\t    VerifySequence(v, {str, str}, \"push_back() must be able to push elements from self.\");\n    }\n\n#if EASTL_EXCEPTIONS_ENABLED\n    // test constructors & destructors called appropriate when exception thrown during modification.\n    EATEST_VERIFY(TestObject::Reset());\n\n    // emplace_back() - constructing the new element throws\n    {\n\t    eastl::vector<TestObject> v;\n\t    v.push_back(TestObject{});\n\t    EATEST_VERIFY_THROW(v.emplace_back(TestObject::throw_on_construct));\n    }\n    EATEST_VERIFY(TestObject::Reset());\n\n    // push_back() - move constructing an element already in the container throws and capacity is exhausted.\n    {\n\t    eastl::vector<TestObject> v;\n\t    v.push_back(TestObject{});\n\t    v.back().mbThrowOnCopy = true; // throw during construction of new element, from an element within the vector.\n\t    EATEST_VERIFY(v.size() == v.capacity()); // push_back() will cause existing elements to be moved.\n\t    EATEST_VERIFY_THROW(v.push_back(TestObject{}));\n    }\n    EATEST_VERIFY(TestObject::Reset());\n\n#endif\n\n    return nErrorCount;\n}\n"
  },
  {
    "path": "test/source/TestVectorMap.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n#include \"TestMap.h\"\n#include \"EASTLTest.h\"\n#include <EASTL/vector_map.h>\n#include <EASTL/vector_multimap.h>\n#include <EASTL/vector.h>\n#include <EASTL/deque.h>\n#include <EASTL/string.h>\n#include <EASTL/fixed_string.h>\n#include <EASTL/fixed_vector.h>\n#include <EASTL/utility.h>\n#include \"TestAssociativeContainers.h\"\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <map>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::vector_map<int, int>;\ntemplate class eastl::vector_multimap<float, int>;\ntemplate class eastl::vector_map<TestObject, TestObject>;\ntemplate class eastl::vector_multimap<TestObject, TestObject>;\n\n\n///////////////////////////////////////////////////////////////////////////////\n// typedefs\n//\ntypedef eastl::vector_map<int, int> VM1;\ntypedef eastl::vector_map<int, int, eastl::less<int>, EASTLAllocatorType, eastl::deque<eastl::pair<int, int> > > VM2;\n\ntypedef eastl::vector_map<TestObject, TestObject> VM4;\ntypedef eastl::vector_map<TestObject, TestObject, eastl::less<TestObject>, EASTLAllocatorType, eastl::deque<eastl::pair<TestObject, TestObject> > > VM5;\n\nstatic_assert(sizeof(eastl::vector_map<int, int>) == sizeof(eastl::vector<int>), \"if is_empty_v<Compare>, sizeof(vector_map) == sizeof(RandomAccessContainer)\");\nstatic_assert(sizeof(eastl::vector_map<double, double>) == sizeof(eastl::vector<double>), \"if is_empty_v<Compare>, sizeof(vector_map) == sizeof(RandomAccessContainer)\");\n\ntypedef eastl::vector_multimap<int, int> VMM1;\ntypedef eastl::vector_multimap<int, int, eastl::less<int>, EASTLAllocatorType, eastl::deque<eastl::pair<int, int> > > VMM2;\n\ntypedef eastl::vector_multimap<TestObject, TestObject> VMM4;\ntypedef eastl::vector_multimap<TestObject, TestObject, eastl::less<TestObject>, EASTLAllocatorType, eastl::deque<eastl::pair<TestObject, TestObject> > > VMM5;\n\nstatic_assert(sizeof(eastl::vector_multimap<int, int>) == sizeof(eastl::vector<eastl::pair<int, int>>), \"if is_empty_v<Compare>, sizeof(vector_multimap) == sizeof(RandomAccessContainer)\");\nstatic_assert(sizeof(eastl::vector_multimap<TestObject, TestObject>) == sizeof(eastl::vector<eastl::pair<TestObject, TestObject>>), \"if is_empty_v<Compare>, sizeof(vector_multimap) == sizeof(RandomAccessContainer)\");\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\ttypedef std::map<int, int> VM3;\n\ttypedef std::map<TestObject, TestObject> VM6;\n\ttypedef std::multimap<int, int> VMM3;\n\ttypedef std::multimap<TestObject, TestObject> VMM6;\n#endif\n///////////////////////////////////////////////////////////////////////////////\n\ntemplate <typename T1>\nint TestVectorMapAtKey()\n{\n\tint nErrorCount = 0;\n\n\ttypedef T1 TOMap;\n\ttypedef typename TOMap::key_type key_type;\n\ttypedef typename TOMap::mapped_type mapped_type;\n\n\tTOMap map1;\n\tmap1[key_type(1)] = mapped_type(1);\n\tmap1[key_type(3)] = mapped_type(3);\n\tmap1[key_type(0)] = mapped_type(1);\n\tEATEST_VERIFY(map1.at_key(key_type(0)) == mapped_type(1));\n\tEATEST_VERIFY(map1.at_key(key_type(1)) == mapped_type(1));\n\tEATEST_VERIFY(map1.at_key(key_type(3)) == mapped_type(3));\n\n\treturn nErrorCount;\n}\n\nint TestVectorMap()\n{\n\tint nErrorCount = 0;\n\n\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t{   // Test construction\n\t\t\tnErrorCount += TestMapConstruction<VM1, VM3, false>();\n\t\t\tnErrorCount += TestMapConstruction<VM2, VM3, false>();\n\t\t\tnErrorCount += TestMapConstruction<VM4, VM6, false>();\n\t\t\tnErrorCount += TestMapConstruction<VM5, VM6, false>();\n\t\t\tnErrorCount += TestMapConstruction<eastl::vector_map<int, int, eastl::less<void>>, std::map<int, int>, false>();\n\n\t\t\tnErrorCount += TestMapConstruction<VMM1, VMM3, true>();\n\t\t\tnErrorCount += TestMapConstruction<VMM2, VMM3, true>();\n\t\t\tnErrorCount += TestMapConstruction<VMM4, VMM6, true>();\n\t\t\tnErrorCount += TestMapConstruction<VMM5, VMM6, true>();\n\t\t\tnErrorCount += TestMapConstruction<eastl::vector_multimap<int, int, eastl::less<void>>, std::multimap<int, int>, true>();\n\t\t}\n\n\n\t\t{   // Test mutating functionality.\n\t\t\tnErrorCount += TestMapMutation<VM1, VM3, false>();\n\t\t\tnErrorCount += TestMapMutation<VM2, VM3, false>();\n\t\t\tnErrorCount += TestMapMutation<VM4, VM6, false>();\n\t\t\tnErrorCount += TestMapMutation<VM5, VM6, false>();\n\t\t\tnErrorCount += TestMapMutation<eastl::vector_map<int, int, eastl::less<void>>, std::map<int, int>, false>();\n\n\t\t\tnErrorCount += TestMapMutation<VMM1, VMM3, true>();\n\t\t\tnErrorCount += TestMapMutation<VMM2, VMM3, true>();\n\t\t\tnErrorCount += TestMapMutation<VMM4, VMM6, true>();\n\t\t\tnErrorCount += TestMapMutation<VMM5, VMM6, true>();\n\t\t\tnErrorCount += TestMapMutation<eastl::vector_multimap<int, int, eastl::less<void>>, std::multimap<int, int>, true>();\n\t\t}\n\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n\t{   // Test search functionality.\n\t\tnErrorCount += TestMapSearch<VM1, false>();\n\t\tnErrorCount += TestMapSearch<VM2, false>();\n\t\tnErrorCount += TestMapSearch<VM4, false>();\n\t\tnErrorCount += TestMapSearch<VM5, false>();\n\t\tnErrorCount += TestMapSearch<eastl::vector_map<int, int, eastl::less<void>>, false>();\n\n\t\tnErrorCount += TestMapSearch<VMM1, true>();\n\t\tnErrorCount += TestMapSearch<VMM2, true>();\n\t\tnErrorCount += TestMapSearch<VMM4, true>();\n\t\tnErrorCount += TestMapSearch<VMM5, true>();\n\t\tnErrorCount += TestMapSearch<eastl::vector_multimap<int, int, eastl::less<void>>, true>();\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestMapCpp11<eastl::vector_map<int, TestObject> >();\n\t\tnErrorCount += TestMapCpp11<eastl::vector_map<int, TestObject, eastl::less<int>, EASTLAllocatorType, eastl::deque<eastl::pair<int, TestObject> > > >();\n\t\tnErrorCount += TestMapCpp11<eastl::vector_map<int, TestObject, eastl::less<void>>>();\n\n\t\tnErrorCount += TestMultimapCpp11<eastl::vector_multimap<int, TestObject> >();\n\t\tnErrorCount += TestMultimapCpp11<eastl::vector_multimap<int, TestObject, eastl::less<int>, EASTLAllocatorType, eastl::deque<eastl::pair<int, TestObject> > > >();\n\t\tnErrorCount += TestMultimapCpp11<eastl::vector_multimap<int, TestObject, eastl::less<void>> >();\n\t}\n\n\t{\n\t\t// Tests for element access: operator[] and at()\n\t\t\n\t\t// todo: can't enable these tests until the current at() function is removed (which gets by index rather than by key) and we can replace with a semanticly correct one.\n\t\t\n\t\t//nErrorCount += TestMapAccess<VM1>();\n\t\t//nErrorCount += TestMapAccess<VM2>();\n\t\t//nErrorCount += TestMapAccess<VM4>();\n\t\t//nErrorCount += TestMapAccess<VM5>();\n\t\t//nErrorCount += TestMapHeterogeneousAccess<eastl::vector_map<ExplicitString, int, eastl::less<void>>>();\n\t\t \n\t\tnErrorCount += TestVectorMapAtKey<VM1>();\n\t\tnErrorCount += TestVectorMapAtKey<VM2>();\n\t\tnErrorCount += TestVectorMapAtKey<VM4>();\n\t\tnErrorCount += TestVectorMapAtKey<VM5>();\n\t\tnErrorCount += TestVectorMapAtKey<eastl::vector_map<int, TestObject, eastl::less<void>>>();\n\t}\n\n    {\n        // insert at the upper bound of a range\n        VMM1 vmm = {{0, 0}};\n        VERIFY(vmm.emplace(0, 0) != vmm.begin());\n    }\n\n\n\t{ // Misc tests\n\n\t\t// const key_compare& key_comp() const;\n\t\t// key_compare&       key_comp();\n\t\tVM2       vm;\n\t\tconst VM2 vmc;\n\n\t\tconst VM2::key_compare& kc = vmc.key_comp();\n\t\tvm.key_comp() = kc;\n\n\t\t// ensure count can be called from a const object\n\t\tvmc.count(0);\n\t}\n\n\t{\n\t\tconst VMM1 vmm;\n\n\t\t// ensure count can be called from a const object\n\t\tvmm.count(0);\n\t}\n\n\t{\n\t\t// Misc testing\n\t\ttypedef eastl::fixed_vector<eastl::pair<int, float>, 8> FV;\n\t\ttypedef eastl::vector_map<int, float, eastl::less<int>, FV::allocator_type, FV> FixedVectorMap;\n\n\t\tFixedVectorMap fvm;\n\n\t\tfor(int i = FV::kMaxSize - 1; i >= 0; i--)\n\t\t\tfvm.insert(eastl::pair<int, float>(i, (float)i));\n\n\t\tFixedVectorMap::iterator it = fvm.find(3);\n\t\tEATEST_VERIFY(it != fvm.end());\n\t}\n\n\t{\n\t\t// Misc testing\n\t\ttypedef eastl::fixed_string<char, 16>   KeyStringType;\n\t\ttypedef eastl::fixed_string<char, 24>   ValueStringType;\n\t\ttypedef eastl::pair<ValueStringType, bool> StringMapValueType;\n\n\t\ttypedef eastl::vector_map<KeyStringType, StringMapValueType> StringMapType;\n\t\tStringMapType stringMap;\n\n\t\tstringMap.reserve(20);\n\t\tEATEST_VERIFY(stringMap.capacity() == 20);\n\n\t\tStringMapValueType& v1 = stringMap[\"abc\"];\n\t\tEATEST_VERIFY(strlen(v1.first.c_str()) == 0);\n\t\tv1.first.clear();\n\t\tEATEST_VERIFY(strlen(v1.first.c_str()) == 0);\n\n\t\tStringMapValueType& v2 = stringMap[\"def\"];\n\t\tEATEST_VERIFY(strlen(v2.first.c_str()) == 0);\n\t\tv2.first = \"def\";\n\t\tEATEST_VERIFY(strlen(v2.first.c_str()) == 3);\n\t}\n\n\t{\n\t\t// Regression for problem observed in EAWebKit\n\t\ttypedef eastl::vector_map<eastl::string, void*> TestVectorMap;\n\n\t\tTestVectorMap tvm;\n\n\t\ttvm[\"Parameters\"]      = NULL;\n\t\ttvm[\"ThemeParameters\"] = NULL; \n\t\ttvm[\"CookieInfo\"]      = NULL; \n\t\ttvm[\"DiskCacheInfo\"]   = NULL; \n\t\ttvm[\"RamCacheInfo\"]    = NULL;\n\t\ttvm[\"SSLCert\"]         = NULL;\n\t\ttvm[\"AllowedDomain\"]   = NULL;\n\t}\n\n\t{     // find / find_as / lower_bound / upper_bound\n\t\t{ // vector_map\n\t\t\teastl::vector_map<string, int> vss = {{\"abc\", 11},   {\"def\", 22}, {\"ghi\", 33}, {\"jklmnop\", 44},\n\t\t\t\t\t\t\t\t\t\t\t\t  {\"qrstu\", 55}, {\"vw\", 66},  {\"x\", 77},   {\"yz\", 88}};\n\t\t\tVERIFY(vss.find(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t\tVERIFY(vss.lower_bound(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.upper_bound(\"ghi\") != vss.end());\n\t\t}\n\n\t\t{ // const vector_map\n\t\t\tconst eastl::vector_map<string, int> vss = {{\"abc\", 11},   {\"def\", 22}, {\"ghi\", 33}, {\"jklmnop\", 44},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\"qrstu\", 55}, {\"vw\", 66},  {\"x\", 77},   {\"yz\", 88}};\n\t\t\tVERIFY(vss.find(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t\tVERIFY(vss.lower_bound(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.upper_bound(\"ghi\") != vss.end());\n\t\t}\n\n\t\t// vector_multimap\n\t\t{\n\t\t\teastl::vector_multimap<string, int> vss = {{\"abc\", 11},   {\"def\", 22}, {\"ghi\", 33}, {\"jklmnop\", 44},\n\t\t\t\t\t\t\t\t\t\t\t\t\t   {\"qrstu\", 55}, {\"vw\", 66},  {\"x\", 77},   {\"yz\", 88}};\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t}\n\n\t\t// const vector_multimap\n\t\t{\n\t\t\tconst eastl::vector_multimap<string, int> vss = {{\"abc\", 11},   {\"def\", 22}, {\"ghi\", 33}, {\"jklmnop\", 44},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t {\"qrstu\", 55}, {\"vw\", 66},  {\"x\", 77},   {\"yz\", 88}};\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t}\n\t}\n\n\t{ // heterogenous functions - vector_map\n\t\teastl::vector_map<ExplicitString, int, eastl::less<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\t{ // heterogenous insertion - vector_map\n\t\t// Ideally would use TestMapHeterogeneousInsertion<T>() instead of this test, but\n\t\t//   - we are missing try_emplace and insert_or_assign\n\t\t//   - at(size_type) needs to be removed and at_key() should be renamed to at()\n\n\t\teastl::vector_map<ExplicitString, int, eastl::less<void>> m;\n\n\t\t// insert:\n\t\tm[\"0\"] = 1;\n\t\tm[\"1\"] = 1;\n\t\tm[\"3\"] = 3;\n\n\t\tExplicitString::Reset();\n\n\t\t// no construction of key_type:\n\n\t\tEATEST_VERIFY(m[\"0\"] == 1);\n\t\tEATEST_VERIFY(m[\"1\"] == 1);\n\t\tEATEST_VERIFY(m[\"3\"] == 3);\n\n\t\tEATEST_VERIFY(m.at_key(\"0\") == 1);\n\t\tEATEST_VERIFY(m.at_key(\"1\") == 1);\n\t\tEATEST_VERIFY(m.at_key(\"3\") == 3);\n\n\t\tVERIFY(ExplicitString::sCtorFromStrCount == 0);\n\t}\n\n\t{ // heterogenous functions - vector_multimap\n\t\teastl::vector_multimap<ExplicitString, int, eastl::less<void>> m{ { ExplicitString::Create(\"found\"), 1 } };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(m);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(m);\n\n\t\tVERIFY(m.equal_range_small(\"not found\") == eastl::make_pair(m.lower_bound(\"not found\"), m.upper_bound(\"not found\")));\n\t\tVERIFY(m.equal_range_small(\"found\") == eastl::make_pair(m.lower_bound(\"found\"), m.upper_bound(\"found\")));\n\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(m);\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/TestVectorSet.cpp",
    "content": "/////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#include \"TestSet.h\"\n#include \"EASTLTest.h\"\n#include <EASTL/vector_set.h>\n#include <EASTL/vector_multiset.h>\n#include <EASTL/vector.h>\n#include <EASTL/deque.h>\n#include <EABase/eabase.h>\n#include \"TestAssociativeContainers.h\"\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t#include <set>\n#endif\nEA_RESTORE_ALL_VC_WARNINGS()\n\nusing namespace eastl;\n\n\n// Template instantations.\n// These tell the compiler to compile all the functions for the given class.\ntemplate class eastl::vector_set<int>;\ntemplate class eastl::vector_multiset<float>;\ntemplate class eastl::vector_set<TestObject>;\ntemplate class eastl::vector_multiset<TestObject>;\n\nstatic_assert(sizeof(eastl::vector_set<int>) == sizeof(eastl::vector<int>), \"if is_empty_v<Compare>, sizeof(vector_set) == sizeof(RandomAccessContainer)\");\nstatic_assert(sizeof(eastl::vector_set<TestObject>) == sizeof(eastl::vector<TestObject>), \"if is_empty_v<Compare>, sizeof(vector_set) == sizeof(RandomAccessContainer)\");\nstatic_assert(sizeof(eastl::vector_multiset<int>) == sizeof(eastl::vector<int>), \"if is_empty_v<Compare>, sizeof(vector_multiset) == sizeof(RandomAccessContainer)\");\nstatic_assert(sizeof(eastl::vector_multiset<TestObject>) == sizeof(eastl::vector<TestObject>), \"if is_empty_v<Compare>, sizeof(vector_multiset) == sizeof(RandomAccessContainer)\");\n\n\n///////////////////////////////////////////////////////////////////////////////\n// typedefs\n//\ntypedef eastl::vector_set<int> VS1;\ntypedef eastl::vector_set<int, eastl::less<int>, EASTLAllocatorType, eastl::deque<int> > VS2;\ntypedef eastl::vector_set<TestObject> VS4;\ntypedef eastl::vector_set<TestObject, eastl::less<TestObject>, EASTLAllocatorType, eastl::deque<TestObject> > VS5;\ntypedef eastl::vector_multiset<int> VMS1;\ntypedef eastl::vector_multiset<int, eastl::less<int>, EASTLAllocatorType, eastl::deque<int> > VMS2;\ntypedef eastl::vector_multiset<TestObject> VMS4;\ntypedef eastl::vector_multiset<TestObject, eastl::less<TestObject>, EASTLAllocatorType, eastl::deque<TestObject> > VMS5;\n\n#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\ttypedef std::set<int> VS3;\n\ttypedef std::set<TestObject> VS6;\n\ttypedef std::multiset<int> VMS3;\n\ttypedef std::multiset<TestObject> VMS6;\n#endif\n///////////////////////////////////////////////////////////////////////////////\n\n\nstruct EA_REMOVE_AT_2025_OCT LessNonTransparent\n{\n\ttemplate<typename A, typename B>\n\tEA_CPP14_CONSTEXPR auto operator()(A&& a, B&& b) const\n\t{\n\t\treturn eastl::forward<A>(a) < eastl::forward<B>(b);\n\t}\n};\n\n\nint TestVectorSet()\n{\n\tint nErrorCount = 0;\n\n\t#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\t\t{   // Test construction\n\t\t\tnErrorCount += TestSetConstruction<VS1, VS3, false>();\n\t\t\tnErrorCount += TestSetConstruction<VS2, VS3, false>();\n\t\t\tnErrorCount += TestSetConstruction<VS4, VS6, false>();\n\t\t\tnErrorCount += TestSetConstruction<VS5, VS6, false>();\n\t\t\tnErrorCount += TestSetConstruction<eastl::vector_set<int, eastl::less<void>>, std::set<int>, false>();\n\n\t\t\tnErrorCount += TestSetConstruction<VMS1, VMS3, true>();\n\t\t\tnErrorCount += TestSetConstruction<VMS2, VMS3, true>();\n\t\t\tnErrorCount += TestSetConstruction<VMS4, VMS6, true>();\n\t\t\tnErrorCount += TestSetConstruction<VMS5, VMS6, true>();\n\t\t\tnErrorCount += TestSetConstruction<eastl::vector_multiset<int, eastl::less<void>>, std::multiset<int>, true>();\n\t\t}\n\n\n\t\t{   // Test mutating functionality.\n\t\t\tnErrorCount += TestSetMutation<VS1, VS3, false>();\n\t\t\tnErrorCount += TestSetMutation<VS2, VS3, false>();\n\t\t\tnErrorCount += TestSetMutation<VS4, VS6, false>();\n\t\t\tnErrorCount += TestSetMutation<VS5, VS6, false>();\n\t\t\tnErrorCount += TestSetMutation<eastl::vector_set<int, eastl::less<void>>, std::set<int>, false>();\n\n\t\t\tnErrorCount += TestSetMutation<VMS1, VMS3, true>();\n\t\t\tnErrorCount += TestSetMutation<VMS2, VMS3, true>();\n\t\t\tnErrorCount += TestSetMutation<VMS4, VMS6, true>();\n\t\t\tnErrorCount += TestSetMutation<VMS5, VMS6, true>();\n\t\t\tnErrorCount += TestSetMutation<eastl::vector_multiset<int, eastl::less<void>>, std::multiset<int>, true>();\n\t\t}\n\t#endif // EA_COMPILER_NO_STANDARD_CPP_LIBRARY\n\n\n\t{   // Test search functionality.\n\t\tnErrorCount += TestSetSearch<VS1, false>();\n\t\tnErrorCount += TestSetSearch<VS2, false>();\n\t\tnErrorCount += TestSetSearch<VS4, false>();\n\t\tnErrorCount += TestSetSearch<VS5, false>();\n\t\tnErrorCount += TestSetSearch<eastl::vector_set<int, eastl::less<void>>, false>();\n\n\t\tnErrorCount += TestSetSearch<VMS1, true>();\n\t\tnErrorCount += TestSetSearch<VMS2, true>();\n\t\tnErrorCount += TestSetSearch<VMS4, true>();\n\t\tnErrorCount += TestSetSearch<VMS5, true>();\n\t\tnErrorCount += TestSetSearch<eastl::vector_multiset<int, eastl::less<void>>, true>();\n\t}\n\n\n\t{\n\t\t// C++11 emplace and related functionality\n\t\tnErrorCount += TestSetCpp11<VS4>();\n\t\tnErrorCount += TestSetCpp11<VS5>();\n\t\tnErrorCount += TestSetCpp11<eastl::vector_set<TestObject, eastl::less<void>>>();\n\n\t\tnErrorCount += TestMultisetCpp11<VMS4>();\n\t\tnErrorCount += TestMultisetCpp11<VMS5>();\n\t\tnErrorCount += TestMultisetCpp11<eastl::vector_multiset<TestObject, eastl::less<void>>>();\n\t}\n\n\n    {\n        // insert at the upper bound of a range\n        VMS1 vms = {0};\n        VERIFY(vms.insert(0) != vms.begin());\n    }\n\n\n\t{ // Misc tests\n\t\t{\n\t\t\t// const key_compare& key_comp() const;\n\t\t\t// key_compare&\t   key_comp();\n\t\t\tVS2\t   vs;\n\t\t\tconst VS2 vsc;\n\n\t\t\t// ensure count can be called from a const object\n\t\t\tconst VS2::key_compare& kc = vsc.key_comp();\n\t\t\tvs.key_comp() = kc;\n\t\t\tvsc.count(0);\n\t\t}\n\n\t\t{\n\t\t\t// ensure count can be called from a const object\n\t\t\tconst VMS1 vms;\n\t\t\tvms.count(0);\n\t\t}\n\t}\n\n\t{ // find / find_as / lower_bound / upper_bound\n\t\t{ // vector_set\n\t\t\teastl::vector_set<string> vss = {\"abc\", \"def\", \"ghi\", \"jklmnop\", \"qrstu\", \"vw\", \"x\", \"yz\"};\n\t\t\tVERIFY(vss.find(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.find(\"GHI\") == vss.end());\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t\tVERIFY(vss.lower_bound(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.upper_bound(\"ghi\") != vss.end());\n\t\t}\n\n\t\t{ // const vector_set\n\t\t\tconst eastl::vector_set<string> vss = {\"abc\", \"def\", \"ghi\", \"jklmnop\", \"qrstu\", \"vw\", \"x\", \"yz\"};\n\t\t\tVERIFY(vss.find(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.find(\"GHI\") == vss.end());\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t\tVERIFY(vss.lower_bound(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.upper_bound(\"ghi\") != vss.end());\n\t\t}\n\n\t\t{ // vector_multiset\n\t\t\teastl::vector_multiset<string> vss = {\"abc\", \"def\", \"ghi\", \"jklmnop\", \"qrstu\", \"vw\", \"x\", \"yz\"};\n\t\t\tVERIFY(vss.find(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.find(\"GHI\") == vss.end());\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t\tVERIFY(vss.lower_bound(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.upper_bound(\"ghi\") != vss.end());\n\t\t}\n\n\t\t{ // const vector_multiset\n\t\t\tconst eastl::vector_multiset<string> vss = {\"abc\", \"def\", \"ghi\", \"jklmnop\", \"qrstu\", \"vw\", \"x\", \"yz\"};\n\t\t\tVERIFY(vss.find(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.find(\"GHI\") == vss.end());\n\t\t\tVERIFY(vss.find_as(\"GHI\", TestStrCmpI_2()) != vss.end());\n\t\t\tVERIFY(vss.lower_bound(\"ghi\") != vss.end());\n\t\t\tVERIFY(vss.upper_bound(\"ghi\") != vss.end());\n\t\t}\n\t}\n\n\t{ // heterogenous functions - vector_set\n\t\teastl::vector_set<ExplicitString, eastl::less<void>> s = { ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestSetHeterogeneousInsertion<decltype(s)>();\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // heterogenous functions - vector_multiset\n\t\teastl::vector_multiset<ExplicitString, eastl::less<void>> s = { ExplicitString::Create(\"found\") };\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousLookup(s);\n\t\tnErrorCount += TestOrderedAssociativeContainerHeterogeneousLookup(s);\n\n\t\tVERIFY(s.equal_range_small(\"not found\") == eastl::make_pair(s.lower_bound(\"not found\"), s.upper_bound(\"not found\")));\n\t\tVERIFY(s.equal_range_small(\"found\") == eastl::make_pair(s.lower_bound(\"found\"), s.upper_bound(\"found\")));\n\n\t\tnErrorCount += TestAssociativeContainerHeterogeneousErasure(s);\n\t}\n\n\t{ // insert(P&&) was incorrectly defined in the rbtree base type.\n\t\t// should never have been defined for set, multiset.\n\t\t// it does not correctly support heterogeneous insertion (unconditionally creates a key_type).\n\t\t// this test exists purely to check that the addition of insert(KX&&) for heterogeneous keys didn't break existing (unlikely) calls to insert(P&&) that\n\t\t// shouldn't have been supported.\n\t\tEASTL_INTERNAL_DISABLE_DEPRECATED()\n\t\teastl::vector_set<ExplicitString, LessNonTransparent> s = { ExplicitString::Create(\"a\") };\n\t\ts.insert(\"a\");\n\n\t\teastl::vector_multiset<ExplicitString, LessNonTransparent> s2 = { ExplicitString::Create(\"a\") };\n\t\ts2.insert(\"a\");\n\t\tEASTL_INTERNAL_RESTORE_DEPRECATED()\n\n\t\teastl::vector_set<ExplicitString, eastl::less<void>> s3 = { ExplicitString::Create(\"a\") };\n\t\ts3.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\n\t\teastl::vector_multiset<eastl::string, eastl::less<void>> s4 = { \"a\" };\n\t\ts4.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\n\t\teastl::vector_set<eastl::string> s5 = { \"a\" };\n\t\ts5.insert(\"a\"); // shouldn't call the deprecated insert() overload\n\t}\n\n\treturn nErrorCount;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/source/main.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Electronic Arts Inc. All rights reserved.\n///////////////////////////////////////////////////////////////////////////////\n\n\n#include \"EASTLTest.h\"\n#include <EAStdC/EASprintf.h>\n#include <EASTL/internal/config.h>\n#include <EASTL/internal/thread_support.h>\n\nEA_DISABLE_ALL_VC_WARNINGS()\n#include <string.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\nEA_RESTORE_ALL_VC_WARNINGS()\n\n\n#include \"EAMain/EAEntryPointMain.inl\"\n#include \"EASTLTestAllocator.h\"\n\n///////////////////////////////////////////////////////////////////////////////\n// Required by EASTL.\n//\n#if !EASTL_EASTDC_VSNPRINTF\n\tint Vsnprintf8(char* pDestination, size_t n, const char*  pFormat, va_list arguments)\n\t{\n\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t}\n\n\tint Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments)\n\t{\n\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t}\n\n\tint Vsnprintf32(char32_t* pDestination, size_t n, const char32_t* pFormat, va_list arguments)\n\t{\n\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t}\n\n\t#if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE\n\t\tint Vsnprintf8(char8_t* pDestination, size_t n, const char8_t*  pFormat, va_list arguments)\n\t\t{\n\t\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t\t}\n\t#endif\n\n\t#if defined(EA_WCHAR_UNIQUE) && EA_WCHAR_UNIQUE\n\t\tint VsnprintfW(wchar_t* pDestination, size_t n, const wchar_t* pFormat, va_list arguments)\n\t\t{\n\t\t\treturn EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);\n\t\t}\n\t#endif\n#endif\n\n\n///////////////////////////////////////////////////////////////////////////////\n// EAMain\n//\nint EAMain(int argc, char* argv[])\n{\n\tusing namespace EA::UnitTest;\n\n\tint nErrorCount = 0;\n\n\tEA::EAMain::PlatformStartup();\n\n\tEASTLTest_SetGeneralAllocator();\n\n\tnErrorCount += EASTLTest_CheckMemory();\n\n\t// Parse command line arguments\n\tfor(int i = 1; i < argc; i++)\n\t{\n\t\t// Example usage: -l:7\n\t\tif(strstr(argv[i], \"-l:\") == argv[i])\n\t\t{\n\t\t\tgEASTL_TestLevel = atoi(argv[i] + 3);\n\n\t\t\tif(gEASTL_TestLevel < kEASTL_TestLevelLow)\n\t\t\t   gEASTL_TestLevel = kEASTL_TestLevelLow;\n\t\t\tif(gEASTL_TestLevel > kEASTL_TestLevelHigh)\n\t\t\t   gEASTL_TestLevel = kEASTL_TestLevelHigh;\n\t\t}\n\t}\n\n\tTestApplication testSuite(\"EASTL Unit Tests\", argc, argv);\n\n\ttestSuite.AddTest(\"Algorithm\",\t\t\t\tTestAlgorithm);\n\ttestSuite.AddTest(\"Allocator\",\t\t\t\tTestAllocator);\n\ttestSuite.AddTest(\"AllocatorPropagate\",\t\tTestAllocatorPropagate);\n\ttestSuite.AddTest(\"Any\",\t\t\t\t    TestAny);\n\ttestSuite.AddTest(\"Array\",\t\t\t\t\tTestArray);\n\ttestSuite.AddTest(\"Bit\",\t\t\t\t\tTestBit);\n#if EA_COMPILER_CPP17_ENABLED\n\ttestSuite.AddTest(\"BadExpectedAccess\",  \tTestBadExpectedAccess);\n#endif\n\ttestSuite.AddTest(\"BitVector\",\t\t\t\tTestBitVector);\n\ttestSuite.AddTest(\"Bitset\",\t\t\t\t\tTestBitset);\n\ttestSuite.AddTest(\"CharTraits\",\t\t\t    TestCharTraits);\n\ttestSuite.AddTest(\"Chrono\",\t\t\t\t\tTestChrono);\n\ttestSuite.AddTest(\"Concepts\", \t\t\t\tTestConcepts);\n\ttestSuite.AddTest(\"ContainerBehaviour\",\t\tTestContainerBehaviour);\n\ttestSuite.AddTest(\"Deque\",\t\t\t\t\tTestDeque);\n#if EA_COMPILER_CPP17_ENABLED\n\ttestSuite.AddTest(\"Expected\",\t\t\t\tTestExpected);\n#endif\n\ttestSuite.AddTest(\"Extra\",\t\t\t\t\tTestExtra);\n\ttestSuite.AddTest(\"Finally\",\t\t\t\tTestFinally);\n\ttestSuite.AddTest(\"FixedFunction\",\t\t\tTestFixedFunction);\n\ttestSuite.AddTest(\"FixedHash\",\t\t\t\tTestFixedHash);\n\ttestSuite.AddTest(\"FixedList\",\t\t\t\tTestFixedList);\n\ttestSuite.AddTest(\"FixedMap\",\t\t\t\tTestFixedMap);\n\ttestSuite.AddTest(\"FixedSList\",\t\t\t\tTestFixedSList);\n\ttestSuite.AddTest(\"FixedSet\",\t\t\t\tTestFixedSet);\n\ttestSuite.AddTest(\"FixedString\",\t\t\tTestFixedString);\n\ttestSuite.AddTest(\"FixedTupleVector\",\t\tTestFixedTupleVector);\n\ttestSuite.AddTest(\"FixedVector\",\t\t\tTestFixedVector);\n\ttestSuite.AddTest(\"Functional\",\t\t\t\tTestFunctional);\n\ttestSuite.AddTest(\"Hash\",\t\t\t\t\tTestHash);\n\ttestSuite.AddTest(\"Heap\",\t\t\t\t\tTestHeap);\n\ttestSuite.AddTest(\"IntrusiveHash\",\t\t\tTestIntrusiveHash);\n\ttestSuite.AddTest(\"IntrusiveList\",\t\t\tTestIntrusiveList);\n\ttestSuite.AddTest(\"IntrusiveSDList\",\t\tTestIntrusiveSDList);\n\ttestSuite.AddTest(\"IntrusiveSList\",\t\t\tTestIntrusiveSList);\n\ttestSuite.AddTest(\"Iterator\",\t\t\t\tTestIterator);\n\ttestSuite.AddTest(\"LRUCache\",\t\t\t\tTestLruCache);\n\ttestSuite.AddTest(\"List\",\t\t\t\t\tTestList);\n\ttestSuite.AddTest(\"ListMap\",\t\t\t\tTestListMap);\n\ttestSuite.AddTest(\"Map\",\t\t\t\t\tTestMap);\n\ttestSuite.AddTest(\"Memory\",\t\t\t\t\tTestMemory);\n\ttestSuite.AddTest(\"Meta\",\t\t\t\t    TestMeta);\n\ttestSuite.AddTest(\"NumericLimits\",\t\t\tTestNumericLimits);\n\ttestSuite.AddTest(\"Optional\",\t\t\t\tTestOptional);\n\ttestSuite.AddTest(\"Random\",\t\t\t\t\tTestRandom);\n\ttestSuite.AddTest(\"Ratio\",\t\t\t\t\tTestRatio);\n\ttestSuite.AddTest(\"RingBuffer\",\t\t\t\tTestRingBuffer);\n\ttestSuite.AddTest(\"SList\",\t\t\t\t\tTestSList);\n\ttestSuite.AddTest(\"SegmentedVector\",\t\tTestSegmentedVector);\n\ttestSuite.AddTest(\"Set\",\t\t\t\t\tTestSet);\n\ttestSuite.AddTest(\"SmartPtr\",\t\t\t\tTestSmartPtr);\n\ttestSuite.AddTest(\"Sort\",\t\t\t\t\tTestSort);\n\ttestSuite.AddTest(\"Span\",\t\t\t\t    TestSpan);\n\ttestSuite.AddTest(\"String\",\t\t\t\t\tTestString);\n\ttestSuite.AddTest(\"StringHashMap\",\t\t\tTestStringHashMap);\n\ttestSuite.AddTest(\"StringMap\",\t\t\t\tTestStringMap);\n\ttestSuite.AddTest(\"StringView\",\t\t\t    TestStringView);\n\ttestSuite.AddTest(\"TestCppCXTypeTraits\",\tTestCppCXTypeTraits);\n\ttestSuite.AddTest(\"Tuple\",\t\t\t\t\tTestTuple);\n\ttestSuite.AddTest(\"TupleVector\",\t\t\tTestTupleVector);\n\ttestSuite.AddTest(\"TypeTraits\",\t\t\t\tTestTypeTraits);\n#if EA_COMPILER_CPP17_ENABLED\n\ttestSuite.AddTest(\"Unexpected\",\t\t\t\tTestUnexpected);\n#endif\n\ttestSuite.AddTest(\"Utility\",\t\t\t\tTestUtility);\n\ttestSuite.AddTest(\"Variant\",\t\t\t\tTestVariant);\n\ttestSuite.AddTest(\"Vector\",\t\t\t\t\tTestVector);\n\ttestSuite.AddTest(\"VectorMap\",\t\t\t\tTestVectorMap);\n\ttestSuite.AddTest(\"VectorSet\",\t\t\t\tTestVectorSet);\n\ttestSuite.AddTest(\"AtomicBasic\",\t\t\tTestAtomicBasic);\n\ttestSuite.AddTest(\"AtomicRaw\",\t\t\tTestAtomicRaw);\n#if EASTL_THREAD_SUPPORT_AVAILABLE\n\ttestSuite.AddTest(\"AtomicMT\",\t\t\t\tTestAtomicMultiThreaded);\n#endif\n\ttestSuite.AddTest(\"AtomicAsm\",\t\t\t\tTestAtomicAsm);\n\ttestSuite.AddTest(\"Bitcast\",\t\t\t\tTestBitcast);\n\ttestSuite.AddTest(\"Flags\",\t\t\t\t\tTestFlags);\n\n\n\tnErrorCount += testSuite.Run();\n\n\tnErrorCount += EASTLTest_CheckMemory();\n\n\tEA::EAMain::PlatformShutdown(nErrorCount);\n\n\treturn nErrorCount;\n}\n"
  }
]