Merge branch 'development' of https://github.com/o3de/o3de into cgalvan/DraftStreamingImageAssetPixelAPI

This commit is contained in:
Chris Galvan
2022-01-25 09:35:58 -06:00
101 changed files with 5428 additions and 1380 deletions
@@ -32,10 +32,10 @@ def Menus_FileMenuOptions_Work():
file_menu_options = [
("New Level",),
#("Open Level",), Temporarily disabled due to https://github.com/o3de/o3de/issues/6605
#("Import",), Temporarily disabled due to https://github.com/o3de/o3de/issues/6746
("Open Level",),
#("Import",), #Temporarily disabled due to https://github.com/o3de/o3de/issues/6746
("Save",),
#("Save As",), Temporarily disabled due to https://github.com/o3de/o3de/issues/6605
("Save As",),
("Save Level Statistics",),
("Edit Project Settings",),
#("Edit Platform Settings",), Temporarily disabled due to https://github.com/o3de/o3de/issues/6604
+5 -5
View File
@@ -64,11 +64,11 @@ namespace AzToolsFramework
//! @name Reverse URLs.
//! Used to identify common actions and override them when necessary.
//@{
constexpr inline AZ::Crc32 EditModeMove = AZ_CRC_CE("com.o3de.action.editor.editmode.move");
constexpr inline AZ::Crc32 EditModeRotate = AZ_CRC_CE("com.o3de.action.editor.editmode.rotate");
constexpr inline AZ::Crc32 EditModeScale = AZ_CRC_CE("com.o3de.action.editor.editmode.scale");
constexpr inline AZ::Crc32 SnapToGrid = AZ_CRC_CE("com.o3de.action.editor.snaptogrid");
constexpr inline AZ::Crc32 SnapAngle = AZ_CRC_CE("com.o3de.action.editor.snapangle");
constexpr inline AZ::Crc32 EditModeMove = AZ_CRC_CE("org.o3de.action.editor.editmode.move");
constexpr inline AZ::Crc32 EditModeRotate = AZ_CRC_CE("org.o3de.action.editor.editmode.rotate");
constexpr inline AZ::Crc32 EditModeScale = AZ_CRC_CE("org.o3de.action.editor.editmode.scale");
constexpr inline AZ::Crc32 SnapToGrid = AZ_CRC_CE("org.o3de.action.editor.snaptogrid");
constexpr inline AZ::Crc32 SnapAngle = AZ_CRC_CE("org.o3de.action.editor.snapangle");
//@}
}
+2 -1
View File
@@ -45,7 +45,8 @@ bool ModalWindowDismisser::eventFilter(QObject* object, QEvent* event)
{
if (dialog->isModal())
{
if (event->type() == QEvent::Show)
QEvent::Type test = event->type();
if (test == QEvent::Show || test == QEvent::WindowActivate)
{
auto it = AZStd::find(m_windows.begin(), m_windows.end(), dialog);
if (it == m_windows.end())
@@ -64,7 +64,7 @@ public class LumberyardActivity extends NativeActivity
////////////////////////////////////////////////////////////////
// called from the native to get the application package name
// e.g. com.lumberyard.samples for SamplesProject
// e.g. org.o3de.samples for SamplesProject
public String GetPackageName()
{
return getApplicationContext().getPackageName();
@@ -116,7 +116,7 @@ namespace AZ
const char* GetObbStoragePath() const { return m_obbStoragePath.c_str(); }
//! Get the dot separated package name for the current application.
//! e.g. com.lumberyard.samples for SamplesProject
//! e.g. org.o3de.samples for SamplesProject
const char* GetPackageName() const { return m_packageName.c_str(); }
//! Get the app version code (android:versionCode in the manifest).
+1 -1
View File
@@ -52,7 +52,7 @@ namespace AZ
const char* GetObbStoragePath();
//! Get the dot separated package name for the current application.
//! e.g. com.o3de.samples for SamplesProject
//! e.g. org.o3de.samples for SamplesProject
const char* GetPackageName();
//! Get the app version code (android:versionCode in the manifest).
+15 -15
View File
@@ -15,9 +15,9 @@ namespace AZ::IO
// Class template instantations
template class BasicPath<AZStd::string>;
template class BasicPath<FixedMaxPathString>;
template class PathIterator<PathView>;
template class PathIterator<Path>;
template class PathIterator<FixedMaxPath>;
template class PathIterator<const PathView>;
template class PathIterator<const Path>;
template class PathIterator<const FixedMaxPath>;
// Swap function instantiations
template void swap<AZStd::string>(Path& lhs, Path& rhs) noexcept;
@@ -38,16 +38,16 @@ namespace AZ::IO
const typename BasicPath<FixedMaxPathString>::value_type* rhs);
// Iterator compare instantiations
template bool operator==<PathView>(const PathIterator<PathView>& lhs,
const PathIterator<PathView>& rhs);
template bool operator==<Path>(const PathIterator<Path>& lhs,
const PathIterator<Path>& rhs);
template bool operator==<FixedMaxPath>(const PathIterator<FixedMaxPath>& lhs,
const PathIterator<FixedMaxPath>& rhs);
template bool operator!=<PathView>(const PathIterator<PathView>& lhs,
const PathIterator<PathView>& rhs);
template bool operator!=<Path>(const PathIterator<Path>& lhs,
const PathIterator<Path>& rhs);
template bool operator!=<FixedMaxPath>(const PathIterator<FixedMaxPath>& lhs,
const PathIterator<FixedMaxPath>& rhs);
template bool operator==<const PathView>(const PathIterator<const PathView>& lhs,
const PathIterator<const PathView>& rhs);
template bool operator==<const Path>(const PathIterator<const Path>& lhs,
const PathIterator<const Path>& rhs);
template bool operator==<const FixedMaxPath>(const PathIterator<const FixedMaxPath>& lhs,
const PathIterator<const FixedMaxPath>& rhs);
template bool operator!=<const PathView>(const PathIterator<const PathView>& lhs,
const PathIterator<const PathView>& rhs);
template bool operator!=<const Path>(const PathIterator<const Path>& lhs,
const PathIterator<const Path>& rhs);
template bool operator!=<const FixedMaxPath>(const PathIterator<const FixedMaxPath>& lhs,
const PathIterator<const FixedMaxPath>& rhs);
}
+11 -10
View File
@@ -43,9 +43,9 @@ namespace AZ::IO
public:
using string_view_type = AZStd::string_view;
using value_type = char;
using const_iterator = const PathIterator<PathView>;
using const_iterator = PathIterator<const PathView>;
using iterator = const_iterator;
friend PathIterator<PathView>;
friend const_iterator;
// constructors and destructor
constexpr PathView() = default;
@@ -319,9 +319,9 @@ namespace AZ::IO
using value_type = typename StringType::value_type;
using traits_type = typename StringType::traits_type;
using string_view_type = AZStd::string_view;
using const_iterator = const PathIterator<BasicPath>;
using const_iterator = PathIterator<const BasicPath>;
using iterator = const_iterator;
friend PathIterator<BasicPath>;
friend const_iterator;
// constructors and destructor
constexpr BasicPath() = default;
@@ -692,7 +692,7 @@ namespace AZ::IO
friend PathType;
using iterator_category = AZStd::bidirectional_iterator_tag;
using value_type = PathType;
using value_type = AZStd::remove_cv_t<PathType>;
using difference_type = ptrdiff_t;
using pointer = const value_type*;
using reference = const value_type&;
@@ -703,8 +703,9 @@ namespace AZ::IO
constexpr PathIterator() = default;
constexpr PathIterator(const PathIterator&) = default;
constexpr PathIterator(PathIterator&&) noexcept = default;
constexpr PathIterator& operator=(const PathIterator&) = default;
constexpr PathIterator& operator=(PathIterator&&) noexcept = default;
constexpr reference operator*() const;
@@ -733,10 +734,10 @@ namespace AZ::IO
ParserState m_state{ Singular };
};
template <typename PathType1>
constexpr bool operator==(const PathIterator<PathType1>& lhs, const PathIterator<PathType1>& rhs);
template <typename PathType1>
constexpr bool operator!=(const PathIterator<PathType1>& lhs, const PathIterator<PathType1>& rhs);
template <typename PathType>
constexpr bool operator==(const PathIterator<PathType>& lhs, const PathIterator<PathType>& rhs);
template <typename PathType>
constexpr bool operator!=(const PathIterator<PathType>& lhs, const PathIterator<PathType>& rhs);
}
#include <AzCore/IO/Path/Path.inl>
+16 -16
View File
@@ -399,7 +399,7 @@ namespace AZ::IO
constexpr auto PathView::begin() const -> const_iterator
{
auto pathParser = parser::PathParser::CreateBegin(m_path, m_preferred_separator);
PathIterator<PathView> it;
const_iterator it;
it.m_path_ref = this;
it.m_state = static_cast<typename const_iterator::ParserState>(pathParser.m_parser_state);
it.m_path_entry_view = pathParser.m_path_raw_entry;
@@ -409,7 +409,7 @@ namespace AZ::IO
constexpr auto PathView::end() const -> const_iterator
{
PathIterator<PathView> it;
const_iterator it;
it.m_state = const_iterator::AtEnd;
it.m_path_ref = this;
return it;
@@ -1262,7 +1262,7 @@ namespace AZ::IO
constexpr auto BasicPath<StringType>::begin() const -> const_iterator
{
auto pathParser = parser::PathParser::CreateBegin(m_path, m_preferred_separator);
PathIterator<BasicPath> it;
const_iterator it;
it.m_path_ref = this;
it.m_state = static_cast<typename const_iterator::ParserState>(pathParser.m_parser_state);
it.m_path_entry_view = pathParser.m_path_raw_entry;
@@ -1273,7 +1273,7 @@ namespace AZ::IO
template <typename StringType>
constexpr auto BasicPath<StringType>::end() const -> const_iterator
{
PathIterator<BasicPath> it;
const_iterator it;
it.m_state = const_iterator::AtEnd;
it.m_path_ref = this;
return it;
@@ -1529,16 +1529,16 @@ namespace AZ::IO
const typename BasicPath<FixedMaxPathString>::value_type* rhs);
// Iterator compare explicit declarations
extern template bool operator==<PathView>(const PathIterator<PathView>& lhs,
const PathIterator<PathView>& rhs);
extern template bool operator==<Path>(const PathIterator<Path>& lhs,
const PathIterator<Path>& rhs);
extern template bool operator==<FixedMaxPath>(const PathIterator<FixedMaxPath>& lhs,
const PathIterator<FixedMaxPath>& rhs);
extern template bool operator!=<PathView>(const PathIterator<PathView>& lhs,
const PathIterator<PathView>& rhs);
extern template bool operator!=<Path>(const PathIterator<Path>& lhs,
const PathIterator<Path>& rhs);
extern template bool operator!=<FixedMaxPath>(const PathIterator<FixedMaxPath>& lhs,
const PathIterator<FixedMaxPath>& rhs);
extern template bool operator==<const PathView>(const PathIterator<const PathView>& lhs,
const PathIterator<const PathView>& rhs);
extern template bool operator==<const Path>(const PathIterator<const Path>& lhs,
const PathIterator<const Path>& rhs);
extern template bool operator==<const FixedMaxPath>(const PathIterator<const FixedMaxPath>& lhs,
const PathIterator<const FixedMaxPath>& rhs);
extern template bool operator!=<const PathView>(const PathIterator<const PathView>& lhs,
const PathIterator<const PathView>& rhs);
extern template bool operator!=<const Path>(const PathIterator<const Path>& lhs,
const PathIterator<const Path>& rhs);
extern template bool operator!=<const FixedMaxPath>(const PathIterator<const FixedMaxPath>& lhs,
const PathIterator<const FixedMaxPath>& rhs);
}
@@ -10,6 +10,7 @@
#include <AzCore/AzCore_Traits_Platform.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/std/concepts/concepts.h>
namespace AZ::IO::Internal
{
@@ -17,7 +18,7 @@ namespace AZ::IO::Internal
{
return elem == '/' || elem == '\\';
}
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::Internal::is_input_iterator_v<InputIt>>>
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::input_iterator<InputIt>>>
static constexpr bool HasDrivePrefix(InputIt first, EndIt last)
{
size_t prefixSize = AZStd::distance(first, last);
@@ -46,7 +47,7 @@ namespace AZ::IO::Internal
//! Windows root names can have include drive letter within them
template <typename InputIt>
constexpr auto ConsumeRootName(InputIt entryBeginIter, InputIt entryEndIter, const char preferredSeparator)
-> AZStd::enable_if_t<AZStd::Internal::is_forward_iterator_v<InputIt>, InputIt>
-> AZStd::enable_if_t<AZStd::forward_iterator<InputIt>, InputIt>
{
if (preferredSeparator == PosixPathSeparator)
{
@@ -147,7 +148,7 @@ namespace AZ::IO::Internal
//! If the preferred separator is '/' just checks if the path starts with a '/
//! Otherwise a check for a Windows absolute path occurs
//! Windows absolute paths can include a RootName
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::Internal::is_input_iterator_v<InputIt>>>
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::input_iterator<InputIt>>>
static constexpr bool IsAbsolute(InputIt first, EndIt last, const char preferredSeparator)
{
size_t pathSize = AZStd::distance(first, last);
@@ -208,11 +209,11 @@ namespace AZ::IO::parser
enum ParserState : uint8_t
{
// Zero is a special sentinel value used by default constructed iterators.
PS_BeforeBegin = PathIterator<PathView>::BeforeBegin,
PS_InRootName = PathIterator<PathView>::InRootName,
PS_InRootDir = PathIterator<PathView>::InRootDir,
PS_InFilenames = PathIterator<PathView>::InFilenames,
PS_AtEnd = PathIterator<PathView>::AtEnd
PS_BeforeBegin = PathView::const_iterator::BeforeBegin,
PS_InRootName = PathView::const_iterator::InRootName,
PS_InRootDir = PathView::const_iterator::InRootDir,
PS_InFilenames = PathView::const_iterator::InFilenames,
PS_AtEnd = PathView::const_iterator::AtEnd
};
struct PathParser
+4 -4
View File
@@ -248,14 +248,14 @@
#if defined(__has_builtin)
#if __has_builtin(__builtin_is_constant_evaluated)
#define az_builtin_is_constant_evaluated() __builtin_is_constant_evaluated()
#define az_has_builtin_is_constant_evaluated() true
#define az_has_builtin_is_constant_evaluated true
#endif
#elif AZ_COMPILER_MSVC >= 1928
#define az_builtin_is_constant_evaluated() __builtin_is_constant_evaluated()
#define az_has_builtin_is_constant_evaluated() true
#define az_has_builtin_is_constant_evaluated true
#elif AZ_COMPILER_GCC
#define az_builtin_is_constant_evaluated() __builtin_is_constant_evaluated()
#define az_has_builtin_is_constant_evaluated() true
#define az_has_builtin_is_constant_evaluated true
#endif
#endif
@@ -271,7 +271,7 @@
}
}
#define az_builtin_is_constant_evaluated() AZ::Internal::builtin_is_constant_evaluated()
#define az_has_builtin_is_constant_evaluated() false
#define az_has_builtin_is_constant_evaluated false
#endif
// define builtin functions used by char_traits class for efficient compile time and runtime
@@ -19,6 +19,7 @@ set(FILES
any.h
base.h
config.h
concepts/concepts.h
createdestroy.h
docs.h
exceptions.h
@@ -27,11 +28,14 @@ set(FILES
hash.cpp
hash.h
hash_table.h
iterator/iterator_primitives.h
iterator.h
limits.h
numeric.h
math.h
optional.h
ranges/iter_move.h
ranges/ranges.h
ratio.h
reference_wrapper.h
sort.h
@@ -151,6 +155,7 @@ set(FILES
typetraits/alignment_of.h
typetraits/config.h
typetraits/common_type.h
typetraits/common_reference.h
typetraits/conjunction.h
typetraits/disjunction.h
typetraits/extent.h
@@ -217,4 +222,6 @@ set(FILES
typetraits/void_t.h
typetraits/internal/type_sequence_traits.h
typetraits/internal/is_template_copy_constructible.h
utility/declval.h
utility/move.h
)
+2
View File
@@ -30,4 +30,6 @@ namespace AZStd
using std::nullptr_t;
using sys_time_t = AZ::s64;
using std::byte;
}
@@ -0,0 +1,840 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/function/invoke.h>
#include <AzCore/std/iterator/iterator_primitives.h>
#include <AzCore/std/ranges/iter_move.h>
#include <AzCore/std/typetraits/add_pointer.h>
#include <AzCore/std/typetraits/common_reference.h>
#include <AzCore/std/typetraits/extent.h>
#include <AzCore/std/typetraits/is_array.h>
#include <AzCore/std/typetraits/is_assignable.h>
#include <AzCore/std/typetraits/is_class.h>
#include <AzCore/std/typetraits/is_constructible.h>
#include <AzCore/std/typetraits/is_destructible.h>
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/std/typetraits/is_floating_point.h>
#include <AzCore/std/typetraits/is_function.h>
#include <AzCore/std/typetraits/is_integral.h>
#include <AzCore/std/typetraits/is_object.h>
#include <AzCore/std/typetraits/is_same.h>
#include <AzCore/std/typetraits/is_signed.h>
#include <AzCore/std/typetraits/is_void.h>
#include <AzCore/std/typetraits/remove_cvref.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utility/declval.h>
#include <AzCore/std/utility/move.h>
namespace AZStd
{
// alias std::pointer_traits into the AZStd::namespace
using std::pointer_traits;
// Alias re-declarations from iterator.h
/// Identifying tag for input iterators.
using input_iterator_tag = std::input_iterator_tag;
/// Identifying tag for output iterators.
using output_iterator_tag = std::output_iterator_tag;
/// Identifying tag for forward iterators.
using forward_iterator_tag = std::forward_iterator_tag;
/// Identifying tag for bidirectional iterators.
using bidirectional_iterator_tag = std::bidirectional_iterator_tag;
/// Identifying tag for random-access iterators.
using random_access_iterator_tag = std::random_access_iterator_tag;
/// Identifying tag for contagious iterators
struct contiguous_iterator_tag;
}
namespace AZStd::Internal
{
template <typename T, typename = void>
constexpr bool pointer_traits_has_to_address_v = false;
template <typename T>
constexpr bool pointer_traits_has_to_address_v<T, enable_if_t<
is_void_v<void_t<decltype(pointer_traits<T>::to_address(declval<const T&>()))>>> > = true;
// pointer_traits isn't SFINAE friendly https://cplusplus.github.io/LWG/lwg-active.html#3545
// So working around that by checking if type T has an element_type alias
template <typename T, typename = void>
constexpr bool pointer_traits_valid_and_has_to_address_v = false;
template <typename T>
constexpr bool pointer_traits_valid_and_has_to_address_v<T, enable_if_t<has_element_type_v<T>> >
= pointer_traits_has_to_address_v<T>;
}
namespace AZStd
{
//! Implements the C++20 to_address function
//! This obtains the address represented by ptr without forming a reference
//! to the pointee type
template <typename T>
constexpr T* to_address(T* ptr) noexcept
{
static_assert(!AZStd::is_function_v<T>, "Invoking to address on a function pointer is not allowed");
return ptr;
}
//! Fancy pointer overload which delegates to using a specialization of pointer_traits<T>::to_address
//! if that is a well-formed expression, otherwise it returns ptr->operator->()
//! For example invoking `to_address(AZStd::reverse_iterator<const char*>(char_ptr))`
//! Returns an element of type const char*
template <typename T>
constexpr auto to_address(const T& ptr) noexcept
{
if constexpr (AZStd::Internal::pointer_traits_valid_and_has_to_address_v<T>)
{
return pointer_traits<T>::to_address(ptr);
}
else
{
return to_address(ptr.operator->());
}
}
}
namespace AZStd::Internal
{
// Variadic template which maps types to true For SFINAE
template <class... Args>
constexpr bool sfinae_trigger_v = true;
template <class It, class = void>
constexpr bool is_class_or_enum = false;
template <class It>
constexpr bool is_class_or_enum<It, enable_if_t<
(is_class_v<remove_cvref_t<It>> || is_enum_v<remove_cvref_t<It>>)>> = true;
template<class LHS, class RHS, class = void>
constexpr bool assignable_from_impl = false;
template<class LHS, class RHS>
constexpr bool assignable_from_impl<LHS, RHS, enable_if_t<is_lvalue_reference_v<LHS>
&& common_reference_with<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&>
&& same_as<decltype(declval<LHS>() = declval<RHS>()), LHS> >> = true;
template<class T, class U, class = void>
constexpr bool common_with_impl = false;
template<class T, class U>
constexpr bool common_with_impl<T, U, enable_if_t<
same_as<common_type_t<T, U>, common_type_t<U, T>>
&& sfinae_trigger_v<decltype(static_cast<common_type_t<T, U>>(declval<T>()))>
&& sfinae_trigger_v<decltype(static_cast<common_type_t<T, U>>(declval<U>()))>
&& common_reference_with<add_lvalue_reference_t<const T>, add_lvalue_reference_t<const U>>
&& common_reference_with<add_lvalue_reference_t<common_type_t<T, U>>, common_reference_t<add_lvalue_reference_t<const T>, add_lvalue_reference_t<const U>>>
>> = true;
}
namespace AZStd
{
template<class T, class U>
/*concept*/ constexpr bool common_with = Internal::common_with_impl<T, U>;
template<class LHS, class RHS>
/*concept*/ constexpr bool assignable_from = Internal::assignable_from_impl<LHS, RHS>;
template<class T, class... Args>
/*concept*/ constexpr bool constructible_from = destructible<T> && is_constructible_v<T, Args...>;
template<class T>
/*concept*/ constexpr bool move_constructible = constructible_from<T, T> && convertible_to<T, T>;
template<class Derived, class Base>
/*concept*/ constexpr bool derived_from = is_base_of_v<Base, Derived> && is_convertible_v<const volatile Derived*, const volatile Base*>;
}
namespace AZStd::ranges::Internal
{
template <class T, class U, class = void>
constexpr bool is_class_or_enum_with_swap_adl = false;
template <class T, class U>
constexpr bool is_class_or_enum_with_swap_adl<T, U, enable_if_t<
(is_class_v<remove_cvref_t<T>> || is_enum_v<remove_cvref_t<T>>
|| is_class_v<remove_cvref_t<U>> || is_enum_v<remove_cvref_t<T>>)
&& is_void_v<void_t<decltype(swap(declval<T&>(), declval<U&>()))>>
>> = true;
template <class T>
void swap(T&, T&) = delete;
struct swap_fn
{
template <class T, class U>
constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(swap(AZStd::forward<T>(t), AZStd::forward<U>(u))))
->enable_if_t<is_class_or_enum_with_swap_adl<T, U>>
{
swap(AZStd::forward<T>(t), AZStd::forward<U>(u));
}
// ranges::swap customization point https://eel.is/c++draft/concepts#concept.swappable-2.2
// Implemented in ranges.h as to prevent circular dependency.
// ranges::swap_ranges depends on the range concepts that can't be defined here
template <class T, class U>
constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept((*this)(*t, *u)))
->enable_if_t<!is_class_or_enum_with_swap_adl<T, U>
&& is_array_v<T> && is_array_v<U> && (extent_v<T> == extent_v<U>)
>;
template <class T>
constexpr auto operator()(T& t1, T& t2) const noexcept(noexcept(is_nothrow_move_constructible_v<T>&& is_nothrow_move_assignable_v<T>))
->enable_if_t<move_constructible<T>&& assignable_from<T&, T>>
{
auto temp(AZStd::move(t1));
t1 = AZStd::move(t2);
t2 = AZStd::move(temp);
}
};
}
namespace AZStd::ranges
{
inline namespace customization_point_object
{
inline constexpr auto swap = Internal::swap_fn{};
}
}
namespace AZStd::Internal
{
template <class T, class = void>
constexpr bool swappable_impl = false;
template <class T>
constexpr bool swappable_impl<T, void_t<decltype(AZStd::ranges::swap(declval<T&>(), declval<T&>()))>> = true;
template <class T, class U, class = void>
constexpr bool swappable_with_impl = false;
template <class T, class U>
constexpr bool swappable_with_impl<T, U, enable_if_t<common_reference_with<T, U>
&& sfinae_trigger_v<
decltype(AZStd::ranges::swap(declval<T&>(), declval<T&>())),
decltype(AZStd::ranges::swap(declval<U&>(), declval<U&>())),
decltype(AZStd::ranges::swap(declval<T&>(), declval<U&>())),
decltype(AZStd::ranges::swap(declval<U&>(), declval<T&>()))>>> = true;
}
namespace AZStd
{
template <class T>
/*concept*/ constexpr bool signed_integral = integral<T> && is_signed_v<T>;
template <class T>
/*concept*/ constexpr bool unsigned_integral = integral<T> && !signed_integral<T>;
template<class T>
/*concept*/ constexpr bool swappable = Internal::swappable_impl<T>;
template<class T, class U>
/*concept*/ constexpr bool swappable_with = Internal::swappable_with_impl<T, U>;
}
namespace AZStd::Internal
{
// boolean-testable concept (exposition only in the C++standard)
template<class T>
constexpr bool boolean_testable_impl = convertible_to<T, bool>;
template<class T, class = void>
constexpr bool boolean_testable = false;
template<class T>
constexpr bool boolean_testable<T, enable_if_t<boolean_testable_impl<T> && boolean_testable_impl<decltype(!declval<T>())>>> = true;
// weakly comparable ==, !=
template<class T, class U, class = void>
constexpr bool weakly_equality_comparable_with = false;
template<class T, class U>
constexpr bool weakly_equality_comparable_with<T, U, enable_if_t<
boolean_testable<decltype(declval<AZStd::remove_reference_t<T>&>() == declval<AZStd::remove_reference_t<U>&>())>
&& boolean_testable<decltype(declval<AZStd::remove_reference_t<T>&>() != declval<AZStd::remove_reference_t<U>&>())>
&& boolean_testable<decltype(declval<AZStd::remove_reference_t<U>&>() == declval<AZStd::remove_reference_t<T>&>())>
&& boolean_testable<decltype(declval<AZStd::remove_reference_t<U>&>() != declval<AZStd::remove_reference_t<T>&>())>
>> = true;
// partially ordered <, >, <=, >=
template<class, class U, class = void>
constexpr bool partially_ordered_with_impl = false;
template<class T, class U>
constexpr bool partially_ordered_with_impl<T, U, enable_if_t<
boolean_testable<decltype(declval<const remove_reference_t<T>&>() < declval<const remove_reference_t<U>&>())>
&& boolean_testable<decltype(declval<const remove_reference_t<T>&>() > declval<const remove_reference_t<U>&>())>
&& boolean_testable<decltype(declval<const remove_reference_t<T>&>() <= declval<const remove_reference_t<U>&>())>
&& boolean_testable<decltype(declval<const remove_reference_t<T>&>() >= declval<const remove_reference_t<U>&>())>
&& boolean_testable<decltype(declval<const remove_reference_t<U>&>() < declval<const remove_reference_t<T>&>())>
&& boolean_testable<decltype(declval<const remove_reference_t<U>&>() > declval<const remove_reference_t<T>&>())>
&& boolean_testable<decltype(declval<const remove_reference_t<U>&>() <= declval<const remove_reference_t<T>&>())>
&& boolean_testable<decltype(declval<const remove_reference_t<U>&>() >= declval<const remove_reference_t<T>&>())>
>> = true;
}
namespace AZStd
{
template<class T>
/*concept*/ constexpr bool equality_comparable = Internal::weakly_equality_comparable_with<T, T>;
}
namespace AZStd::Internal
{
// equally_comparable + partially ordered
template<class, class U, class = void>
constexpr bool equally_comparable_with_impl = false;
template<class T, class U>
constexpr bool equally_comparable_with_impl<T, U, enable_if_t<equality_comparable<T>
&& equality_comparable<U>
&& common_reference_with<const remove_reference_t<T>&, const remove_reference_t<U>&>
&& equality_comparable<common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>>
&& Internal::weakly_equality_comparable_with<T, U>
>> = true;
}
namespace AZStd
{
template<class T, class U>
/*concept*/ constexpr bool equality_comparable_with = Internal::equally_comparable_with_impl<T, U>;
template<class T, class U>
/*concept*/ constexpr bool partially_ordered_with = Internal::partially_ordered_with_impl<T, U>;
template<class T>
/*concept*/ constexpr bool totally_ordered = equality_comparable<T> && partially_ordered_with<T, T>;
}
namespace AZStd::Internal
{
// equally_comparable + partially ordered
template<class, class U, class = void>
constexpr bool totally_ordered_with_impl = false;
template<class T, class U>
constexpr bool totally_ordered_with_impl<T, U, enable_if_t<totally_ordered<T>&& totally_ordered<U>
&& equality_comparable_with<T, U>
&& totally_ordered<common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>>
&& partially_ordered_with<T, U>
>> = true;
}
namespace AZStd
{
template<class T, class U>
/*concept*/ constexpr bool totally_ordered_with = Internal::totally_ordered_with_impl<T, U>;
}
namespace AZStd::Internal
{
template<class T, class = void>
inline constexpr bool is_default_initializable = false;
template<class T>
inline constexpr bool is_default_initializable<T, void_t<decltype(::new T)>> = true;
template<class T, class = void>
constexpr bool default_initializable_impl = false;
template<class T>
constexpr bool default_initializable_impl < T, enable_if_t < constructible_from<T>
&& sfinae_trigger_v<decltype(T{}) > && Internal::is_default_initializable<T> >> = true;
template <class T, class = void>
constexpr bool movable_impl = false;
template <class T>
constexpr bool movable_impl<T, enable_if_t<is_object_v<T> && move_constructible<T> &&
assignable_from<T&, T> && swappable<T>> > = true;
template <class T, class = void>
constexpr bool copy_constructible_impl = false;
template <class T>
constexpr bool copy_constructible_impl<T, enable_if_t<move_constructible<T> &&
constructible_from<T, T&> && convertible_to<T&, T> &&
constructible_from<T, const T&> && convertible_to<const T&, T> &&
constructible_from<T, const T> && convertible_to<const T, T>> > = true;
}
namespace AZStd
{
// movable
template <class T>
/*concept*/ constexpr bool movable = Internal::movable_impl<T>;
// default_initializable
template<class T>
/*concept*/ constexpr bool default_initializable = Internal::default_initializable_impl<T>;
// copy constructible
template<class T>
/*concept*/ constexpr bool copy_constructible = Internal::copy_constructible_impl<T>;
}
namespace AZStd::Internal
{
template <class T, class = void>
constexpr bool copyable_impl = false;
template <class T>
constexpr bool copyable_impl<T, enable_if_t<copy_constructible<T> && movable<T> && assignable_from<T&, T&> &&
assignable_from<T&, const T&> && assignable_from<T&, const T>> > = true;
}
namespace AZStd
{
// copyable
template<class T>
/*concept*/ constexpr bool copyable = Internal::copyable_impl<T>;
// semiregular
template<class T>
/*concept*/ constexpr bool semiregular = copyable<T> && default_initializable<T>;
// regular
template<class T>
/*concept*/ constexpr bool regular = semiregular<T> && equality_comparable<T>;
}
// Iterator Concepts
namespace AZStd::Internal
{
template <class T>
constexpr bool is_integer_like = integral<T> && !same_as<T, bool>;
template <class T>
constexpr bool is_signed_integer_like = signed_integral<T>;
template <class T, class = void>
constexpr bool weakly_incrementable_impl = false;
template <class T>
constexpr bool weakly_incrementable_impl<T, enable_if_t<movable<T>
&& is_signed_integer_like<iter_difference_t<T>>
&& same_as<decltype(++declval<T&>()), T&>
&& sfinae_trigger_v<decltype(declval<T&>()++)> >> = true;
}
namespace AZStd
{
// models weakly_incrementable concept
template <class T>
/*concept*/ constexpr bool weakly_incrementable = Internal::weakly_incrementable_impl<T>;
// models input_or_output_iterator concept
template <class T>
/*concept*/ constexpr bool input_or_output_iterator = !is_void_v<T>
&& weakly_incrementable<T>;
}
namespace AZStd::Internal
{
template <class T, class = void>
constexpr bool incrementable_impl = false;
template <class T>
constexpr bool incrementable_impl<T, enable_if_t<regular<T>
&& weakly_incrementable<T>
&& same_as<decltype(declval<T&>()++), T> >> = true;
}
namespace AZStd
{
template <class T>
/*concept*/ constexpr bool incrementable = Internal::incrementable_impl<T>;
}
namespace AZStd
{
template<class S, class I>
/*concept*/ constexpr bool sentinel_for = semiregular<S> &&
input_or_output_iterator<I> &&
Internal::weakly_equality_comparable_with<S, I>;
template<class S, class I>
inline constexpr bool disable_sized_sentinel_for = false;
}
namespace AZStd::Internal
{
template<class S, class I, class = void>
/*concept*/ constexpr bool sized_sentinel_for_impl = false;
template<class S, class I>
/*concept*/ constexpr bool sized_sentinel_for_impl<S, I, enable_if_t<
sentinel_for<S, I>
&& !disable_sized_sentinel_for<remove_cv_t<S>, remove_cv_t<I>>
&& same_as<decltype(declval<S>() - declval<I>()), iter_difference_t<I>>
&& same_as<decltype(declval<I>() - declval<S>()), iter_difference_t<I>> >> = true;
}
namespace AZStd
{
template<class S, class I>
/*concept*/ constexpr bool sized_sentinel_for = Internal::sized_sentinel_for_impl<S, I>;
template<class I>
struct iterator_traits;
}
namespace AZStd::Internal
{
// ITER_CONCEPT(I) general concept
template<class I, class = void>
constexpr bool use_traits_iterator_concept_for_concept = false;
template<class I>
constexpr bool use_traits_iterator_concept_for_concept<I, void_t<typename iterator_traits<I>::iterator_concept>> = true;
template<class I, class = void>
constexpr bool use_traits_iterator_category_for_concept = false;
template<class I>
constexpr bool use_traits_iterator_category_for_concept<I,
void_t<typename iterator_traits<I>::iterator_category>> = !use_traits_iterator_concept_for_concept<I>;
template<class I, class = void>
constexpr bool use_random_access_iterator_tag_for_concept = false;
template<class I>
constexpr bool use_random_access_iterator_tag_for_concept<I,
void_t<iterator_traits<I>>> = !use_traits_iterator_concept_for_concept<I>
&& !use_traits_iterator_category_for_concept<I>;
template<class I, class = void>
struct iter_concept;
template<class I>
struct iter_concept<I, enable_if_t<use_traits_iterator_concept_for_concept<I>>>
{
using type = typename iterator_traits<I>::iterator_concept;
};
template<class I>
struct iter_concept<I, enable_if_t<use_traits_iterator_category_for_concept<I>>>
{
using type = typename iterator_traits<I>::iterator_category;
};
template<class I>
struct iter_concept<I, enable_if_t<use_random_access_iterator_tag_for_concept<I>>>
{
using type = random_access_iterator_tag;
};
template<class I>
using iter_concept_t = typename iter_concept<I>::type;
}
namespace AZStd
{
// indirectly readable
template <class In>
/*concept*/ constexpr bool indirectly_readable = Internal::indirectly_readable_impl<remove_cvref_t<In>>;
}
namespace AZStd::Internal
{
// model the indirectly writable concept
template <class Out, class T, class = void>
constexpr bool indirectly_writable_impl = false;
template <class Out, class T>
constexpr bool indirectly_writable_impl<Out, T, void_t<
decltype(*declval<Out&>() = declval<T>()),
decltype(*declval<Out>() = declval<T>()),
decltype(const_cast<const iter_reference_t<Out>&&>(*declval<Out&>()) = declval<T>()),
decltype(const_cast<const iter_reference_t<Out>&&>(*declval<Out>()) = declval<T>())>
> = true;
}
namespace AZStd
{
// indirectly writable
template <class Out, class T>
/*concept*/ constexpr bool indirectly_writable = Internal::indirectly_writable_impl<Out, T>;
// indirectly movable
template<class In, class Out>
/*concept*/ constexpr bool indirectly_movable = indirectly_readable<In> && indirectly_writable<Out, iter_rvalue_reference_t<In>>;
}
namespace AZStd::Internal
{
template<class In, class Out, class = void>
constexpr bool indirectly_movable_storage_impl = false;
template<class In, class Out>
constexpr bool indirectly_movable_storage_impl<In, Out, enable_if_t<
indirectly_movable<In, Out> &&
indirectly_writable<Out, iter_value_t<In>> &&
movable<iter_value_t<In>> &&
constructible_from<iter_value_t<In>, iter_rvalue_reference_t<In>> &&
assignable_from<iter_value_t<In>&, iter_rvalue_reference_t<In>>> > = true;
}
namespace AZStd
{
template<class In, class Out>
/*concept*/ constexpr bool indirectly_movable_storable = Internal::indirectly_movable_storage_impl<In, Out>;
}
namespace AZStd::Internal
{
template<class In, class Out, class = void>
constexpr bool indirectly_copyable_impl = false;
template<class In, class Out>
constexpr bool indirectly_copyable_impl<In, Out, enable_if_t<
indirectly_readable<In> &&
indirectly_writable<Out, iter_reference_t<In>>> > = true;
}
namespace AZStd
{
// indirectly copyable
template<class In, class Out>
/*concept*/ constexpr bool indirectly_copyable = Internal::indirectly_copyable_impl<In, Out>;
}
namespace AZStd::Internal
{
template<class In, class Out, class = void>
constexpr bool indirectly_copyable_storable_impl = false;
template<class In, class Out>
constexpr bool indirectly_copyable_storable_impl<In, Out, enable_if_t<
indirectly_copyable<In, Out> &&
indirectly_writable<Out, iter_value_t<In>&> &&
indirectly_writable<Out, const iter_value_t<In>&> &&
indirectly_writable<Out, iter_value_t<In>&&> &&
indirectly_writable<Out, const iter_value_t<In>&&> &&
copyable<iter_value_t<In>> &&
constructible_from<iter_value_t<In>, iter_reference_t<In>> &&
assignable_from<iter_value_t<In>&, iter_reference_t<In>>> > = true;
}
namespace AZStd
{
template<class In, class Out>
/*concept*/ constexpr bool indirectly_copyable_storable = Internal::indirectly_copyable_storable_impl<In, Out>;
}
namespace AZStd::ranges::Internal
{
template<class I1, class I2>
void iter_swap(I1, I2) = delete;
template <class I1, class I2, class = void>
constexpr bool iter_swap_adl = false;
template <class I1, class I2>
constexpr bool iter_swap_adl<I1, I2, void_t<decltype(iter_swap(declval<I1>(), declval<I2>()))>> = true;
template <class I1, class I2, class = void>
constexpr bool is_class_or_enum_with_iter_swap_adl = false;
template <class I1, class I2>
constexpr bool is_class_or_enum_with_iter_swap_adl<I1, I2, enable_if_t<iter_swap_adl<I1, I2>
&& (is_class_v<remove_cvref_t<I1>> || is_enum_v<remove_cvref_t<I1>>)
&& (is_class_v<remove_cvref_t<I2>> || is_enum_v<remove_cvref_t<I2>>)>> = true;
struct iter_swap_fn
{
template <class I1, class I2>
constexpr auto operator()(I1&& i1, I2&& i2) const
->enable_if_t<is_class_or_enum_with_iter_swap_adl<I1, I2>
>
{
iter_swap(AZStd::forward<I1>(i1), AZStd::forward<I1>(i2));
}
template <class I1, class I2>
constexpr auto operator()(I1&& i1, I2&& i2) const
->enable_if_t<!is_class_or_enum_with_iter_swap_adl<I1, I2>
&& indirectly_readable<I1>
&& indirectly_readable<I2>
&& swappable_with<iter_reference_t<I1>, iter_reference_t<I2>>
>
{
ranges::swap(*i1, *i2);
}
template <class I1, class I2>
constexpr auto operator()(I1&& i1, I2&& i2) const
->enable_if_t<!is_class_or_enum_with_iter_swap_adl<I1, I2>
&& indirectly_movable_storable<I1, I2>
&& indirectly_movable_storable<I2, I1>
>
{
*AZStd::forward<I1>(i1) = iter_exchange_move(AZStd::forward<I2>(i2), AZStd::forward<I1>(i1));
}
private:
template<class X, class Y>
static constexpr iter_value_t<X> iter_exchange_move(X&& x, Y&& y)
noexcept(noexcept(iter_value_t<X>(iter_move(x))) && noexcept(*x = iter_move(y)))
{
iter_value_t<X> old_value(iter_move(x));
*x = iter_move(y);
return old_value;
}
};
}
namespace AZStd::ranges
{
inline namespace customization_point_object
{
inline constexpr Internal::iter_swap_fn iter_swap{};
}
}
namespace AZStd::Internal
{
template <class I1, class I2, class = void>
constexpr bool indirectly_swappable_impl = false;
template <class I1, class I2>
constexpr bool indirectly_swappable_impl<I1, I2, enable_if_t<
indirectly_readable<I1>&& indirectly_readable<I2>
&& sfinae_trigger_v<
decltype(AZStd::ranges::iter_swap(declval<I1>(), declval<I1>())),
decltype(AZStd::ranges::iter_swap(declval<I2>(), declval<I2>())),
decltype(AZStd::ranges::iter_swap(declval<I1>(), declval<I2>())),
decltype(AZStd::ranges::iter_swap(declval<I2>(), declval<I1>()))>>> = true;
}
namespace AZStd
{
template<class I1, class I2 = I1>
/*concept*/ constexpr bool indirectly_swappable = Internal::indirectly_swappable_impl<I1, I2>;
}
namespace AZStd::Internal
{
template<class I, class = void>
constexpr bool input_iterator_impl = false;
template<class I>
constexpr bool input_iterator_impl<I, enable_if_t<input_or_output_iterator<I>
&& derived_from<iter_concept_t<I>, input_iterator_tag>
&& indirectly_readable<I>
>> = true;
}
namespace AZStd
{
// input iterator
template<class I>
/*concept*/ constexpr bool input_iterator = Internal::input_iterator_impl<I>;
}
namespace AZStd::Internal
{
template<class I, class T, class = void>
constexpr bool output_iterator_impl = false;
template<class I, class T>
constexpr bool output_iterator_impl<I, T, enable_if_t<input_or_output_iterator<I>
&& indirectly_writable<I, T>
&& sfinae_trigger_v<decltype(*declval<I&>()++ = AZStd::declval<T>())>
>> = true;
}
namespace AZStd
{
// output iterator
template<class I, class T>
/*concept*/ constexpr bool output_iterator = Internal::output_iterator_impl<I, T>;
}
namespace AZStd::Internal
{
template<class I, class = void>
constexpr bool forward_iterator_impl = false;
template<class I>
constexpr bool forward_iterator_impl<I, enable_if_t<input_iterator<I>
&& derived_from<Internal::iter_concept_t<I>, forward_iterator_tag>
&& incrementable<I>
&& sentinel_for<I, I>> > = true;
}
namespace AZStd
{
// forward_iterator
template<class I>
/*concept*/ constexpr bool forward_iterator = Internal::forward_iterator_impl<I>;
}
namespace AZStd::Internal
{
template<class I, class = void>
constexpr bool bidirectional_iterator_impl = false;
template<class I>
constexpr bool bidirectional_iterator_impl<I, enable_if_t<forward_iterator<I>
&& derived_from<iter_concept_t<I>, bidirectional_iterator_tag>
&& same_as<decltype(--declval<I&>()), I&>
&& same_as<decltype(declval<I&>()--), I> >> = true;
}
namespace AZStd
{
// bidirectional iterator
template<class I>
/*concept*/ constexpr bool bidirectional_iterator = Internal::bidirectional_iterator_impl<I>;
}
namespace AZStd::Internal
{
template<class I, class = void>
constexpr bool random_access_iterator_impl = false;
template<class I>
constexpr bool random_access_iterator_impl<I, enable_if_t<bidirectional_iterator<I>
&& derived_from<iter_concept_t<I>, random_access_iterator_tag>
&& totally_ordered<I>
&& sized_sentinel_for<I, I>
&& same_as<decltype(declval<I&>() += declval<const iter_difference_t<I>>()), I&>
&& same_as<decltype(declval<const I>() + declval<const iter_difference_t<I>>()), I>
&& same_as<decltype(declval<iter_difference_t<I>>() + declval<const I>()), I>
&& same_as<decltype(declval<I&>() -= declval<const iter_difference_t<I>>()), I&>
&& same_as<decltype(declval<const I>() - declval<const iter_difference_t<I>>()), I>
&& same_as<decltype(declval<const I&>()[declval<iter_difference_t<I>>()]), iter_reference_t<I>>>>
= true;
}
namespace AZStd
{
template<class I>
/*concept*/ constexpr bool random_access_iterator = Internal::random_access_iterator_impl<I>;
}
namespace AZStd::Internal
{
template<class I, class = void>
constexpr bool contiguous_iterator_impl = false;
template<class I>
constexpr bool contiguous_iterator_impl<I, enable_if_t<random_access_iterator<I>
&& derived_from<iter_concept_t<I>, contiguous_iterator_tag>
&& is_lvalue_reference_v<iter_reference_t<I>>
&& indirectly_readable<I>
&& same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>>
> >
= same_as<decltype(to_address(declval<const I&>())), add_pointer_t<iter_reference_t<I>>>;
}
namespace AZStd
{
// contiguous iterator
template<class I>
/*concept*/ constexpr bool contiguous_iterator = Internal::contiguous_iterator_impl<I>;
}
namespace AZStd::Internal
{
// models the predicate concept
template <bool, class F, class... Args>
constexpr bool predicate_impl = false;
template <class F, class... Args>
constexpr bool predicate_impl<true, F, Args...> = Internal::boolean_testable<invoke_result_t<F, Args...>>;
}
namespace AZStd
{
// models the predicate concept
template <class F, class... Args>
/*concept*/ constexpr bool predicate = Internal::predicate_impl<regular_invocable<F, Args...>, F, Args...>;
// models the relation concept
template <class R, class T, class U>
/*concept*/ constexpr bool relation = predicate<R, T, T> && predicate<R, U, U>
&& predicate<R, T, U> && predicate<R, U, T>;
// models the equivalence_relation concept
template <class R, class T, class U>
/*concept*/ constexpr bool equivalence_relation = relation<R, T, U>;
// models the strict_weak_order concept
// Note: semantically this is different than equivalence_relation
template <class R, class T, class U>
/*concept*/ constexpr bool strict_weak_order = relation<R, T, U>;
}
@@ -135,9 +135,10 @@ namespace AZStd
AZ_FORCE_INLINE this_type& operator--() { --m_offset; return *this; }
AZ_FORCE_INLINE this_type operator--(int) { this_type tmp = *this; --m_offset; return tmp; }
AZ_FORCE_INLINE this_type& operator+=(difference_type offset) { m_offset += offset; return *this; }
AZ_FORCE_INLINE this_type operator+(difference_type offset) { this_type tmp = *this; tmp += offset; return tmp; }
AZ_FORCE_INLINE this_type operator+(difference_type offset) const { this_type tmp = *this; tmp += offset; return tmp; }
friend AZ_FORCE_INLINE this_type operator+(difference_type offset, const this_type& rhs) { this_type tmp = rhs; tmp += offset; return tmp; }
AZ_FORCE_INLINE this_type& operator-=(difference_type offset) { m_offset -= offset; return *this; }
AZ_FORCE_INLINE this_type operator-(difference_type offset) { this_type tmp = *this; tmp -= offset; return tmp; }
AZ_FORCE_INLINE this_type operator-(difference_type offset) const { this_type tmp = *this; tmp -= offset; return tmp; }
/// ???
AZ_FORCE_INLINE difference_type operator-(const this_type& rhs) const
{
@@ -197,9 +198,10 @@ namespace AZStd
AZ_FORCE_INLINE this_type& operator--() { --base_type::m_offset; return *this; }
AZ_FORCE_INLINE this_type operator--(int) { this_type tmp = *this; --base_type::m_offset; return tmp; }
AZ_FORCE_INLINE this_type& operator+=(difference_type offset) { base_type::m_offset += offset; return *this; }
AZ_FORCE_INLINE this_type operator+(difference_type offset) { this_type tmp = *this; tmp += offset; return tmp; }
AZ_FORCE_INLINE this_type operator+(difference_type offset) const { this_type tmp = *this; tmp += offset; return tmp; }
friend AZ_FORCE_INLINE this_type operator+(difference_type offset, const this_type& rhs) { this_type tmp = rhs; tmp += offset; return tmp; }
AZ_FORCE_INLINE this_type& operator-=(difference_type offset) { base_type::m_offset -= offset; return *this; }
AZ_FORCE_INLINE this_type operator-(difference_type offset) { this_type tmp = *this; tmp -= offset; return tmp; }
AZ_FORCE_INLINE this_type operator-(difference_type offset) const { this_type tmp = *this; tmp -= offset; return tmp; }
AZ_FORCE_INLINE difference_type operator-(const this_type& rhs) const
{
return rhs.m_offset <= base_type::m_offset ? base_type::m_offset - rhs.m_offset : -(difference_type)(rhs.m_offset - base_type::m_offset);
@@ -9,6 +9,7 @@
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/concepts/concepts.h>
#include <AzCore/std/createdestroy.h>
#include <AzCore/std/typetraits/typetraits.h>
@@ -101,7 +102,7 @@ namespace AZStd::Internal
//! Invokes destructor on all elements in range
//! No-op on empty container
//! Nothing to destroy since the storage is empty.
template <typename InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt>>>
template <typename InputIt, typename = enable_if_t<input_iterator<InputIt>>>
static constexpr void unsafe_destroy(InputIt, InputIt) noexcept
{
}
@@ -214,7 +215,7 @@ namespace AZStd::Internal
//! Destructs elements in the range [begin, end).
//! This does not modify the size of the storage
//! This is a no-op for trivial types
template <typename InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt>>>
template <typename InputIt, typename = enable_if_t<input_iterator<InputIt>>>
void unsafe_destroy(InputIt, InputIt) noexcept
{
}
@@ -334,7 +335,7 @@ namespace AZStd::Internal
//! Destructs elements in the range [begin, end).
//! This does not modify the size of the storage
//! Invokes the destuctor via the AZStd::destroy method
template <typename InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt>>>
template <typename InputIt, typename = enable_if_t<input_iterator<InputIt>>>
void unsafe_destroy(InputIt first, InputIt last) noexcept(is_nothrow_destructible_v<value_type>)
{
AZSTD_CONTAINER_ASSERT(first >= data() && first <= data() + size(), "begin iterator is not in range of storage");
@@ -410,7 +411,7 @@ namespace AZStd
AZStd::uninitialized_fill_n(data(), numElements, value);
}
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
template <class InputIt, typename = AZStd::enable_if_t<input_iterator<InputIt>>>
fixed_vector(InputIt first, InputIt last)
{
resize_no_construct(AZStd::distance(first, last));
@@ -615,7 +616,7 @@ namespace AZStd
insert(end(), numElements, value);
}
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
template <class InputIt, typename = AZStd::enable_if_t<input_iterator<InputIt>>>
void assign(InputIt first, InputIt last)
{
clear();
@@ -641,8 +642,18 @@ namespace AZStd
return &newElement;
}
AZStd::uninitialized_move(insertPosPtr, dataEnd, insertPosPtr + 1);
// We need to move data with care, it is overlapping.
// first move the last element into the uninitialized position as that will not overlap.
pointer nonOverlap = dataEnd - 1;
AZStd::uninitialized_move(nonOverlap, dataEnd, dataEnd);
// copy the memory backwards while performing AZStd::move on the existing elements the area with overlapping memory
// to move the elments to the right by 1
AZStd::move_backward(insertPosPtr, nonOverlap, dataEnd);
// add new elements
AZStd::construct_at(insertPosPtr, AZStd::forward<Args>(args)...);
resize_no_construct(size() + 1);
return iterator(insertPosPtr);
}
iterator insert(const_iterator insertPos, const_reference value)
@@ -707,7 +718,7 @@ namespace AZStd
}
}
template<class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
template<class InputIt, typename = AZStd::enable_if_t<input_iterator<InputIt>>>
void insert(const_iterator insertPos, InputIt first, InputIt last)
{
// specialize for iterator categories.
@@ -7,9 +7,37 @@
*/
#pragma once
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/std/containers/array.h>
#include <AzCore/std/limits.h>
#include <AzCore/std/ranges/ranges.h>
#include <AzCore/std/typetraits/type_identity.h>
namespace AZStd
{
inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
template <class T, size_t Extent = dynamic_extent>
class span;
}
namespace AZStd::Internal
{
template <class T>
inline constexpr bool is_std_array = false;
template <class U, size_t N>
inline constexpr bool is_std_array<::AZStd::array<U, N>> = true;
template <class T>
inline constexpr bool is_std_span = false;
template <class U, size_t Extent>
inline constexpr bool is_std_span<::AZStd::span<U, Extent>> = true;
template <class T, class U>
inline constexpr bool is_array_convertible = is_convertible_v<T(*)[], U(*)[]>;
}
namespace AZStd
{
@@ -33,97 +61,149 @@ namespace AZStd
*
* Since the span does not copy and store any data, it is only valid as long as the data used to create it is valid.
*/
template <class T>
class span final
template <class T, size_t Extent>
class span
{
public:
using element_type = T;
using value_type = AZStd::remove_cv_t<T>;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using size_type = AZStd::size_t;
using difference_type = AZStd::ptrdiff_t;
using iterator = T*;
using const_iterator = const T*;
using pointer = element_type*;
using const_pointer = const element_type*;
using reference = element_type&;
using const_reference = const element_type&;
using iterator = element_type*;
using const_iterator = const element_type*;
using reverse_iterator = AZStd::reverse_iterator<iterator>;
using const_reverse_iterator = AZStd::reverse_iterator<const_iterator>;
constexpr span();
inline static constexpr size_t extent = Extent;
constexpr span() noexcept = default;;
~span() = default;
constexpr span(pointer s, size_type length);
template <class It, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
Extent == dynamic_extent>* = nullptr>
constexpr span(It first, size_type length);
constexpr span(pointer first, pointer last);
template <class It, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
Extent != dynamic_extent, int> = 0>
constexpr explicit span(It first, size_type length);
// We explicitly delete this constructor because it's too easy to accidentally
// create a span to just the first element instead of an entire array.
constexpr span(const_pointer s) = delete;
template <class It, class End, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
sized_sentinel_for<End, It> &&
Extent == dynamic_extent>* = nullptr>
constexpr span(It first, End last);
template<typename Container>
constexpr span(Container& data);
template <class It, class End, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
sized_sentinel_for<End, It> &&
Extent != dynamic_extent, int> = 0>
constexpr explicit span(It first, End last);
template<typename Container>
constexpr span(const Container& data);
template<size_t N, class = enable_if_t<N == dynamic_extent || N == Extent>>
constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;
constexpr span(const span&) = default;
template <class U, size_t N, class = enable_if_t<N == dynamic_extent || N == Extent>>
constexpr span(array<U, N>& data) noexcept;
template <class U, size_t N, class = enable_if_t<N == dynamic_extent || N == Extent>>
constexpr span(const array<U, N>& data) noexcept;
constexpr span(span&& other);
template <class R, class = enable_if_t<ranges::contiguous_range<R> &&
ranges::sized_range<R> &&
(ranges::borrowed_range<R> || is_const_v<element_type>) &&
!Internal::is_std_span<remove_cvref_t<R>> &&
!Internal::is_std_array<remove_cvref_t<R>> &&
!is_array_v<remove_cvref_t<R>> &&
Internal::is_array_convertible<remove_reference_t<ranges::range_reference_t<R>>, element_type> >>
constexpr span(R&& r);
template <class U, size_t OtherExtent, class = enable_if_t<
(extent == dynamic_extent || OtherExtent == dynamic_extent || extent == OtherExtent)
&& Internal::is_array_convertible<U, element_type> >>
constexpr span(const span<U, OtherExtent>& other);
constexpr span(const span&) noexcept = default;
constexpr span& operator=(const span& other) = default;
constexpr span& operator=(span&& other);
// subviews -> https://eel.is/c++draft/views#span.sub
template <size_t Count>
constexpr span<element_type, Count> first() const;
template <size_t Count>
constexpr span<element_type, Count> last() const;
template <size_t Offset, size_t Count = dynamic_extent>
constexpr auto subspan() const;
constexpr size_type size() const;
constexpr span<element_type, dynamic_extent> first(size_type count) const;
constexpr span<element_type, dynamic_extent> last(size_type count) const;
constexpr span<element_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent) const;
constexpr bool empty() const;
// observers - https://eel.is/c++draft/views#span.obs
constexpr size_type size() const noexcept;
constexpr size_type size_bytes() const noexcept;
constexpr pointer data();
constexpr const_pointer data() const;
[[nodiscard]] constexpr bool empty() const noexcept;
constexpr const_reference operator[](size_type index) const;
constexpr reference operator[](size_type index);
// element access - https://eel.is/c++draft/views#span.elem
constexpr reference operator[](size_type index) const;
constexpr reference front() const;
constexpr reference back() const;
constexpr pointer data() const noexcept;
constexpr void erase();
// iterator support - https://eel.is/c++draft/views#span.iterators
constexpr iterator begin() const noexcept;
constexpr iterator end() const noexcept;
constexpr iterator begin();
constexpr iterator end();
constexpr const_iterator begin() const;
constexpr const_iterator end() const;
constexpr const_iterator cbegin() const;
constexpr const_iterator cend() const;
constexpr reverse_iterator rbegin();
constexpr reverse_iterator rend();
constexpr const_reverse_iterator rbegin() const;
constexpr const_reverse_iterator rend() const;
constexpr const_reverse_iterator crbegin() const;
constexpr const_reverse_iterator crend() const;
friend bool operator==(span lhs, span rhs)
{
return lhs.m_begin == rhs.m_begin && lhs.m_end == rhs.m_end;
}
friend bool operator!=(span lhs, span rhs) { return !(lhs == rhs); }
friend bool operator< (span lhs, span rhs) { return lhs.m_begin < rhs.m_begin || lhs.m_begin == rhs.m_begin && lhs.m_end < rhs.m_end; }
friend bool operator> (span lhs, span rhs) { return lhs.m_begin > rhs.m_begin || lhs.m_begin == rhs.m_begin && lhs.m_end > rhs.m_end; }
friend bool operator<=(span lhs, span rhs) { return lhs == rhs || lhs < rhs; }
friend bool operator>=(span lhs, span rhs) { return lhs == rhs || lhs > rhs; }
constexpr reverse_iterator rbegin() const noexcept;
constexpr reverse_iterator rend() const noexcept;
private:
pointer m_begin;
pointer m_end;
pointer m_data{};
size_type m_size{};
};
// deduction guides https://eel.is/c++draft/views#span.deduct
template <class It, class EndOrSize, class = enable_if_t<contiguous_iterator<It>>>
span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>>;
// array deductions
template <class T, size_t N>
span(T(&)[N]) -> span<T, N>;
template <class T, size_t N>
span(array<T, N>&) -> span<T, N>;
template <class T, size_t N>
span(const array<T, N>&) -> span<const T, N>;
template <class R, class = enable_if_t<ranges::contiguous_range<R>>>
span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
// [span.objectrep], views of object representation
template <class ElementType, size_t Extent>
auto as_bytes(span<ElementType, Extent> s) noexcept
-> span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>;
template <class ElementType, size_t Extent>
auto as_writable_bytes(span<ElementType, Extent> s) noexcept
-> enable_if_t<!is_const_v<ElementType>, span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>>;
} // namespace AZStd
namespace AZStd::ranges
{
template<class ElementType, size_t Extent>
inline constexpr bool enable_view<span<ElementType, Extent>> = true;
template<class ElementType, size_t Extent>
inline constexpr bool enable_borrowed_range<span<ElementType, Extent>> = true;
}
#include <AzCore/std/containers/span.inl>
@@ -9,116 +9,206 @@
namespace AZStd
{
template <class Element>
inline constexpr span<Element>::span()
: m_begin(nullptr)
, m_end(nullptr)
{ }
template <class T, size_t Extent>
template <class It, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
Extent == dynamic_extent>*>
inline constexpr span<T, Extent>::span(It first, size_type length)
: m_data{ to_address(first) }
, m_size{ length }
{}
template <class Element>
inline constexpr span<Element>::span(pointer s, size_type length)
: m_begin(s)
, m_end(m_begin + length)
template <class T, size_t Extent>
template <class It, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
Extent != dynamic_extent, int>>
inline constexpr span<T, Extent>::span(It first, size_type length)
: m_data{ to_address(first) }
, m_size{ length }
{}
template <class T, size_t Extent>
template <class It, class End, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
sized_sentinel_for<End, It> &&
Extent == dynamic_extent>*>
inline constexpr span<T, Extent>::span(It first, End last)
: m_data{to_address(first)}
, m_size(last - first)
{}
template <class T, size_t Extent>
template <class It, class End, enable_if_t<contiguous_iterator<It> &&
Internal::is_array_convertible<remove_reference_t<iter_reference_t<It>>, T> &&
sized_sentinel_for<End, It> &&
Extent != dynamic_extent, int>>
inline constexpr span<T, Extent>::span(It first, End last)
: m_data{to_address(first)}
, m_size(last - first)
{}
template <class T, size_t Extent>
template <size_t N, class>
inline constexpr span<T, Extent>::span(type_identity_t<element_type>(&arr)[N]) noexcept
: m_data{ arr }
, m_size{ N }
{}
template <class T, size_t Extent>
template <class U, size_t N, class>
inline constexpr span<T, Extent>::span(array<U, N>& arr) noexcept
: m_data{ arr.data() }
, m_size{ arr.size() }
{}
template <class T, size_t Extent>
template <class U, size_t N, class>
inline constexpr span<T, Extent>::span(const array<U, N>& arr) noexcept
: m_data{ arr.data() }
, m_size{ arr.size() }
{}
template <class T, size_t Extent>
template <class R, class>
inline constexpr span<T, Extent>::span(R&& r)
: m_data{ ranges::data(r) }
, m_size{ ranges::size(r) }
{
if (length == 0) erase();
AZ_Assert(Extent == dynamic_extent || Extent == m_size, "The extent of the span is non dynamic,"
" therefore the range size must match the extent. Extent=%zu, Range size=%zu",
Extent, ranges::size(r));
}
template <class Element>
inline constexpr span<Element>::span(pointer first, pointer last)
: m_begin(first)
, m_end(last)
{ }
template<class Element>
template<typename Container>
inline constexpr span<Element>::span(Container& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }
template<class Element>
template<typename Container>
inline constexpr span<Element>::span(const Container& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }
template <class Element>
inline constexpr span<Element>::span(span&& other)
: span(other.m_begin, other.m_end)
template <class T, size_t Extent>
template <class U, size_t OtherExtent, class>
inline constexpr span<T, Extent>::span(const span<U, OtherExtent>& other)
: m_data{ other.data() }
, m_size{ other.size() }
{
#if AZ_DEBUG_BUILD // Clearing the original pointers isn't necessary, but is good for debugging
other.m_begin = nullptr;
other.m_end = nullptr;
#endif
AZ_Assert(Extent == dynamic_extent || Extent == m_size, "The extent of the span is non dynamic,"
" therefore the current size of the other span must match the extent. Extent=%zu, Other span size=%zu",
Extent, other.size());
}
template <class Element>
inline constexpr AZStd::size_t span<Element>::size() const { return m_end - m_begin; }
template <class Element>
inline constexpr bool span<Element>::empty() const { return m_end == m_begin; }
template <class Element>
inline constexpr Element* span<Element>::data() { return m_begin; }
template <class Element>
inline constexpr const Element* span<Element>::data() const { return m_begin; }
template <class Element>
inline constexpr span<Element>& span<Element>::operator=(span<Element>&& other)
// subviews
template <class T, size_t Extent>
template <size_t Count>
inline constexpr auto span<T, Extent>::first() const -> span<element_type, Count>
{
m_begin = other.m_begin;
m_end = other.m_end;
#if AZ_DEBUG_BUILD // Clearing the original pointers isn't necessary, but is good for debugging
other.m_begin = nullptr;
other.m_end = nullptr;
#endif
return *this;
static_assert(Count <= Extent, "Count is larger than the Extent of the span, a subview of the first"
" Count elemnts of the span cannot be returned");
AZ_Assert(Count <= size(), "Count %zu is larger than span size %zu", Count, size());
return span<element_type, Count>{data(), Count};
}
template <class Element>
inline constexpr const Element& span<Element>::operator[](AZStd::size_t index) const
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::first(size_type count) const -> span<element_type, dynamic_extent>
{
AZ_Assert(count <= size(), "Count %zu is larger than current size of span size %zu", count, size());
return { data(), count };
}
template <class T, size_t Extent>
template <size_t Count>
inline constexpr auto span<T, Extent>::last() const -> span<element_type, Count>
{
static_assert(Count <= Extent, "Count is larger than the Extent of the span, a subview of the last"
" Count elements of the span cannot be returned");
AZ_Assert(Count <= size(), "Count %zu is larger than span size %zu", Count, size());
return span<element_type, Count>{data() + (size() - Count), Count};
}
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::last(size_type count) const -> span<element_type, dynamic_extent>
{
AZ_Assert(count <= size(), "Count %zu is larger than span size %zu", count, size());
return { data() + (size() - count), count };
}
template <class T, size_t Extent>
template <size_t Offset, size_t Count>
inline constexpr auto span<T, Extent>::subspan() const
{
static_assert(Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset),
"Subspan Offset must <= span Extent and the Count must be either dynamic_extent"
" or <= (span Extent - Offset)");
AZ_Assert(Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset),
"Either the Subspan Offset %zu is larger than the span size %zu or the Count != dynamic_extent and"
" its value %zu is greater than \"span size - Offset\" %zu",
Offset, size(), Count, size() - Offset);
using return_type = span<element_type, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)>;
return return_type{ data() + Offset, Count != dynamic_extent ? Count : size() - Offset };
}
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::subspan(size_type offset, size_type count) const -> span<element_type, dynamic_extent>
{
AZ_Assert(offset <= size() && (count == dynamic_extent || count <= size() - offset),
"Either the Subspan offset %zu is larger than the span size %zu or the count != dynamic_extent and"
" its value %zu is greater than \"span size - offset\" %zu",
offset, size(), count, size() - offset);
return { data() + offset, count != dynamic_extent ? count : size() - offset };
}
// observers
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::size() const noexcept -> size_type { return m_size; }
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::size_bytes() const noexcept -> size_type { return m_size * sizeof(element_type); }
template <class T, size_t Extent>
[[nodiscard]] inline constexpr bool span<T, Extent>::empty() const noexcept{ return size() == 0; }
// element access
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::operator[](size_type index) const -> reference
{
AZ_Assert(index < size(), "index value is out of range");
return m_begin[index];
return data()[index];
}
template <class Element>
inline constexpr Element& span<Element>::operator[](AZStd::size_t index)
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::front() const -> reference
{
AZ_Assert(index < size(), "index value is out of range");
return m_begin[index];
AZ_Assert(!empty(), "span cannot be empty when invoking front");
return *data();
}
template <class Element>
inline constexpr void span<Element>::erase() { m_begin = m_end = nullptr; }
template <class Element>
inline constexpr Element* span<Element>::begin() { return m_begin; }
template <class Element>
inline constexpr Element* span<Element>::end() { return m_end; }
template <class Element>
inline constexpr const Element* span<Element>::begin() const { return m_begin; }
template <class Element>
inline constexpr const Element* span<Element>::end() const { return m_end; }
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::back() const -> reference
{
AZ_Assert(!empty(), "span cannot be empty when invoking back");
return *(data() + (size() - 1));
}
template <class Element>
inline constexpr const Element* span<Element>::cbegin() const { return m_begin; }
template <class Element>
inline constexpr const Element* span<Element>::cend() const { return m_end; }
// iterator support
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::data() const noexcept -> pointer { return m_data; }
template <class Element>
inline constexpr AZStd::reverse_iterator<Element*> span<Element>::rbegin() { return AZStd::reverse_iterator<Element*>(m_end); }
template <class Element>
inline constexpr AZStd::reverse_iterator<Element*> span<Element>::rend() { return AZStd::reverse_iterator<Element*>(m_begin); }
template <class Element>
inline constexpr AZStd::reverse_iterator<const Element*> span<Element>::rbegin() const { return AZStd::reverse_iterator<const Element*>(m_end); }
template <class Element>
inline constexpr AZStd::reverse_iterator<const Element*> span<Element>::rend() const { return AZStd::reverse_iterator<const Element*>(m_begin); }
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::begin() const noexcept -> iterator{ return m_data; }
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::end() const noexcept -> iterator { return m_data + m_size; }
template <class Element>
inline constexpr AZStd::reverse_iterator<const Element*> span<Element>::crbegin() const { return AZStd::reverse_iterator<const Element*>(cend()); }
template <class Element>
inline constexpr AZStd::reverse_iterator<const Element*> span<Element>::crend() const { return AZStd::reverse_iterator<const Element*>(cbegin()); }
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::rbegin() const noexcept -> reverse_iterator { return AZStd::make_reverse_iterator(end()); }
template <class T, size_t Extent>
inline constexpr auto span<T, Extent>::rend() const noexcept -> reverse_iterator { return AZStd::make_reverse_iterator(begin()); }
template <class ElementType, size_t Extent>
inline auto as_bytes(span<ElementType, Extent> s) noexcept
-> span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
{
return span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>(
reinterpret_cast<const byte*>(s.data()), s.size_bytes());
}
template <class ElementType, size_t Extent>
inline auto as_writable_bytes(span<ElementType, Extent> s) noexcept
-> enable_if_t<!is_const_v<ElementType>, span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>>
{
return span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>(
reinterpret_cast<byte*>(s.data()), s.size_bytes());
}
} // namespace AZStd
+357 -277
View File
@@ -7,22 +7,19 @@
*/
#pragma once
#include <AzCore/std/concepts/concepts.h>
#include <AzCore/std/iterator.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/is_array.h>
#include <AzCore/std/typetraits/is_assignable.h>
#include <AzCore/std/typetraits/is_constructible.h>
#include <AzCore/std/typetraits/is_destructible.h>
#include <AzCore/std/typetraits/is_function.h>
#include <AzCore/std/typetraits/is_trivially_copyable.h>
#include <AzCore/std/typetraits/is_void.h>
#include <AzCore/std/utils.h> // AZStd::addressof
namespace AZStd
{
// alias std::pointer_traits into the AZStd::namespace
using std::pointer_traits;
//! Bring the names of uninitialized_default_construct and
//! uninitialized_default_construct_n into the AZStd namespace
using std::uninitialized_default_construct;
@@ -34,42 +31,6 @@ namespace AZStd
using std::uninitialized_value_construct_n;
}
namespace AZStd::Internal
{
template <typename T, typename = void>
constexpr bool pointer_traits_has_to_address_v = false;
template <typename T>
constexpr bool pointer_traits_has_to_address_v<T, AZStd::void_t<decltype(AZStd::pointer_traits<T>::to_address(declval<const T&>()))>> = true;
}
namespace AZStd
{
//! Implements the C++20 to_address function
//! This obtains the address represented by ptr without forming a reference
//! to the pointee type
template <typename T>
constexpr T* to_address(T* ptr) noexcept
{
static_assert(!AZStd::is_function_v<T>, "Invoking to address on a function pointer is not allowed");
return ptr;
}
//! Fancy pointer overload which delegates to using a specialization of pointer_traits<T>::to_address
//! if that is a well-formed expression, otherwise it returns ptr->operator->()
//! For example invoking `to_address(AZStd::reverse_iterator<const char*>(char_ptr))`
//! Returns an element of type const char*
template <typename T>
constexpr auto to_address(const T& ptr) noexcept
{
if constexpr (AZStd::Internal::pointer_traits_has_to_address_v<T>)
{
return pointer_traits<T>::to_address(ptr);
}
else
{
return AZStd::to_address(ptr.operator->());
}
}
}
namespace AZStd::Internal
{
/**
@@ -81,7 +42,7 @@ namespace AZStd::Internal
/**
* Type has trivial destructor. We don't call it.
*/
template <class InputIterator, class ValueType = typename iterator_traits<InputIterator>::value_type, bool = is_trivially_destructible_v<ValueType>>
template <class InputIterator, class ValueType = iter_value_t<InputIterator>, bool = is_trivially_destructible_v<ValueType>>
struct destroy
{
static constexpr void range(InputIterator first, InputIterator last) { (void)first; (void)last; }
@@ -163,7 +124,7 @@ namespace AZStd::Internal
* Default object construction.
*/
// placement new isn't a core constant expression therefore it cannot be used in a constexpr function
template<class InputIterator, class ValueType = typename iterator_traits<InputIterator>::value_type,
template<class InputIterator, class ValueType = iter_value_t<InputIterator>,
bool = is_trivially_constructible_v<ValueType>>
struct construct
{
@@ -242,93 +203,125 @@ namespace AZStd::Internal
//////////////////////////////////////////////////////////////////////////
// Sequence copy. If we use optimized version we use memcpy.
/**
* Helper class to determine if we have apply fast copy. There are 2 conditions
* Class to determine if we have apply fast copy. There are 2 conditions
* - trivial copy ctor.
* - all iterators satisfy the C++20 are contiguous iterator concept: pointers or iterator classes with
* the iterator_concept typedef set to contiguous_iterator_tag
* - all iterators satisfy the C++20 are contiguous iterator concept
*/
template<class Out, class = void>
constexpr bool indirectly_trivially_copyable = false;
template<class Out>
constexpr bool indirectly_trivially_copyable<Out,
enable_if_t<indirectly_readable<Out>>> = is_trivially_copyable_v<iter_value_t<Out>>;
template<class InputIterator, class ResultIterator>
struct is_fast_copy_helper
{
using value_type = typename iterator_traits<ResultIterator>::value_type;
static constexpr bool value = AZStd::is_trivially_copyable_v<value_type>
&& Internal::satisfies_contiguous_iterator_concept_v<InputIterator>
&& Internal::satisfies_contiguous_iterator_concept_v<ResultIterator>;
};
using is_fast_copy = bool_constant<indirectly_trivially_copyable<ResultIterator>
&& contiguous_iterator<InputIterator>
&& contiguous_iterator<ResultIterator>
>;
// Use this trait to to determine copy mode, based on the iterator category and object copy properties,
// Use it when when you call uninitialized_copy, Internal::copy, Internal::move, etc.
template< typename InputIterator, typename ResultIterator >
struct is_fast_copy
: public ::AZStd::integral_constant<bool, ::AZStd::Internal::is_fast_copy_helper<InputIterator, ResultIterator>::value> {};
template<class InputIterator, class ResultIterator>
constexpr bool is_fast_copy_v = is_fast_copy<InputIterator, ResultIterator>::value;
// is_fast_copy argument is no longer used.
template <class InputIterator, class ForwardIterator>
constexpr ForwardIterator copy(const InputIterator& first, const InputIterator& last, ForwardIterator result, const false_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
constexpr ForwardIterator copy(InputIterator first, InputIterator last, ForwardIterator result, bool)
{
InputIterator iter(first);
for (; iter != last; ++result, ++iter)
if constexpr (is_fast_copy_v<InputIterator, ForwardIterator>)
{
*result = *iter;
}
// Specialized copy for contiguous iterators which are trivially copyable
size_t numElements = last - first;
if (numElements > 0)
{
#if az_has_builtin_memcpy
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Size of value types must match for a trivial copy");
__builtin_memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
#else
if (az_builtin_is_constant_evaluated())
{
for (; first != last; ++result, ++first)
{
*result = *first;
}
return result;
return result;
}
else
{
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Size of value types must match for a trivial copy");
AZ_Assert((static_cast<const void*>(&*result) < static_cast<const void*>(&*first))
|| (static_cast<const void*>(&*result) >= static_cast<const void*>(&*first + numElements)),
"AZStd::copy memory overlaps use AZStd::copy_backward!");
::memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
}
#endif
}
return result + numElements;
}
else
{
for (; first != last; ++result, ++first)
{
*result = *first;
}
return result;
}
}
// Specialized copy for contiguous iterators (pointers) and trivial copy type.
// This overload cannot be constexpr until builtin_memcpy is added to MSVC compilers
template <class InputIterator, class ForwardIterator>
inline ForwardIterator copy(const InputIterator& first, const InputIterator& last, ForwardIterator result, const true_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
{
// \todo Make sure memory ranges don't overlap, otherwise people should use move and move_backward.
static_assert(sizeof(typename iterator_traits<InputIterator>::value_type) == sizeof(typename iterator_traits<ForwardIterator>::value_type), "Size of value types must match for a trivial copy");
AZStd::size_t numElements = last - first;
if (numElements > 0)
{
AZ_Assert((static_cast<const void*>(&*result) < static_cast<const void*>(&*first)) || (static_cast<const void*>(&*result) >= static_cast<const void*>(&*first + numElements)), "AZStd::copy memory overlaps use AZStd::copy_backward!");
AZ_Assert((static_cast<const void*>(&*result + numElements) <= static_cast<const void*>(&*first)) || (static_cast<const void*>(&*result + numElements) > static_cast<const void*>(&*first + numElements)), "AZStd::copy memory overlaps use AZStd::copy_backward!");
/*AZSTD_STL::*/ memcpy(&*result, &*first, numElements * sizeof(typename iterator_traits<InputIterator>::value_type));
}
return result + numElements;
}
// Copy backward.
template <class BidirectionalIterator1, class BidirectionalIterator2>
constexpr BidirectionalIterator2 copy_backward(const BidirectionalIterator1& first, const BidirectionalIterator1& last, BidirectionalIterator2 result, const false_type& /* is_fast_copy<BidirectionalIterator1,BidirectionalIterator2>() */)
constexpr BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result, bool)
{
BidirectionalIterator1 iter(last);
while (first != iter)
if constexpr (is_fast_copy_v<BidirectionalIterator1, BidirectionalIterator2>)
{
*--result = *--iter;
// Specialized copy for contiguous iterators which are trivially copyable
size_t numElements = last - first;
if (numElements > 0)
{
#if az_has_builtin_memmove
static_assert(sizeof(iter_value_t<BidirectionalIterator1>) == sizeof(iter_value_t<BidirectionalIterator2>), "Size of value types must match for a trivial copy");
result -= numElements;
__builtin_memmove(to_address(result), to_address(first), numElements * sizeof(iter_value_t<BidirectionalIterator1>));
#else
if (az_builtin_is_constant_evaluated())
{
while (first != last)
{
*--result = *--last;
}
return result;
}
else
{
static_assert(sizeof(iter_value_t<BidirectionalIterator1>) == sizeof(iter_value_t<BidirectionalIterator2>), "Size of value types must match for a trivial copy");
result -= numElements;
AZ_Assert(((&*result + numElements) <= &*first) || ((&*result + numElements) > (&*first + numElements)), "AZStd::copy_backward memory overlaps use AZStd::copy!");
::memmove(&*result, &*first, numElements * sizeof(iter_value_t<BidirectionalIterator1>));
}
#endif
}
return result;
}
return result;
}
// Specialized copy for contiguous iterators (pointers) and trivial copy type.
// This overload cannot be constexpr until builtin_memcpy is added to MSVC compilers
template <class BidirectionalIterator1, class BidirectionalIterator2>
inline BidirectionalIterator2 copy_backward(const BidirectionalIterator1& first, const BidirectionalIterator1& last, BidirectionalIterator2 result, const true_type& /* is_fast_copy<BidirectionalIterator1,BidirectionalIterator2>() */)
{
// \todo Make sure memory ranges don't overlap, otherwise people should use move and move_backward.
static_assert(sizeof(typename iterator_traits<BidirectionalIterator1>::value_type) == sizeof(typename iterator_traits<BidirectionalIterator2>::value_type), "Size of value types must match for a trivial copy");
AZStd::size_t numElements = last - first;
if (numElements > 0)
else
{
result -= numElements;
AZ_Assert((&*result < &*first) || (&*result >= (&*first + numElements)), "AZStd::copy_backward memory overlaps use AZStd::copy!");
AZ_Assert(((&*result + numElements) <= &*first) || ((&*result + numElements) > (&*first + numElements)), "AZStd::copy_backward memory overlaps use AZStd::copy!");
/*AZSTD_STL::*/ memcpy(&*result, &*first, numElements * sizeof(typename iterator_traits<BidirectionalIterator1>::value_type));
while (first != last)
{
*--result = *--last;
}
return result;
}
return result;
}
template <class BidirectionalIterator1, class ForwardIterator>
constexpr ForwardIterator reverse_copy(const BidirectionalIterator1& first, const BidirectionalIterator1& last, ForwardIterator dest)
constexpr ForwardIterator reverse_copy(BidirectionalIterator1 first, BidirectionalIterator1 last, ForwardIterator dest)
{
BidirectionalIterator1 iter(last);
while (iter != first)
while (last != first)
{
*(dest++) = *(--iter);
*(dest++) = *(--last);
}
return dest;
@@ -342,143 +335,209 @@ namespace AZStd
* Specialized algorithms 20.4.4. We extend that by adding faster specialized versions when we have trivial assign type.
*/
template <class InputIterator, class ForwardIterator>
constexpr ForwardIterator uninitialized_copy(const InputIterator& first, const InputIterator& last, ForwardIterator result, const false_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
constexpr ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result, bool)
{
InputIterator iter(first);
for (; iter != last; ++result, ++iter)
// Specialized copy for contiguous iterators which are trivially copyable
if constexpr (Internal::is_fast_copy_v<InputIterator, ForwardIterator>)
{
::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*iter);
}
size_t numElements = last - first;
if (numElements > 0)
{
#if az_has_builtin_memcpy
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Value type sizes must match for a trivial copy");
__builtin_memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
#else
if (az_builtin_is_constant_evaluated())
{
for (; first != last; ++result, ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(result)), *first);
}
return result;
return result;
}
else
{
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Value type sizes must match for a trivial copy");
::memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
}
#endif
}
return result + numElements;
}
else
{
for (; first != last; ++result, ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(result)), *first);
}
return result;
}
}
// Specialized copy for contiguous iterators and trivial copy type.
// This overload cannot be constexpr until builtin_memcpy is added to MSVC compilers
template <class InputIterator, class ForwardIterator>
inline ForwardIterator uninitialized_copy(const InputIterator& first, const InputIterator& last, ForwardIterator result, const true_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
{
static_assert(sizeof(typename iterator_traits<InputIterator>::value_type) == sizeof(typename iterator_traits<ForwardIterator>::value_type), "Value type sizes must match for a trivial copy");
AZStd::size_t numElements = last - first;
if (numElements > 0)
{
/*AZSTD_STL::*/
memcpy(&*result, &*first, numElements * sizeof(typename iterator_traits<InputIterator>::value_type));
}
return result + numElements;
}
template <class InputIterator, class ForwardIterator>
constexpr ForwardIterator uninitialized_copy(const InputIterator& first, const InputIterator& last, ForwardIterator result)
constexpr ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
{
return uninitialized_copy(first, last, result, Internal::is_fast_copy<InputIterator, ForwardIterator>());
return uninitialized_copy(first, last, result, {});
}
// 25.3.1 Copy
template<class InputIterator, class OutputIterator>
constexpr OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
return AZStd::Internal::copy(first, last, result, AZStd::Internal::is_fast_copy<InputIterator, OutputIterator>());
return Internal::copy(first, last, result, {});
}
template <class BidirectionalIterator, class OutputIterator>
constexpr OutputIterator reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator dest)
{
return AZStd::Internal::reverse_copy(first, last, dest);
return Internal::reverse_copy(first, last, dest);
}
template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result)
{
return AZStd::Internal::copy_backward(first, last, result, AZStd::Internal::is_fast_copy<BidirectionalIterator1, BidirectionalIterator2>());
return Internal::copy_backward(first, last, result, {});
}
}
namespace AZStd::Internal
{
//////////////////////////////////////////////////////////////////////////
// Sequence move. If we use optimized version we use memmove.
// Sequence move
template <class InputIterator, class ForwardIterator>
constexpr ForwardIterator move(const InputIterator& first, const InputIterator& last, ForwardIterator result, const false_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
constexpr ForwardIterator move(InputIterator first, InputIterator last, ForwardIterator result, bool)
{
InputIterator iter(first);
for (; iter != last; ++result, ++iter)
// Specialized copy for contiguous iterators which are trivially copyable
if constexpr (is_fast_copy_v<InputIterator, ForwardIterator>)
{
*result = AZStd::move(*iter);
size_t numElements = last - first;
if (numElements > 0)
{
#if az_has_builtin_memcpy
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Size of value types must match for a trivial copy");
__builtin_memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
#else
if (az_builtin_is_constant_evaluated())
{
for (; first != last; ++result, ++first)
{
*result = ::AZStd::move(*first);
}
return result;
}
else
{
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Size of value types must match for a trivial copy");
AZ_Assert((static_cast<const void*>(&*result) < static_cast<const void*>(&*first))
|| (static_cast<const void*>(&*result) >= static_cast<const void*>(&*first + numElements)),
"AZStd::move memory overlaps use AZStd::move_backward!");
::memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
}
#endif
}
return result + numElements;
}
else
{
for (; first != last; ++result, ++first)
{
*result = ::AZStd::move(*first);
}
return result;
}
return result;
}
// Specialized copy for contiguous iterators (pointers) and trivial copy type.
// This overload cannot be constexpr until builtin_memmove is added to MSVC compilers
template <class InputIterator, class ForwardIterator>
inline ForwardIterator move(const InputIterator& first, const InputIterator& last, ForwardIterator result, const true_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
{
static_assert(sizeof(typename iterator_traits<InputIterator>::value_type) == sizeof(typename iterator_traits<ForwardIterator>::value_type), "Size of value types must match for a trivial copy");
AZStd::size_t numElements = last - first;
if (numElements > 0)
{
/*AZSTD_STL::*/
memmove(&*result, &*first, numElements * sizeof(typename iterator_traits<InputIterator>::value_type));
}
return result + numElements;
}
// For generic iterators, move is the same as copy.
template <class BidirectionalIterator1, class BidirectionalIterator2>
constexpr BidirectionalIterator2 move_backward(const BidirectionalIterator1& first, const BidirectionalIterator1& last, BidirectionalIterator2 result, const false_type& /* is_fast_copy<BidirectionalIterator1,BidirectionalIterator2>() */)
constexpr BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result, bool)
{
BidirectionalIterator1 iter(last);
while (first != iter)
// Specialized copy for contiguous iterators which are trivially copyable
if constexpr (is_fast_copy_v<BidirectionalIterator1, BidirectionalIterator1>)
{
*--result = AZStd::move(*--iter);
size_t numElements = last - first;
if (numElements > 0)
{
#if az_has_builtin_memmove
static_assert(sizeof(iter_value_t<BidirectionalIterator1>) == sizeof(iter_value_t<BidirectionalIterator2>), "Size of value types must match for a trivial copy");
result -= numElements;
__builtin_memmove(to_address(result), to_address(first), numElements * sizeof(iter_value_t<BidirectionalIterator1>));
#else
if (az_builtin_is_constant_evaluated())
{
while (first != last)
{
*--result = ::AZStd::move(*--last);
}
return result;
}
else
{
static_assert(sizeof(iter_value_t<BidirectionalIterator1>) == sizeof(iter_value_t<BidirectionalIterator2>), "Size of value types must match for a trivial copy");
result -= numElements;
AZ_Assert((static_cast<const void*>(&*result + numElements) <= static_cast<const void*>(&*first))
|| (static_cast<const void*>(&*result + numElements) > static_cast<const void*>(&*first + numElements)),
"AZStd::move_backward memory overlaps use AZStd::move!");
::memmove(to_address(result), to_address(first), numElements * sizeof(iter_value_t<BidirectionalIterator1>));
}
#endif
}
return result;
}
return result;
}
// Specialized copy for contiguous iterators (pointers) and trivial copy type.
// This overload cannot be constexpr until builtin_memmove is added to MSVC compilers
template <class BidirectionalIterator1, class BidirectionalIterator2>
inline BidirectionalIterator2 move_backward(const BidirectionalIterator1& first, const BidirectionalIterator1& last, BidirectionalIterator2 result, const true_type& /* is_fast_copy<BidirectionalIterator1,BidirectionalIterator2>() */)
{
// \todo Make sure memory ranges don't overlap, otherwise people should use move and move_backward.
static_assert(sizeof(typename iterator_traits<BidirectionalIterator1>::value_type) == sizeof(typename iterator_traits<BidirectionalIterator2>::value_type), "Size of value types must match for a trivial copy");
AZStd::size_t numElements = last - first;
result -= numElements;
if (numElements > 0)
else
{
/*AZSTD_STL::*/
memmove(&*result, &*first, numElements * sizeof(typename iterator_traits<BidirectionalIterator1>::value_type));
while (first != last)
{
*--result = ::AZStd::move(*--last);
}
return result;
}
return result;
}
template <class InputIterator, class ForwardIterator>
constexpr ForwardIterator uninitialized_move(const InputIterator& first, const InputIterator& last, ForwardIterator result, const false_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
constexpr ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result, bool)
{
InputIterator iter(first);
for (; iter != last; ++result, ++iter)
// Specialized copy for contiguous iterators which are trivially copyable
if constexpr (is_fast_copy_v<InputIterator, ForwardIterator>)
{
::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(AZStd::move(*iter));
}
return result;
}
// Specialized copy for contiguous iterators and trivial move type. (since the object is POD we will just perform a copy)
// This overload cannot be constexpr until builtin_memcpy is added to MSVC compilers
template <class InputIterator, class ForwardIterator>
inline ForwardIterator uninitialized_move(const InputIterator& first, const InputIterator& last, ForwardIterator result, const true_type& /* is_fast_copy<InputIterator,ForwardIterator>() */)
{
static_assert(sizeof(typename iterator_traits<InputIterator>::value_type) == sizeof(typename iterator_traits<ForwardIterator>::value_type), "Value type sizes must match for a trivial copy");
AZStd::size_t numElements = last - first;
if (numElements > 0)
{
/*AZSTD_STL::*/
memcpy(&*result, &*first, numElements * sizeof(typename iterator_traits<InputIterator>::value_type));
}
return result + numElements;
}
size_t numElements = last - first;
if (numElements > 0)
{
#if az_has_builtin_memcpy
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Value type sizes must match for a trivial copy");
__builtin_memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
#else
if (az_builtin_is_constant_evaluated())
{
for (; first != last; ++result, ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(result)), ::AZStd::move(*first));
}
return result;
}
else
{
static_assert(sizeof(iter_value_t<InputIterator>) == sizeof(iter_value_t<ForwardIterator>), "Value type sizes must match for a trivial copy");
::memcpy(to_address(result), to_address(first), numElements * sizeof(iter_value_t<InputIterator>));
}
#endif
}
return result + numElements;
}
else
{
for (; first != last; ++result, ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(result)), ::AZStd::move(*first));
}
return result;
}
}
// end of sequence move.
//////////////////////////////////////////////////////////////////////////
}
@@ -492,19 +551,19 @@ namespace AZStd
template <typename InputIt, typename ForwardIt>
ForwardIt uninitialized_move(InputIt first, InputIt last, ForwardIt result)
{
return AZStd::Internal::uninitialized_move(first, last, result, AZStd::Internal::is_fast_copy<InputIt, InputIt>{});
return AZStd::Internal::uninitialized_move(first, last, result, {});
}
// 25.3.2 Move
template<class InputIterator, class OutputIterator>
OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)
{
return AZStd::Internal::move(first, last, result, AZStd::Internal::is_fast_copy<InputIterator, OutputIterator>());
return AZStd::Internal::move(first, last, result, {});
}
template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result)
{
return AZStd::Internal::move_backward(first, last, result, AZStd::Internal::is_fast_copy<BidirectionalIterator1, BidirectionalIterator2>());
return AZStd::Internal::move_backward(first, last, result, {});
}
}
@@ -516,63 +575,77 @@ namespace AZStd::Internal
* Helper class to determine if we have apply fast fill. There are 3 conditions
* - trivial assign
* - size of type == 1 (chars) to use memset
* - contiguous iterators (pointers)
* - contiguous iterators
*/
template<class Out, class = void>
constexpr bool indirectly_copy_assignable = false;
template<class Out>
constexpr bool indirectly_copy_assignable<Out, enable_if_t<indirectly_readable<Out>>> =
is_trivially_copy_assignable_v<iter_value_t<Out>> && sizeof(iter_value_t<Out>) == 1;
template<class Iterator>
struct is_fast_fill_helper
{
using value_type = typename iterator_traits<Iterator>::value_type;
constexpr static bool value = is_trivially_copy_assignable_v<value_type> && sizeof(value_type) == 1
&& Internal::satisfies_contiguous_iterator_concept_v<Iterator>;
};
// Use this trait to to determine fill mode, based on the iterator, value size, etc.
// Use it when you call uninitialized_fill, uninitialized_fill_n, fill and fill_n.
template< typename Iterator >
struct is_fast_fill
: public ::AZStd::integral_constant<bool, ::AZStd::Internal::is_fast_fill_helper<Iterator>::value>
{};
using is_fast_fill = bool_constant<indirectly_copy_assignable<Iterator> && contiguous_iterator<Iterator>>;
template<class Iterator>
constexpr bool is_fast_fill_v = is_fast_fill<Iterator>::value;
// The fast fill trait is no longer used
// It is detected using C++20 concepts now
template <class ForwardIterator, class T>
constexpr void fill(const ForwardIterator& first, const ForwardIterator& last, const T& value, const false_type& /* is_fast_fill<ForwardIterator>() */)
constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value, bool)
{
ForwardIterator iter(first);
for (; iter != last; ++iter)
if constexpr (is_fast_fill_v<ForwardIterator>)
{
*iter = value;
size_t numElements = last - first;
if (numElements > 0)
{
if (az_builtin_is_constant_evaluated())
{
for (; first != last; ++first)
{
*first = value;
}
}
else
{
::memset(to_address(first), reinterpret_cast<const unsigned char&>(value), numElements);
}
}
}
}
// Specialized version for character types where memset can be used
// This overload cannot be constexpr until builtin_memset is added to MSVC compilers
template <class ForwardIterator, class T>
inline void fill(const ForwardIterator& first, const ForwardIterator& last, const T& value, const true_type& /* is_fast_fill<ForwardIterator>() */)
{
AZStd::size_t numElements = last - first;
if (numElements > 0)
else
{
/*AZSTD_STL::*/
memset((void*)&*first, *reinterpret_cast<const unsigned char*>(&value), numElements);
for (; first != last; ++first)
{
*first = value;
}
}
}
template <class ForwardIterator, class Size, class T>
constexpr void fill_n(ForwardIterator first, Size numElements, const T& value, const false_type& /* is_fast_fill<ForwardIterator>() */)
constexpr void fill_n(ForwardIterator first, Size numElements, const T& value, bool)
{
for (; numElements--; ++first)
if constexpr (is_fast_fill_v<ForwardIterator>)
{
*first = value;
if (numElements)
{
if (az_builtin_is_constant_evaluated())
{
for (; numElements--; ++first)
{
*first = value;
}
}
else
{
::memset(to_address(first), reinterpret_cast<const unsigned char&>(value), numElements);
}
}
}
}
// Specialized version for character types where memset can be used to perform the fill
// This overload cannot be constexpr until builtin_memset is added to MSVC compilers
template <class ForwardIterator, class Size, class T>
inline void fill_n(ForwardIterator first, Size numElements, const T& value, const true_type& /* is_fast_fill<ForwardIterator>() */)
{
if (numElements > 0)
else
{
/*AZSTD_STL::*/
memset(&*first, *reinterpret_cast<const unsigned char*>(&value), numElements);
for (; numElements--; ++first)
{
*first = value;
}
}
}
}
@@ -580,78 +653,85 @@ namespace AZStd::Internal
namespace AZStd
{
template <class ForwardIterator, class T>
constexpr void fill(const ForwardIterator& first, const ForwardIterator& last, const T& value)
constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value)
{
Internal::fill(first, last, value, Internal::is_fast_fill<ForwardIterator>());
Internal::fill(first, last, value, {});
}
template <class ForwardIterator, class Size, class T>
constexpr void fill_n(ForwardIterator first, Size numElements, const T& value)
{
Internal::fill_n(first, numElements, value, Internal::is_fast_fill<ForwardIterator>());
Internal::fill_n(first, numElements, value, {});
}
template <class ForwardIterator, class T>
constexpr void uninitialized_fill(const ForwardIterator& first, const ForwardIterator& last, const T& value, const false_type& /* is_fast_fill<ForwardIterator>() */)
constexpr void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value, bool)
{
ForwardIterator iter(first);
for (; iter != last; ++iter)
if constexpr (Internal::is_fast_fill_v<ForwardIterator>)
{
::new (static_cast<void*>(&*iter)) typename iterator_traits<ForwardIterator>::value_type(value);
size_t numElements = last - first;
if (numElements > 0)
{
if (az_builtin_is_constant_evaluated())
{
for (; first != last; ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(first)), value);
}
}
else
{
::memset(to_address(first), reinterpret_cast<const unsigned char&>(value), numElements);
}
}
}
}
// Specialized overload for types which meet the following criteria.
// 1. Has it's iterator_traits<T>::iterator_concept type set to to contiguous_iterator_tag
// 2. Is trivially assignable
// 3. Has a sizeof(T) == 1
// In such a case memset can be used to fill in the data
// This overload cannot be constexpr until builtin_memset is added to MSVC compilers
template <class ForwardIterator, class T>
inline void uninitialized_fill(const ForwardIterator& first, const ForwardIterator& last, const T& value, const true_type& /* is_fast_fill<ForwardIterator>() */)
{
AZStd::size_t numElements = last - first;
if (numElements > 0)
else
{
/*AZSTD_STL::*/
memset(&*first, *reinterpret_cast<const unsigned char*>(&value), numElements);
for (; first != last; ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(first)), value);
}
}
}
template <class ForwardIterator, class Size, class T>
constexpr void uninitialized_fill(ForwardIterator first, Size numElements, const T& value)
{
return uninitialized_fill(first, numElements, value, Internal::is_fast_fill<ForwardIterator>());
return uninitialized_fill(first, numElements, value, {});
}
template <class ForwardIterator, class Size, class T>
constexpr void uninitialized_fill_n(ForwardIterator first, Size numElements, const T& value, const false_type& /* is_fast_fill<ForwardIterator>() */)
constexpr void uninitialized_fill_n(ForwardIterator first, Size numElements, const T& value, bool)
{
for (; numElements--; ++first)
if constexpr (Internal::is_fast_fill_v<ForwardIterator>)
{
::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(value);
if (numElements > 0)
{
if (az_builtin_is_constant_evaluated())
{
for (; numElements--; ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(first)), value);
}
}
else
{
::memset(to_address(first), reinterpret_cast<const unsigned char&>(value), numElements);
}
}
}
}
// Specialized overload for types which meet the following criteria.
// 1. Has it's iterator_traits<T>::iterator_concept type set to to contiguous_iterator_tag
// 2. Is trivially assignable
// 3. Has a sizeof(T) == 1
// In such a case memset can be used to fill in the data
template <class ForwardIterator, class Size, class T>
inline void uninitialized_fill_n(ForwardIterator first, Size numElements, const T& value, const true_type& /* is_fast_fill<ForwardIterator>() */)
{
if (numElements)
else
{
/*AZSTD_STL::*/
memset(&*first, *reinterpret_cast<const unsigned char*>(&value), numElements);
for (; numElements--; ++first)
{
construct_at(static_cast<iter_value_t<ForwardIterator>*>(to_address(first)), value);
}
}
}
template <class ForwardIterator, class Size, class T>
constexpr void uninitialized_fill_n(ForwardIterator first, Size numElements, const T& value)
{
return uninitialized_fill_n(first, numElements, value, Internal::is_fast_fill<ForwardIterator>());
return uninitialized_fill_n(first, numElements, value, {});
}
}
@@ -38,4 +38,12 @@ namespace AZStd
{
return Internal::INVOKE(Internal::InvokeTraits::forward<F>(f), Internal::InvokeTraits::forward<Args>(args)...);
}
// models the invocable concept
template <class F, class... Args>
/*concept*/ constexpr bool invocable = is_invocable_v<F, Args...>;
// models the regular_invocable concept
template <class F, class... Args>
/*concept*/ constexpr bool regular_invocable = invocable<F, Args...>;
}
+8 -55
View File
@@ -8,19 +8,19 @@
#pragma once
#include <AzCore/std/base.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/typetraits/is_convertible.h>
#include <AzCore/std/typetraits/is_base_of.h> // use by ConstIteratorCast
#include <AzCore/std/iterator/iterator_primitives.h>
#include <AzCore/std/typetraits/is_base_of.h>
#include <AzCore/std/typetraits/is_convertible.h>
#include <AzCore/std/typetraits/remove_cv.h>
#include <AzCore/std/typetraits/is_reference.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utils.h>
#include <iterator>
namespace AZStd
{
// Everything unless specified is based on C++ standard 24 (lib.iterators).
// Everything unless specified is based on C++ standard 20 (lib.iterators).
/// Identifying tag for input iterators.
using input_iterator_tag = std::input_iterator_tag;
@@ -51,16 +51,6 @@ namespace AZStd::Internal
typename Iterator::reference>
> = true;
template <typename Iterator, typename = void>
inline constexpr bool has_iterator_category_v = false;
template <typename Iterator>
inline constexpr bool has_iterator_category_v<Iterator, AZStd::void_t<typename Iterator::iterator_category>> = true;
template <typename Iterator, typename = void>
inline constexpr bool has_iterator_concept_v = false;
template <typename Iterator>
inline constexpr bool has_iterator_concept_v<Iterator, AZStd::void_t<typename Iterator::iterator_concept>> = true;
// Iterator iterator_category alias must be one of the iterator category tags
template <typename Iterator, bool>
struct iterator_traits_category_tags
@@ -98,6 +88,8 @@ namespace AZStd
struct iterator_traits
: Internal::iterator_traits_type_aliases<Iterator, Internal::has_iterator_type_aliases_v<Iterator>>
{
// Internal type alias meant to indicate that this is the primary template
using _is_primary_template = iterator_traits;
};
/**
@@ -114,45 +106,6 @@ namespace AZStd
using iterator_category = random_access_iterator_tag;
using iterator_concept = contiguous_iterator_tag;
};
}
namespace AZStd::Internal
{
// iterator_category tag testers
template <typename Iterator, typename Category, bool = has_iterator_category_v<iterator_traits<Iterator>>>
inline constexpr bool has_iterator_category_convertible_to_v = false;
template <typename Iterator, typename Category>
inline constexpr bool has_iterator_category_convertible_to_v<Iterator, Category, true> = is_convertible_v<typename iterator_traits<Iterator>::iterator_category, Category>;
template <typename Iterator>
inline constexpr bool is_input_iterator_v = has_iterator_category_convertible_to_v<Iterator, input_iterator_tag>;
template <typename Iterator>
inline constexpr bool is_forward_iterator_v = has_iterator_category_convertible_to_v<Iterator, forward_iterator_tag>;
template <typename Iterator>
inline constexpr bool is_bidirectional_iterator_v = has_iterator_category_convertible_to_v<Iterator, bidirectional_iterator_tag>;
template <typename Iterator>
inline constexpr bool is_random_access_iterator_v = has_iterator_category_convertible_to_v<Iterator, random_access_iterator_tag>;
template <typename Iterator>
inline constexpr bool is_contiguous_iterator_v = has_iterator_category_convertible_to_v<Iterator, contiguous_iterator_tag>;
template <typename Iterator>
inline constexpr bool is_exactly_input_iterator_v = has_iterator_category_convertible_to_v<Iterator, input_iterator_tag> && !has_iterator_category_convertible_to_v<Iterator, forward_iterator_tag>;
// iterator concept testers
template <typename Derived, typename Base>
inline constexpr bool derived_from = is_base_of_v<Base, Derived> && is_convertible_v<const volatile Derived*, const volatile Base*>;
template <typename Iterator, typename Concept, bool = has_iterator_concept_v<iterator_traits<Iterator>>>
inline constexpr bool satisfies_iterator_concept = false;
template <typename Iterator, typename Concept>
inline constexpr bool satisfies_iterator_concept<Iterator, Concept, true> = derived_from<typename iterator_traits<Iterator>::iterator_concept, Concept>;
template <typename Iterator>
inline constexpr bool satisfies_contiguous_iterator_concept_v = satisfies_iterator_concept<Iterator, contiguous_iterator_tag>;
}
namespace AZStd
@@ -0,0 +1,200 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/base.h>
#include <AzCore/std/ranges/iter_move.h>
#include <AzCore/std/typetraits/common_reference.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/is_array.h>
#include <AzCore/std/typetraits/is_class.h>
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/std/typetraits/is_integral.h>
#include <AzCore/std/typetraits/is_object.h>
#include <AzCore/std/typetraits/is_lvalue_reference.h>
#include <AzCore/std/typetraits/is_rvalue_reference.h>
#include <AzCore/std/typetraits/is_signed.h>
#include <AzCore/std/typetraits/is_void.h>
#include <AzCore/std/typetraits/remove_extent.h>
#include <AzCore/std/typetraits/void_t.h>
namespace AZStd
{
// Bring in std utility functions into AZStd namespace
using std::forward;
// forward declare iterator_traits to avoid iterator.h include
template <class I>
struct iterator_traits;
}
// C++20 range traits for iteratable types
namespace AZStd::Internal
{
// Models the can-reference concept which isn't available until C++20
// template <class T, class = void>
template <class T>
constexpr bool can_reference = true;
template <>
inline constexpr bool can_reference<void> = false;
// Models the dereferencable concept which isn't available until C++20
template <class T, class = void>
/*concept*/ constexpr bool dereferenceable = false;
template <class T>
constexpr bool dereferenceable<T, enable_if_t<can_reference<decltype(*declval<T>())>>> = true;
template <class T, class = void>
constexpr bool is_primary_template_v = false;
template <class T>
constexpr bool is_primary_template_v<T, enable_if_t<is_same_v<T, typename T::_is_primary_template>>> = true;
// indirectly readable traits
template <typename T, typename = void>
constexpr bool has_value_type_v = false;
template <typename T>
constexpr bool has_value_type_v<T, void_t<typename T::value_type>> = true;
template <typename T, typename = void>
constexpr bool has_element_type_v = false;
template <typename T>
constexpr bool has_element_type_v<T, void_t<typename T::element_type>> = true;
template <typename T, typename = void>
struct object_type_value_requires {};
template <typename T>
struct object_type_value_requires<T, enable_if_t<is_object_v<T>>>
{
using value_type = remove_cv_t<T>;
};
template <typename T, typename = void>
struct indirectly_readable_requires {};
template <typename T>
struct indirectly_readable_requires<T, enable_if_t<!is_primary_template_v<iterator_traits<T>>
&& is_void_v<void_t<typename iterator_traits<T>::value_type>> >>
{
// iterator_traits has been been specialized
using value_type = typename iterator_traits<T>::value_type;
};
template <typename T>
struct indirectly_readable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& is_array_v<T>>>
{
using value_type = remove_cv_t<remove_extent_t<T>>;
};
template <typename T>
struct indirectly_readable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& has_value_type_v<T> && !has_element_type_v<T>>>
: object_type_value_requires<typename T::value_type> {};
template <typename T>
struct indirectly_readable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& has_element_type_v<T> && !has_value_type_v<T>>>
: object_type_value_requires<typename T::element_type> {};
template <typename T>
struct indirectly_readable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& has_value_type_v<T>&& has_element_type_v<T>
&& same_as<remove_cv_t<typename T::element_type>, remove_cv_t<typename T::value_type>> >>
: object_type_value_requires<typename T::value_type> {};
// incrementable traits
template <typename T, typename = void>
constexpr bool has_difference_type_v = false;
template <typename T>
constexpr bool has_difference_type_v<T, void_t<typename T::difference_type>> = true;
template <typename T, typename = void>
struct object_type_difference_requires {};
template <typename T>
struct object_type_difference_requires<T, enable_if_t<is_object_v<T>>>
{
using difference_type = ptrdiff_t;
};
template <typename T, typename = void>
struct incrementable_requires {};
// iterator_traits has been specialized
template <typename T>
struct incrementable_requires<T, enable_if_t<!is_primary_template_v<iterator_traits<T>>
&& is_void_v<void_t<typename iterator_traits<T>::difference_type>> >>
{
using difference_type = typename iterator_traits<T>::difference_type;
};
template <typename T>
struct incrementable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& has_difference_type_v<T>>>
{
using difference_type = typename T::difference_type;
};
template <typename T>
struct incrementable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& !has_difference_type_v<T>
&& integral<decltype(declval<T>() - declval<T>())> >>
{
using difference_type = make_signed_t<decltype(declval<T>() - declval<T>())>;
};
}
namespace AZStd
{
// indirectly_readable_traits for iter_value_t
template <typename T>
struct indirectly_readable_traits
: Internal::indirectly_readable_requires<T> {};
template <typename T>
struct indirectly_readable_traits<T*>
: Internal::object_type_value_requires<T> {};
template <typename T>
struct indirectly_readable_traits<const T>
: indirectly_readable_traits<T> {};
template <typename T>
using iter_value_t = typename indirectly_readable_traits<remove_cvref_t<T>>::value_type;
template <typename T>
using iter_reference_t = enable_if_t<Internal::dereferenceable<T>, decltype(*declval<T&>())>;
// incrementable_traits for iter_difference_t
template <typename T>
struct incrementable_traits
: Internal::incrementable_requires<T> {};
template <typename T>
struct incrementable_traits<T*>
: Internal::object_type_difference_requires<T> {};
template <typename T>
struct incrementable_traits<const T>
: incrementable_traits<T> {};
template <typename T>
using iter_difference_t = typename incrementable_traits<remove_cvref_t<T>>::difference_type;
template <typename T>
using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<T&>()));
namespace Internal
{
// model the indirectly readable concept
template <class In, class = void>
constexpr bool indirectly_readable_impl = false;
template <class In>
constexpr bool indirectly_readable_impl<In, enable_if_t<same_as<decltype(*declval<In>()), iter_reference_t<In>>
&& same_as<decltype(AZStd::ranges::iter_move(declval<In>())), iter_rvalue_reference_t<In>>
&& common_reference_with<iter_reference_t<In>&&, iter_value_t<In>&>
&& common_reference_with<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&>
&& common_reference_with<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>>> = true;
}
template <typename T>
using iter_common_reference_t = enable_if_t<Internal::indirectly_readable_impl<T>,
common_reference_t<iter_reference_t<T>, iter_value_t<T>&>>;
}
@@ -0,0 +1,81 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/base.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/is_class.h>
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/std/typetraits/is_lvalue_reference.h>
#include <AzCore/std/typetraits/is_rvalue_reference.h>
#include <AzCore/std/typetraits/remove_cvref.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utility/move.h>
#include <AzCore/std/utility/declval.h>
namespace AZStd
{
// Bring in std utility functions into AZStd namespace
using std::forward;
}
// C++20 range traits for iteratable types
namespace AZStd::ranges::Internal
{
void iter_move();
template <typename It, typename = void>
constexpr bool iter_move_adl = false;
template <typename It>
constexpr bool iter_move_adl<It, void_t<decltype(iter_move(declval<It>()))>> = true;
template <typename It, typename = void>
constexpr bool is_class_or_enum_with_iter_move_adl = false;
template <typename It>
constexpr bool is_class_or_enum_with_iter_move_adl<It, enable_if_t<iter_move_adl<It>
&& (is_class_v<remove_cvref_t<It>> || is_enum_v<remove_cvref_t<It>>)>>
= true;
struct iter_move_fn
{
template <typename It>
constexpr auto operator()(It&& it) const
->enable_if_t<is_class_or_enum_with_iter_move_adl<It>,
decltype(iter_move(AZStd::forward<It>(it)))>
{
return iter_move(AZStd::forward<It>(it));
}
template <typename It>
constexpr auto operator()(It&& it) const
->enable_if_t<!is_class_or_enum_with_iter_move_adl<It>&& is_lvalue_reference_v<decltype(*AZStd::forward<It>(it))>,
decltype(AZStd::move(*AZStd::forward<It>(it)))>
{
return AZStd::move(*AZStd::forward<It>(it));
}
template <typename It>
constexpr auto operator()(It&& it) const
->enable_if_t<!is_class_or_enum_with_iter_move_adl<It> && !is_lvalue_reference_v<decltype(*AZStd::forward<It>(it))>,
decltype(*AZStd::forward<It>(it))>
{
return *AZStd::forward<It>(it);
}
};
}
namespace AZStd::ranges
{
inline namespace customization_point_object
{
inline constexpr auto iter_move = Internal::iter_move_fn{};
}
}
File diff suppressed because it is too large Load Diff
@@ -74,7 +74,7 @@ namespace AZStd
constexpr basic_fixed_string(const_pointer ptr);
// #6
template<class InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_t>>>
template<class InputIt, typename = enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_t>>>
constexpr basic_fixed_string(InputIt first, InputIt last);
// #7
@@ -146,7 +146,7 @@ namespace AZStd
constexpr auto append(size_type count, Element ch) -> basic_fixed_string&;
template<class InputIt>
constexpr auto append(InputIt first, InputIt last)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>;
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>;
constexpr auto append(AZStd::initializer_list<Element> ilist) -> basic_fixed_string&;
constexpr auto assign(const basic_fixed_string& rhs) -> basic_fixed_string&;
@@ -161,7 +161,7 @@ namespace AZStd
constexpr auto assign(size_type count, Element ch) -> basic_fixed_string&;
template<class InputIt>
constexpr auto assign(InputIt first, InputIt last)
->enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>;
->enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>;
constexpr auto assign(AZStd::initializer_list<Element> ilist) -> basic_fixed_string&;
@@ -179,7 +179,7 @@ namespace AZStd
constexpr auto insert(const_iterator insertPos, size_type count, Element ch) -> iterator;
template<class InputIt>
constexpr auto insert(const_iterator insertPos, InputIt first, InputIt last)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, iterator>;
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, iterator>;
constexpr auto insert(const_iterator insertPos, AZStd::initializer_list<Element> ilist) -> iterator;
@@ -215,7 +215,7 @@ namespace AZStd
constexpr auto replace(const_iterator first, const_iterator last, size_type count, Element ch) -> basic_fixed_string&;
template<class InputIt>
constexpr auto replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>;
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>;
constexpr auto replace(const_iterator first, const_iterator last, AZStd::initializer_list<Element> ilist) -> basic_fixed_string&;
constexpr auto at(size_type offset) -> reference;
@@ -325,14 +325,14 @@ namespace AZStd
template<class Element, size_t MaxElementCount, class Traits>
template<class InputIt>
inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::append(InputIt first, InputIt last)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>
{
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
return append(AZStd::to_address(first), AZStd::distance(first, last));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// Input Iterator pointer type doesn't match the const_pointer type
// So the elements need to be appended one by one into the buffer
@@ -461,14 +461,14 @@ namespace AZStd
template<class Element, size_t MaxElementCount, class Traits>
template<class InputIt>
inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::assign(InputIt first, InputIt last)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>
{
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
return assign(AZStd::to_address(first), AZStd::distance(first, last));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// Input Iterator pointer type doesn't match the const_pointer type
// So the elements need to be assigned one by one into the buffer
@@ -627,15 +627,15 @@ namespace AZStd
template<class Element, size_t MaxElementCount, class Traits>
template<class InputIt>
inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::insert(const_iterator insertPos,
InputIt first, InputIt last)-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, iterator>
InputIt first, InputIt last)-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, iterator>
{ // insert [_First, _Last) at _Where
size_type insertOffset = AZStd::distance(cbegin(), insertPos);
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
insert(insertOffset, AZStd::to_address(first), AZStd::distance(first, last));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// Input Iterator pointer type doesn't match the const_pointer type
// So the elements need to be inserted one by one into the buffer
@@ -927,14 +927,14 @@ namespace AZStd
template<class Element, size_t MaxElementCount, class Traits>
template<class InputIt>
inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::replace(const_iterator first, const_iterator last,
InputIt replaceFirst, InputIt replaceLast) -> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>
InputIt replaceFirst, InputIt replaceLast) -> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, basic_fixed_string&>
{ // replace [first, last) with [replaceFirst,replaceLast)
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
return replace(first, last, AZStd::to_address(replaceFirst), AZStd::distance(replaceFirst, replaceLast));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// Input Iterator pointer type doesn't match the const_pointer type
// So the elements need to be appended one by one into the buffer
@@ -114,28 +114,23 @@ namespace AZStd
assign(count, ch);
}
template<class InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_t>>>
template<class InputIt, typename = enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_t>>>
inline basic_string(InputIt first, InputIt last, const Allocator& alloc = Allocator())
: m_storage{ skip_element_tag{}, alloc }
{ // construct from [first, last)
assign(first, last);
}
inline basic_string(const_pointer first, const_pointer last)
{ // construct from [first, last), const pointers
assign(first, last - first);
}
inline basic_string(const this_type& rhs)
: m_storage{ skip_element_tag{}, rhs.m_storage.second() }
{
assign(rhs, 0, npos);
assign(rhs);
}
inline basic_string(this_type&& rhs)
: m_storage{ skip_element_tag{}, AZStd::move(rhs.m_storage.second()) }
: m_storage{ skip_element_tag{}, rhs.m_storage.second() }
{
assign(AZStd::forward<this_type>(rhs));
assign(AZStd::move(rhs));
}
inline basic_string(const this_type& rhs, size_type rhsOffset, size_type count = npos)
@@ -251,14 +246,14 @@ namespace AZStd
template<class InputIt>
inline auto append(InputIt first, InputIt last)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, this_type&>
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, this_type&>
{ // append [first, last)
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
return append(AZStd::to_address(first), AZStd::distance(first, last));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// Input Iterator pointer type doesn't match the const_pointer type
// So the elements need to be appended one by one into the buffer
@@ -299,7 +294,7 @@ namespace AZStd
inline this_type& assign(const this_type& rhs)
{
return assign(rhs, 0, npos);
return this != &rhs ? assign(rhs, 0, npos) : *this;
}
inline this_type& assign(basic_string_view<Element, Traits> view)
@@ -319,7 +314,8 @@ namespace AZStd
pointer rhsData = rhs.data();
// Memmove the right hand side string data if it is using the short string optimization
// Otherwise set the pointer to the right hand side
if (rhs.m_storage.first().ShortStringOptimizationActive())
if (rhs.m_storage.first().ShortStringOptimizationActive() ||
(get_allocator() != rhs.get_allocator() && !allocator_traits<allocator_type>::propagate_on_container_move_assignment::value))
{
Traits::move(data, rhsData, rhs.size() + 1); // string + null-terminator
}
@@ -395,14 +391,14 @@ namespace AZStd
template<class InputIt>
auto assign(InputIt first, InputIt last)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, this_type&>
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, this_type&>
{
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
return assign(AZStd::to_address(first), AZStd::distance(first, last));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// forward iterator pointer type doesn't match the const_pointer type
// So the elements need to be assigned one by one into the buffer
@@ -431,7 +427,7 @@ namespace AZStd
inputCopy.push_back(static_cast<Element>(*first));
}
return assign(inputCopy.c_str(), inputCopy.size());
return assign(AZStd::move(inputCopy));
}
}
inline this_type& insert(size_type offset, const this_type& rhs) { return insert(offset, rhs, 0, npos); }
@@ -539,15 +535,15 @@ namespace AZStd
template<class InputIt>
auto insert(const_iterator insertPos, InputIt first, InputIt last)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, iterator>
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, iterator>
{ // insert [_First, _Last) at _Where
size_type insertOffset = AZStd::distance(cbegin(), insertPos);
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
insert(insertOffset, AZStd::to_address(first), AZStd::distance(first, last));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// Input Iterator pointer type doesn't match the const_pointer type
// So the elements need to be inserted one by one into the buffer
@@ -834,14 +830,14 @@ namespace AZStd
template<class InputIt>
inline auto replace(const_iterator first, const_iterator last, InputIt replaceFirst, InputIt replaceLast)
-> enable_if_t<Internal::is_input_iterator_v<InputIt> && !is_convertible_v<InputIt, size_type>, this_type&>
-> enable_if_t<input_iterator<InputIt> && !is_convertible_v<InputIt, size_type>, this_type&>
{
if constexpr (Internal::satisfies_contiguous_iterator_concept_v<InputIt>
if constexpr (contiguous_iterator<InputIt>
&& is_same_v<typename AZStd::iterator_traits<InputIt>::value_type, value_type>)
{
return replace(first, last, AZStd::to_address(replaceFirst), AZStd::distance(replaceFirst, replaceLast));
}
else if constexpr (Internal::is_forward_iterator_v<InputIt>)
else if constexpr (forward_iterator<InputIt>)
{
// Input Iterator pointer type doesn't match the const_pointer type
// So the elements need to be appended one by one into the buffer
@@ -1031,12 +1027,19 @@ namespace AZStd
// same allocator, swap storage
m_storage.first().swap(rhs.m_storage.first());
}
else if (allocator_traits<allocator_type>::propagate_on_container_swap::value)
{
// The allocator propagates on swap, so the allocators can be swapped
m_storage.first().swap(rhs.m_storage.first());
using AZStd::swap;
swap(m_storage.second(), rhs.m_storage.second());
}
else
{
// different allocator, do multiple assigns
this_type tmp = *this;
*this = rhs;
rhs = tmp;
this_type tmp = AZStd::move(*this);
*this = AZStd::move(rhs);
rhs = AZStd::move(tmp);
}
}
@@ -7,6 +7,7 @@
*/
#pragma once
#include <AzCore/std/ranges/ranges.h>
#include <AzCore/std/createdestroy.h>
#include <AzCore/std/iterator.h>
#include <AzCore/std/limits.h>
@@ -613,8 +614,9 @@ namespace AZStd
{}
template <typename It, typename End, typename = AZStd::enable_if_t<
Internal::satisfies_contiguous_iterator_concept_v<It>
&& is_same_v<typename AZStd::iterator_traits<It>::value_type, value_type>
contiguous_iterator<It>
&& sized_sentinel_for<End, It>
&& is_same_v<iter_value_t<It>, value_type>
&& !is_convertible_v<End, size_type>>
>
constexpr basic_string_view(It first, End last)
@@ -961,23 +963,6 @@ namespace AZStd
using string_view = basic_string_view<char>;
using wstring_view = basic_string_view<wchar_t>;
template<class Element, class Traits = AZStd::char_traits<Element>>
using basic_const_string = basic_string_view<Element, Traits>;
using const_string = string_view;
using const_wstring = wstring_view;
template <class Element, class Traits = AZStd::char_traits<Element>>
constexpr typename basic_string_view<Element, Traits>::const_iterator begin(basic_string_view<Element, Traits> sv)
{
return sv.begin();
}
template <class Element, class Traits = AZStd::char_traits<Element>>
constexpr typename basic_string_view<Element, Traits>::const_iterator end(basic_string_view<Element, Traits> sv)
{
return sv.end();
}
inline namespace literals
{
inline namespace string_view_literals
@@ -1024,6 +1009,15 @@ namespace AZStd
} // namespace AZStd
namespace AZStd::ranges
{
template <class Element, class Traits>
inline constexpr bool enable_borrowed_range<basic_string_view<Element, Traits>> = true;
template <class Element, class Traits>
inline constexpr bool enable_view<basic_string_view<Element, Traits>> = true;
}
//! Use this macro to simplify safe printing of a string_view which may not be null-terminated.
//! Example: AZStd::string::format("Safely formatted: %.*s", AZ_STRING_ARG(myString));
#define AZ_STRING_ARG(str) aznumeric_cast<int>(str.size()), str.data()
@@ -0,0 +1,230 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/typetraits/config.h>
#include <AzCore/std/typetraits/common_type.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/is_const.h>
#include <AzCore/std/typetraits/is_convertible.h>
#include <AzCore/std/typetraits/is_lvalue_reference.h>
#include <AzCore/std/typetraits/is_rvalue_reference.h>
#include <AzCore/std/typetraits/is_same.h>
#include <AzCore/std/typetraits/is_volatile.h>
#include <AzCore/std/typetraits/remove_reference.h>
#include <AzCore/std/typetraits/remove_cvref.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utility/declval.h>
namespace AZStd
{
template <class T, class U, template<class> class TQual, template<class> class UQual>
struct basic_common_reference
{};
}
namespace AZStd::Internal
{
// const volatile and reference qualifier copy templates
template <class T, class QualType>
struct copy_cv_qual
{
using type = conditional_t<is_const_v<T>, conditional_t<is_volatile_v<T>, const volatile QualType, const QualType>,
conditional_t<is_volatile_v<T>, volatile QualType, QualType>>;
};
template <class T,class QualType>
using copy_cv_qual_t = typename copy_cv_qual<T, QualType>::type;
static_assert(is_same_v<copy_cv_qual_t<int, float>, float>);
static_assert(is_same_v<copy_cv_qual_t<const int, float>, const float>);
static_assert(is_same_v<copy_cv_qual_t<volatile int, float>, volatile float>);
static_assert(is_same_v<copy_cv_qual_t<const volatile int, float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<int, const float>, const float>);
static_assert(is_same_v<copy_cv_qual_t<const int, const float>, const float>);
static_assert(is_same_v<copy_cv_qual_t<volatile int, const float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<const volatile int, const float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<int, volatile float>, volatile float>);
static_assert(is_same_v<copy_cv_qual_t<const int, volatile float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<volatile int, volatile float>, volatile float>);
static_assert(is_same_v<copy_cv_qual_t<const volatile int, volatile float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<int, const volatile float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<const int, const volatile float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<volatile int, const volatile float>, const volatile float>);
static_assert(is_same_v<copy_cv_qual_t<const volatile int, const volatile float>, const volatile float>);
template <class T, class QualType>
struct copy_reference_qual
{
using type = conditional_t<is_lvalue_reference_v<T>, QualType&,
conditional_t<is_rvalue_reference_v<T>, QualType&&, QualType>>;
};
template <class T, class QualType>
using copy_reference_qual_t = typename copy_reference_qual<T, QualType>::type;
static_assert(is_same_v<copy_reference_qual_t<int, float>, float>);
static_assert(is_same_v<copy_reference_qual_t<int&, float>, float&>);
static_assert(is_same_v<copy_reference_qual_t<int&&, float>, float&&>);
static_assert(is_same_v<copy_reference_qual_t<int, float&>, float&>);
static_assert(is_same_v<copy_reference_qual_t<int&, float&>, float&>);
static_assert(is_same_v<copy_reference_qual_t<int&&, float&>, float&>);
static_assert(is_same_v<copy_reference_qual_t<int, float&&>, float&&>);
static_assert(is_same_v<copy_reference_qual_t<int&, float&&>, float&>);
static_assert(is_same_v<copy_reference_qual_t<int&&, float&&>, float&&>);
template <class T, class QualType>
using copy_cvref_qual_t = copy_cv_qual_t<copy_reference_qual_t<T, QualType>, QualType>;
template <class T>
struct copy_qualifiers_from_t
{
template <class X>
using templ = copy_cvref_qual_t<T, X>;
};
template <class T, class U>
using cond_res = decltype(false ? declval<copy_cv_qual_t<remove_reference_t<T>, remove_reference_t<U>>&>()
: declval<copy_cv_qual_t<remove_reference_t<U>, remove_reference_t<T>>&>());
// common reference helper templates begin
template <class T, class U, typename = void>
struct common_reference_base_reference_test;
// COMMON_REF is defined within the C++ standard at https://eel.is/c++draft/meta.trans.other#3.5
template <class T, class U>
struct common_reference_base_reference_test<T, U,
enable_if_t<is_lvalue_reference_v<T>&& is_lvalue_reference_v<U>,
void_t<cond_res<T,U>> >>
{
// Uses the ternary operator for determining the common type
using type = cond_res<T, U>;
};
template <class T, class U>
struct common_reference_base_reference_test<T, U, enable_if_t<is_rvalue_reference_v<T>&& is_rvalue_reference_v<U>>>
{
using C = remove_reference_t<typename common_reference_base_reference_test<remove_reference_t<T>&, remove_reference_t<U>&>::type>;
using type = AZStd::enable_if_t<is_convertible_v<T, C>&& is_convertible_v<U, C>, C>;
};
template <class T, class U>
struct common_reference_base_reference_test<T, U, enable_if_t<is_rvalue_reference_v<T>&& is_lvalue_reference_v<U>>>
{
// Turn rvalue references to const lvalue references
using D = typename common_reference_base_reference_test<const remove_reference_t<T>&, remove_reference_t<U>&>::type;
using type = AZStd::enable_if_t<is_convertible_v<T, D>, D>;
};
template <class T, class U>
struct common_reference_base_reference_test<T, U, enable_if_t<is_lvalue_reference_v<T>&& is_rvalue_reference_v<U>>>
{
// Swap the parameters to call the 3rd specialization for common_reference_base_reference_test
using type = typename common_reference_base_reference_test<U, T>::type;
};
template <class T, class U, typename = void>
constexpr bool has_reference_test = false;
template <class T, class U>
constexpr bool has_reference_test<T, U, void_t<typename common_reference_base_reference_test<T, U>::type>> = true;
template <class T, class U, typename = void>
struct basic_common_reference_test;
template <class T, class U>
struct basic_common_reference_test<T, U, void_t<typename basic_common_reference<remove_cvref_t<T>, remove_cvref_t<U>,
copy_qualifiers_from_t<T>::template templ, copy_qualifiers_from_t<U>::template templ>::type>>
{
using type = typename basic_common_reference<remove_cvref_t<T>, remove_cvref_t<U>,
copy_qualifiers_from_t<T>::template templ, copy_qualifiers_from_t<U>::template templ>::type;
};
template <class T, class U, typename = void>
constexpr bool has_basic_common_reference_test = false;
template <class T, class U>
constexpr bool has_basic_common_reference_test<T, U,
void_t<typename basic_common_reference_test<T, U>::type>> = true;
template <class T, class U, typename = void>
constexpr bool has_condition_result_test = false;
template <class T, class U>
constexpr bool has_condition_result_test<T, U, void_t<decltype(false ? declval<T>() : declval<U>())>> = true;
template <class T, class U, typename = void>
struct common_reference_base_test
{};
template <class T, class U>
struct common_reference_base_test<T, U, enable_if_t<has_reference_test<T, U>>>
: common_reference_base_reference_test<T, U>
{};
template <class T, class U>
struct common_reference_base_test<T, U, enable_if_t<!has_reference_test<T, U>
&& has_basic_common_reference_test<T, U>>>
: basic_common_reference_test<T, U>
{};
template <class T, class U>
struct common_reference_base_test<T, U, enable_if_t<!has_reference_test<T, U>
&& !has_basic_common_reference_test<T, U> && has_condition_result_test<T,U>>>
{
using type = decltype(false ? declval<T>() : declval<U>());
};
template <class T, class U>
struct common_reference_base_test<T, U, enable_if_t<!has_reference_test<T, U>
&& !has_basic_common_reference_test<T, U> && !has_condition_result_test<T, U>>>
: common_type<T, U>
{};
template <class... T>
struct common_reference_base
{};
template <class T>
struct common_reference_base<T>
{
using type = T;
};
template <class T, class U>
struct common_reference_base<T, U>
: common_reference_base_test<T, U>
{};
template <class T, class U, class V, class... Rs>
struct common_reference_base<T, U, V, Rs...>
: common_reference_base<typename common_reference_base<T, U>::type, V, Rs...>
{};
}
namespace AZStd
{
template <class... T>
struct common_reference
: Internal::common_reference_base<T...>
{};
template <class... T>
using common_reference_t = typename common_reference<T...>::type;
// models the common reference concept
namespace Internal
{
template<class T, class U, typename = void>
constexpr bool common_reference_with_impl = false;
template<class T, class U>
constexpr bool common_reference_with_impl<T, U, enable_if_t<
same_as<common_reference_t<T, U>, common_reference_t<U, T>>
&& convertible_to<T, common_reference_t<T, U>>
&& convertible_to<U, common_reference_t<T, U>>
>> = true;
}
template<class T, class U>
/*concept*/ constexpr bool common_reference_with = Internal::common_reference_with_impl<T, U>;
}
@@ -8,12 +8,26 @@
#pragma once
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/intrinsics.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utility/declval.h>
namespace AZStd
{
using std::is_convertible;
using std::is_convertible_v;
// models the C++20 convertible_to concept
namespace Internal
{
template<typename From, typename To, typename = void>
constexpr bool convertible_to_impl = false;
template<typename From, typename To>
constexpr bool convertible_to_impl<From, To, enable_if_t<
is_convertible_v<From, To>, void_t<decltype(static_cast<To>(declval<From>()))>>> = true;
}
template<typename From, typename To>
constexpr bool is_convertible_v = std::is_convertible_v<From, To>;
/*concept*/ constexpr bool convertible_to = Internal::convertible_to_impl<From, To>;
}
@@ -21,4 +21,7 @@ namespace AZStd
constexpr bool is_trivially_destructible_v = std::is_trivially_destructible<T>::value;
template<class T>
constexpr bool is_nothrow_destructible_v = std::is_nothrow_destructible<T>::value;
template<class T>
/*concept*/ constexpr bool destructible = is_nothrow_destructible_v<T>;
}
@@ -13,4 +13,7 @@ namespace AZStd
{
using std::is_floating_point;
using std::is_floating_point_v;
template<class T>
/*concept*/ constexpr bool floating_point = is_floating_point_v<T>;
}
@@ -13,4 +13,7 @@ namespace AZStd
{
using std::is_integral;
using std::is_integral_v;
template<class T>
/*concept*/ constexpr bool integral = is_integral_v<T>;
}
@@ -13,4 +13,8 @@ namespace AZStd
{
using std::is_same;
using std::is_same_v;
// models the same_as concept
template <class T, class U>
/*concept*/ constexpr bool same_as = is_same_v<T, U>;
}
@@ -27,6 +27,8 @@
#include <AzCore/std/typetraits/add_volatile.h>
#include <AzCore/std/typetraits/alignment_of.h>
#include <AzCore/std/typetraits/aligned_storage.h>
#include <AzCore/std/typetraits/common_reference.h>
#include <AzCore/std/typetraits/common_type.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/conjunction.h>
#include <AzCore/std/typetraits/decay.h>
@@ -0,0 +1,15 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <utility>
namespace AZStd
{
using std::declval;
}
@@ -0,0 +1,19 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
namespace AZStd
{
// rvalue
// rvalue move
template<class T>
constexpr AZStd::remove_reference_t<T>&& move(T&& t)
{
return static_cast<AZStd::remove_reference_t<T>&&>(t);
}
}
+2 -9
View File
@@ -22,22 +22,15 @@
#include <AzCore/std/typetraits/is_convertible.h>
#include <AzCore/std/typetraits/is_lvalue_reference.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utility/declval.h>
#include <AzCore/std/utility/move.h>
#include <utility>
namespace AZStd
{
//////////////////////////////////////////////////////////////////////////
// rvalue
// rvalue move
template<class T>
constexpr AZStd::remove_reference_t<T>&& move(T && t)
{
return static_cast<AZStd::remove_reference_t<T>&&>(t);
}
using std::forward;
using std::declval;
using std::exchange;
template <class T>
@@ -86,7 +86,7 @@
#define AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE nullptr
#define AZ_TRAIT_SYSTEMFILE_FSYNC_IS_DEFINED 1
#define AZ_TRAIT_SYSTEMFILE_UNIX_LIKE_PLATFORM_IS_WRITEABLE_DEFINED_ELSEWHERE 0
#define AZ_TRAIT_TEST_ROOT_FOLDER "/sdcard/Android/data/com.lumberyard.tests/files"
#define AZ_TRAIT_TEST_ROOT_FOLDER "/sdcard/Android/data/org.o3de.tests/files"
#define AZ_TRAIT_TEST_SUPPORT_DLOPEN 0
#define AZ_TRAIT_TEST_SUPPORT_LOADLIBRARY 0
#define AZ_TRAIT_TEST_SUPPORT_MODULE_LOADING 0
@@ -0,0 +1,202 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/concepts/concepts.h>
namespace UnitTest
{
class ConceptsTestFixture
: public ScopedAllocatorSetupFixture
{};
TEST_F(ConceptsTestFixture, GeneralConcepts)
{
// concept same_as
static_assert(AZStd::same_as<ConceptsTestFixture, ConceptsTestFixture>);
static_assert(!AZStd::same_as<ConceptsTestFixture, ScopedAllocatorSetupFixture>);
// concept derived_from
static_assert(AZStd::derived_from<ConceptsTestFixture, ScopedAllocatorSetupFixture>);
static_assert(!AZStd::derived_from<ScopedAllocatorSetupFixture, ConceptsTestFixture>);
// concept convertible_to
static_assert(AZStd::convertible_to<ConceptsTestFixture&, ScopedAllocatorSetupFixture&>);
static_assert(!AZStd::convertible_to<ScopedAllocatorSetupFixture&, ConceptsTestFixture&>);
// Test structs to validate common_reference_with and common_with concepts
struct Base {};
struct TestBase : Base {};
struct NoMove
{
NoMove(NoMove&&) = delete;
NoMove& operator=(NoMove&&) = delete;
};
struct NoDestructible
{
~NoDestructible() = delete;
};
struct NoDefaultInitializable
{
NoDefaultInitializable(bool);
};
struct CopyOnly
{
CopyOnly(const CopyOnly&) = default;
};
struct MoveOnly
{
MoveOnly(MoveOnly&&) = default;
};
struct MoveableButNotCopyable
{
MoveableButNotCopyable(MoveableButNotCopyable&&) = default;
MoveableButNotCopyable& operator=(MoveableButNotCopyable&&) = default;
};
// concept common_reference_with
static_assert(AZStd::common_reference_with<TestBase&, Base&>);
static_assert(AZStd::same_as<AZStd::common_reference_t<const TestBase&, Base&>, const Base&>);
static_assert(!AZStd::common_reference_with<AllocatorsTestFixture, ScopedAllocatorSetupFixture>);
// concept common_with
static_assert(AZStd::common_with<TestBase, Base>);
static_assert(!AZStd::common_with<AllocatorsTestFixture, AllocatorsBenchmarkFixture>);
// arithmetic concepts
// concept integral
static_assert(AZStd::integral<int>);
static_assert(!AZStd::integral<float>);
// concept signed_integral
static_assert(AZStd::signed_integral<int>);
static_assert(!AZStd::signed_integral<unsigned int>);
static_assert(!AZStd::signed_integral<float>);
// concept signed_integral
static_assert(AZStd::unsigned_integral<unsigned int>);
static_assert(!AZStd::unsigned_integral<int>);
static_assert(!AZStd::unsigned_integral<float>);
// concept floating_point
static_assert(AZStd::floating_point<float>);
static_assert(!AZStd::floating_point<int>);
// concept assignable_from
static_assert(AZStd::assignable_from<Base&, TestBase>);
static_assert(!AZStd::assignable_from<TestBase&, Base>);
// concept swappable
static_assert(AZStd::swappable<Base>);
static_assert(!AZStd::swappable<NoMove>);
static_assert(AZStd::swappable_with<Base, Base>);
static_assert(!AZStd::swappable_with<NoMove, Base>);
// concept destructible
static_assert(AZStd::destructible<Base>);
static_assert(!AZStd::destructible<NoDestructible>);
// concept constructible_from
static_assert(AZStd::constructible_from<NoDefaultInitializable, bool>);
static_assert(!AZStd::constructible_from<NoDefaultInitializable>);
// concept default_initializable
static_assert(AZStd::default_initializable<Base>);
static_assert(!AZStd::default_initializable<NoDefaultInitializable>);
// concept move_constructible
static_assert(AZStd::move_constructible<MoveOnly>);
static_assert(!AZStd::move_constructible<NoMove>);
// concept copy_constructible
static_assert(AZStd::copy_constructible<CopyOnly>);
static_assert(!AZStd::copy_constructible<MoveOnly>);
// concept equality_comparable
static_assert(AZStd::equality_comparable<AZStd::string_view>);
static_assert(!AZStd::equality_comparable<Base>);
static_assert(AZStd::equality_comparable_with<AZStd::string_view, const char*>);
static_assert(!AZStd::equality_comparable_with<Base, TestBase>);
static_assert(!AZStd::equality_comparable_with<Base, const char*>);
// concept totally_ordered
static_assert(AZStd::totally_ordered<AZStd::string_view>);
static_assert(!AZStd::totally_ordered<Base>);
static_assert(AZStd::totally_ordered_with<AZStd::string_view, const char*>);
static_assert(!AZStd::totally_ordered_with<Base, TestBase>);
static_assert(!AZStd::totally_ordered_with<Base, const char*>);
// concept movable
static_assert(AZStd::movable<MoveableButNotCopyable>);
static_assert(!AZStd::movable<NoMove>);
// concept copyable
static_assert(AZStd::copyable<Base>);
static_assert(!AZStd::copyable<MoveableButNotCopyable>);
// concept semiregular
static_assert(AZStd::semiregular<Base>);
static_assert(!AZStd::semiregular<MoveableButNotCopyable>);
// concept regular
static_assert(AZStd::regular<AZStd::string_view>);
static_assert(!AZStd::regular<Base>);
// concept invocable
static_assert(AZStd::invocable<decltype(AZStd::ranges::swap), int&, int&>);
static_assert(!AZStd::invocable<decltype(AZStd::ranges::swap), int&, float&>);
// concept predicate
auto BooleanPredicate = [](double) -> int
{
return 0;
};
auto BasePredicate = [](int) -> Base
{
return Base{};
};
static_assert(AZStd::predicate<decltype(BooleanPredicate), double>);
static_assert(!AZStd::predicate<decltype(BooleanPredicate), Base>);
static_assert(!AZStd::predicate<decltype(BasePredicate), int>);
// concept relation
struct RelationPredicate
{
bool operator()(AZStd::string_view, Base) const;
bool operator()(Base, AZStd::string_view) const;
bool operator()(AZStd::string_view, AZStd::string_view) const;
bool operator()(Base, Base) const;
// non-complete relation
bool operator()(Base, int) const;
bool operator()(int, Base) const;
};
static_assert(AZStd::relation<RelationPredicate, AZStd::string_view, Base>);
static_assert(AZStd::relation<RelationPredicate, Base, AZStd::string_view>);
static_assert(!AZStd::relation<RelationPredicate, int, Base>);
static_assert(!AZStd::relation<RelationPredicate, Base, int>);
//concept equivalence_relation
static_assert(AZStd::equivalence_relation<RelationPredicate, AZStd::string_view, Base>);
static_assert(AZStd::equivalence_relation<RelationPredicate, Base, AZStd::string_view>);
static_assert(!AZStd::equivalence_relation<RelationPredicate, int, Base>);
static_assert(!AZStd::equivalence_relation<RelationPredicate, Base, int>);
//concept strict_weak_order
static_assert(AZStd::strict_weak_order<RelationPredicate, AZStd::string_view, Base>);
static_assert(AZStd::strict_weak_order<RelationPredicate, Base, AZStd::string_view>);
static_assert(!AZStd::strict_weak_order<RelationPredicate, int, Base>);
static_assert(!AZStd::strict_weak_order<RelationPredicate, Base, int>);
}
}
+76 -86
View File
@@ -6,6 +6,7 @@
*
*/
#include "UserTypes.h"
#include <AzCore/std/concepts/concepts.h>
#include <AzCore/std/iterator.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/array.h>
@@ -13,13 +14,11 @@
#include <AzCore/std/containers/set.h>
#include <AzCore/std/utils.h>
using namespace AZStd;
using namespace UnitTestInternal;
namespace UnitTest
{
class Iterators
: public AllocatorsFixture
: public ScopedAllocatorSetupFixture
{
};
@@ -28,30 +27,30 @@ namespace UnitTest
{
Container int_container = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }};
typename Container::iterator iter_begin = begin(int_container);
typename Container::iterator iter_begin = AZStd::begin(int_container);
EXPECT_EQ(*iter_begin, 0);
EXPECT_EQ(*next(iter_begin), 1);
EXPECT_EQ(*next(iter_begin, 2), 2);
EXPECT_EQ(*AZStd::next(iter_begin), 1);
EXPECT_EQ(*AZStd::next(iter_begin, 2), 2);
++iter_begin;
EXPECT_EQ(*iter_begin, 1);
typename Container::iterator iter_end = end(int_container);
EXPECT_EQ(iter_end, int_container.end());
EXPECT_EQ(*prev(iter_end), 9);
EXPECT_EQ(*prev(iter_end, 2), 8);
EXPECT_EQ(*AZStd::prev(iter_end), 9);
EXPECT_EQ(*AZStd::prev(iter_end, 2), 8);
--iter_end;
EXPECT_EQ(*iter_end, 9);
typename Container::reverse_iterator iter_rbegin = rbegin(int_container);
typename Container::reverse_iterator iter_rbegin = AZStd::rbegin(int_container);
EXPECT_EQ(*iter_rbegin, 9);
EXPECT_EQ(*next(iter_rbegin), 8);
EXPECT_EQ(*next(iter_rbegin, 2), 7);
EXPECT_EQ(*AZStd::next(iter_rbegin), 8);
EXPECT_EQ(*AZStd::next(iter_rbegin, 2), 7);
++iter_rbegin;
EXPECT_EQ(*iter_rbegin, 8);
typename Container::reverse_iterator iter_rend = rend(int_container);
EXPECT_EQ(*prev(iter_rend), 0);
EXPECT_EQ(*prev(iter_rend, 2), 1);
typename Container::reverse_iterator iter_rend = AZStd::rend(int_container);
EXPECT_EQ(*AZStd::prev(iter_rend), 0);
EXPECT_EQ(*AZStd::prev(iter_rend, 2), 1);
--iter_rend;
EXPECT_EQ(*iter_rend, 0);
@@ -65,30 +64,30 @@ namespace UnitTest
{
Container int_container = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }};
typename Container::const_iterator iter_cbegin = cbegin(int_container);
typename Container::const_iterator iter_cbegin = AZStd::cbegin(int_container);
EXPECT_EQ(*iter_cbegin, 0);
EXPECT_EQ(*next(iter_cbegin), 1);
EXPECT_EQ(*next(iter_cbegin, 2), 2);
EXPECT_EQ(*AZStd::next(iter_cbegin), 1);
EXPECT_EQ(*AZStd::next(iter_cbegin, 2), 2);
++iter_cbegin;
EXPECT_EQ(*iter_cbegin, 1);
typename Container::const_iterator iter_cend = cend(int_container);
typename Container::const_iterator iter_cend = AZStd::cend(int_container);
EXPECT_EQ(iter_cend, int_container.cend());
EXPECT_EQ(*prev(iter_cend), 9);
EXPECT_EQ(*prev(iter_cend, 2), 8);
EXPECT_EQ(*AZStd::prev(iter_cend), 9);
EXPECT_EQ(*AZStd::prev(iter_cend, 2), 8);
--iter_cend;
EXPECT_EQ(*iter_cend, 9);
typename Container::const_reverse_iterator iter_crbegin = crbegin(int_container);
typename Container::const_reverse_iterator iter_crbegin = AZStd::crbegin(int_container);
EXPECT_EQ(*iter_crbegin, 9);
EXPECT_EQ(*next(iter_crbegin), 8);
EXPECT_EQ(*next(iter_crbegin, 2), 7);
EXPECT_EQ(*AZStd::next(iter_crbegin), 8);
EXPECT_EQ(*AZStd::next(iter_crbegin, 2), 7);
++iter_crbegin;
EXPECT_EQ(*iter_crbegin, 8);
typename Container::const_reverse_iterator iter_crend = crend(int_container);
EXPECT_EQ(*prev(iter_crend), 0);
EXPECT_EQ(*prev(iter_crend, 2), 1);
typename Container::const_reverse_iterator iter_crend = AZStd::crend(int_container);
EXPECT_EQ(*AZStd::prev(iter_crend), 0);
EXPECT_EQ(*AZStd::prev(iter_crend, 2), 1);
--iter_crend;
EXPECT_EQ(*iter_crend, 0);
}
@@ -98,15 +97,15 @@ namespace UnitTest
{
const ConstContainer const_int_container = {{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }};
typename ConstContainer::const_iterator const_iter_begin = begin(const_int_container);
typename ConstContainer::const_iterator const_iter_begin = AZStd::begin(const_int_container);
EXPECT_EQ(*const_iter_begin, 10);
EXPECT_EQ(*next(const_iter_begin), 11);
EXPECT_EQ(*next(const_iter_begin, 2), 12);
EXPECT_EQ(*AZStd::next(const_iter_begin), 11);
EXPECT_EQ(*AZStd::next(const_iter_begin, 2), 12);
typename ConstContainer::const_iterator const_iter_end = end(const_int_container);
typename ConstContainer::const_iterator const_iter_end = AZStd::end(const_int_container);
EXPECT_EQ(const_iter_end, const_int_container.end());
EXPECT_EQ(*prev(const_iter_end), 19);
EXPECT_EQ(*prev(const_iter_end, 2), 18);
EXPECT_EQ(*AZStd::prev(const_iter_end), 19);
EXPECT_EQ(*AZStd::prev(const_iter_end, 2), 18);
}
TEST_F(Iterators, FunctionWrappers_MutableContainers)
@@ -136,87 +135,78 @@ namespace UnitTest
{
int int_array[10] = { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 };
EXPECT_EQ(*begin(int_array), 20);
EXPECT_EQ(*next(begin(int_array)), 21);
EXPECT_EQ(*next(begin(int_array), 2), 22);
EXPECT_EQ(*AZStd::begin(int_array), 20);
EXPECT_EQ(*AZStd::next(AZStd::begin(int_array)), 21);
EXPECT_EQ(*AZStd::next(AZStd::begin(int_array), 2), 22);
EXPECT_EQ(end(int_array) - AZ_ARRAY_SIZE(int_array), begin(int_array));
EXPECT_EQ(*prev(end(int_array)), 29);
EXPECT_EQ(*prev(end(int_array), 2), 28);
EXPECT_EQ(AZStd::end(int_array) - AZ_ARRAY_SIZE(int_array), AZStd::begin(int_array));
EXPECT_EQ(*AZStd::prev(AZStd::end(int_array)), 29);
EXPECT_EQ(*AZStd::prev(AZStd::end(int_array), 2), 28);
EXPECT_EQ(*rbegin(int_array), 29);
EXPECT_EQ(*next(rbegin(int_array)), 28);
EXPECT_EQ(*next(rbegin(int_array), 2), 27);
EXPECT_EQ(*AZStd::rbegin(int_array), 29);
EXPECT_EQ(*AZStd::next(AZStd::rbegin(int_array)), 28);
EXPECT_EQ(*AZStd::next(AZStd::rbegin(int_array), 2), 27);
EXPECT_EQ(*prev(rend(int_array)), 20);
EXPECT_EQ(*prev(rend(int_array), 2), 21);
EXPECT_EQ(*AZStd::prev(AZStd::rend(int_array)), 20);
EXPECT_EQ(*AZStd::prev(AZStd::rend(int_array), 2), 21);
EXPECT_EQ(*crbegin(int_array), 29);
EXPECT_EQ(*next(crbegin(int_array)), 28);
EXPECT_EQ(*next(crbegin(int_array), 2), 27);
EXPECT_EQ(*AZStd::crbegin(int_array), 29);
EXPECT_EQ(*AZStd::next(AZStd::crbegin(int_array)), 28);
EXPECT_EQ(*AZStd::next(AZStd::crbegin(int_array), 2), 27);
EXPECT_EQ(*prev(crend(int_array)), 20);
EXPECT_EQ(*prev(crend(int_array), 2), 21);
EXPECT_EQ(*AZStd::prev(AZStd::crend(int_array)), 20);
EXPECT_EQ(*AZStd::prev(AZStd::crend(int_array), 2), 21);
//verify we can successfully modify the value in a non-const iterator
*begin(int_array) = -42;
EXPECT_EQ(*begin(int_array), -42);
*AZStd::begin(int_array) = -42;
EXPECT_EQ(*AZStd::begin(int_array), -42);
}
TEST_F(Iterators, FunctionWrappers_ConstRawArray)
{
const int const_int_array[10] = { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 };
EXPECT_EQ(*cbegin(const_int_array), 30);
EXPECT_EQ(*next(cbegin(const_int_array)), 31);
EXPECT_EQ(*next(cbegin(const_int_array), 2), 32);
EXPECT_EQ(*AZStd::cbegin(const_int_array), 30);
EXPECT_EQ(*AZStd::next(AZStd::cbegin(const_int_array)), 31);
EXPECT_EQ(*AZStd::next(AZStd::cbegin(const_int_array), 2), 32);
EXPECT_EQ(cend(const_int_array) - AZ_ARRAY_SIZE(const_int_array), cbegin(const_int_array));
EXPECT_EQ(*prev(cend(const_int_array)), 39);
EXPECT_EQ(*prev(cend(const_int_array), 2), 38);
EXPECT_EQ(AZStd::cend(const_int_array) - AZ_ARRAY_SIZE(const_int_array), AZStd::cbegin(const_int_array));
EXPECT_EQ(*AZStd::prev(AZStd::cend(const_int_array)), 39);
EXPECT_EQ(*AZStd::prev(AZStd::cend(const_int_array), 2), 38);
}
TEST_F(Iterators, IteratorTraits_ResolveAtCompileTime)
{
using list_type = AZStd::list<int>;
static_assert(AZStd::Internal::has_iterator_category_v<typename list_type::iterator>);
static_assert(AZStd::Internal::has_iterator_type_aliases_v<typename list_type::iterator>);
constexpr bool list_type_iterator_type_aliases = AZStd::Internal::has_iterator_type_aliases_v<typename list_type::iterator>;
static_assert(AZStd::is_convertible_v<AZStd::Internal::iterator_traits_type_aliases<typename list_type::iterator, list_type_iterator_type_aliases>::iterator_category,
AZStd::input_iterator_tag>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::iterator>::iterator_category, bidirectional_iterator_tag>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::iterator>::value_type, int>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::iterator>::difference_type, AZStd::ptrdiff_t>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::iterator>::pointer, int*>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::iterator>::reference, int&>);
static_assert(AZStd::Internal::is_input_iterator_v<typename list_type::iterator>);
static_assert(!AZStd::Internal::has_iterator_concept_v<AZStd::iterator_traits<typename list_type::iterator>>);
static_assert(!AZStd::Internal::satisfies_contiguous_iterator_concept_v<typename list_type::iterator>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::iterator>::iterator_category, AZStd::bidirectional_iterator_tag>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::iterator>::value_type, int>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::iterator>::difference_type, AZStd::ptrdiff_t>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::iterator>::pointer, int*>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::iterator>::reference, int&>);
static_assert(AZStd::input_iterator<typename list_type::iterator>);
static_assert(!AZStd::contiguous_iterator<typename list_type::iterator>);
static_assert(AZStd::Internal::has_iterator_category_v<typename list_type::const_iterator>);
static_assert(AZStd::Internal::has_iterator_type_aliases_v<typename list_type::const_iterator>);
constexpr bool list_type_const_iterator_type_aliases = AZStd::Internal::has_iterator_type_aliases_v<typename list_type::const_iterator>;
static_assert(AZStd::is_convertible_v<AZStd::Internal::iterator_traits_type_aliases<typename list_type::iterator, list_type_const_iterator_type_aliases>::iterator_category,
AZStd::input_iterator_tag>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::iterator_category, bidirectional_iterator_tag>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::value_type, int>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::difference_type, AZStd::ptrdiff_t>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::pointer, const int*>);
static_assert(is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::reference, const int&>);
static_assert(AZStd::Internal::is_input_iterator_v<typename list_type::const_iterator>);
static_assert(!AZStd::Internal::has_iterator_concept_v<AZStd::iterator_traits<typename list_type::const_iterator>>);
static_assert(!AZStd::Internal::satisfies_contiguous_iterator_concept_v<typename list_type::const_iterator>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::iterator_category, AZStd::bidirectional_iterator_tag>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::value_type, int>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::difference_type, AZStd::ptrdiff_t>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::pointer, const int*>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<typename list_type::const_iterator>::reference, const int&>);
static_assert(AZStd::input_iterator<typename list_type::const_iterator>);
static_assert(!AZStd::contiguous_iterator<typename list_type::const_iterator>);
using pointer_type = const char*;
static_assert(AZStd::Internal::has_iterator_category_v<AZStd::iterator_traits<pointer_type>>);
static_assert(AZStd::Internal::has_iterator_type_aliases_v<AZStd::iterator_traits<pointer_type>>);
static_assert(is_same_v<AZStd::iterator_traits<pointer_type>::iterator_concept, contiguous_iterator_tag>);
static_assert(is_same_v<AZStd::iterator_traits<pointer_type>::iterator_category, random_access_iterator_tag>);
static_assert(is_same_v<AZStd::iterator_traits<pointer_type>::value_type, char>);
static_assert(is_same_v<AZStd::iterator_traits<pointer_type>::difference_type, AZStd::ptrdiff_t>);
static_assert(is_same_v<AZStd::iterator_traits<pointer_type>::pointer, const char*>);
static_assert(is_same_v<AZStd::iterator_traits<pointer_type>::reference, const char&>);
static_assert(AZStd::Internal::has_iterator_concept_v<AZStd::iterator_traits<pointer_type>>);
static_assert(AZStd::Internal::satisfies_contiguous_iterator_concept_v<pointer_type>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<pointer_type>::iterator_concept, AZStd::contiguous_iterator_tag>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<pointer_type>::iterator_category, AZStd::random_access_iterator_tag>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<pointer_type>::value_type, char>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<pointer_type>::difference_type, AZStd::ptrdiff_t>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<pointer_type>::pointer, const char*>);
static_assert(AZStd::is_same_v<AZStd::iterator_traits<pointer_type>::reference, const char&>);
static_assert(AZStd::contiguous_iterator<pointer_type>);
}
}
@@ -0,0 +1,583 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/ranges/ranges.h>
namespace UnitTest
{
class RangesTestFixture
: public ScopedAllocatorSetupFixture
{};
struct RangeLikeCustomizationPoint {};
RangeLikeCustomizationPoint* begin(RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
RangeLikeCustomizationPoint* end(RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
const RangeLikeCustomizationPoint* cbegin(const RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
const RangeLikeCustomizationPoint* cend(const RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
RangeLikeCustomizationPoint* rbegin(RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
RangeLikeCustomizationPoint* rend(RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
const RangeLikeCustomizationPoint* crbegin(const RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
const RangeLikeCustomizationPoint* crend(const RangeLikeCustomizationPoint& rangeLike)
{
return &rangeLike;
}
constexpr size_t size(const RangeLikeCustomizationPoint&)
{
return 0;
}
constexpr size_t size(RangeLikeCustomizationPoint&)
{
return 0;
}
// range access
TEST_F(RangesTestFixture, RangesBegin_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray + 0, AZStd::ranges::begin(extentArray));
}
TEST_F(RangesTestFixture, RangesBegin_DoesNotCompile_WithNoExtentArray)
{
using ArrayNoExtentType = int[];
static_assert(!AZStd::invocable<decltype(AZStd::ranges::begin), ArrayNoExtentType>);
}
TEST_F(RangesTestFixture, RangesBegin_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.begin(), AZStd::ranges::begin(strView));
}
TEST_F(RangesTestFixture, RangesBegin_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::begin(rangeLike));
}
TEST_F(RangesTestFixture, RangesEnd_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray + 5, AZStd::ranges::end(extentArray));
}
TEST_F(RangesTestFixture, RangesEnd_DoesNotCompile_WithNoExtentArray)
{
using ArrayNoExtentType = int[];
static_assert(!AZStd::invocable<decltype(AZStd::ranges::end), ArrayNoExtentType>);
}
TEST_F(RangesTestFixture, RangesEnd_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.end(), AZStd::ranges::end(strView));
}
TEST_F(RangesTestFixture, RangesEnd_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::end(rangeLike));
}
TEST_F(RangesTestFixture, RangesCBegin_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray + 0, AZStd::ranges::cbegin(extentArray));
}
TEST_F(RangesTestFixture, RangesCBegin_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.cbegin(), AZStd::ranges::cbegin(strView));
}
TEST_F(RangesTestFixture, RangesCBegin_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::cbegin(rangeLike));
}
TEST_F(RangesTestFixture, RangesCEnd_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray + 5, AZStd::ranges::cend(extentArray));
}
TEST_F(RangesTestFixture, RangesCEnd_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.cend(), AZStd::ranges::cend(strView));
}
TEST_F(RangesTestFixture, RangesCEnd_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::cend(rangeLike));
}
TEST_F(RangesTestFixture, RangesRBegin_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray + 5, AZStd::ranges::rbegin(extentArray).base());
}
TEST_F(RangesTestFixture, RangesRBegin_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.rbegin(), AZStd::ranges::rbegin(strView));
}
TEST_F(RangesTestFixture, RangesRBegin_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::rbegin(rangeLike));
}
TEST_F(RangesTestFixture, RangesREnd_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray, AZStd::ranges::rend(extentArray).base());
}
TEST_F(RangesTestFixture, RangesREnd_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.rend(), AZStd::ranges::rend(strView));
}
TEST_F(RangesTestFixture, RangesREnd_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::rend(rangeLike));
}
TEST_F(RangesTestFixture, RangesCRBegin_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray + 5, AZStd::ranges::crbegin(extentArray).base());
}
TEST_F(RangesTestFixture, RangesCRBegin_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.crbegin(), AZStd::ranges::crbegin(strView));
}
TEST_F(RangesTestFixture, RangesCRBegin_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::crbegin(rangeLike));
}
TEST_F(RangesTestFixture, RangesCREnd_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
ArrayExtentType extentArray{};
EXPECT_EQ(extentArray + 0, AZStd::ranges::crend(extentArray).base());
}
TEST_F(RangesTestFixture, RangesCREnd_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.crend(), AZStd::ranges::crend(strView));
}
TEST_F(RangesTestFixture, RangesCREnd_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::crend(rangeLike));
}
// range access - size
TEST_F(RangesTestFixture, RangesSize_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
constexpr ArrayExtentType extentArray{};
static_assert(5 == AZStd::ranges::size(extentArray));
}
TEST_F(RangesTestFixture, RangesSize_DoesNotCompile_WithNoExtentArray)
{
using ArrayNoExtentType = int[];
static_assert(!AZStd::invocable<decltype(AZStd::ranges::size), ArrayNoExtentType>);
}
TEST_F(RangesTestFixture, RangesSize_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
EXPECT_EQ(strView.size(), AZStd::ranges::size(strView));
}
TEST_F(RangesTestFixture, RangesSize_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(0, AZStd::ranges::size(rangeLike));
}
TEST_F(RangesTestFixture, RangesSSize_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
constexpr ArrayExtentType extentArray{};
static_assert(AZStd::signed_integral<decltype(AZStd::ranges::ssize(extentArray))>);
static_assert(5 == AZStd::ranges::ssize(extentArray));
}
TEST_F(RangesTestFixture, RangesSSize_DoesNotCompile_WithNoExtentArray)
{
using ArrayNoExtentType = int[];
static_assert(!AZStd::invocable<decltype(AZStd::ranges::ssize), ArrayNoExtentType>);
}
TEST_F(RangesTestFixture, RangesSSize_Compiles_WithMemberOverload)
{
AZStd::string_view strView;
static_assert(AZStd::signed_integral<decltype(AZStd::ranges::ssize(strView))>);
EXPECT_EQ(strView.size(), AZStd::ranges::ssize(strView));
}
TEST_F(RangesTestFixture, RangesSSize_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
static_assert(AZStd::signed_integral<decltype(AZStd::ranges::ssize(rangeLike))>);
EXPECT_EQ(0, AZStd::ranges::ssize(rangeLike));
}
// range access - empty
TEST_F(RangesTestFixture, RangesEmpty_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
constexpr ArrayExtentType extentArray{};
static_assert(!AZStd::ranges::empty(extentArray));
}
TEST_F(RangesTestFixture, RangesEmpty_DoesNotCompile_WithNoExtentArray)
{
using ArrayNoExtentType = int[];
static_assert(!AZStd::invocable<decltype(AZStd::ranges::empty), ArrayNoExtentType>);
}
TEST_F(RangesTestFixture, RangesEmpty_Compiles_WithMemberOverload)
{
constexpr AZStd::string_view strView;
static_assert(AZStd::ranges::empty(strView));
}
TEST_F(RangesTestFixture, RangesEmpty_Compiles_WithADL)
{
constexpr RangeLikeCustomizationPoint rangeLike;
static_assert(AZStd::ranges::empty(rangeLike));
}
// range access - data
TEST_F(RangesTestFixture, RangesData_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
constexpr ArrayExtentType extentArray{};
EXPECT_EQ(extentArray, AZStd::ranges::data(extentArray));
}
TEST_F(RangesTestFixture, RangesData_DoesNotCompile_WithNoExtentArray)
{
using ArrayNoExtentType = int[];
static_assert(!AZStd::invocable<decltype(AZStd::ranges::data), ArrayNoExtentType>);
}
TEST_F(RangesTestFixture, RangesData_Compiles_WithMemberOverload)
{
constexpr AZStd::string_view strView;
EXPECT_EQ(strView.data(), AZStd::ranges::data(strView));
}
TEST_F(RangesTestFixture, RangesData_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::data(rangeLike));
}
// range access - cdata
TEST_F(RangesTestFixture, RangesCData_Compiles_WithExtentArray)
{
using ArrayExtentType = int[5];
constexpr ArrayExtentType extentArray{};
EXPECT_EQ(extentArray, AZStd::ranges::cdata(extentArray));
}
TEST_F(RangesTestFixture, RangesCData_DoesNotCompile_WithNoExtentArray)
{
using ArrayNoExtentType = int[];
static_assert(!AZStd::invocable<decltype(AZStd::ranges::cdata), ArrayNoExtentType>);
}
TEST_F(RangesTestFixture, RangesCData_Compiles_WithMemberOverload)
{
constexpr AZStd::string_view strView;
EXPECT_EQ(strView.data(), AZStd::ranges::cdata(strView));
}
TEST_F(RangesTestFixture, RangesCData_Compiles_WithADL)
{
RangeLikeCustomizationPoint rangeLike;
EXPECT_EQ(&rangeLike, AZStd::ranges::cdata(rangeLike));
}
// Ranges TypeTraits Test
TEST_F(RangesTestFixture, RangesTypeTraits_Compiles)
{
// string_view
static_assert(AZStd::same_as<AZStd::ranges::iterator_t<AZStd::string_view>, const char*>);
static_assert(AZStd::same_as<AZStd::ranges::sentinel_t<AZStd::string_view>, const char*>);
static_assert(AZStd::same_as<AZStd::ranges::range_difference_t<AZStd::string_view>, ptrdiff_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_size_t<AZStd::string_view>, size_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_value_t<AZStd::string_view>, char>);
static_assert(AZStd::same_as<AZStd::ranges::range_reference_t<AZStd::string_view>, const char&>);
static_assert(AZStd::same_as<AZStd::ranges::range_rvalue_reference_t<AZStd::string_view>, const char&&>);
// string
static_assert(AZStd::same_as<AZStd::ranges::iterator_t<AZStd::string>, char*>);
static_assert(AZStd::same_as<AZStd::ranges::sentinel_t<AZStd::string>, char*>);
static_assert(AZStd::same_as<AZStd::ranges::range_difference_t<AZStd::string>, ptrdiff_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_size_t<AZStd::string>, size_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_value_t<AZStd::string>, char>);
static_assert(AZStd::same_as<AZStd::ranges::range_reference_t<AZStd::string>, char&>);
static_assert(AZStd::same_as<AZStd::ranges::range_rvalue_reference_t<AZStd::string>, char&&>);
// int array type
using ArrayExtentType = int[5];
static_assert(AZStd::same_as<AZStd::ranges::iterator_t<ArrayExtentType>, int*>);
static_assert(AZStd::same_as<AZStd::ranges::sentinel_t<ArrayExtentType>, int*>);
static_assert(AZStd::same_as<AZStd::ranges::range_difference_t<ArrayExtentType>, ptrdiff_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_size_t<ArrayExtentType>, size_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_value_t<ArrayExtentType>, int>);
static_assert(AZStd::same_as<AZStd::ranges::range_reference_t<ArrayExtentType>, int&>);
static_assert(AZStd::same_as<AZStd::ranges::range_rvalue_reference_t<ArrayExtentType>, int&&>);
// RangeLikeCustomizationPoint type which specializes several range functions
static_assert(AZStd::same_as<AZStd::ranges::iterator_t<RangeLikeCustomizationPoint>, RangeLikeCustomizationPoint*>);
static_assert(AZStd::same_as<AZStd::ranges::sentinel_t<RangeLikeCustomizationPoint>, RangeLikeCustomizationPoint*>);
static_assert(AZStd::same_as<AZStd::ranges::range_difference_t<RangeLikeCustomizationPoint>, ptrdiff_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_size_t<RangeLikeCustomizationPoint>, size_t>);
static_assert(AZStd::same_as<AZStd::ranges::range_value_t<RangeLikeCustomizationPoint>, RangeLikeCustomizationPoint>);
static_assert(AZStd::same_as<AZStd::ranges::range_reference_t<RangeLikeCustomizationPoint>, RangeLikeCustomizationPoint&>);
static_assert(AZStd::same_as<AZStd::ranges::range_rvalue_reference_t<RangeLikeCustomizationPoint>, RangeLikeCustomizationPoint&&>);
}
// Ranges Concepts Test
TEST_F(RangesTestFixture, RangesConcepts_Compiles)
{
using ArrayExtentType = int[5];
// concept - range
static_assert(AZStd::ranges::range<AZStd::string_view>);
static_assert(AZStd::ranges::range<ArrayExtentType>);
static_assert(AZStd::ranges::range<AZ::IO::PathView>);
static_assert(!AZStd::ranges::range<int>);
// concept - sized_range
static_assert(AZStd::ranges::sized_range<AZStd::string_view>);
static_assert(AZStd::ranges::sized_range<ArrayExtentType>);
// Path classes do not have a size() function so they are not a sized_range
static_assert(!AZStd::ranges::sized_range<AZ::IO::PathView>);
// concept - borrowed_range
static_assert(AZStd::ranges::borrowed_range<AZStd::string_view>);
static_assert(AZStd::ranges::borrowed_range<ArrayExtentType&>);
static_assert(!AZStd::ranges::borrowed_range<ArrayExtentType>);
// concept - output_range
static_assert(AZStd::ranges::output_range<AZStd::string, char>);
static_assert(!AZStd::ranges::output_range<AZStd::string_view, char>);
// concept - input_range
static_assert(AZStd::ranges::input_range<AZStd::list<int>>);
static_assert(AZStd::ranges::input_range<AZStd::string>);
static_assert(AZStd::ranges::input_range<AZStd::string_view>);
// concept - forward_range
static_assert(AZStd::ranges::forward_range<AZStd::list<int>>);
static_assert(AZStd::ranges::forward_range<AZStd::string>);
static_assert(AZStd::ranges::forward_range<AZStd::string_view>);
// concept - bidirectional_range
static_assert(AZStd::ranges::bidirectional_range<AZStd::list<int>>);
static_assert(AZStd::ranges::bidirectional_range<AZStd::string>);
static_assert(AZStd::ranges::bidirectional_range<AZStd::string_view>);
// concept - random_access_range
static_assert(!AZStd::ranges::random_access_range<AZStd::list<int>>);
static_assert(AZStd::ranges::random_access_range<AZStd::deque<int>>);
static_assert(AZStd::ranges::random_access_range<AZStd::string>);
static_assert(AZStd::ranges::random_access_range<AZStd::string_view>);
// concept - contiguous_range
static_assert(!AZStd::ranges::contiguous_range<AZStd::deque<int>>);
static_assert(AZStd::ranges::contiguous_range<AZStd::string>);
static_assert(AZStd::ranges::contiguous_range<AZStd::string_view>);
// concept - common_range
static_assert(AZStd::ranges::common_range<ArrayExtentType>);
static_assert(AZStd::ranges::common_range<AZStd::list<int>>);
static_assert(AZStd::ranges::common_range<AZStd::deque<int>>);
static_assert(AZStd::ranges::common_range<AZStd::string>);
static_assert(AZStd::ranges::common_range<AZStd::string_view>);
// concept - view
static_assert(AZStd::ranges::view<AZStd::string_view>);
static_assert(!AZStd::ranges::view<ArrayExtentType>);
// concept - viewable_range
static_assert(AZStd::ranges::viewable_range<AZStd::string>);
static_assert(AZStd::ranges::viewable_range<AZStd::string_view>);
static_assert(!AZStd::ranges::viewable_range<ArrayExtentType>);
}
// Ranges iterator operations
TEST_F(RangesTestFixture, RangesAdvance_PositiveDifference_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
auto strIter = testString.begin();
// difference overload
AZStd::ranges::advance(strIter, 5);
ASSERT_NE(testString.end(), strIter);
EXPECT_EQ(' ', *strIter);
// bound overload
AZStd::ranges::advance(strIter, testString.end());
EXPECT_EQ(testString.end(), strIter);
// difference + bound overload
strIter = testString.begin();
ptrdiff_t charactersToTraverse = 20;
EXPECT_EQ(charactersToTraverse - testString.size(), AZStd::ranges::advance(strIter, charactersToTraverse, testString.end()));
EXPECT_EQ(testString.end(), strIter);
strIter = testString.begin();
charactersToTraverse = 5;
EXPECT_EQ(0, AZStd::ranges::advance(strIter, charactersToTraverse, testString.end()));
ASSERT_NE(testString.end(), strIter);
EXPECT_EQ(' ', *strIter);
}
TEST_F(RangesTestFixture, RangesAdvance_NegativeDifference_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
auto strIter = testString.end();
// difference overload
AZStd::ranges::advance(strIter, -5);
ASSERT_NE(testString.end(), strIter);
EXPECT_EQ('W', *strIter);
// difference + bound overload
strIter = testString.end();
ptrdiff_t charactersToTraverse = -20;
EXPECT_EQ(charactersToTraverse + testString.size(), AZStd::ranges::advance(strIter, charactersToTraverse, testString.begin()));
EXPECT_EQ(testString.begin(), strIter);
strIter = testString.end();
charactersToTraverse = -5;
EXPECT_EQ(0, AZStd::ranges::advance(strIter, charactersToTraverse, testString.begin()));
ASSERT_NE(testString.end(), strIter);
ASSERT_NE(testString.begin(), strIter);
EXPECT_EQ('W', *strIter);
}
TEST_F(RangesTestFixture, RangesDistance_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
EXPECT_EQ(testString.size(), AZStd::ranges::distance(testString));
EXPECT_EQ(testString.size(), AZStd::ranges::distance(testString.begin(), testString.end()));
AZStd::list<char> testList{ 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
EXPECT_EQ(testList.size(), AZStd::ranges::distance(testList));
EXPECT_EQ(testList.size(), AZStd::ranges::distance(testList.begin(), testList.end()));
}
TEST_F(RangesTestFixture, RangesNext_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
auto strIter = testString.begin();
auto boundIter = testString.begin() + 5;
// single increment
EXPECT_EQ(testString.begin() + 1, AZStd::ranges::next(strIter));
// increment by value
strIter = testString.begin();
EXPECT_EQ(testString.begin() + 5, AZStd::ranges::next(strIter, 5));
// increment until bound
strIter = testString.begin();
EXPECT_EQ(testString.begin() + 5, AZStd::ranges::next(strIter, boundIter));
// increment by value up until bound
strIter = testString.begin();
EXPECT_EQ(testString.begin() + 5, AZStd::ranges::next(strIter, 10, boundIter));
strIter = testString.begin();
EXPECT_EQ(testString.begin() + 4, AZStd::ranges::next(strIter, 4, boundIter));
}
TEST_F(RangesTestFixture, RangesPrev_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
auto strIter = testString.end();
auto boundIter = testString.end() - 5;
// single decrement
EXPECT_EQ(testString.end() - 1, AZStd::ranges::prev(strIter));
// decrement by value
strIter = testString.end();
EXPECT_EQ(testString.end() - 5, AZStd::ranges::prev(strIter, 5));
// decrement by value up until bound
strIter = testString.end();
EXPECT_EQ(testString.end() - 5, AZStd::ranges::prev(strIter, 10, boundIter));
strIter = testString.end();
EXPECT_EQ(testString.end() - 4, AZStd::ranges::prev(strIter, 4, boundIter));
}
}
@@ -0,0 +1,249 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/containers/span.h>
namespace UnitTest
{
class SpanTestFixture
: public ScopedAllocatorSetupFixture
{};
// range access
TEST_F(SpanTestFixture, IsConstructibleWithContiguousRangeLikeContainers)
{
constexpr AZStd::string_view testStringView{ "Foo" };
AZStd::string testString{ "Foo" };
AZStd::vector testVector{ 'F', 'o', 'o' };
AZStd::fixed_vector testFixedVector{ 'F', 'o', 'o' };
AZStd::array testStdArray{ 'F', 'o', 'o' };
const char testCArray[]{ 'F', 'o', 'o' };
constexpr AZStd::span stringViewSpan(testStringView);
static_assert(stringViewSpan.data() == testStringView.data());
AZStd::span testStringSpan(testString);
EXPECT_EQ(testStringSpan.data(), testString.data());
AZStd::span testVectorSpan(testVector);
EXPECT_EQ(testVectorSpan.data(), testVector.data());
AZStd::span testFixedVectorSpan(testFixedVector);
EXPECT_EQ(testFixedVectorSpan.data(), testFixedVector.data());
AZStd::span testStdArraySpan(testStdArray);
EXPECT_EQ(testStdArraySpan.data(), testStdArray.data());
AZStd::span testCArraySpan(testCArray);
EXPECT_EQ(AZStd::data(testCArray), testCArraySpan.data());
}
TEST_F(SpanTestFixture, IsConstructibleWithContiguousIterators)
{
constexpr AZStd::string_view testStringView{ "Foo" };
AZStd::string testString{ "Foo" };
AZStd::vector testVector{ 'F', 'o', 'o' };
AZStd::fixed_vector testFixedVector{ 'F', 'o', 'o' };
AZStd::array testStdArray{ 'F', 'o', 'o' };
const char testCArray[]{ 'F', 'o', 'o' };
constexpr AZStd::span stringViewSpan(testStringView.begin(), testStringView.end());
static_assert(stringViewSpan.data() == testStringView.data());
AZStd::span testStringSpan(testString.begin(), testString.end());
EXPECT_EQ(testStringSpan.data(), testString.data());
AZStd::span testVectorSpan(testVector.begin(), testVector.end());
EXPECT_EQ(testVectorSpan.data(), testVector.data());
AZStd::span testFixedVectorSpan(testFixedVector.begin(), testFixedVector.end());
EXPECT_EQ(testFixedVectorSpan.data(), testFixedVector.data());
AZStd::span testStdArraySpan(testStdArray.begin(), testStdArray.end());
EXPECT_EQ(testStdArraySpan.data(), testStdArray.data());
AZStd::span testCArraySpan(AZStd::begin(testCArray), AZStd::end(testCArray));
EXPECT_EQ(AZStd::data(testCArray), testCArraySpan.data());
}
TEST_F(SpanTestFixture, ObserverMethods_ReturnsCorrectValues)
{
AZStd::vector<int> intVector{ 4, 5, 6, 1, 7 };
AZStd::span intSpan(intVector);
EXPECT_FALSE(intSpan.empty());
EXPECT_EQ(intVector.size(), intSpan.size());
EXPECT_EQ(intSpan.size() * sizeof(int), intSpan.size_bytes());
intSpan = {};
EXPECT_TRUE(intSpan.empty());
EXPECT_EQ(0, intSpan.size());
EXPECT_EQ(0, intSpan.size_bytes());
}
TEST_F(SpanTestFixture, ElementAccessorMethods_Succeeds)
{
AZStd::vector<int> intVector{ 4, 5, 6, 1, 7 };
AZStd::span intSpan(intVector);
EXPECT_EQ(intVector.data(), intSpan.data());
EXPECT_EQ(4, intSpan.front());
EXPECT_EQ(7, intSpan.back());
EXPECT_EQ(6, intSpan[2]);
// Create subspan from elements 1 .. end - 1
intSpan = intSpan.subspan(1, intSpan.size() - 2);
EXPECT_NE(intVector.data(), intSpan.data());
EXPECT_EQ(5, intSpan.front());
EXPECT_EQ(1, intSpan.back());
EXPECT_EQ(6, intSpan[1]);
}
TEST_F(SpanTestFixture, Supspan_Returns_Subview_Succeeds)
{
AZStd::vector<int> intVector{ 4, 5, 6, 1, 7 };
AZStd::span intSpan(intVector);
// dynamic_extent subspan with count
auto dynamicIntSubSpan = intSpan.subspan(1, 2);
ASSERT_EQ(2, dynamicIntSubSpan.size());
EXPECT_EQ(5, dynamicIntSubSpan[0]);
EXPECT_EQ(6, dynamicIntSubSpan[1]);
// dynamic_extent subspan without count
dynamicIntSubSpan = intSpan.subspan(1);
ASSERT_EQ(4, dynamicIntSubSpan.size());
EXPECT_EQ(5, dynamicIntSubSpan[0]);
EXPECT_EQ(6, dynamicIntSubSpan[1]);
EXPECT_EQ(1, dynamicIntSubSpan[2]);
EXPECT_EQ(7, dynamicIntSubSpan[3]);
// template subspan with count
auto templateIntSubSpan1 = intSpan.subspan<1, 3>();
static_assert(decltype(templateIntSubSpan1)::extent == 3);
ASSERT_EQ(3, templateIntSubSpan1.size());
EXPECT_EQ(5, templateIntSubSpan1[0]);
EXPECT_EQ(6, templateIntSubSpan1[1]);
EXPECT_EQ(1, templateIntSubSpan1[2]);
// template subspan without count
auto templateIntSubSpan2 = intSpan.subspan<1>();
static_assert(decltype(templateIntSubSpan2)::extent == AZStd::dynamic_extent);
ASSERT_EQ(4, templateIntSubSpan2.size());
EXPECT_EQ(5, templateIntSubSpan2[0]);
EXPECT_EQ(6, templateIntSubSpan2[1]);
EXPECT_EQ(1, templateIntSubSpan2[2]);
EXPECT_EQ(7, templateIntSubSpan2[3]);
// get subspan of fixed extent span without count
auto subSpanOfSubSpan = templateIntSubSpan1.subspan<1>();
static_assert(decltype(subSpanOfSubSpan)::extent == 2);
ASSERT_EQ(2, subSpanOfSubSpan.size());
EXPECT_EQ(6, subSpanOfSubSpan[0]);
EXPECT_EQ(1, subSpanOfSubSpan[1]);
}
TEST_F(SpanTestFixture, FirstMethod_Returns_FirstCountElementsOfSpan)
{
constexpr size_t vectorElementCount = 5;
AZStd::vector<int> intVector{ 4, 5, 6, 1, 7 };
AZStd::span intSpan(intVector);
{
// No templated first function
auto prefixSpan = intSpan.first(3);
ASSERT_EQ(3, prefixSpan.size());
EXPECT_EQ(4, prefixSpan[0]);
EXPECT_EQ(5, prefixSpan[1]);
EXPECT_EQ(6, prefixSpan[2]);
auto prefixSpanRedux = prefixSpan.first(1);
ASSERT_EQ(1, prefixSpanRedux.size());
EXPECT_EQ(4, prefixSpanRedux[0]);
// Test failure of preconditions by requesting more
// elements thant stored in the span
AZ_TEST_START_TRACE_SUPPRESSION;
intSpan.first(intSpan.size() + 1);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
{
// templated first function
auto prefixSpan = intSpan.first<3>();
static_assert(decltype(prefixSpan)::extent == 3);
ASSERT_EQ(3, prefixSpan.size());
EXPECT_EQ(4, prefixSpan[0]);
EXPECT_EQ(5, prefixSpan[1]);
EXPECT_EQ(6, prefixSpan[2]);
auto prefixSpanRedux = prefixSpan.first<1>();
ASSERT_EQ(1, prefixSpanRedux.size());
EXPECT_EQ(4, prefixSpanRedux[0]);
// Test failure of preconditions by requesting more
// elements thant stored in the span
AZ_TEST_START_TRACE_SUPPRESSION;
intSpan.first<vectorElementCount + 1>();
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
}
TEST_F(SpanTestFixture, LastCountElementsOfSpan)
{
constexpr size_t vectorElementCount = 5;
AZStd::vector<int> intVector{ 4, 5, 6, 1, 7 };
AZStd::span intSpan(intVector);
{
// No templated last function
auto suffixSpan = intSpan.last(3);
ASSERT_EQ(3, suffixSpan.size());
EXPECT_EQ(6, suffixSpan[0]);
EXPECT_EQ(1, suffixSpan[1]);
EXPECT_EQ(7, suffixSpan[2]);
auto suffixSpanRedux = suffixSpan.last(1);
ASSERT_EQ(1, suffixSpanRedux.size());
EXPECT_EQ(7, suffixSpanRedux[0]);
// Test failure of preconditions by requesting more
// elements thant stored in the span
AZ_TEST_START_TRACE_SUPPRESSION;
intSpan.last(intSpan.size() + 1);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
{
// templated last function
auto suffixSpan = intSpan.last<3>();
static_assert(decltype(suffixSpan)::extent == 3);
ASSERT_EQ(3, suffixSpan.size());
EXPECT_EQ(6, suffixSpan[0]);
EXPECT_EQ(1, suffixSpan[1]);
EXPECT_EQ(7, suffixSpan[2]);
auto suffixSpanRedux = suffixSpan.last<1>();
ASSERT_EQ(1, suffixSpanRedux.size());
EXPECT_EQ(7, suffixSpanRedux[0]);
// Test failure of preconditions by requesting more
// elements thant stored in the span
AZ_TEST_START_TRACE_SUPPRESSION;
intSpan.last<vectorElementCount + 1>();
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
}
}
+420 -301
View File
@@ -45,197 +45,197 @@ namespace UnitTest
// Primary type categories:
// alignment_of and align_to
AZ_TEST_STATIC_ASSERT(alignment_of<int>::value == 4);
AZ_TEST_STATIC_ASSERT(alignment_of<char>::value == 1);
static_assert(alignment_of<int>::value == 4);
static_assert(alignment_of<char>::value == 1);
AZ_TEST_STATIC_ASSERT(alignment_of<MyClass>::value == 16);
aligned_storage<sizeof(int)*100, 16>::type alignedArray;
static_assert(alignment_of<MyClass>::value == 16);
aligned_storage<sizeof(int) * 100, 16>::type alignedArray;
AZ_TEST_ASSERT((((AZStd::size_t)&alignedArray) & 15) == 0);
AZ_TEST_STATIC_ASSERT((alignment_of< aligned_storage<sizeof(int)*5, 8>::type >::value) == 8);
AZ_TEST_STATIC_ASSERT(sizeof(aligned_storage<sizeof(int), 16>::type) == 16);
static_assert((alignment_of< aligned_storage<sizeof(int) * 5, 8>::type >::value) == 8);
static_assert(sizeof(aligned_storage<sizeof(int), 16>::type) == 16);
// is_void
AZ_TEST_STATIC_ASSERT(is_void<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_void<void>::value == true);
AZ_TEST_STATIC_ASSERT(is_void<void const>::value == true);
AZ_TEST_STATIC_ASSERT(is_void<void volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_void<void const volatile>::value == true);
static_assert(is_void<int>::value == false);
static_assert(is_void<void>::value == true);
static_assert(is_void<void const>::value == true);
static_assert(is_void<void volatile>::value == true);
static_assert(is_void<void const volatile>::value == true);
// is_integral
AZ_TEST_STATIC_ASSERT(is_integral<unsigned char>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<unsigned short>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<unsigned int>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<unsigned long>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<signed char>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<signed short>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<signed int>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<signed long>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<bool>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<char>::value == true);
//AZ_TEST_STATIC_ASSERT(is_integral<wchar_t>::value == true);
static_assert(is_integral<unsigned char>::value == true);
static_assert(is_integral<unsigned short>::value == true);
static_assert(is_integral<unsigned int>::value == true);
static_assert(is_integral<unsigned long>::value == true);
static_assert(is_integral<signed char>::value == true);
static_assert(is_integral<signed short>::value == true);
static_assert(is_integral<signed int>::value == true);
static_assert(is_integral<signed long>::value == true);
static_assert(is_integral<bool>::value == true);
static_assert(is_integral<char>::value == true);
//static_assert(is_integral<wchar_t>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<char const >::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<short const>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<int const>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<long const>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<char volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<short volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<int volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<long volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<char const volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<short const volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<int const volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<long const volatile>::value == true);
static_assert(is_integral<char const >::value == true);
static_assert(is_integral<short const>::value == true);
static_assert(is_integral<int const>::value == true);
static_assert(is_integral<long const>::value == true);
static_assert(is_integral<char volatile>::value == true);
static_assert(is_integral<short volatile>::value == true);
static_assert(is_integral<int volatile>::value == true);
static_assert(is_integral<long volatile>::value == true);
static_assert(is_integral<char const volatile>::value == true);
static_assert(is_integral<short const volatile>::value == true);
static_assert(is_integral<int const volatile>::value == true);
static_assert(is_integral<long const volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_integral<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_integral<MyStruct const>::value == false);
AZ_TEST_STATIC_ASSERT(is_integral<MyStruct const volatile>::value == false);
static_assert(is_integral<MyStruct>::value == false);
static_assert(is_integral<MyStruct const>::value == false);
static_assert(is_integral<MyStruct const volatile>::value == false);
// is_floating_point
AZ_TEST_STATIC_ASSERT(is_floating_point<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_floating_point<float>::value == true);
AZ_TEST_STATIC_ASSERT(is_floating_point<float const>::value == true);
AZ_TEST_STATIC_ASSERT(is_floating_point<float volatile>::value == true);
AZ_TEST_STATIC_ASSERT(is_floating_point<float const volatile>::value == true);
static_assert(is_floating_point<int>::value == false);
static_assert(is_floating_point<float>::value == true);
static_assert(is_floating_point<float const>::value == true);
static_assert(is_floating_point<float volatile>::value == true);
static_assert(is_floating_point<float const volatile>::value == true);
// is_array
AZ_TEST_STATIC_ASSERT(is_array<int*>::value == false);
AZ_TEST_STATIC_ASSERT(is_array<int[5]>::value == true);
AZ_TEST_STATIC_ASSERT(is_array<const int[5]>::value == true);
AZ_TEST_STATIC_ASSERT(is_array<volatile int[5]>::value == true);
AZ_TEST_STATIC_ASSERT(is_array<const volatile int[5]>::value == true);
static_assert(is_array<int*>::value == false);
static_assert(is_array<int[5]>::value == true);
static_assert(is_array<const int[5]>::value == true);
static_assert(is_array<volatile int[5]>::value == true);
static_assert(is_array<const volatile int[5]>::value == true);
AZ_TEST_STATIC_ASSERT(is_array<float[]>::value == true);
AZ_TEST_STATIC_ASSERT(is_array<const float[]>::value == true);
AZ_TEST_STATIC_ASSERT(is_array<volatile float[]>::value == true);
AZ_TEST_STATIC_ASSERT(is_array<const volatile float[]>::value == true);
static_assert(is_array<float[]>::value == true);
static_assert(is_array<const float[]>::value == true);
static_assert(is_array<volatile float[]>::value == true);
static_assert(is_array<const volatile float[]>::value == true);
// is_pointer
AZ_TEST_STATIC_ASSERT(is_pointer<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_pointer<int*>::value == true);
AZ_TEST_STATIC_ASSERT(is_pointer<const MyStruct*>::value == true);
AZ_TEST_STATIC_ASSERT(is_pointer<volatile int*>::value == true);
AZ_TEST_STATIC_ASSERT(is_pointer<const volatile MyStruct*>::value == true);
static_assert(is_pointer<int>::value == false);
static_assert(is_pointer<int*>::value == true);
static_assert(is_pointer<const MyStruct*>::value == true);
static_assert(is_pointer<volatile int*>::value == true);
static_assert(is_pointer<const volatile MyStruct*>::value == true);
// is_reference
AZ_TEST_STATIC_ASSERT(is_reference<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_reference<int&>::value == true);
AZ_TEST_STATIC_ASSERT(is_reference<const MyStruct&>::value == true);
AZ_TEST_STATIC_ASSERT(is_reference<volatile int&>::value == true);
AZ_TEST_STATIC_ASSERT(is_reference<const volatile MyStruct&>::value == true);
static_assert(is_reference<int>::value == false);
static_assert(is_reference<int&>::value == true);
static_assert(is_reference<const MyStruct&>::value == true);
static_assert(is_reference<volatile int&>::value == true);
static_assert(is_reference<const volatile MyStruct&>::value == true);
// is_member_object_pointer
AZ_TEST_STATIC_ASSERT(is_member_object_pointer<MyStruct*>::value == false);
AZ_TEST_STATIC_ASSERT(is_member_object_pointer<int (MyStruct::*)()>::value == false);
AZ_TEST_STATIC_ASSERT(is_member_object_pointer<int MyStruct::*>::value == true);
static_assert(is_member_object_pointer<MyStruct*>::value == false);
static_assert(is_member_object_pointer<int (MyStruct::*)()>::value == false);
static_assert(is_member_object_pointer<int MyStruct::*>::value == true);
// is_member_function_pointer
AZ_TEST_STATIC_ASSERT(is_member_function_pointer<MyStruct*>::value == false);
AZ_TEST_STATIC_ASSERT(is_member_function_pointer<int (MyStruct::*)()>::value == true);
AZ_TEST_STATIC_ASSERT(is_member_function_pointer<int MyStruct::*>::value == false);
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() const>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() volatile>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() const volatile>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() &>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() const&>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() const volatile&>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() &&>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() const&&>::value));
AZ_TEST_STATIC_ASSERT((is_member_function_pointer<int (MyStruct::*)() const volatile&&>::value));
static_assert(is_member_function_pointer<MyStruct*>::value == false);
static_assert(is_member_function_pointer<int (MyStruct::*)()>::value == true);
static_assert(is_member_function_pointer<int MyStruct::*>::value == false);
static_assert((is_member_function_pointer<int (MyStruct::*)() const>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)() volatile>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)() const volatile>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)()&>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)() const&>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)() const volatile&>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)()&&>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)() const&&>::value));
static_assert((is_member_function_pointer<int (MyStruct::*)() const volatile&&>::value));
// is_enum
AZ_TEST_STATIC_ASSERT(is_enum<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_enum<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_enum<MyEnum>::value == true);
static_assert(is_enum<int>::value == false);
static_assert(is_enum<MyStruct>::value == false);
static_assert(is_enum<MyEnum>::value == true);
// is_union
AZ_TEST_STATIC_ASSERT(is_union<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_union<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_union<MyUnion>::value == true);
static_assert(is_union<int>::value == false);
static_assert(is_union<MyStruct>::value == false);
static_assert(is_union<MyUnion>::value == true);
// is_class
AZ_TEST_STATIC_ASSERT(is_class<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_class<MyStruct>::value == true);
AZ_TEST_STATIC_ASSERT(is_class<MyClass>::value == true);
static_assert(is_class<int>::value == false);
static_assert(is_class<MyStruct>::value == true);
static_assert(is_class<MyClass>::value == true);
// is_function
AZ_TEST_STATIC_ASSERT(is_function<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_function<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_function<int(float, char)>::value == true);
static_assert(is_function<int>::value == false);
static_assert(is_function<MyStruct>::value == false);
static_assert(is_function<int(float, char)>::value == true);
//////////////////////////////////////////////////////////////////////////
// composite type categories:
// is_arithmetic
AZ_TEST_STATIC_ASSERT(is_arithmetic<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_arithmetic<int>::value == true);
AZ_TEST_STATIC_ASSERT(is_arithmetic<float>::value == true);
static_assert(is_arithmetic<MyStruct>::value == false);
static_assert(is_arithmetic<int>::value == true);
static_assert(is_arithmetic<float>::value == true);
// is_fundamental
AZ_TEST_STATIC_ASSERT(is_fundamental<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_fundamental<int>::value == true);
AZ_TEST_STATIC_ASSERT(is_fundamental<const float>::value == true);
AZ_TEST_STATIC_ASSERT(is_fundamental<void>::value == true);
static_assert(is_fundamental<MyStruct>::value == false);
static_assert(is_fundamental<int>::value == true);
static_assert(is_fundamental<const float>::value == true);
static_assert(is_fundamental<void>::value == true);
// is_object
AZ_TEST_STATIC_ASSERT(is_object<MyStruct>::value == true);
AZ_TEST_STATIC_ASSERT(is_object<MyStruct&>::value == false);
AZ_TEST_STATIC_ASSERT(is_object<int(short, float)>::value == false);
AZ_TEST_STATIC_ASSERT(is_object<void>::value == false);
static_assert(is_object<MyStruct>::value == true);
static_assert(is_object<MyStruct&>::value == false);
static_assert(is_object<int(short, float)>::value == false);
static_assert(is_object<void>::value == false);
// is_scalar
AZ_TEST_STATIC_ASSERT(is_scalar<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_scalar<MyStruct*>::value == true);
AZ_TEST_STATIC_ASSERT(is_scalar<const float>::value == true);
AZ_TEST_STATIC_ASSERT(is_scalar<int>::value == true);
static_assert(is_scalar<MyStruct>::value == false);
static_assert(is_scalar<MyStruct*>::value == true);
static_assert(is_scalar<const float>::value == true);
static_assert(is_scalar<int>::value == true);
// is_compound
AZ_TEST_STATIC_ASSERT(is_compound<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_compound<MyStruct>::value == true);
AZ_TEST_STATIC_ASSERT(is_compound<int(short, float)>::value == true);
AZ_TEST_STATIC_ASSERT(is_compound<float[]>::value == true);
AZ_TEST_STATIC_ASSERT(is_compound<int&>::value == true);
AZ_TEST_STATIC_ASSERT(is_compound<const void*>::value == true);
static_assert(is_compound<int>::value == false);
static_assert(is_compound<MyStruct>::value == true);
static_assert(is_compound<int(short, float)>::value == true);
static_assert(is_compound<float[]>::value == true);
static_assert(is_compound<int&>::value == true);
static_assert(is_compound<const void*>::value == true);
// is_member_pointer
AZ_TEST_STATIC_ASSERT(is_member_pointer<MyStruct*>::value == false);
AZ_TEST_STATIC_ASSERT(is_member_pointer<int MyStruct::*>::value == true);
AZ_TEST_STATIC_ASSERT(is_member_pointer<int (MyStruct::*)()>::value == true);
static_assert(is_member_pointer<MyStruct*>::value == false);
static_assert(is_member_pointer<int MyStruct::*>::value == true);
static_assert(is_member_pointer<int (MyStruct::*)()>::value == true);
//////////////////////////////////////////////////////////////////////////
// type properties:
// is_const
AZ_TEST_STATIC_ASSERT(is_const<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_const<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_const<const MyStruct>::value == true);
AZ_TEST_STATIC_ASSERT(is_const<const float>::value == true);
static_assert(is_const<MyStruct>::value == false);
static_assert(is_const<int>::value == false);
static_assert(is_const<const MyStruct>::value == true);
static_assert(is_const<const float>::value == true);
// is_volatile
AZ_TEST_STATIC_ASSERT(is_volatile<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_volatile<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_volatile<volatile MyStruct>::value == true);
AZ_TEST_STATIC_ASSERT(is_volatile<volatile float>::value == true);
static_assert(is_volatile<MyStruct>::value == false);
static_assert(is_volatile<int>::value == false);
static_assert(is_volatile<volatile MyStruct>::value == true);
static_assert(is_volatile<volatile float>::value == true);
// is_pod
AZ_TEST_STATIC_ASSERT(is_pod<MyStruct>::value == true);
AZ_TEST_STATIC_ASSERT(is_pod<int>::value == true);
AZ_TEST_STATIC_ASSERT(is_pod<const MyClass>::value == false);
AZ_TEST_STATIC_ASSERT((is_pod< aligned_storage<30, 32>::type >::value) == true);
static_assert(is_pod<MyStruct>::value == true);
static_assert(is_pod<int>::value == true);
static_assert(is_pod<const MyClass>::value == false);
static_assert((is_pod< aligned_storage<30, 32>::type >::value) == true);
// is_empty
AZ_TEST_STATIC_ASSERT(is_empty<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_empty<MyEmptyStruct>::value == true);
AZ_TEST_STATIC_ASSERT(is_empty<int>::value == false);
static_assert(is_empty<MyStruct>::value == false);
static_assert(is_empty<MyEmptyStruct>::value == true);
static_assert(is_empty<int>::value == false);
// is_polymorphic
AZ_TEST_STATIC_ASSERT(is_polymorphic<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_polymorphic<MyClass>::value == true);
static_assert(is_polymorphic<MyStruct>::value == false);
static_assert(is_polymorphic<MyClass>::value == true);
// is_abstract
AZ_TEST_STATIC_ASSERT(is_abstract<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_abstract<MyInterface>::value == true);
static_assert(is_abstract<MyStruct>::value == false);
static_assert(is_abstract<MyInterface>::value == true);
// has_trivial_constructor
static_assert(is_trivially_constructible_v<MyStruct>);
@@ -264,20 +264,20 @@ namespace UnitTest
// has_nothrow_assign
// is_signed
AZ_TEST_STATIC_ASSERT(is_signed<int>::value == true);
AZ_TEST_STATIC_ASSERT(is_signed<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_signed<unsigned int>::value == false);
static_assert(is_signed<int>::value == true);
static_assert(is_signed<MyStruct>::value == false);
static_assert(is_signed<unsigned int>::value == false);
static_assert(is_signed<float>::value);
// is_unsigned
AZ_TEST_STATIC_ASSERT(is_unsigned<int>::value == false);
AZ_TEST_STATIC_ASSERT(is_unsigned<MyStruct>::value == false);
AZ_TEST_STATIC_ASSERT(is_unsigned<unsigned int>::value == true);
AZ_TEST_STATIC_ASSERT(is_unsigned<float>::value == false);
static_assert(is_unsigned<int>::value == false);
static_assert(is_unsigned<MyStruct>::value == false);
static_assert(is_unsigned<unsigned int>::value == true);
static_assert(is_unsigned<float>::value == false);
// true and false types
AZ_TEST_STATIC_ASSERT(true_type::value == true);
AZ_TEST_STATIC_ASSERT(false_type::value == false);
static_assert(true_type::value == true);
static_assert(false_type::value == false);
//! function traits tests
struct NotMyStruct
@@ -290,7 +290,7 @@ namespace UnitTest
{
bool operator()(FunctionTestStruct&) const { return true; };
};
using PrimitiveFunctionPtr = int(*)(bool, float, double, AZ::u8, AZ::s8, AZ::u16, AZ::s16, AZ::u32, AZ::s32, AZ::u64, AZ::s64);
using NotMyStructMemberPtr = int(NotMyStruct::*)();
using ComplexFunctionPtr = float(*)(MyEmptyStruct&, NotMyStructMemberPtr, MyUnion*);
@@ -298,27 +298,27 @@ namespace UnitTest
using MemberFunctionPtr = void(MyInterface::*)(int);
using ConstMemberFunctionPtr = bool(FunctionTestStruct::*)(FunctionTestStruct&) const;
AZ_TEST_STATIC_ASSERT((AZStd::is_same<AZStd::function_traits<PrimitiveFunctionPtr>::result_type, int>::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<AZStd::function_traits<PrimitiveFunctionPtr>::get_arg_t<10>, AZ::s64>::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<AZStd::function_traits_get_arg_t<PrimitiveFunctionPtr, 5>, AZ::u16>::value));
AZ_TEST_STATIC_ASSERT((AZStd::function_traits<PrimitiveFunctionPtr>::arity == 11));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<AZStd::function_traits_get_result_t<ComplexFunction>, float>::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<AZStd::function_traits_get_arg_t<ComplexFunction, 1>, int(NotMyStruct::*)()>::value));
AZ_TEST_STATIC_ASSERT((AZStd::function_traits<ComplexFunction>::arity == 3));
static_assert((AZStd::is_same<AZStd::function_traits<PrimitiveFunctionPtr>::result_type, int>::value));
static_assert((AZStd::is_same<AZStd::function_traits<PrimitiveFunctionPtr>::get_arg_t<10>, AZ::s64>::value));
static_assert((AZStd::is_same<AZStd::function_traits_get_arg_t<PrimitiveFunctionPtr, 5>, AZ::u16>::value));
static_assert((AZStd::function_traits<PrimitiveFunctionPtr>::arity == 11));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<MemberFunctionPtr>::class_fp_type, void(MyInterface::*)(int)>::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<MemberFunctionPtr>::raw_fp_type, void(*)(int)>::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<MemberFunctionPtr>::class_type, MyInterface>::value));
AZ_TEST_STATIC_ASSERT((AZStd::function_traits<MemberFunctionPtr>::arity == 1));
static_assert((AZStd::is_same<AZStd::function_traits_get_result_t<ComplexFunction>, float>::value));
static_assert((AZStd::is_same<AZStd::function_traits_get_arg_t<ComplexFunction, 1>, int(NotMyStruct::*)()>::value));
static_assert((AZStd::function_traits<ComplexFunction>::arity == 3));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<ConstMemberFunctionPtr>::class_fp_type, bool(FunctionTestStruct::*)(FunctionTestStruct&) const> ::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<ConstMemberFunctionPtr>::raw_fp_type, bool(*)(FunctionTestStruct&)> ::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<ConstMemberFunctionPtr>::class_type, FunctionTestStruct>::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits_get_arg_t<ConstMemberFunctionPtr, 0>, FunctionTestStruct&>::value));
AZ_TEST_STATIC_ASSERT((AZStd::function_traits<ConstMemberFunctionPtr>::arity == 1));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<decltype(&FunctionTestStruct::operator())>::class_fp_type, bool(FunctionTestStruct::*)(FunctionTestStruct&) const>::value));
static_assert((AZStd::is_same<typename AZStd::function_traits<MemberFunctionPtr>::class_fp_type, void(MyInterface::*)(int)>::value));
static_assert((AZStd::is_same<typename AZStd::function_traits<MemberFunctionPtr>::raw_fp_type, void(*)(int)>::value));
static_assert((AZStd::is_same<typename AZStd::function_traits<MemberFunctionPtr>::class_type, MyInterface>::value));
static_assert((AZStd::function_traits<MemberFunctionPtr>::arity == 1));
static_assert((AZStd::is_same<typename AZStd::function_traits<ConstMemberFunctionPtr>::class_fp_type, bool(FunctionTestStruct::*)(FunctionTestStruct&) const> ::value));
static_assert((AZStd::is_same<typename AZStd::function_traits<ConstMemberFunctionPtr>::raw_fp_type, bool(*)(FunctionTestStruct&)> ::value));
static_assert((AZStd::is_same<typename AZStd::function_traits<ConstMemberFunctionPtr>::class_type, FunctionTestStruct>::value));
static_assert((AZStd::is_same<typename AZStd::function_traits_get_arg_t<ConstMemberFunctionPtr, 0>, FunctionTestStruct&>::value));
static_assert((AZStd::function_traits<ConstMemberFunctionPtr>::arity == 1));
static_assert((AZStd::is_same<typename AZStd::function_traits<decltype(&FunctionTestStruct::operator())>::class_fp_type, bool(FunctionTestStruct::*)(FunctionTestStruct&) const>::value));
auto lambdaFunction = [](FunctionTestStruct, int) -> bool
{
@@ -326,16 +326,16 @@ namespace UnitTest
};
using LambdaType = decltype(lambdaFunction);
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<LambdaType>::raw_fp_type, bool(*)(FunctionTestStruct, int)>::value));
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<LambdaType>::class_fp_type, bool(LambdaType::*)(FunctionTestStruct, int) const>::value));
AZ_TEST_STATIC_ASSERT((AZStd::function_traits<LambdaType>::arity == 2));
static_assert((AZStd::is_same<typename AZStd::function_traits<LambdaType>::raw_fp_type, bool(*)(FunctionTestStruct, int)>::value));
static_assert((AZStd::is_same<typename AZStd::function_traits<LambdaType>::class_fp_type, bool(LambdaType::*)(FunctionTestStruct, int) const>::value));
static_assert((AZStd::function_traits<LambdaType>::arity == 2));
static_assert(AZStd::is_same<AZStd::function_traits<LambdaType>::return_type, bool>::value, "Lambda result type should be bool");
AZStd::function<void(LambdaType*, ComplexFunction&)> stdFunction;
using StdFunctionType = decay_t<decltype(stdFunction)>;
AZ_TEST_STATIC_ASSERT((AZStd::is_same<typename AZStd::function_traits<StdFunctionType>::raw_fp_type, void(*)(LambdaType*, ComplexFunction&)>::value));
AZ_TEST_STATIC_ASSERT((AZStd::function_traits<StdFunctionType>::arity == 2));
}
static_assert((AZStd::is_same<typename AZStd::function_traits<StdFunctionType>::raw_fp_type, void(*)(LambdaType*, ComplexFunction&)>::value));
static_assert((AZStd::function_traits<StdFunctionType>::arity == 2));
}
struct ConstMethodTestStruct
{
@@ -343,145 +343,264 @@ namespace UnitTest
void NonConstMethod() { }
};
AZ_TEST_STATIC_ASSERT((static_cast<uint32_t>(function_traits<decltype(&ConstMethodTestStruct::ConstMethod)>::qual_flags) & static_cast<uint32_t>(Internal::qualifier_flags::const_)) != 0);
AZ_TEST_STATIC_ASSERT((static_cast<uint32_t>(function_traits<decltype(&ConstMethodTestStruct::NonConstMethod)>::qual_flags) & static_cast<uint32_t>(Internal::qualifier_flags::const_)) == 0);
}
static_assert((static_cast<uint32_t>(function_traits<decltype(&ConstMethodTestStruct::ConstMethod)>::qual_flags)& static_cast<uint32_t>(Internal::qualifier_flags::const_)) != 0);
static_assert((static_cast<uint32_t>(function_traits<decltype(&ConstMethodTestStruct::NonConstMethod)>::qual_flags)& static_cast<uint32_t>(Internal::qualifier_flags::const_)) == 0);
TEST(TypeTraits, StdRemoveConstCompiles)
{
static_assert(AZStd::is_same_v<int, AZStd::remove_const_t<const int>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_const_t<int>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<int*, AZStd::remove_const_t<int* const>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<const int*, AZStd::remove_const_t<const int*>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<const volatile int*, AZStd::remove_const_t<const volatile int* const>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_const_t<AZStd::remove_reference_t<const int&>>>, "C++11 std::remove_const_t has failed");
}
TEST(TypeTraits, StdRemoveVolatileCompiles)
{
static_assert(AZStd::is_same_v<int, AZStd::remove_volatile_t<volatile int>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_volatile_t<int>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<int*, AZStd::remove_volatile_t<int* volatile>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<volatile int*, AZStd::remove_volatile_t<volatile int*>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<const volatile int*, AZStd::remove_volatile_t<const volatile int*>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<const int*, AZStd::remove_volatile_t<const int* volatile>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_volatile_t<AZStd::remove_reference_t<volatile int&>>>, "C++11 std::remove_volatile_t has failed");
}
TEST(TypeTraits, StdIsConstCompiles)
{
static_assert(!AZStd::is_const_v<int>, "C++11 std::is_const has failed");
static_assert(AZStd::is_const_v<const int>, "C++11 std::is_const has failed");
// references are never const
static_assert(!AZStd::is_const_v<const int&>, "C++11 std::is_const has failed");
// pointer checks for constness
static_assert(!AZStd::is_const_v<const int*>, "C++11 std::is_const has failed");
static_assert(AZStd::is_const_v<const int* const>, "C++11 std::is_const has failed");
static_assert(AZStd::is_const_v<int* const>, "C++11 std::is_const has failed");
}
TEST(TypeTraits, StdIsVolatileCompiles)
{
static_assert(!AZStd::is_volatile_v<int>, "C++11 std::is_volatile has failed");
static_assert(AZStd::is_volatile_v<volatile int>, "C++11 std::is_volatile has failed");
// references are never volatile
static_assert(!AZStd::is_volatile_v<volatile int&>, "C++11 std::is_volatile has failed");
// pointer checks for volatile
static_assert(!AZStd::is_volatile_v<volatile int*>, "C++11 std::is_volatile has failed");
static_assert(AZStd::is_volatile_v<const int* volatile>, "C++11 std::is_volatile has failed");
static_assert(!AZStd::is_volatile_v<volatile int* const>, "C++11 std::is_volatile has failed");
static_assert(AZStd::is_volatile_v<int* volatile>, "C++11 std::is_volatile has failed");
}
TEST(TypeTraits, TemplateIsCopyConstructible_WithCopyConstructibleValueType_ReturnsTrue)
{
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::vector<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::list<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::forward_list<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::map<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::multimap<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_map<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multimap<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::set<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::multiset<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_set<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multiset<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::pair<int, int>>::value, "");
struct CopyableType
TEST(TypeTraits, StdRemoveConstCompiles)
{
CopyableType() = default;
CopyableType(const CopyableType&) = default;
};
static_assert(AZStd::Internal::template_is_copy_constructible<CopyableType>::value, "");
}
static_assert(AZStd::is_same_v<int, AZStd::remove_const_t<const int>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_const_t<int>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<int*, AZStd::remove_const_t<int* const>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<const int*, AZStd::remove_const_t<const int*>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<const volatile int*, AZStd::remove_const_t<const volatile int* const>>, "C++11 std::remove_const_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_const_t<AZStd::remove_reference_t<const int&>>>, "C++11 std::remove_const_t has failed");
}
TEST(TypeTraits, TemplateIsCopyConstructible_WithOutCopyConstructibleValueType_ReturnsFalse)
{
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::vector<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::list<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::forward_list<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::map<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::map<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::multimap<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::multimap<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_map<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_map<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multimap<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multimap<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::set<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::multiset<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_set<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multiset<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::pair<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::pair<int, AZStd::unique_ptr<int>>>::value, "");
struct MoveOnly
TEST(TypeTraits, StdRemoveVolatileCompiles)
{
MoveOnly() = default;
MoveOnly(const MoveOnly&) = delete;
MoveOnly(MoveOnly&&) = default;
};
static_assert(!AZStd::Internal::template_is_copy_constructible<MoveOnly>::value, "");
}
static_assert(AZStd::is_same_v<int, AZStd::remove_volatile_t<volatile int>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_volatile_t<int>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<int*, AZStd::remove_volatile_t<int* volatile>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<volatile int*, AZStd::remove_volatile_t<volatile int*>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<const volatile int*, AZStd::remove_volatile_t<const volatile int*>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<const int*, AZStd::remove_volatile_t<const int* volatile>>, "C++11 std::remove_volatile_t has failed");
static_assert(AZStd::is_same_v<int, AZStd::remove_volatile_t<AZStd::remove_reference_t<volatile int&>>>, "C++11 std::remove_volatile_t has failed");
}
TEST(TypeTraits, MakeSignedCompiles)
{
static_assert(AZStd::is_same_v<typename AZStd::make_signed<AZ::s8>::type, AZ::s8>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::u8>, AZ::s8>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s16>, AZ::s16>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::u16>, AZ::s16>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s32>, AZ::s32>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::u32>, AZ::s32>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s64>, AZ::s64>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s64>, AZ::s64>);
}
TEST(TypeTraits, MakeUnsignedCompiles)
{
static_assert(AZStd::is_same_v<typename AZStd::make_unsigned<AZ::s8>::type, AZ::u8>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::u8>, AZ::u8>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s16>, AZ::u16>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::u16>, AZ::u16>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s32>, AZ::u32>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::u32>, AZ::u32>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s64>, AZ::u64>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s64>, AZ::u64>);
}
// VS2017 workaround, calling decltype directly on the fully specialized aznumeric_cast template
// function fails with error C3556: 'aznumeric_cast': incorrect argument to 'decltype'
// So invoke the attempt to invoke function in a non-evaluated context and SFINAE to prevent a compile
// error
template <typename T, typename = void>
constexpr bool NumericCastInvocable = false;
template <typename T>
constexpr bool NumericCastInvocable<T, AZStd::void_t<decltype(aznumeric_cast<int>(AZStd::declval<T>()))>> = true;
TEST(TypeTraits, NumericCastConversionOperatorCompiles)
{
struct AzNumericCastConvertibleCompileTest
TEST(TypeTraits, StdIsConstCompiles)
{
constexpr operator int() { return {}; };
};
static_assert(NumericCastInvocable<AzNumericCastConvertibleCompileTest>, "aznumeric_cast conversion operator overload is should be compilable");
static_assert(!AZStd::is_const_v<int>, "C++11 std::is_const has failed");
static_assert(AZStd::is_const_v<const int>, "C++11 std::is_const has failed");
// references are never const
static_assert(!AZStd::is_const_v<const int&>, "C++11 std::is_const has failed");
// pointer checks for constness
static_assert(!AZStd::is_const_v<const int*>, "C++11 std::is_const has failed");
static_assert(AZStd::is_const_v<const int* const>, "C++11 std::is_const has failed");
static_assert(AZStd::is_const_v<int* const>, "C++11 std::is_const has failed");
}
TEST(TypeTraits, StdIsVolatileCompiles)
{
static_assert(!AZStd::is_volatile_v<int>, "C++11 std::is_volatile has failed");
static_assert(AZStd::is_volatile_v<volatile int>, "C++11 std::is_volatile has failed");
// references are never volatile
static_assert(!AZStd::is_volatile_v<volatile int&>, "C++11 std::is_volatile has failed");
// pointer checks for volatile
static_assert(!AZStd::is_volatile_v<volatile int*>, "C++11 std::is_volatile has failed");
static_assert(AZStd::is_volatile_v<const int* volatile>, "C++11 std::is_volatile has failed");
static_assert(!AZStd::is_volatile_v<volatile int* const>, "C++11 std::is_volatile has failed");
static_assert(AZStd::is_volatile_v<int* volatile>, "C++11 std::is_volatile has failed");
}
struct CommonReferenceSpecializationTest
{};
}
namespace AZStd
{
template <template <class> class TQual, template <class> class UQual>
struct basic_common_reference<UnitTest::CommonReferenceSpecializationTest, int, TQual, UQual>
{
using type = int&;
};
template <template <class> class TQual, template <class> class UQual>
struct basic_common_reference<int, UnitTest::CommonReferenceSpecializationTest, TQual, UQual>
{
using type = int&;
};
}
namespace UnitTest
{
TEST(TypeTraits, StdCommonReferenceCompiles)
{
// Test std::common_reference bullet https://eel.is/c++draft/meta.trans.other#6.3.1
static_assert(AZStd::is_same_v<AZStd::common_reference_t<volatile float&, const float&>, const volatile float&>, "C++20 std::common_reference has failed");
static_assert(AZStd::is_same_v<AZStd::common_reference_t<float&&, const float&>, const float&>, "C++20 std::common_reference has failed");
static_assert(AZStd::is_same_v<AZStd::common_reference_t<const float&&, const float&>, const float&>, "C++20 std::common_reference has failed");
static_assert(AZStd::is_same_v<AZStd::common_reference_t<int&&, float&>, float>, "C++20 std::common_reference has failed");
static_assert(AZStd::is_same_v<AZStd::common_reference_t<int, float&&>, float>, "C++20 std::common_reference has failed");
// Test std::common_reference customization point https://eel.is/c++draft/meta.trans.other#6.3.2
static_assert(AZStd::is_same_v<AZStd::common_reference_t<UnitTest::CommonReferenceSpecializationTest, int>, int&>, "C++ basic_common_reference_customization_point has failed");
static_assert(AZStd::is_same_v<AZStd::common_reference_t<int, UnitTest::CommonReferenceSpecializationTest>, int&>, "C++ basic_common_reference_customization_point has failed");
// Test std::common_reference bullet https://eel.is/c++draft/meta.trans.other#6.3.3
static_assert(AZStd::is_same_v<AZStd::common_reference_t<int, float>, float>, "C++20 std::common_reference has failed");
static_assert(AZStd::is_same_v<AZStd::common_reference_t<float, int>, float>, "C++20 std::common_reference has failed");
static_assert(AZStd::is_same_v<AZStd::common_reference_t<float, const int>, float>, "C++20 std::common_reference has failed");
// Test std::common_reference bullet https://eel.is/c++draft/meta.trans.other#6.3.3
using Int64Milliseconds = AZStd::chrono::duration<int64_t, AZStd::milli>;
using DoubleMilliseconds = AZStd::chrono::duration<double, AZStd::milli>;
static_assert(AZStd::is_same_v<AZStd::common_reference_t<Int64Milliseconds, DoubleMilliseconds>, DoubleMilliseconds>,
"C++20 std::common_reference common_type check has failed");
}
TEST(TypeTraits, TemplateIsCopyConstructible_WithCopyConstructibleValueType_ReturnsTrue)
{
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::vector<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::list<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::forward_list<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::map<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::multimap<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_map<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multimap<int, int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::set<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::multiset<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_set<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multiset<int>>::value, "");
static_assert(AZStd::Internal::template_is_copy_constructible<AZStd::pair<int, int>>::value, "");
struct CopyableType
{
CopyableType() = default;
CopyableType(const CopyableType&) = default;
};
static_assert(AZStd::Internal::template_is_copy_constructible<CopyableType>::value, "");
}
TEST(TypeTraits, TemplateIsCopyConstructible_WithOutCopyConstructibleValueType_ReturnsFalse)
{
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::vector<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::list<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::forward_list<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::map<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::map<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::multimap<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::multimap<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_map<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_map<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multimap<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multimap<int, AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::set<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::multiset<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_set<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::unordered_multiset<AZStd::unique_ptr<int>>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::pair<AZStd::unique_ptr<int>, int>>::value, "");
static_assert(!AZStd::Internal::template_is_copy_constructible<AZStd::pair<int, AZStd::unique_ptr<int>>>::value, "");
struct MoveOnly
{
MoveOnly() = default;
MoveOnly(const MoveOnly&) = delete;
MoveOnly(MoveOnly&&) = default;
};
static_assert(!AZStd::Internal::template_is_copy_constructible<MoveOnly>::value, "");
}
TEST(TypeTraits, MakeSignedCompiles)
{
static_assert(AZStd::is_same_v<typename AZStd::make_signed<AZ::s8>::type, AZ::s8>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::u8>, AZ::s8>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s16>, AZ::s16>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::u16>, AZ::s16>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s32>, AZ::s32>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::u32>, AZ::s32>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s64>, AZ::s64>);
static_assert(AZStd::is_same_v<AZStd::make_signed_t<AZ::s64>, AZ::s64>);
}
TEST(TypeTraits, MakeUnsignedCompiles)
{
static_assert(AZStd::is_same_v<typename AZStd::make_unsigned<AZ::s8>::type, AZ::u8>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::u8>, AZ::u8>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s16>, AZ::u16>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::u16>, AZ::u16>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s32>, AZ::u32>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::u32>, AZ::u32>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s64>, AZ::u64>);
static_assert(AZStd::is_same_v<AZStd::make_unsigned_t<AZ::s64>, AZ::u64>);
}
struct IteratorTraitsSpecializationTest {};
}
namespace AZStd
{
template <>
struct iterator_traits<UnitTest::IteratorTraitsSpecializationTest>
{
using difference_type = ptrdiff_t;
using value_type = char;
using pointer = char*;
using reference = char&;
using iterator_category = random_access_iterator_tag;
using iterator_concept = contiguous_iterator_tag;
};
}
namespace UnitTest
{
TEST(TypeTraits, IterValueCompiles)
{
struct IterValueWithValueAndElementTypeTest
{
using element_type = volatile char;
using value_type = const char;
};
static_assert(AZStd::is_same_v<AZStd::iter_value_t<AZStd::string_view>, typename AZStd::string_view::value_type>);
static_assert(AZStd::is_same_v<AZStd::iter_value_t<AZStd::unique_ptr<char>>, typename AZStd::unique_ptr<char>::element_type>);
static_assert(AZStd::is_same_v<AZStd::iter_value_t<AZ::u32[]>, AZ::u32>);
static_assert(AZStd::is_same_v<AZStd::iter_value_t<AZ::u32*>, AZ::u32>);
static_assert(AZStd::is_same_v<AZStd::iter_value_t<IterValueWithValueAndElementTypeTest>, char>);
static_assert(AZStd::is_same_v<AZStd::iter_value_t<UnitTest::IteratorTraitsSpecializationTest>, char>);
}
TEST(TypeTraits, IterDifferenceCompiles)
{
struct IterDifferenceTest
{
using difference_type = AZ::s8;
};
static_assert(AZStd::is_same_v<AZStd::iter_difference_t<AZ::s32>, AZ::s32>);
static_assert(AZStd::is_same_v<AZStd::iter_difference_t<AZ::u32>, AZ::s32 >);
static_assert(AZStd::is_same_v<AZStd::iter_difference_t<AZ::s32*>, ptrdiff_t>);
static_assert(AZStd::is_same_v<AZStd::iter_difference_t<IterDifferenceTest>, AZ::s8>);
static_assert(AZStd::is_same_v<AZStd::iter_difference_t<const IterDifferenceTest>, AZ::s8>);
static_assert(AZStd::is_same_v<AZStd::iter_difference_t<UnitTest::IteratorTraitsSpecializationTest>, ptrdiff_t>);
}
TEST(TypeTraits, IterReferenceCompiles)
{
static_assert(AZStd::is_same_v<AZStd::iter_reference_t<typename AZStd::string_view::iterator>, const char&>);
static_assert(AZStd::is_same_v<AZStd::iter_reference_t<typename AZStd::list<char>::iterator>, char&>);
static_assert(AZStd::is_same_v<AZStd::iter_reference_t<AZ::u32[]>, AZ::u32&>);
static_assert(AZStd::is_same_v<AZStd::iter_reference_t<AZ::u32*>, AZ::u32&>);
static_assert(AZStd::is_same_v<AZStd::iter_reference_t<typename AZStd::list<char>::const_iterator>, const char&>);
static_assert(AZStd::is_same_v<AZStd::iter_reference_t<std::istreambuf_iterator<char>>, char>);
}
// Test customizing the ranges::iter_move function
struct IterMoveCustomizationPointTest
{
int operator*();
};
char&& iter_move(IterMoveCustomizationPointTest&);
TEST(TypeTraits, IterRvalueReferenceCompiles)
{
static_assert(AZStd::is_same_v<AZStd::iter_rvalue_reference_t<typename AZStd::string_view::iterator>, const char&&>);
static_assert(AZStd::is_same_v<AZStd::iter_rvalue_reference_t<typename AZStd::list<char>::iterator>, char&&>);
static_assert(AZStd::is_same_v<AZStd::iter_rvalue_reference_t<AZ::u32[]>, AZ::u32&&>);
static_assert(AZStd::is_same_v<AZStd::iter_rvalue_reference_t<AZ::u32*>, AZ::u32&&>);
static_assert(AZStd::is_same_v<AZStd::iter_rvalue_reference_t<typename AZStd::list<char>::const_iterator>, const char&&>);
static_assert(AZStd::is_same_v<AZStd::iter_rvalue_reference_t<std::istreambuf_iterator<char>>, char>);
static_assert(AZStd::is_same_v<AZStd::iter_rvalue_reference_t<IterMoveCustomizationPointTest>, char&&>);
}
// VS2017 workaround, calling decltype directly on the fully specialized aznumeric_cast template
// function fails with error C3556: 'aznumeric_cast': incorrect argument to 'decltype'
// So invoke the attempt to invoke function in a non-evaluated context and SFINAE to prevent a compile
// error
template <typename T, typename = void>
constexpr bool NumericCastInvocable = false;
template <typename T>
constexpr bool NumericCastInvocable<T, AZStd::void_t<decltype(aznumeric_cast<int>(AZStd::declval<T>()))>> = true;
TEST(TypeTraits, NumericCastConversionOperatorCompiles)
{
struct AzNumericCastConvertibleCompileTest
{
constexpr operator int() { return {}; };
};
static_assert(NumericCastInvocable<AzNumericCastConvertibleCompileTest>, "aznumeric_cast conversion operator overload should be compilable");
}
}
@@ -182,6 +182,7 @@ set(FILES
AZStd/Atomics.cpp
AZStd/Any.cpp
AZStd/Bitset.cpp
AZStd/ConceptsTests.cpp
AZStd/CreateDestroy.cpp
AZStd/ConcurrentAllocators.cpp
AZStd/ConcurrentContainers.cpp
@@ -205,9 +206,11 @@ set(FILES
AZStd/Optional.cpp
AZStd/Pair.cpp
AZStd/Parallel.cpp
AZStd/RangesTests.cpp
AZStd/ScopedLockTests.cpp
AZStd/SetsIntrusive.cpp
AZStd/SmartPtr.cpp
AZStd/SpanTests.cpp
AZStd/String.cpp
AZStd/TypeTraits.cpp
AZStd/Tuple.cpp
@@ -15,7 +15,7 @@ namespace AZ
{
ScopedAutoTempDirectory::ScopedAutoTempDirectory()
{
char tempDirectoryTemplate[] = "/sdcard/Android/data/com.lumberyard.tests/files/UnitTest-XXXXXX";
char tempDirectoryTemplate[] = "/sdcard/Android/data/org.o3de.tests/files/UnitTest-XXXXXX";
const char* tempDir = mkdtemp(tempDirectoryTemplate);
AZ_Error("AzTest", tempDir, "Unable to create temp directory %s", tempDirectoryTemplate);
memset(m_tempDirectory, '\0', sizeof(m_tempDirectory));
@@ -177,7 +177,6 @@ namespace AzToolsFramework
auto data = index.data(AssetBrowserModel::Roles::EntryRole);
if (data.canConvert<const AssetBrowserEntry*>())
{
[[maybe_unused]] bool isEnabled = (option.state & QStyle::State_Enabled) != 0;
QStyle* style = option.widget ? option.widget->style() : QApplication::style();
@@ -223,7 +222,6 @@ namespace AzToolsFramework
// sources with no children should be greyed out.
if (sourceEntry->GetChildCount() == 0)
{
isEnabled = false; // draw in disabled style.
actualPalette.setCurrentColorGroup(QPalette::Disabled);
}
}
@@ -285,7 +283,7 @@ namespace AzToolsFramework
initStyleOption(&optionV4, index);
optionV4.state &= ~(QStyle::State_HasFocus | QStyle::State_Selected);
if (m_assetBrowserFilerModel && m_assetBrowserFilerModel->GetStringFilter()
if (m_assetBrowserFilerModel && m_assetBrowserFilerModel->GetStringFilter()
&& !m_assetBrowserFilerModel->GetStringFilter()->GetFilterString().isEmpty())
{
displayString = RichTextHighlighter::HighlightText(displayString, m_assetBrowserFilerModel->GetStringFilter()->GetFilterString());
@@ -316,7 +314,7 @@ namespace AzToolsFramework
absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / TreeIconPathOneChild;
break;
}
[[maybe_unused]] bool pixmapLoadedSuccess = pixmap.load(absoluteIconPath.c_str());
[[maybe_unused]] bool pixmapLoadedSuccess = pixmap.load(absoluteIconPath.c_str());
AZ_Assert(pixmapLoadedSuccess, "Error loading Branch Icons in SearchEntryDelegate");
m_branchIcons[static_cast<EntryBranchType>(branchType)] = pixmap;
@@ -693,7 +693,12 @@ namespace AzToolsFramework
SliceEditorEntityOwnershipServiceNotificationBus::Broadcast(
&SliceEditorEntityOwnershipServiceNotifications::OnSaveStreamForGameBegin, stream, streamType, tempEntities);
sourceEntities.insert(sourceEntities.end(), tempEntities.begin(), tempEntities.end());
sourceEntities.reserve(sourceEntities.size() + tempEntities.size());
for (AZStd::unique_ptr<AZ::Entity>& tempEntity : tempEntities)
{
sourceEntities.emplace_back(tempEntity.release());
}
tempEntities = {};
// Add the root slice metadata entity so that we export any level components
sourceEntities.push_back(GetRootSlice()->GetMetadataEntity());
@@ -217,7 +217,7 @@ namespace AzToolsFramework
});
EditorActionRequestBus::Broadcast(
&EditorActionRequests::AddActionViaBusCrc, AZ_CRC_CE("com.o3de.action.editortransform.prefabopen"),
&EditorActionRequests::AddActionViaBusCrc, AZ_CRC_CE("org.o3de.action.editortransform.prefabopen"),
m_actions.back().get());
}
@@ -237,7 +237,7 @@ namespace AzToolsFramework
});
EditorActionRequestBus::Broadcast(
&EditorActionRequests::AddActionViaBusCrc, AZ_CRC_CE("com.o3de.action.editortransform.prefabclose"),
&EditorActionRequests::AddActionViaBusCrc, AZ_CRC_CE("org.o3de.action.editortransform.prefabclose"),
m_actions.back().get());
}
}
@@ -23,11 +23,11 @@ namespace AzToolsFramework
/// @name Reverse URLs.
/// Used to identify common actions and override them when necessary.
//@{
static const AZ::Crc32 s_backAction = AZ_CRC("com.o3de.action.common.back", 0x80c3030f);
static const AZ::Crc32 s_deleteAction = AZ_CRC("com.o3de.action.common.delete", 0x58e78eed);
static const AZ::Crc32 s_duplicateAction = AZ_CRC("com.o3de.action.common.duplicate", 0xbc5a4a23);
static const AZ::Crc32 s_nextComponentMode = AZ_CRC("com.o3de.action.common.nextComponentMode", 0xf9aca3a8);
static const AZ::Crc32 s_previousComponentMode = AZ_CRC("com.o3de.action.common.previousComponentMode", 0x0580eaec);
static const AZ::Crc32 s_backAction = AZ_CRC_CE("org.o3de.action.common.back");
static const AZ::Crc32 s_deleteAction = AZ_CRC_CE("org.o3de.action.common.delete");
static const AZ::Crc32 s_duplicateAction = AZ_CRC_CE("org.o3de.action.common.duplicate");
static const AZ::Crc32 s_nextComponentMode = AZ_CRC_CE("org.o3de.action.common.nextComponentMode");
static const AZ::Crc32 s_previousComponentMode = AZ_CRC_CE("org.o3de.action.common.previousComponentMode");
//@}
/// Specific Action properties to be sent to a type implementing
@@ -101,7 +101,7 @@ namespace AzToolsFramework
{
}
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.o3de.action.---").
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'org.o3de.action.---").
AZStd::vector<AZStd::function<void()>> m_callbacks; //!< Callbacks associated with this Action (note: with multi-selections
//!< there will be a callback per Entity/Component).
AZStd::unique_ptr<QAction> m_action; //!< The QAction associated with the overrideWidget for all ComponentMode actions.
@@ -17,23 +17,23 @@ namespace AzToolsFramework
//! @name Reverse URLs.
//! Used to identify common actions and override them when necessary.
//@{
constexpr inline AZ::Crc32 LockSelection = AZ_CRC_CE("com.o3de.action.editortransform.lockselect");
constexpr inline AZ::Crc32 UnlockSelection = AZ_CRC_CE("com.o3de.action.editortransform.unlockselect");
constexpr inline AZ::Crc32 HideSelection = AZ_CRC_CE("com.o3de.action.editortransform.hideselect");
constexpr inline AZ::Crc32 ShowSelection = AZ_CRC_CE("com.o3de.action.editortransform.showselect");
constexpr inline AZ::Crc32 UnlockAll = AZ_CRC_CE("com.o3de.action.editortransform.unlockall");
constexpr inline AZ::Crc32 ShowAll = AZ_CRC_CE("com.o3de.action.editortransform.unhideall");
constexpr inline AZ::Crc32 SelectAll = AZ_CRC_CE("com.o3de.action.editortransform.selectall");
constexpr inline AZ::Crc32 InvertSelect = AZ_CRC_CE("com.o3de.action.editortransform.invertselect");
constexpr inline AZ::Crc32 DuplicateSelect = AZ_CRC_CE("com.o3de.action.editortransform.duplicateselect");
constexpr inline AZ::Crc32 DeleteSelect = AZ_CRC_CE("com.o3de.action.editortransform.deleteselect");
constexpr inline AZ::Crc32 EditEscaspe = AZ_CRC_CE("com.o3de.action.editortransform.editescape");
constexpr inline AZ::Crc32 EditPivot = AZ_CRC_CE("com.o3de.action.editortransform.editpivot");
constexpr inline AZ::Crc32 EditReset = AZ_CRC_CE("com.o3de.action.editortransform.editreset");
constexpr inline AZ::Crc32 EditResetManipulator = AZ_CRC_CE("com.o3de.action.editortransform.editresetmanipulator");
constexpr inline AZ::Crc32 ViewportUiVisible = AZ_CRC_CE("com.o3de.action.editortransform.viewportuivisible");
constexpr inline AZ::Crc32 Helpers = AZ_CRC_CE("com.o3de.action.editor.helpers");
constexpr inline AZ::Crc32 Icons = AZ_CRC_CE("com.o3de.action.editor.icons");
constexpr inline AZ::Crc32 LockSelection = AZ_CRC_CE("org.o3de.action.editortransform.lockselect");
constexpr inline AZ::Crc32 UnlockSelection = AZ_CRC_CE("org.o3de.action.editortransform.unlockselect");
constexpr inline AZ::Crc32 HideSelection = AZ_CRC_CE("org.o3de.action.editortransform.hideselect");
constexpr inline AZ::Crc32 ShowSelection = AZ_CRC_CE("org.o3de.action.editortransform.showselect");
constexpr inline AZ::Crc32 UnlockAll = AZ_CRC_CE("org.o3de.action.editortransform.unlockall");
constexpr inline AZ::Crc32 ShowAll = AZ_CRC_CE("org.o3de.action.editortransform.unhideall");
constexpr inline AZ::Crc32 SelectAll = AZ_CRC_CE("org.o3de.action.editortransform.selectall");
constexpr inline AZ::Crc32 InvertSelect = AZ_CRC_CE("org.o3de.action.editortransform.invertselect");
constexpr inline AZ::Crc32 DuplicateSelect = AZ_CRC_CE("org.o3de.action.editortransform.duplicateselect");
constexpr inline AZ::Crc32 DeleteSelect = AZ_CRC_CE("org.o3de.action.editortransform.deleteselect");
constexpr inline AZ::Crc32 EditEscaspe = AZ_CRC_CE("org.o3de.action.editortransform.editescape");
constexpr inline AZ::Crc32 EditPivot = AZ_CRC_CE("org.o3de.action.editortransform.editpivot");
constexpr inline AZ::Crc32 EditReset = AZ_CRC_CE("org.o3de.action.editortransform.editreset");
constexpr inline AZ::Crc32 EditResetManipulator = AZ_CRC_CE("org.o3de.action.editortransform.editresetmanipulator");
constexpr inline AZ::Crc32 ViewportUiVisible = AZ_CRC_CE("org.o3de.action.editortransform.viewportuivisible");
constexpr inline AZ::Crc32 Helpers = AZ_CRC_CE("org.o3de.action.editor.helpers");
constexpr inline AZ::Crc32 Icons = AZ_CRC_CE("org.o3de.action.editor.icons");
//@}
//! Provide interface for EditorTransformComponentSelection requests.
@@ -67,7 +67,7 @@ namespace //anonymous
"project_id": "{91FB81A1-072C-4A80-8FCC-7E2C4C767B4D}",
"android_settings" : {
"package_name" : "com.lumberyard.yourgame",
"package_name" : "org.o3de.yourgame",
"version_number" : 1,
"version_name" : "1.0.0.0",
"orientation" : "landscape"
@@ -197,7 +197,7 @@ namespace AzToolsFramework
AZStd::vector<AzToolsFramework::ActionOverride> PlaceHolderComponentMode::PopulateActionsImpl()
{
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("com.o3de.action.placeholder.test");
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("org.o3de.action.placeholder.test");
return AZStd::vector<AzToolsFramework::ActionOverride>
{
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2505ee83c0e435700601d38c7c4b08b601478c5194a088ff6577e1017731b3ae
size 2368
oid sha256:2323fb234c075a6d18eed7575338fcb2c3aef119c19d5aedb2b45c18b3c8d69e
size 2275
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:32d4da537649036b18aa116c1337b8b23d1a4536b907034a1262cc6764e65627
size 1615
oid sha256:4f8b3aeeecb6baad0ba0be4c1f7b128fc609af82fea88019d322d85de693519c
size 1969
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6a7f38fe03aba465b65189fdf183281c0d7397962f93168379ebca25f9581a30
size 3362
oid sha256:d6cb3e1b2d44927f300877c63c4181dabe08861bcc085ecfa9dee40e145af2cf
size 2504
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:02392ac01615ce21710b8566085941fea67926cab062ac2a4c7cdfc594aff428
size 5482
oid sha256:746bc5803e8d5dd84b5c255211d167f61beac1c4f9a5a206edff340610fffe7d
size 3247
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3636ef346cf87d2382ed67ef0a7396bfe3b4df13f9ef223b1911e96ef42ae2ec
size 8238
oid sha256:1f93be4cff524be96f0fdd2f2bc5c233b8c1391bb8c47abacd028026ed7ce672
size 3887
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:df22836ffc2ab5cca07c6e0d152ed8ef01d56d66cdc56435d6b48304753c4990
size 196450
oid sha256:c40fdabfe1391421cef0c1d7fb3e5b2173aac29d6aaf664ed54b9c39aee5e077
size 17714
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:70250143d6b53978c7a164330c38cf34777688b92e0def691b68777be111ac75
size 156821
oid sha256:22c800b9b1ea513c93162e5549492b2841bc9c8bf94b1a9273f26be1dd4e4517
size 16494
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:80752114b225ad43028278ac8372cbf4543f493a55e5fe05c24ff1e20f9b24b5
size 324436
oid sha256:264aff020a8bc1665aaddaec10e4e453b1a551b4c84c08fddbb315c5aa7202c1
size 33469
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:44de927141f19e10672012a8e0675d03fd06e6b20d5a7c759cdc233a1262ef55
size 441038
oid sha256:6dded39dd078168e92f1fd47e4728f99f06a6a988a57d5e56ddc0eeb3d4985ef
size 50380
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d3fb185179d26442087087401dd96443ed094122b8b7a1b7985aae299764bcf6
size 271782
oid sha256:de82dd62268697af0a02dbfad1cd37f153cc0dc08a2d40cec0bbf4fe582fcb50
size 16257
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:04c9bc74b51d3bd7cf85e178b15c631fd78c6251ef014a41506f36852ec4a500
size 209127
oid sha256:70a234b518d00b6be6459f2731d84c23271683d72b775909683ea3b5738d3313
size 13053
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:913fdddb651ff6d74fb0583b06c6f32f6c87bf9eabe4b861d662c9c409cff733
size 461061
oid sha256:0cc200156f762ee8101b8b9eb3d6640c130a889b4507f95eb160524109bfde1d
size 27508
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cb9fd81fb4ad83132db7401fe412cce61bf0577e1822653115930f31f3db6241
size 570118
oid sha256:c6b01162660664b097ce26ffef1c4171b33565b380f58064c78980335617ca5e
size 42415
@@ -6,7 +6,7 @@
"project_id": "{91FB81A1-072C-4A80-8FCC-7E2C4C767B4D}",
"android_settings" : {
"package_name" : "com.lumberyard.yourgame",
"package_name" : "org.o3de.yourgame",
"version_number" : 1,
"version_name" : "1.0.0.0",
"orientation" : "landscape"
@@ -2,7 +2,7 @@
"project_name" : "AzTestRunner",
"product_name" : "AzTestRunner Project",
"android_settings": {
"package_name" : "com.lumberyard.tests",
"package_name" : "org.o3de.tests",
"version_number": 1,
"version_name" : "1.0.0",
"orientation" : "landscape",
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>AzTestRunner</string>
<key>CFBundleIdentifier</key>
<string>com.lumberyard.tests</string>
<string>org.o3de.tests</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -198,9 +198,7 @@ namespace O3DE::ProjectManager
return true;
}
bool forceRegistration = false;
// check if an engine with this name is already registered
// check if an engine with this name is already registered and has a valid engine.json
auto existingEngineResult = m_pythonBindings->GetEngineInfo(engineInfo.m_name);
if (existingEngineResult)
{
@@ -232,10 +230,11 @@ namespace O3DE::ProjectManager
// user elected not to change the name or force registration
return false;
}
forceRegistration = true;
}
// always force register in case there is an engine registered in o3de_manifest.json, but
// the engine.json is missing or corrupt in which case GetEngineInfo() fails
constexpr bool forceRegistration = true;
auto registerOutcome = m_pythonBindings->SetEngineInfo(engineInfo, forceRegistration);
if (!registerOutcome)
{
@@ -459,6 +459,9 @@ namespace O3DE::ProjectManager
if (!pybind11::isinstance<pybind11::none>(enginePathResult))
{
engineInfo = EngineInfoFromPath(enginePathResult);
// it is possible an engine is registered in o3de_manifest.json but the engine.json is
// missing or corrupt in which case we do not consider it a registered engine
}
});
@@ -177,6 +177,11 @@ namespace AWSCore
using OnSuccessFunction = AZStd::function<void(AwsApiRequestJob* job)>;
using OnFailureFunction = AZStd::function<void(AwsApiRequestJob* job)>;
class Function;
template<class Allocator = AZ::SystemAllocator>
static AwsApiRequestJob* Create(OnSuccessFunction onSuccess, OnFailureFunction onFailure = OnFailureFunction{}, IConfig* config = GetDefaultConfig());
static Config* GetDefaultConfig()
{
static AwsApiJobConfigHolder<Config> s_configHolder{};
@@ -188,10 +193,6 @@ namespace AWSCore
{
}
RequestType request;
ResultType result;
ErrorType error;
/// Override AZ:Job defined method to reset request state when
/// the job object is reused.
void Reset(bool isClearDependent) override
@@ -209,35 +210,11 @@ namespace AWSCore
return m_wasSuccess;
}
RequestType request;
ResultType result;
ErrorType error;
protected:
/// Constructor for creating AwsApiRequestJob Jobs that can handle queued responses
/// for OnSuccess, OnFailure, and DoCleanup
AwsApiRequestJob(OnSuccessFunction onSuccess,
OnFailureFunction onFailure,
IConfig* config = GetDefaultConfig()
) : AwsApiClientJobType(false, config)
, m_queueOnSuccess{ true }
, m_onSuccess{ onSuccess }
, m_queueOnFailure{ true }
, m_onFailure{ onFailure }
, m_queueDelete{ true }
{
}
bool m_wasSuccess{ false };
// Flag and optional function call to queue for onSuccess events
bool m_queueOnSuccess{ false };
OnSuccessFunction m_onSuccess{};
// Flag and optional function call to queue for onFailure events
bool m_queueOnFailure{ false };
OnFailureFunction m_onFailure{};
// Flag to queue the delete during the DoCleanup calls
bool m_queueDelete{ false };
void Process() override
{
@@ -295,56 +272,86 @@ namespace AWSCore
/// Called when request has completed successfully.
virtual void OnSuccess()
{
if (m_queueOnSuccess)
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onSuccess)
{
m_onSuccess(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
}
/// Called when the request fails.
virtual void OnFailure()
{
if (m_queueOnFailure)
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onFailure)
{
m_onFailure(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
}
/// Called when request can't process and still requires cleanup (Specifically for our derived class Function which does not use auto delete)
/// Called when request can't process and still requires cleanup (Specifically for the derived class AwsApiRequestJob<RequestTraits>::Function which does not use auto delete)
virtual void DoCleanup()
{
if (m_queueDelete)
{
AZStd::function<void()> callbackHandler = [this]()
{
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
}
public:
template<class Allocator = AZ::SystemAllocator>
static AwsApiRequestJob* Create(OnSuccessFunction onSuccess, OnFailureFunction onFailure = OnFailureFunction{}, IConfig* config = GetDefaultConfig())
{
return azcreate(AwsApiRequestJob, (onSuccess, onFailure, config), Allocator);
}
bool m_wasSuccess{ false };
};
/// A specialization of AwsApiRequestJob that lets you provide functions
/// that are called on success or failure of the request.
template<class RequestTraits>
class AwsApiRequestJob<RequestTraits>::Function
: public AwsApiRequestJob
{
public:
// To use a different allocator, extend this class and use this macro.
AZ_CLASS_ALLOCATOR(Function, AZ::SystemAllocator, 0);
Function(OnSuccessFunction onSuccess, OnFailureFunction onFailure = OnFailureFunction{}, IConfig* config = GetDefaultConfig())
: AwsApiRequestJobType(
false, config) // No auto delete - we need to perform our callbacks on the main thread so we queue them through tickbus
, m_onSuccess{ onSuccess }
, m_onFailure{ onFailure }
{
}
private:
void OnSuccess() override
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onSuccess)
{
m_onSuccess(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
void OnFailure() override
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onFailure)
{
m_onFailure(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
// Code doesn't use auto delete - this allows code to make sure things get cleaned up in cases where success or failure can't be
// called.
void DoCleanup() override
{
AZStd::function<void()> callbackHandler = [this]()
{
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
OnSuccessFunction m_onSuccess;
OnFailureFunction m_onFailure;
};
template<class RequestTraits>
template<class Allocator>
AwsApiRequestJob<RequestTraits>* AwsApiRequestJob<RequestTraits>::Create(
OnSuccessFunction onSuccess, OnFailureFunction onFailure, IConfig* config)
{
return azcreate(Function, (onSuccess, onFailure, config), Allocator);
}
} // namespace AWSCore
@@ -150,6 +150,11 @@ namespace AWSCore
using OnSuccessFunction = AZStd::function<void(ServiceRequestJob* job)>;
using OnFailureFunction = AZStd::function<void(ServiceRequestJob* job)>;
class Function;
template<class Allocator = AZ::SystemAllocator>
static ServiceRequestJob* Create(OnSuccessFunction onSuccess, OnFailureFunction onFailure = OnFailureFunction{}, IConfig* config = GetDefaultConfig());
static Config* GetDefaultConfig()
{
static AwsApiJobConfigHolder<Config> s_configHolder{};
@@ -212,45 +217,6 @@ namespace AWSCore
}
protected:
/// The URL created by appending the API path to the service URL.
/// The path may contain {param} format parameters. The
/// RequestType::parameters.BuildRequest method is responsible
/// for replacing these parts of the url.
const Aws::String& m_requestUrl;
/// Constructor for creating ServiceRequestJob Jobs that can handle queued responses
/// for OnSuccess, OnFailure, and DoCleanup
ServiceRequestJob(OnSuccessFunction onSuccess,
OnFailureFunction onFailure,
IConfig* config = GetDefaultConfig()
) : ServiceClientJobType{ false, config }
, m_requestUrl{ config->GetRequestUrl() }
, m_queueOnSuccess{ true }
, m_onSuccess{ onSuccess }
, m_queueOnFailure{ true }
, m_onFailure{ onFailure }
, m_queueDelete{ true }
{
}
// Flag and optional function call to queue for onSuccess events
bool m_queueOnSuccess{ false };
OnSuccessFunction m_onSuccess{};
// Flag and optional function call to queue for onFailure events
bool m_queueOnFailure{ false };
OnFailureFunction m_onFailure{};
// Flag to queue the delete during the DoCleanup calls
bool m_queueDelete{ false };
std::shared_ptr<Aws::Client::AWSAuthV4Signer> m_AWSAuthSigner{ nullptr };
// Passed in configuration contains the AWS Credentials to use. If this request requires credentials
// check in the constructor and set this bool to indicate if we're not valid before placing the credentials
// in the m_AWSAuthSigner
bool m_missingCredentials{ false };
/// Called to prepare the request. By default no changes
/// are made to the parameters object. Override to defer the preparation
/// of parameters until running on the job's worker thread,
@@ -270,50 +236,31 @@ namespace AWSCore
/// Called when a request completes without error.
virtual void OnSuccess()
{
if (m_queueOnSuccess)
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onSuccess)
{
m_onSuccess(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
}
/// Called when an error occurs.
virtual void OnFailure()
{
if (m_queueOnFailure)
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onFailure)
{
m_onFailure(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
}
/// Provided so derived functions that do not auto delete can clean up
virtual void DoCleanup()
{
if (m_queueDelete)
{
AZStd::function<void()> callbackHandler = [this]()
{
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
}
/// The URL created by appending the API path to the service URL.
/// The path may contain {param} format parameters. The
/// RequestType::parameters.BuildRequest method is responsible
/// for replacing these parts of the url.
const Aws::String& m_requestUrl;
std::shared_ptr<Aws::Client::AWSAuthV4Signer> m_AWSAuthSigner{ nullptr };
// Passed in configuration contains the AWS Credentials to use. If this request requires credentials
// check in the constructor and set this bool to indicate if we're not valid before placing the credentials
// in the m_AWSAuthSigner
bool m_missingCredentials{ false };
private:
bool BuildRequest(RequestBuilder& request) override
{
@@ -658,13 +605,73 @@ namespace AWSCore
AZ_Printf(logRequestsChannel, "Response Body:\n");
PrintRequestOutput(responseContent);
}
public:
template<class Allocator = AZ::SystemAllocator>
static ServiceRequestJob* Create(OnSuccessFunction onSuccess, OnFailureFunction onFailure = OnFailureFunction{}, IConfig* config = GetDefaultConfig())
{
return azcreate(ServiceRequestJob, (onSuccess, onFailure, config), Allocator);
}
};
/// A derived class that calls lambda functions on job completion.
template<class RequestTraits>
class ServiceRequestJob<RequestTraits>::Function
: public ServiceRequestJob
{
public:
// To use a different allocator, extend this class and use this macro.
AZ_CLASS_ALLOCATOR(Function, AZ::SystemAllocator, 0);
Function(OnSuccessFunction onSuccess, OnFailureFunction onFailure = OnFailureFunction{}, IConfig* config = GetDefaultConfig())
: ServiceRequestJob(false, config) // No auto delete - The Function class will handle it with the DoCleanup() function
, m_onSuccess{ onSuccess }
, m_onFailure{ onFailure }
{
}
private:
void OnSuccess() override
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onSuccess)
{
m_onSuccess(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
void OnFailure() override
{
AZStd::function<void()> callbackHandler = [this]()
{
if (m_onFailure)
{
m_onFailure(this);
}
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
// Code doesn't use auto delete - this ensure things get cleaned up in cases when code can't call success or failure
void DoCleanup() override
{
AZStd::function<void()> callbackHandler = [this]()
{
delete this;
};
AZ::TickBus::QueueFunction(callbackHandler);
}
OnSuccessFunction m_onSuccess;
OnFailureFunction m_onFailure;
};
template<class RequestType>
template<class Allocator>
ServiceRequestJob<RequestType>* ServiceRequestJob<RequestType>::Create(
OnSuccessFunction onSuccess, OnFailureFunction onFailure, IConfig* config)
{
return azcreate(Function, (onSuccess, onFailure, config), Allocator);
}
} // namespace AWSCore
@@ -16,7 +16,9 @@ namespace AZ
AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialAssignmentSerializer, AZ::SystemAllocator, 0);
JsonSerializationResult::Result JsonMaterialAssignmentSerializer::Load(
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
void* outputValue,
[[maybe_unused]] const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
@@ -62,6 +64,7 @@ namespace AZ
LoadAny<AZ::Color>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZStd::string>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Data::AssetId>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Data::Asset<AZ::Data::AssetData>>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Data::Asset<AZ::RPI::ImageAsset>>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>(propertyValue, inputPropertyPair.value, context, result))
{
@@ -78,7 +81,10 @@ namespace AZ
}
JsonSerializationResult::Result JsonMaterialAssignmentSerializer::Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
rapidjson::Value& outputValue,
const void* inputValue,
const void* defaultValue,
[[maybe_unused]] const Uuid& valueTypeId,
JsonSerializerContext& context)
{
namespace JSR = AZ::JsonSerializationResult;
@@ -138,9 +144,9 @@ namespace AZ
StoreAny<AZ::Color>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZStd::string>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Data::AssetId>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Data::Asset<AZ::Data::AssetData>>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Data::Asset<AZ::RPI::ImageAsset>>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>(
propertyValue, outputPropertyValue, context, result))
StoreAny<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>(propertyValue, outputPropertyValue, context, result))
{
outputPropertyValueContainer.AddMember(
rapidjson::Value::StringRefType(propertyName.GetCStr()), outputPropertyValue,
@@ -164,7 +170,9 @@ namespace AZ
template<typename T>
bool JsonMaterialAssignmentSerializer::LoadAny(
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
AZStd::any& propertyValue,
const rapidjson::Value& inputPropertyValue,
AZ::JsonDeserializerContext& context,
AZ::JsonSerializationResult::ResultCode& result)
{
if (inputPropertyValue.IsObject() && inputPropertyValue.HasMember("Value") && inputPropertyValue.HasMember("$type"))
@@ -187,7 +195,9 @@ namespace AZ
template<typename T>
bool JsonMaterialAssignmentSerializer::StoreAny(
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
const AZStd::any& propertyValue,
rapidjson::Value& outputPropertyValue,
AZ::JsonSerializerContext& context,
AZ::JsonSerializationResult::ResultCode& result)
{
if (propertyValue.is<T>())
@@ -199,7 +209,7 @@ namespace AZ
result.Combine(StoreTypeId(typeValue, azrtti_typeid<T>(), context));
outputPropertyValue.AddMember("$type", typeValue, context.GetJsonAllocator());
T value = AZStd::any_cast<T>(propertyValue);
const T& value = AZStd::any_cast<T>(propertyValue);
result.Combine(
ContinueStoringToJsonObjectField(outputPropertyValue, "Value", &value, nullptr, azrtti_typeid<T>(), context));
return true;
@@ -25,21 +25,31 @@ namespace AZ
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(
void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
void* outputValue,
const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
rapidjson::Value& outputValue,
const void* inputValue,
const void* defaultValue,
const Uuid& valueTypeId,
JsonSerializerContext& context) override;
private:
template<typename T>
bool LoadAny(
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
AZStd::any& propertyValue,
const rapidjson::Value& inputPropertyValue,
AZ::JsonDeserializerContext& context,
AZ::JsonSerializationResult::ResultCode& result);
template<typename T>
bool StoreAny(
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
const AZStd::any& propertyValue,
rapidjson::Value& outputPropertyValue,
AZ::JsonSerializerContext& context,
AZ::JsonSerializationResult::ResultCode& result);
};
} // namespace Render
@@ -154,6 +154,8 @@ namespace AZ
// Create the handlers to manage the execute groups.
auto groups = GetGroups();
AZStd::vector<RHI::FrameGraphExecuteGroup*> groupRefs;
groupRefs.reserve(groups.size());
RHI::GraphGroupId groupId;
uint32_t initGroupIndex = 0;
for (uint32_t i = 0; i < groups.size(); ++i)
@@ -161,14 +163,24 @@ namespace AZ
const FrameGraphExecuteGroupBase* group = static_cast<const FrameGraphExecuteGroupBase*>(groups[i].get());
if (groupId != group->GetGroupId())
{
AddExecuteGroupHandler(groupId, { groups.begin() + initGroupIndex, groups.begin() + i });
groupRefs.clear();
for (size_t groupRefIndex = initGroupIndex; groupRefIndex < i; ++groupRefIndex)
{
groupRefs.push_back(groups[groupRefIndex].get());
}
AddExecuteGroupHandler(groupId, groupRefs);
groupId = group->GetGroupId();
initGroupIndex = i;
}
}
// Add the final handler for the remaining groups.
AddExecuteGroupHandler(groupId, { groups.begin() + initGroupIndex, groups.end() });
groupRefs.clear();
for (size_t groupRefIndex = initGroupIndex; groupRefIndex < groups.size(); ++groupRefIndex)
{
groupRefs.push_back(groups[groupRefIndex].get());
}
AddExecuteGroupHandler(groupId, groupRefs);
}
void FrameGraphExecuter::ExecuteGroupInternal(RHI::FrameGraphExecuteGroup& groupBase)
@@ -33,11 +33,13 @@ namespace AtomToolsFramework
{
if (value.Is<AZ::Data::Asset<AZ::RPI::ImageAsset>>())
{
const AZ::Data::Asset<AZ::RPI::ImageAsset>& imageAsset = value.GetValue<AZ::Data::Asset<AZ::RPI::ImageAsset>>();
return AZStd::any(AZ::Data::Asset<AZ::RPI::StreamingImageAsset>(
imageAsset.GetId(),
azrtti_typeid<AZ::RPI::StreamingImageAsset>(),
imageAsset.GetHint()));
const auto& imageAsset = value.GetValue<AZ::Data::Asset<AZ::RPI::ImageAsset>>();
return AZStd::any(AZ::Data::Asset<AZ::RPI::StreamingImageAsset>(imageAsset.GetId(), azrtti_typeid<AZ::RPI::StreamingImageAsset>(), imageAsset.GetHint()));
}
else if (value.Is<AZ::Data::Instance<AZ::RPI::Image>>())
{
const auto& image = value.GetValue<AZ::Data::Instance<AZ::RPI::Image>>();
return AZStd::any(AZ::Data::Asset<AZ::RPI::StreamingImageAsset>(image->GetAssetId(), azrtti_typeid<AZ::RPI::StreamingImageAsset>()));
}
return AZ::RPI::MaterialPropertyValue::ToAny(value);
@@ -104,6 +104,7 @@ namespace AZ
MaterialComponentController::MaterialComponentController(const MaterialComponentConfig& config)
: m_configuration(config)
{
ConvertAssetsForSerialization();
}
void MaterialComponentController::Activate(EntityId entityId)
@@ -135,6 +136,7 @@ namespace AZ
void MaterialComponentController::SetConfiguration(const MaterialComponentConfig& config)
{
m_configuration = config;
ConvertAssetsForSerialization();
}
const MaterialComponentConfig& MaterialComponentController::GetConfiguration() const
@@ -338,6 +340,7 @@ namespace AZ
// before LoadMaterials() is called [LYN-2249]
auto temp = m_configuration.m_materials;
m_configuration.m_materials = materials;
ConvertAssetsForSerialization();
LoadMaterials();
}
@@ -489,6 +492,7 @@ namespace AZ
auto& materialAssignment = m_configuration.m_materials[materialAssignmentId];
const bool wasEmpty = materialAssignment.m_propertyOverrides.empty();
materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value;
ConvertAssetsForSerialization();
if (materialAssignment.RequiresLoading())
{
@@ -586,6 +590,7 @@ namespace AZ
auto& materialAssignment = m_configuration.m_materials[materialAssignmentId];
const bool wasEmpty = materialAssignment.m_propertyOverrides.empty();
materialAssignment.m_propertyOverrides = propertyOverrides;
ConvertAssetsForSerialization();
if (materialAssignment.RequiresLoading())
{
@@ -667,5 +672,33 @@ namespace AZ
TickBus::Handler::BusConnect();
}
}
void MaterialComponentController::ConvertAssetsForSerialization()
{
for (auto& materialAssignmentPair : m_configuration.m_materials)
{
MaterialAssignment& materialAssignment = materialAssignmentPair.second;
for (auto& propertyPair : materialAssignment.m_propertyOverrides)
{
auto& value = propertyPair.second;
if (value.is<AZ::Data::Asset<AZ::Data::AssetData>>())
{
value = AZStd::any_cast<AZ::Data::Asset<AZ::Data::AssetData>>(value).GetId();
}
else if (value.is<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>())
{
value = AZStd::any_cast<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>(value).GetId();
}
else if (value.is<AZ::Data::Asset<AZ::RPI::ImageAsset>>())
{
value = AZStd::any_cast<AZ::Data::Asset<AZ::RPI::ImageAsset>>(value).GetId();
}
else if (value.is<AZ::Data::Instance<AZ::RPI::Image>>())
{
value = AZStd::any_cast<AZ::Data::Instance<AZ::RPI::Image>>(value)->GetAssetId();
}
}
}
}
} // namespace Render
} // namespace AZ
@@ -99,6 +99,11 @@ namespace AZ
//! Queue material instance recreation notifiucations until tick
void QueueMaterialUpdateNotification();
//! Converts property overrides storing image asset references into asset IDs. This addresses a problem where image property
//! overrides are lost during prefab serialization and patching. This suboptimal function will be removed once the underlying
//! problem is resolved.
void ConvertAssetsForSerialization();
EntityId m_entityId;
MaterialComponentConfig m_configuration;
AZStd::unordered_set<MaterialAssignmentId> m_materialsWithDirtyProperties;
@@ -130,11 +130,11 @@ namespace AZ
}
}
static void ProcessUVsForSubmesh(size_t vertexCount, size_t atomVertexBufferOffset, [[maybe_unused]] size_t emfxSourceVertexStart, const AZ::Vector2* emfxSourceUVs, AZStd::vector<float[2]>& uvBufferData)
static void ProcessUVsForSubmesh(size_t vertexCount, size_t atomVertexBufferOffset, [[maybe_unused]] size_t emfxSourceVertexStart, const AZ::Vector2* emfxSourceUVs, AZStd::vector<AZStd::array<float, 2>>& uvBufferData)
{
for (size_t vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex)
{
emfxSourceUVs[vertexIndex].StoreToFloat2(uvBufferData[atomVertexBufferOffset + vertexIndex]);
emfxSourceUVs[vertexIndex].StoreToFloat2(uvBufferData[atomVertexBufferOffset + vertexIndex].data());
}
}
@@ -175,7 +175,7 @@ namespace AZ
const EMotionFX::Mesh* mesh,
const EMotionFX::SubMesh* subMesh,
size_t atomVertexBufferOffset,
AZStd::vector<uint32_t[MaxSupportedSkinInfluences / 2]>& blendIndexBufferData,
AZStd::vector<AZStd::array<uint32_t, MaxSupportedSkinInfluences / 2>>& blendIndexBufferData,
AZStd::vector<AZStd::array<float, MaxSupportedSkinInfluences>>& blendWeightBufferData,
bool hasClothData)
{
@@ -310,9 +310,9 @@ namespace AZ
AZStd::vector<PackedVector3f> normalBufferData;
AZStd::vector<Vector4> tangentBufferData;
AZStd::vector<PackedVector3f> bitangentBufferData;
AZStd::vector<uint32_t[MaxSupportedSkinInfluences / 2]> blendIndexBufferData;
AZStd::vector<AZStd::array<uint32_t, MaxSupportedSkinInfluences / 2>> blendIndexBufferData;
AZStd::vector<AZStd::array<float, MaxSupportedSkinInfluences>> blendWeightBufferData;
AZStd::vector<float[2]> uvBufferData;
AZStd::vector<AZStd::array<float, 2>> uvBufferData;
//
// Process all LODs from the EMotionFX actor data.
@@ -195,7 +195,9 @@ namespace EMotionFX
memcpy(mesh->m_indices, indexBuffer.begin() + indexBufferOffsetInBytes, indexBufferCountsInBytes);
// Set the polygon buffer
AZ_PUSH_DISABLE_WARNING_MSVC(4244); // warning C4244: '=': conversion from 'const int' to 'uint8', possible loss of data
AZStd::fill(mesh->m_polyVertexCounts, mesh->m_polyVertexCounts + mesh->m_numPolygons, 3);
AZ_POP_DISABLE_WARNING_MSVC
// Skinning data from atom are stored in two separate buffer layer.
AZ::u8 maxSkinInfluences = 255; // Later we will calculate this value from skinning data.
@@ -105,7 +105,9 @@ namespace EMotionFX
}
}
AZ_PUSH_DISABLE_WARNING_MSVC(4244); // warning C4244: '=': conversion from 'const int' to 'uint8', possible loss of data
AZStd::fill(mesh->GetPolygonVertexCounts(), mesh->GetPolygonVertexCounts() + faceCount, 3);
AZ_POP_DISABLE_WARNING_MSVC
AZStd::copy(indices.begin(), indices.end(), mesh->GetIndices());
return mesh;
@@ -22,7 +22,7 @@ namespace LmbrCentral
{
AZ_CLASS_ALLOCATOR_IMPL(EditorTubeShapeComponentMode, AZ::SystemAllocator, 0)
static const AZ::Crc32 s_resetVariableRadii = AZ_CRC("com.o3de.action.tubeshape.reset_radii", 0xa987659c);
static const AZ::Crc32 s_resetVariableRadii = AZ_CRC_CE("org.o3de.action.tubeshape.reset_radii");
static const char* const s_resetRadiiTitle = "Reset Radii";
static const char* const s_resetRadiiDesc = "Reset all variable radius values to the default";
@@ -27,10 +27,10 @@ namespace PhysX
namespace
{
//! Uri's for shortcut actions.
const AZ::Crc32 SetDimensionsSubModeActionUri = AZ_CRC("com.o3de.action.physx.setdimensionssubmode", 0x508b1781);
const AZ::Crc32 SetOffsetSubModeActionUri = AZ_CRC("com.o3de.action.physx.setoffsetsubmode", 0x777ac743);
const AZ::Crc32 SetRotationSubModeActionUri = AZ_CRC("com.o3de.action.physx.setrotationsubmode", 0xf1a8f3ff);
const AZ::Crc32 ResetSubModeActionUri = AZ_CRC("com.o3de.action.physx.resetsubmode", 0x599d1594);
const AZ::Crc32 SetDimensionsSubModeActionUri = AZ_CRC_CE("org.o3de.action.physx.setdimensionssubmode");
const AZ::Crc32 SetOffsetSubModeActionUri = AZ_CRC_CE("org.o3de.action.physx.setoffsetsubmode");
const AZ::Crc32 SetRotationSubModeActionUri = AZ_CRC_CE("org.o3de.action.physx.setrotationsubmode");
const AZ::Crc32 ResetSubModeActionUri = AZ_CRC_CE("org.o3de.action.physx.resetsubmode");
} // namespace
AZ_CLASS_ALLOCATOR_IMPL(ColliderComponentMode, AZ::SystemAllocator, 0);
@@ -24,47 +24,47 @@ namespace PhysX
namespace SubModeData
{
const AZ::Crc32 SwitchToTranslationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtotranslationsubmode");
const AZ::Crc32 SwitchToTranslationSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtotranslationsubmode");
static const char* TranslationTitle = "Switch to Position Mode";
static const char* TranslationToolTip = "Position Mode - Change the position of the joint.";
const AZ::Crc32 SwitchToRotationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtorotationsubmode");
const AZ::Crc32 SwitchToRotationSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtorotationsubmode");
static const char* RotationTitle = "Switch to Rotation Mode";
static const char* RotationToolTip = "Rotation Mode- Change the rotation of the joint.";
const AZ::Crc32 SwitchToMaxForceSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtomaxforce");
const AZ::Crc32 SwitchToMaxForceSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtomaxforce");
static const char* MaxForceTitle = "Switch to Max Force Mode";
static const char* MaxForceToolTip = "Max Force Mode - Change the maximum force allowed before the joint breaks.";
const AZ::Crc32 SwitchToMaxTorqueSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtomaxtorque");
const AZ::Crc32 SwitchToMaxTorqueSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtomaxtorque");
static const char* MaxTorqueTitle = "Switch to Max Torque Mode";
static const char* MaxTorqueToolTip = "Max Torque Mode - Change the maximum torque allowed before the joint breaks.";
const AZ::Crc32 SwitchToDampingSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtodamping");
const AZ::Crc32 SwitchToDampingSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtodamping");
static const char* DampingTitle = "Switch to Damping Mode";
static const char* DampingToolTip = "Damping Mode - Change the damping strength of the joint when beyond the limit.";
const AZ::Crc32 SwitchToStiffnessSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtostiffness");
const AZ::Crc32 SwitchToStiffnessSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtostiffness");
static const char* StiffnessTitle = "Switch to Stiffness Mode";
static const char* StiffnessToolTip = "Stiffness Mode - Change the stiffness strength of the joint when beyond the limit.";
const AZ::Crc32 SwitchToTwistLimitsSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtotwistlimits");
const AZ::Crc32 SwitchToTwistLimitsSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtotwistlimits");
static const char* TwistLimitsTitle = "Switch to Twist Limits Mode";
static const char* TwistLimitsToolTip = "Twist Limits Mode - Change the limits of the joint.";
const AZ::Crc32 SwitchToSwingLimitsSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtoswinglimits");
const AZ::Crc32 SwitchToSwingLimitsSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtoswinglimits");
static const char* SwingLimitsTitle = "Switch to Swing Limits Mode";
static const char* SwingLimitsToolTip = "Swing Limits Mode - Change the limits of the joint.";
const AZ::Crc32 SwitchToSnapPositionSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtosnapposition");
const AZ::Crc32 SwitchToSnapPositionSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtosnapposition");
static const char* SnapPositionTitle = "Switch to Snap Position Mode";
static const char* SnapPositionToolTip = "Snap Position Mode - Snap the position of the joint to another Entity.";
const AZ::Crc32 SwitchToSnapRotationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtosnaprotation");
const AZ::Crc32 SwitchToSnapRotationSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.switchtosnaprotation");
static const char* SnapRotationTitle = "Switch to Snap Rotation Mode";
static const char* SnapRotationToolTip = "Snap Rotation Mode - Snap the rotation of the joint toward another Entity.";
const AZ::Crc32 ResetSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.resetsubmode");
const AZ::Crc32 ResetSubMode = AZ_CRC_CE("org.o3de.action.physx.joints.resetsubmode");
static const char* ResetTitle = "Reset Current Mode";
static const char* ResetToolTip = "Reset changes made during this mode edit.";
@@ -44,13 +44,13 @@ namespace Terrain
AZ_Error(TerrainMeshManagerName, false, "Failed to create Terrain render buffers!");
return;
}
OnTerrainDataChanged(AZ::Aabb::CreateNull(), TerrainDataChangedMask::HeightData);
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect();
m_isInitialized = true;
}
bool TerrainMeshManager::IsInitialized() const
{
return m_isInitialized;
@@ -64,7 +64,7 @@ namespace Terrain
m_rebuildSectors = true;
m_isInitialized = false;
}
bool TerrainMeshManager::CheckRebuildSurfaces(MaterialInstance materialInstance, AZ::RPI::Scene& parentScene)
{
if (!m_rebuildSectors)
@@ -84,7 +84,7 @@ namespace Terrain
const float xLastPatchStart = AZStd::floorf(m_worldBounds.GetMax().GetX() / GridMeters) * GridMeters;
const float yFirstPatchStart = AZStd::floorf(m_worldBounds.GetMin().GetY() / GridMeters) * GridMeters;
const float yLastPatchStart = AZStd::floorf(m_worldBounds.GetMax().GetY() / GridMeters) * GridMeters;
const auto& materialAsset = materialInstance->GetAsset();
const auto& shaderAsset = materialAsset->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg();
@@ -101,7 +101,7 @@ namespace Terrain
for (auto& lod : m_patchModel->GetLods())
{
objectSrgData.m_xyScale = m_sampleSpacing * GridSize;
auto objectSrg = AZ::RPI::ShaderResourceGroup::Create(shaderAsset, materialAsset->GetObjectSrgLayout()->GetName());
if (!objectSrg)
{
@@ -114,7 +114,7 @@ namespace Terrain
AZ::RPI::ModelLod& modelLod = *lod.get();
sectorData.m_drawPackets.emplace_back(modelLod, 0, materialInstance, objectSrg);
AZ::RPI::MeshDrawPacket& drawPacket = sectorData.m_drawPackets.back();
sectorData.m_srgs.emplace_back(objectSrg);
// set the shader option to select forward pass IBL specular if necessary
@@ -136,7 +136,7 @@ namespace Terrain
}
return true;
}
void TerrainMeshManager::DrawMeshes(const AZ::RPI::FeatureProcessor::RenderPacket& process)
{
for (auto& sectorData : m_sectorData)
@@ -194,7 +194,7 @@ namespace Terrain
{
Reset();
}
void TerrainMeshManager::OnTerrainDataChanged([[maybe_unused]] const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask)
{
if ((dataChangedMask & (TerrainDataChangedMask::HeightData | TerrainDataChangedMask::Settings)) != 0)
@@ -202,7 +202,7 @@ namespace Terrain
AZ::Aabb worldBounds = AZ::Aabb::CreateNull();
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(
worldBounds, &AzFramework::Terrain::TerrainDataRequests::GetTerrainAabb);
AZ::Vector2 queryResolution2D = AZ::Vector2(1.0f);
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(
queryResolution2D, &AzFramework::Terrain::TerrainDataRequests::GetTerrainHeightQueryResolution);
@@ -241,7 +241,7 @@ namespace Terrain
}
patchdata.m_indices.reserve(gridSize * gridSize * 6); // total number of quads, 2 triangles with 6 indices per quad.
for (uint16_t y = 0; y < gridSize; ++y)
{
for (uint16_t x = 0; x < gridSize; ++x)
@@ -260,7 +260,7 @@ namespace Terrain
}
}
}
AZ::Outcome<AZ::Data::Asset<AZ::RPI::BufferAsset>> TerrainMeshManager::CreateBufferAsset(
const void* data, const AZ::RHI::BufferViewDescriptor& bufferViewDescriptor, const AZStd::string& bufferName)
{
@@ -291,7 +291,6 @@ namespace Terrain
modelAssetCreator.Begin(AZ::Uuid::CreateRandom());
uint16_t gridSize = GridSize;
[[maybe_unused]] float gridSpacing = GridSpacing;
for (uint32_t i = 0; i < AZ::RPI::ModelLodAsset::LodCountMax && gridSize > 0; ++i)
{
@@ -300,7 +299,7 @@ namespace Terrain
const auto positionBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast<uint32_t>(patchData.m_positions.size()), AZ::RHI::Format::R32G32_FLOAT);
const auto positionsOutcome = CreateBufferAsset(patchData.m_positions.data(), positionBufferViewDesc, "TerrainPatchPositions");
const auto indexBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast<uint32_t>(patchData.m_indices.size()), AZ::RHI::Format::R16_UINT);
const auto indicesOutcome = CreateBufferAsset(patchData.m_indices.data(), indexBufferViewDesc, "TerrainPatchIndices");
@@ -309,7 +308,7 @@ namespace Terrain
AZ_Error(TerrainMeshManagerName, false, "Failed to create GPU buffers for Terrain");
return false;
}
AZ::RPI::ModelLodAssetCreator modelLodAssetCreator;
modelLodAssetCreator.Begin(AZ::Uuid::CreateRandom());
@@ -324,11 +323,10 @@ namespace Terrain
AZ::Data::Asset<AZ::RPI::ModelLodAsset> modelLodAsset;
modelLodAssetCreator.End(modelLodAsset);
modelAssetCreator.AddLodAsset(AZStd::move(modelLodAsset));
gridSize = gridSize / 2;
gridSpacing *= 2.0f;
}
AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset;
@@ -338,7 +336,7 @@ namespace Terrain
return success;
}
template<typename Callback>
void TerrainMeshManager::ForOverlappingSectors(const AZ::Aabb& bounds, Callback callback)
{
+3 -3
View File
@@ -40,6 +40,6 @@ ly_add_target(
)
# the virtual gamepad is needed everywhere except servers:
ly_create_alias(NAME VirtualGamepad.Clients NAMESPACE Gem TARGETS Gem::VirtualGamepad)
ly_create_alias(NAME VirtualGamepad.Tools NAMESPACE Gem TARGETS Gem::VirtualGamepad)
ly_create_alias(NAME VirtualGamepad.Builders NAMESPACE Gem TARGETS Gem::VirtualGamepad Gem::UiBasics.Builders)
ly_create_alias(NAME VirtualGamepad.Clients NAMESPACE Gem TARGETS Gem::VirtualGamepad Gem::LyShine.Clients)
ly_create_alias(NAME VirtualGamepad.Tools NAMESPACE Gem TARGETS Gem::VirtualGamepad Gem::LyShine.Tools)
ly_create_alias(NAME VirtualGamepad.Builders NAMESPACE Gem TARGETS Gem::VirtualGamepad Gem::UiBasics.Builders Gem::LyShine.Builders)
+1 -1
View File
@@ -17,5 +17,5 @@
"icon_path": "preview.png",
"requirements": "",
"documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/virtual-gamepad/",
"dependencies": []
"dependencies": ["LyShine", "UiBasics"]
}
@@ -33,8 +33,8 @@ namespace WhiteBox
AZ::Color, cl_whiteBoxVertexIndicatorColor, AZ::Color::CreateFromRgba(0, 0, 0, 102), nullptr,
AZ::ConsoleFunctorFlags::Null, "The color of the vertex indicator");
static const AZ::Crc32 HideEdge = AZ_CRC("com.o3de.action.whitebox.hide_edge", 0x84f6a9b9);
static const AZ::Crc32 HideVertex = AZ_CRC("com.o3de.action.whitebox.hide_vertex", 0x5f81c937);
static const AZ::Crc32 HideEdge = AZ_CRC_CE("org.o3de.action.whitebox.hide_edge");
static const AZ::Crc32 HideVertex = AZ_CRC_CE("org.o3de.action.whitebox.hide_vertex");
static const char* const HideEdgeTitle = "Hide Edge";
static const char* const HideEdgeDesc = "Hide the selected edge to merge the two connected polygons";
@@ -1,7 +1,7 @@
{
"Tags": ["Android"],
"android_settings" : {
"package_name" : "com.lumberyard.${Name}",
"package_name" : "org.o3de.${Name}",
"version_number" : 1,
"version_name" : "1.0.0.0",
"orientation" : "landscape"
@@ -1,7 +1,7 @@
{
"Tags": ["Android"],
"android_settings" : {
"package_name" : "com.lumberyard.${Name}",
"package_name" : "org.o3de.${Name}",
"version_number" : 1,
"version_name" : "1.0.0.0",
"orientation" : "landscape"
+2 -2
View File
@@ -19,8 +19,8 @@ function(ly_apply_platform_properties target)
set_target_properties(${target}
PROPERTIES
FRAMEWORK TRUE
MACOSX_FRAMEWORK_IDENTIFIER "com.lumberyard.lib.${target_name}"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.lumberyard.lib.${target_name}"
MACOSX_FRAMEWORK_IDENTIFIER "org.o3de.lib.${target_name}"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.o3de.lib.${target_name}"
XCODE_ATTRIBUTE_SKIP_INSTALL "YES"
)
endif()
@@ -415,7 +415,7 @@ class AndroidDeployment(object):
android_package_name = android_support.TEST_RUNNER_PACKAGE_NAME
else:
android_package_name = self.get_android_project_settings(key_name='package_name',
default_value='com.lumberyard.sdk')
default_value='org.o3de.sdk')
if self.clean_deploy and self.check_package_installed(android_package_name, target_device):
logging.info(f"Device '{target_device}': Uninstalling pre-existing APK for {self.game_name} ...")
@@ -436,7 +436,7 @@ class AndroidDeployment(object):
assert not self.is_test_project
android_package_name = self.get_android_project_settings(key_name='package_name',
default_value='com.lumberyard.sdk')
default_value='org.o3de.sdk')
relative_assets_path = f'Android/data/{android_package_name}/files'
output_target = f'{detected_storage}/{relative_assets_path}'
device_timestamp_file = f'{output_target}/{ANDROID_TARGET_TIMESTAMP_FILENAME}'
@@ -539,7 +539,7 @@ class AndroidDeployment(object):
if self.deployment_type == AndroidDeployment.DEPLOY_ASSETS_ONLY:
# If we are deploying assets only without an APK, make sure the APK is even installed first
android_package_name = self.get_android_project_settings(key_name='package_name',
default_value='com.lumberyard.sdk')
default_value='org.o3de.sdk')
if not self.check_package_installed(package_name=android_package_name,
target_device=target_device):
raise common.LmbrCmdError(f"Unable to locate APK for {self.game_name} on device '{target_device}'. Make sure it is installed "
@@ -61,7 +61,7 @@ DEFAULT_CONFIG_CHANGES = [
]
TEST_RUNNER_PROJECT = 'AzTestRunner'
TEST_RUNNER_PACKAGE_NAME = 'com.lumberyard.tests'
TEST_RUNNER_PACKAGE_NAME = 'org.o3de.tests'
# Android Orientation Constants
ORIENTATION_LANDSCAPE = 1 << 0
@@ -89,14 +89,14 @@ def launch_test_on_device(adb_tool, test_module, timeout_secs, test_filter):
"""
# Clear user data before each test
adb_tool.exec(['shell', 'pm', 'clear', 'com.lumberyard.tests'])
adb_tool.exec(['shell', 'pm', 'clear', 'org.o3de.tests'])
# Increase the log buffer to prevent 'end of file' error from logcat
adb_tool.exec(['shell', 'logcat', '-G', f'{LOGCAT_BUFFER_SIZE_MB}M'])
# Start the test activity
exec_args = ['shell', 'am', 'start',
'-n', f'com.lumberyard.tests/.{TEST_ACTIVITY}',
'-n', f'org.o3de.tests/.{TEST_ACTIVITY}',
'--es', test_module, 'AzRunUnitTests',
'--es', 'startdelay', str(TEST_RUNNER_STARTUP_DELAY)]
if test_filter:
@@ -117,7 +117,7 @@ def launch_test_on_device(adb_tool, test_module, timeout_secs, test_filter):
# Make multiple attempts to get the PID of the test process
max_pid_retries = 5
while max_pid_retries > 0:
ret, result_pid, _ = adb_tool.exec(['shell', 'pidof', '-s', 'com.lumberyard.tests'], capture_stdout=True)
ret, result_pid, _ = adb_tool.exec(['shell', 'pidof', '-s', 'org.o3de.tests'], capture_stdout=True)
if ret == 0:
break
time.sleep(1)
@@ -139,7 +139,7 @@ def launch_test_on_device(adb_tool, test_module, timeout_secs, test_filter):
break
# Break out of the loop in case the process dies unexpectly
ret, _, _ = adb_tool.exec(['shell', 'pidof', '-s', 'com.lumberyard.tests'], capture_stdout=True)
ret, _, _ = adb_tool.exec(['shell', 'pidof', '-s', 'org.o3de.tests'], capture_stdout=True)
if ret != 0:
break
@@ -161,7 +161,7 @@ def launch_test_on_device(adb_tool, test_module, timeout_secs, test_filter):
if result_pid:
adb_tool.exec(['shell', 'logcat', f'--pid={result_pid}', '-c'])
# Kill the test launcher process
adb_tool.exec(['shell', 'am', 'force-stop', 'com.lumberyard.tests'])
adb_tool.exec(['shell', 'am', 'force-stop', 'org.o3de.tests'])
time.sleep(2)
return tests_passed
@@ -586,14 +586,14 @@ def test_update_device_file_timestamp(tmpdir):
@pytest.mark.parametrize(
"test_config, test_package_name, test_device_storage_path", [
pytest.param('profile', 'com.amazon.lumberyard.foo', '/data/fool_storage'),
pytest.param('debug', 'com.amazon.lumberyard.foo', '/data/fool_storage'),
pytest.param('profile', 'com.amazon.lumberyard.bar', '/data/fool_storage'),
pytest.param('debug', 'com.amazon.lumberyard.bar', '/data/fool_storage'),
pytest.param('profile', 'com.amazon.lumberyard.foo', '/data/fool_storage2'),
pytest.param('debug', 'com.amazon.lumberyard.foo', '/data/fool_storage2'),
pytest.param('profile', 'com.amazon.lumberyard.bar', '/data/fool_storage2'),
pytest.param('debug', 'com.amazon.lumberyard.bar', '/data/fool_storage2')
pytest.param('profile', 'org.o3de.foo', '/data/fool_storage'),
pytest.param('debug', 'org.o3de.foo', '/data/fool_storage'),
pytest.param('profile', 'org.o3de.bar', '/data/fool_storage'),
pytest.param('debug', 'org.o3de.bar', '/data/fool_storage'),
pytest.param('profile', 'org.o3de.foo', '/data/fool_storage2'),
pytest.param('debug', 'org.o3de.foo', '/data/fool_storage2'),
pytest.param('profile', 'org.o3de.bar', '/data/fool_storage2'),
pytest.param('debug', 'org.o3de.bar', '/data/fool_storage2')
]
)
def test_execute_success(tmpdir, test_config, test_package_name, test_device_storage_path):
@@ -658,14 +658,14 @@ def test_execute_success(tmpdir, test_config, test_package_name, test_device_sto
@pytest.mark.parametrize(
"test_game_name, test_config, test_package_name, test_device_storage_path, test_asset_type", [
pytest.param('game1','profile', 'com.amazon.lumberyard.foo', '/data/fool_storage', 'android'),
pytest.param('game1','debug', 'com.amazon.lumberyard.foo', '/data/fool_storage', 'android'),
pytest.param('game2','profile', 'com.amazon.lumberyard.bar', '/data/fool_storage', 'android'),
pytest.param('game2','debug', 'com.amazon.lumberyard.bar', '/data/fool_storage', 'android'),
pytest.param('game3','profile', 'com.amazon.lumberyard.foo', '/data/fool_storage2', 'pc'),
pytest.param('game3','debug', 'com.amazon.lumberyard.foo', '/data/fool_storage2', 'pc'),
pytest.param('game4','profile', 'com.amazon.lumberyard.bar', '/data/fool_storage2', 'pc'),
pytest.param('game4','debug', 'com.amazon.lumberyard.bar', '/data/fool_storage2', 'pc')
pytest.param('game1','profile', 'org.o3de.foo', '/data/fool_storage', 'android'),
pytest.param('game1','debug', 'org.o3de.foo', '/data/fool_storage', 'android'),
pytest.param('game2','profile', 'org.o3de.bar', '/data/fool_storage', 'android'),
pytest.param('game2','debug', 'org.o3de.bar', '/data/fool_storage', 'android'),
pytest.param('game3','profile', 'org.o3de.foo', '/data/fool_storage2', 'pc'),
pytest.param('game3','debug', 'org.o3de.foo', '/data/fool_storage2', 'pc'),
pytest.param('game4','profile', 'org.o3de.bar', '/data/fool_storage2', 'pc'),
pytest.param('game4','debug', 'org.o3de.bar', '/data/fool_storage2', 'pc')
]
)
def test_execute_clean_deploy_success(tmpdir, test_game_name, test_config, test_package_name, test_device_storage_path, test_asset_type):
@@ -754,14 +754,14 @@ def test_execute_clean_deploy_success(tmpdir, test_game_name, test_config, test_
@pytest.mark.parametrize(
"test_config, test_package_name, test_device_storage_path", [
pytest.param('profile', 'com.amazon.lumberyard.foo', '/data/fool_storage'),
pytest.param('debug', 'com.amazon.lumberyard.foo', '/data/fool_storage'),
pytest.param('profile', 'com.amazon.lumberyard.bar', '/data/fool_storage'),
pytest.param('debug', 'com.amazon.lumberyard.bar', '/data/fool_storage'),
pytest.param('profile', 'com.amazon.lumberyard.foo', '/data/fool_storage2'),
pytest.param('debug', 'com.amazon.lumberyard.foo', '/data/fool_storage2'),
pytest.param('profile', 'com.amazon.lumberyard.bar', '/data/fool_storage2'),
pytest.param('debug', 'com.amazon.lumberyard.bar', '/data/fool_storage2')
pytest.param('profile', 'org.o3de.foo', '/data/fool_storage'),
pytest.param('debug', 'org.o3de.foo', '/data/fool_storage'),
pytest.param('profile', 'org.o3de.bar', '/data/fool_storage'),
pytest.param('debug', 'org.o3de.bar', '/data/fool_storage'),
pytest.param('profile', 'org.o3de.foo', '/data/fool_storage2'),
pytest.param('debug', 'org.o3de.foo', '/data/fool_storage2'),
pytest.param('profile', 'org.o3de.bar', '/data/fool_storage2'),
pytest.param('debug', 'org.o3de.bar', '/data/fool_storage2')
]
)
def test_execute_incremental_deploy_success(tmpdir, test_config, test_package_name, test_device_storage_path):
+2 -2
View File
@@ -122,9 +122,9 @@ def determine_engine_root(starting_path=None):
def get_config_file_values(config_file_path, keys_to_extract):
"""
Read a lumberyard config file and extract specific keys if they are set
Read an o3de config file and extract specific keys if they are set
@param config_file_path: The lumberyard config file to parse
@param config_file_path: The o3de config file to parse
@param keys_to_extract: The specific keys to lookup the values if set
@return: Dictionary of keys and its values (for matched keys)
"""
+1 -1
View File
@@ -173,7 +173,7 @@ TEST_GAME_PROJECT_JSON_FORMAT = """
"project_id": "{{4F3363D3-4A7C-47A6-B464-B21524771358}}",
"android_settings" : {{
"package_name" : "com.lumberyard.yourgame",
"package_name" : "org.o3de.yourgame",
"version_number" : 1,
"version_name" : "1.0.0.0",
"orientation" : "landscape"
@@ -36,8 +36,8 @@ requests==2.25.1 \
traceback2==1.4.0 \
--hash=sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030 \
--hash=sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23
urllib3==1.26.4 \
--hash=sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df \
--hash=sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937
urllib3==1.26.5 \
--hash=sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c \
--hash=sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098
tempfile2==0.1.1 \
--hash=sha256:77fdd256c16804053d3d588168b79595099ea5e874c3fb171893b0ababd10340

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