diff --git a/VERSION b/VERSION index 989b29cc3..d721c7684 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.32.2 +0.32.3 diff --git a/include/aws/crt/Optional.h b/include/aws/crt/Optional.h index 220b652d6..1a7e24a90 100644 --- a/include/aws/crt/Optional.h +++ b/include/aws/crt/Optional.h @@ -3,6 +3,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ +#include #include #include @@ -17,6 +18,8 @@ namespace Aws template class Optional { public: + using ValueType = T; + Optional() : m_value(nullptr) {} Optional(const T &val) { @@ -38,7 +41,15 @@ namespace Aws } } - template Optional &operator=(U &&u) + /** + * Assignment operator for a case when the parameter type is not Optional. + */ + template < + typename U = T, + typename std::enable_if< + !IsSpecializationOf::type, Aws::Crt::Optional>::value, + bool>::type = true> + Optional &operator=(U &&u) { if (m_value) { @@ -84,98 +95,11 @@ namespace Aws m_value = reinterpret_cast(m_storage); } - Optional &operator=(const Optional &other) - { - if (this == &other) - { - return *this; - } - - if (m_value) - { - if (other.m_value) - { - *m_value = *other.m_value; - } - else - { - m_value->~T(); - m_value = nullptr; - } - - return *this; - } - - if (other.m_value) - { - new (m_storage) T(*other.m_value); - m_value = reinterpret_cast(m_storage); - } - - return *this; - } - - template Optional &operator=(const Optional &other) - { - if (this == &other) - { - return *this; - } - - if (m_value) - { - if (other.m_value) - { - *m_value = *other.m_value; - } - else - { - m_value->~T(); - m_value = nullptr; - } - - return *this; - } - - if (other.m_value) - { - new (m_storage) T(*other.m_value); - m_value = reinterpret_cast(m_storage); - } - - return *this; - } - - template Optional &operator=(Optional &&other) - { - if (this == &other) - { - return *this; - } - - if (m_value) - { - if (other.m_value) - { - *m_value = std::forward(*other.m_value); - } - else - { - m_value->~T(); - m_value = nullptr; - } - - return *this; - } + Optional &operator=(const Optional &other) { return assign(other); } - if (other.m_value) - { - new (m_storage) T(std::forward(*other.m_value)); - m_value = reinterpret_cast(m_storage); - } + template Optional &operator=(const Optional &other) { return assign(other); } - return *this; - } + template Optional &operator=(Optional &&other) { return assign(std::move(other)); } template T &emplace(Args &&...args) { @@ -213,6 +137,47 @@ namespace Aws } private: + template Optional &assign(Op &&other) + { + // U is an underlying type of the Optional type passed to this function. Depending on constness of Op, + // U will be either value or const ref. + // NOTE: std::is_const == false, that's why std::remove_reference is needed here. + using U = typename std::conditional< + std::is_const::type>::value, + const typename std::decay::type::ValueType &, + typename std::decay::type::ValueType>::type; + + if ((void *)this == (void *)&other) + { + return *this; + } + + if (m_value) + { + // Optional is a completely different class from the C++ specifics pov. So, we can use only + // public members of `other`. + if (other.has_value()) + { + *m_value = std::forward(other.value()); + } + else + { + m_value->~T(); + m_value = nullptr; + } + + return *this; + } + + if (other.has_value()) + { + new (m_storage) T(std::forward(other.value())); + m_value = reinterpret_cast(m_storage); + } + + return *this; + } + alignas(T) char m_storage[sizeof(T)]; T *m_value; }; diff --git a/include/aws/crt/StringView.h b/include/aws/crt/StringView.h index 3b6dc2f0f..730c1391e 100644 --- a/include/aws/crt/StringView.h +++ b/include/aws/crt/StringView.h @@ -820,25 +820,35 @@ namespace Aws { inline namespace string_view_literals { - inline basic_string_view operator"" _sv(const char *s, size_t length) noexcept +#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 8) +/* On GCC <= 4.8, use old syntax for literal operator (with space after ""). It can't do the modern syntax */ +# define OPERATOR_LITERAL_SV operator"" _sv +#else +/* else use modern syntax (no space after "") to avoid -Wdeprecated-literal-operator warning on Clang 16+ */ +# define OPERATOR_LITERAL_SV operator""_sv +#endif + + inline basic_string_view OPERATOR_LITERAL_SV(const char *s, size_t length) noexcept { return basic_string_view(s, length); } - inline basic_string_view operator"" _sv(const wchar_t * s, size_t length) noexcept + inline basic_string_view OPERATOR_LITERAL_SV(const wchar_t *s, size_t length) noexcept { return basic_string_view(s, length); } - inline basic_string_view operator"" _sv(const char16_t *s, size_t length) noexcept + inline basic_string_view OPERATOR_LITERAL_SV(const char16_t *s, size_t length) noexcept { return basic_string_view(s, length); } - inline basic_string_view operator"" _sv(const char32_t *s, size_t length) noexcept + inline basic_string_view OPERATOR_LITERAL_SV(const char32_t *s, size_t length) noexcept { return basic_string_view(s, length); } + +#undef OPERATOR_LITERAL_SV } // namespace string_view_literals } // namespace literals diff --git a/include/aws/crt/TypeTraits.h b/include/aws/crt/TypeTraits.h new file mode 100644 index 000000000..72ed9d9a6 --- /dev/null +++ b/include/aws/crt/TypeTraits.h @@ -0,0 +1,30 @@ +#pragma once +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include + +namespace Aws +{ + namespace Crt + { + /** + * A type trait for determining if the first template parameter is a template specialization of the second + * template parameter. Based on p2098 (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2098r1.pdf). + * + * @note Known limitations: does not support template classes with non-type template parameter, e.g. std::array. + */ + template class Primary> struct IsSpecializationOf : std::false_type + { + }; + + /* Specialization for the case when the first template parameter is a template specialization of the second + * template parameter. */ + template