diff --git a/include/etl/optional.h b/include/etl/optional.h index fc0db4f7..c7958dfb 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -127,7 +127,7 @@ namespace etl /// Constructor. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl() + optional_impl() ETL_NOEXCEPT : storage() { } @@ -136,7 +136,7 @@ namespace etl /// Constructor with nullopt. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl(etl::nullopt_t) + optional_impl(etl::nullopt_t) ETL_NOEXCEPT : storage() { } @@ -146,7 +146,7 @@ namespace etl /// Copy constructor. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl(const optional_impl& other) + optional_impl(const optional_impl& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { if (other.has_value()) { @@ -160,7 +160,7 @@ namespace etl /// Move constructor. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl(optional_impl&& other) + optional_impl(optional_impl&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { if (other.has_value()) { @@ -177,7 +177,7 @@ namespace etl typename etl::enable_if< etl::is_constructible::value && !etl::is_same::type, etl::in_place_t>::value && !etl::is_same::type, optional_impl>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional_impl(U&& value_) + ETL_CONSTEXPR20_STL optional_impl(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(value_)); } @@ -186,7 +186,7 @@ namespace etl /// Constructor from variadic args. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional_impl(etl::in_place_t, TArgs&&... args) + ETL_CONSTEXPR20_STL optional_impl(etl::in_place_t, TArgs&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(args)...); } @@ -197,6 +197,7 @@ namespace etl //******************************************* template ETL_CONSTEXPR20_STL optional_impl(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) { storage.construct(ilist, etl::forward(args)...); } @@ -207,7 +208,7 @@ namespace etl /// Destructor. //*************************************************************************** ETL_CONSTEXPR20_STL - ~optional_impl() + ~optional_impl() ETL_NOEXCEPT { storage.destroy(); } @@ -216,7 +217,7 @@ namespace etl /// Assignment operator from nullopt. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl& operator=(etl::nullopt_t) + optional_impl& operator=(etl::nullopt_t) ETL_NOEXCEPT { if (has_value()) { @@ -230,7 +231,7 @@ namespace etl /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl& operator=(const optional_impl& other) + optional_impl& operator=(const optional_impl& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { if (this != &other) { @@ -252,7 +253,7 @@ namespace etl /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR20_STL - optional_impl& operator=(optional_impl&& other) + optional_impl& operator=(optional_impl&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { if (this != &other) { @@ -277,7 +278,7 @@ namespace etl template ::value && !etl::is_same::type, optional_impl>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional_impl& operator=(U&& value_) + ETL_CONSTEXPR20_STL optional_impl& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(value_)); @@ -488,7 +489,7 @@ namespace etl /// Reset back to invalid. //*************************************************************************** ETL_CONSTEXPR20_STL - void reset() + void reset() ETL_NOEXCEPT { storage.destroy(); } @@ -518,7 +519,7 @@ namespace etl template < typename U, typename... URest, typename etl::enable_if< !etl::is_base_of< optional_impl, typename etl::remove_cv< typename etl::remove_reference::type>::type>::value, int>::type = 0> - ETL_CONSTEXPR20_STL T& emplace(U&& first, URest&&... rest) + ETL_CONSTEXPR20_STL T& emplace(U&& first, URest&&... rest) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { storage.construct(etl::forward(first), etl::forward(rest)...); @@ -529,7 +530,7 @@ namespace etl /// Emplaces with zero arguments, i.e. default construct emplace. //************************************************************************* ETL_CONSTEXPR20_STL - T& emplace() + T& emplace() ETL_NOEXCEPT_IF(etl::is_nothrow_default_constructible::value) { storage.construct(); @@ -735,7 +736,7 @@ namespace etl //*************************************************************************** /// Constructor. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl() + ETL_CONSTEXPR14 optional_impl() ETL_NOEXCEPT : storage() { } @@ -743,7 +744,7 @@ namespace etl //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(etl::nullopt_t) + ETL_CONSTEXPR14 optional_impl(etl::nullopt_t) ETL_NOEXCEPT : storage() { } @@ -752,7 +753,7 @@ namespace etl //*************************************************************************** /// Copy constructor. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(const optional_impl& other) + ETL_CONSTEXPR14 optional_impl(const optional_impl& other) ETL_NOEXCEPT { if (other.has_value()) { @@ -765,7 +766,7 @@ namespace etl //*************************************************************************** /// Move constructor. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(optional_impl&& other) + ETL_CONSTEXPR14 optional_impl(optional_impl&& other) ETL_NOEXCEPT { if (other.has_value()) { @@ -776,7 +777,7 @@ namespace etl //*************************************************************************** /// Constructor from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(const T& value_) + ETL_CONSTEXPR14 optional_impl(const T& value_) ETL_NOEXCEPT { storage.construct(value_); } @@ -784,7 +785,7 @@ namespace etl //*************************************************************************** /// Constructor from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl(T&& value_) + ETL_CONSTEXPR14 optional_impl(T&& value_) ETL_NOEXCEPT { storage.construct(etl::move(value_)); } @@ -793,7 +794,7 @@ namespace etl /// Constructor from variadic args. //*************************************************************************** template - ETL_CONSTEXPR14 optional_impl(etl::in_place_t, TArgs&&... args) + ETL_CONSTEXPR14 optional_impl(etl::in_place_t, TArgs&&... args) ETL_NOEXCEPT { storage.construct(etl::forward(args)...); } @@ -803,7 +804,7 @@ namespace etl /// Construct from initializer_list and arguments. //******************************************* template - ETL_CONSTEXPR14 optional_impl(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_CONSTEXPR14 optional_impl(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) ETL_NOEXCEPT { storage.construct(ilist, etl::forward(args)...); } @@ -813,7 +814,7 @@ namespace etl //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(etl::nullopt_t) + ETL_CONSTEXPR14 optional_impl& operator=(etl::nullopt_t) ETL_NOEXCEPT { if (has_value()) { @@ -826,7 +827,7 @@ namespace etl //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(const optional_impl& other) + ETL_CONSTEXPR14 optional_impl& operator=(const optional_impl& other) ETL_NOEXCEPT { if (this != &other) { @@ -847,7 +848,7 @@ namespace etl //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(optional_impl&& other) + ETL_CONSTEXPR14 optional_impl& operator=(optional_impl&& other) ETL_NOEXCEPT { if (this != &other) { @@ -868,7 +869,7 @@ namespace etl //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(const T& value_) + ETL_CONSTEXPR14 optional_impl& operator=(const T& value_) ETL_NOEXCEPT { storage.construct(value_); @@ -879,7 +880,7 @@ namespace etl //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** - ETL_CONSTEXPR14 optional_impl& operator=(T&& value_) + ETL_CONSTEXPR14 optional_impl& operator=(T&& value_) ETL_NOEXCEPT { storage.construct(etl::move(value_)); @@ -1058,7 +1059,7 @@ namespace etl //*************************************************************************** /// Swaps this value with another. //*************************************************************************** - ETL_CONSTEXPR14 void swap(optional_impl& other) + ETL_CONSTEXPR14 void swap(optional_impl& other) ETL_NOEXCEPT { optional_impl temp(*this); *this = other; @@ -1068,7 +1069,7 @@ namespace etl //*************************************************************************** /// Reset back to invalid. //*************************************************************************** - ETL_CONSTEXPR14 void reset() + ETL_CONSTEXPR14 void reset() ETL_NOEXCEPT { storage.destroy(); } @@ -1094,7 +1095,7 @@ namespace etl ///\param args The arguments to construct with. //************************************************************************* template - ETL_CONSTEXPR14 T& emplace(TArgs&&... args) + ETL_CONSTEXPR14 T& emplace(TArgs&&... args) ETL_NOEXCEPT { storage.construct(etl::forward(args)...); @@ -1286,7 +1287,7 @@ namespace etl /// Constructor. //*************************************************************************** template - ETL_CONSTEXPR14 optional() + ETL_CONSTEXPR14 optional() ETL_NOEXCEPT : impl_t() { } @@ -1295,12 +1296,12 @@ namespace etl /// Constructor. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional() + ETL_CONSTEXPR20_STL optional() ETL_NOEXCEPT : impl_t() { } #else - optional() + optional() ETL_NOEXCEPT : impl_t() { } @@ -1311,7 +1312,7 @@ namespace etl /// Constructor with nullopt. //*************************************************************************** template - ETL_CONSTEXPR14 optional(etl::nullopt_t) + ETL_CONSTEXPR14 optional(etl::nullopt_t) ETL_NOEXCEPT : impl_t(etl::nullopt) { } @@ -1320,7 +1321,7 @@ namespace etl /// Constructor with nullopt. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional(etl::nullopt_t) + ETL_CONSTEXPR20_STL optional(etl::nullopt_t) ETL_NOEXCEPT : impl_t(etl::nullopt) { } @@ -1328,7 +1329,7 @@ namespace etl //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** - optional(etl::nullopt_t) + optional(etl::nullopt_t) ETL_NOEXCEPT : impl_t(etl::nullopt) { } @@ -1340,7 +1341,7 @@ namespace etl /// Copy constructor. //*************************************************************************** template - ETL_CONSTEXPR14 optional(const optional& other) + ETL_CONSTEXPR14 optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) : impl_t(other) { } @@ -1349,7 +1350,7 @@ namespace etl /// Copy constructor. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional(const optional& other) + ETL_CONSTEXPR20_STL optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) : impl_t(other) { } @@ -1369,8 +1370,8 @@ namespace etl /// Move constructor. //*************************************************************************** template - ETL_CONSTEXPR14 optional(optional&& other) - : impl_t(other) + ETL_CONSTEXPR14 optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) + : impl_t(etl::move(other)) { } @@ -1378,8 +1379,8 @@ namespace etl /// Move constructor. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional(optional&& other) - : impl_t(other) + ETL_CONSTEXPR20_STL optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) + : impl_t(etl::move(other)) { } #endif @@ -1396,7 +1397,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR14 optional(U&& value_) + ETL_CONSTEXPR14 optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::forward(value_)) { } @@ -1410,7 +1411,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && !etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional(U&& value_) + ETL_CONSTEXPR20_STL optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::forward(value_)) { } @@ -1429,7 +1430,7 @@ namespace etl /// Emplace construct from arguments. //*************************************************************************** template - ETL_CONSTEXPR14 explicit optional(etl::in_place_t, Args&&... args) + ETL_CONSTEXPR14 explicit optional(etl::in_place_t, Args&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::in_place_t{}, etl::forward(args)...) { } @@ -1438,7 +1439,7 @@ namespace etl /// Emplace construct from arguments. //*************************************************************************** template - ETL_CONSTEXPR20_STL explicit optional(etl::in_place_t, Args&&... args) + ETL_CONSTEXPR20_STL explicit optional(etl::in_place_t, Args&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) : impl_t(etl::in_place_t{}, etl::forward(args)...) { } @@ -1449,6 +1450,7 @@ namespace etl //******************************************* template ETL_CONSTEXPR14 explicit optional(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : impl_t(etl::in_place_t{}, ilist, etl::forward(args)...) { } @@ -1458,6 +1460,7 @@ namespace etl //******************************************* template ETL_CONSTEXPR20_STL explicit optional(etl::in_place_t, std::initializer_list ilist, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : impl_t(etl::in_place_t{}, ilist, etl::forward(args)...) { } @@ -1469,7 +1472,7 @@ namespace etl /// Assignment operator from nullopt. //*************************************************************************** template - ETL_CONSTEXPR14 optional& operator=(etl::nullopt_t) + ETL_CONSTEXPR14 optional& operator=(etl::nullopt_t) ETL_NOEXCEPT { impl_t::operator=(etl::nullopt); @@ -1480,7 +1483,7 @@ namespace etl /// Assignment operator from nullopt. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional& operator=(etl::nullopt_t) + ETL_CONSTEXPR20_STL optional& operator=(etl::nullopt_t) ETL_NOEXCEPT { impl_t::operator=(etl::nullopt); @@ -1490,7 +1493,7 @@ namespace etl //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** - optional& operator=(etl::nullopt_t) + optional& operator=(etl::nullopt_t) ETL_NOEXCEPT { impl_t::operator=(etl::nullopt); @@ -1503,7 +1506,7 @@ namespace etl /// Assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR14 optional& operator=(const optional& other) + ETL_CONSTEXPR14 optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { impl_t::operator=(other); @@ -1514,7 +1517,7 @@ namespace etl /// Assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional& operator=(const optional& other) + ETL_CONSTEXPR20_STL optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible::value) { impl_t::operator=(other); @@ -1537,7 +1540,7 @@ namespace etl /// Move assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR14 optional& operator=(optional&& other) + ETL_CONSTEXPR14 optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { impl_t::operator=(etl::move(other)); @@ -1548,7 +1551,7 @@ namespace etl /// Move assignment operator from optional. //*************************************************************************** template - ETL_CONSTEXPR20_STL optional& operator=(optional&& other) + ETL_CONSTEXPR20_STL optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible::value) { impl_t::operator=(etl::move(other)); @@ -1565,7 +1568,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR14 optional& operator=(U&& value_) + ETL_CONSTEXPR14 optional& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { impl_t::operator=(etl::forward(value_)); @@ -1580,7 +1583,7 @@ namespace etl && !etl::is_same::type, etl::nullopt_t>::value && !etl::is_pod::type>::value, int>::type = 0> - ETL_CONSTEXPR20_STL optional& operator=(U&& value_) + ETL_CONSTEXPR20_STL optional& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible::value)) { impl_t::operator=(etl::forward(value_)); diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index 5598f896..3a95502a 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -486,7 +486,7 @@ namespace etl /// alternative (index() is zero). //*************************************************************************** #include "diagnostic_uninitialized_push.h" - ETL_CONSTEXPR14 variant() + ETL_CONSTEXPR14 variant() ETL_NOEXCEPT_IF(etl::is_nothrow_default_constructible >::value) { using type = type_from_index<0U>; @@ -501,7 +501,7 @@ namespace etl //*************************************************************************** #include "diagnostic_uninitialized_push.h" template , variant>::value, int> = 0> - ETL_CONSTEXPR14 variant(T&& value) + ETL_CONSTEXPR14 variant(T&& value) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, T&&>::value)) : operation(operation_type< etl::remove_cvref_t, etl::is_copy_constructible >::value, etl::is_move_constructible >::value>::do_operation) , type_id(index_of_type::value) @@ -518,6 +518,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : operation(operation_type< etl::remove_cvref_t, etl::is_copy_constructible >::value, etl::is_move_constructible >::value>::do_operation) , type_id(index_of_type::value) @@ -534,6 +535,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) : type_id(Index) { using type = type_from_index; @@ -552,6 +554,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t, std::initializer_list init, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) : operation(operation_type< etl::remove_cvref_t, etl::is_copy_constructible >::value, etl::is_move_constructible >::value>::do_operation) , type_id(index_of_type::value) @@ -568,6 +571,7 @@ namespace etl #include "diagnostic_uninitialized_push.h" template ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t, std::initializer_list init, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) : type_id(Index) { using type = type_from_index; @@ -585,7 +589,7 @@ namespace etl ///\param other The other variant object to copy. //*************************************************************************** #include "diagnostic_uninitialized_push.h" - ETL_CONSTEXPR14 variant(const variant& other) + ETL_CONSTEXPR14 variant(const variant& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) : operation(other.operation) , type_id(other.type_id) { @@ -605,7 +609,7 @@ namespace etl ///\param other The other variant object to copy. //*************************************************************************** #include "diagnostic_uninitialized_push.h" - ETL_CONSTEXPR14 variant(variant&& other) + ETL_CONSTEXPR14 variant(variant&& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) : operation(other.operation) , type_id(other.type_id) { @@ -623,7 +627,7 @@ namespace etl //*************************************************************************** /// Destructor. //*************************************************************************** - ~variant() + ~variant() ETL_NOEXCEPT { if (!valueless_by_exception()) { @@ -638,7 +642,7 @@ namespace etl /// Emplace by type with variadic constructor parameters. //*************************************************************************** template - T& emplace(TArgs&&... args) + T& emplace(TArgs&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) { static_assert(etl::is_one_of::value, "Unsupported type"); @@ -664,6 +668,7 @@ namespace etl //*************************************************************************** template T& emplace(std::initializer_list il, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) { static_assert(etl::is_one_of::value, "Unsupported type"); @@ -689,6 +694,7 @@ namespace etl //*************************************************************************** template typename etl::variant_alternative_t >& emplace(TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, TArgs...>::value)) { static_assert(Index < sizeof...(TTypes), "Index out of range"); @@ -714,6 +720,7 @@ namespace etl //*************************************************************************** template typename etl::variant_alternative_t >& emplace(std::initializer_list il, TArgs&&... args) + ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, std::initializer_list, TArgs...>::value)) { static_assert(Index < sizeof...(TTypes), "Index out of range"); @@ -739,7 +746,7 @@ namespace etl ///\param value The value to assign. //*************************************************************************** template , variant>::value, int> = 0> - variant& operator=(T&& value) + variant& operator=(T&& value) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible, T&&>::value)) { using type = etl::remove_cvref_t; @@ -762,7 +769,7 @@ namespace etl /// Assignment operator for variant type. ///\param other The variant to assign. //*************************************************************************** - variant& operator=(const variant& other) + variant& operator=(const variant& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) { if (this != &other) { @@ -791,7 +798,7 @@ namespace etl /// Assignment operator for variant type. ///\param other The variant to assign. //*************************************************************************** - variant& operator=(variant&& other) + variant& operator=(variant&& other) ETL_NOEXCEPT_IF((etl::conjunction...>::value)) { if (this != &other) { diff --git a/include/etl/profiles/determine_builtin_support.h b/include/etl/profiles/determine_builtin_support.h index 4a303fc0..b04e96a0 100644 --- a/include/etl/profiles/determine_builtin_support.h +++ b/include/etl/profiles/determine_builtin_support.h @@ -41,6 +41,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_CONSTRUCTIBLE 1 #endif + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE 1 + #endif + + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE 1 + #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1 #endif @@ -93,6 +101,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_CONSTRUCTIBLE __has_builtin(__is_constructible) #endif + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE __has_builtin(__is_nothrow_constructible) + #endif + + #if !defined(ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE __has_builtin(__is_nothrow_assignable) + #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE (__has_builtin(__has_trivial_constructor) || __has_builtin(__is_trivially_constructible)) #endif @@ -143,6 +159,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_CONSTRUCTIBLE 0 #endif +#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE 0 +#endif + +#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE 0 +#endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0 #endif @@ -191,6 +215,8 @@ namespace etl static ETL_CONSTANT bool using_builtin_is_assignable = (ETL_USING_BUILTIN_IS_ASSIGNABLE == 1); static ETL_CONSTANT bool using_builtin_is_constructible = (ETL_USING_BUILTIN_IS_CONSTRUCTIBLE == 1); + static ETL_CONSTANT bool using_builtin_is_nothrow_constructible = (ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE == 1); + static ETL_CONSTANT bool using_builtin_is_nothrow_assignable = (ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE == 1); static ETL_CONSTANT bool using_builtin_is_trivially_constructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE == 1); static ETL_CONSTANT bool using_builtin_is_trivially_destructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE == 1); static ETL_CONSTANT bool using_builtin_is_trivially_copyable = (ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE == 1); diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 411632ff..a6b02867 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -2594,6 +2594,41 @@ namespace etl template using is_move_assignable = std::is_move_assignable; + //********************************************* + // is_nothrow_constructible + template + using is_nothrow_constructible = std::is_nothrow_constructible; + + //********************************************* + // is_nothrow_default_constructible + template + using is_nothrow_default_constructible = std::is_nothrow_default_constructible; + + //********************************************* + // is_nothrow_copy_constructible + template + using is_nothrow_copy_constructible = std::is_nothrow_copy_constructible; + + //********************************************* + // is_nothrow_move_constructible + template + using is_nothrow_move_constructible = std::is_nothrow_move_constructible; + + //********************************************* + // is_nothrow_assignable + template + using is_nothrow_assignable = std::is_nothrow_assignable; + + //********************************************* + // is_nothrow_copy_assignable + template + using is_nothrow_copy_assignable = std::is_nothrow_copy_assignable; + + //********************************************* + // is_nothrow_move_assignable + template + using is_nothrow_move_assignable = std::is_nothrow_move_assignable; + //********************************************* // is_trivially_constructible #if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED @@ -2723,6 +2758,71 @@ namespace etl }; #endif + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_constructible + template + struct is_nothrow_constructible + { + #if ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE + static ETL_CONSTANT bool value = __is_nothrow_constructible(T, TArgs...); + #else + static ETL_CONSTANT bool value = etl::is_arithmetic::value || etl::is_pointer::value; + #endif + }; + + //********************************************* + // is_nothrow_default_constructible + template + struct is_nothrow_default_constructible : public etl::is_nothrow_constructible + { + }; + + //********************************************* + // is_nothrow_copy_constructible + template + struct is_nothrow_copy_constructible : public etl::is_nothrow_constructible::type> + { + }; + + //********************************************* + // is_nothrow_move_constructible + template + struct is_nothrow_move_constructible : public etl::is_nothrow_constructible::type> + { + }; + #endif + + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_assignable + template + struct is_nothrow_assignable + { + #if ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE + static ETL_CONSTANT bool value = __is_nothrow_assignable(T, U); + #else + static ETL_CONSTANT bool value = etl::is_arithmetic::value || etl::is_pointer::value; + #endif + }; + + //********************************************* + // is_nothrow_copy_assignable + template + struct is_nothrow_copy_assignable + : public etl::is_nothrow_assignable::type, typename etl::add_lvalue_reference::type> + { + }; + + //********************************************* + // is_nothrow_move_assignable + template + struct is_nothrow_move_assignable + : public etl::is_nothrow_assignable::type, typename etl::add_rvalue_reference::type> + { + }; + #endif + #if ETL_USING_CPP11 //********************************************* // is_trivially_constructible @@ -2894,6 +2994,104 @@ namespace etl template struct is_move_assignable; + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_constructible + template + struct is_nothrow_constructible_helper; + + template + struct is_nothrow_constructible_helper : public etl::true_type + { + }; + + template + struct is_nothrow_constructible_helper; + + template + struct is_nothrow_constructible : public is_nothrow_constructible_helper::value || etl::is_pointer::value, TArgs...> + { + }; + + //********************************************* + // is_nothrow_default_constructible + template ::value || etl::is_pointer::value> + struct is_nothrow_default_constructible; + + template + struct is_nothrow_default_constructible : public etl::true_type + { + }; + + template + struct is_nothrow_default_constructible; + + //********************************************* + // is_nothrow_copy_constructible + template ::value || etl::is_pointer::value> + struct is_nothrow_copy_constructible; + + template + struct is_nothrow_copy_constructible : public etl::true_type + { + }; + + template + struct is_nothrow_copy_constructible; + + //********************************************* + // is_nothrow_move_constructible + template ::value || etl::is_pointer::value> + struct is_nothrow_move_constructible; + + template + struct is_nothrow_move_constructible : public etl::true_type + { + }; + + template + struct is_nothrow_move_constructible; + + //********************************************* + // is_nothrow_assignable + template ::value || etl::is_pointer::value> + struct is_nothrow_assignable; + + template + struct is_nothrow_assignable : public etl::true_type + { + }; + + template + struct is_nothrow_assignable; + + //********************************************* + // is_nothrow_copy_assignable + template ::value || etl::is_pointer::value> + struct is_nothrow_copy_assignable; + + template + struct is_nothrow_copy_assignable : public etl::true_type + { + }; + + template + struct is_nothrow_copy_assignable; + + //********************************************* + // is_nothrow_move_assignable + template ::value || etl::is_pointer::value> + struct is_nothrow_move_assignable; + + template + struct is_nothrow_move_assignable : public etl::true_type + { + }; + + template + struct is_nothrow_move_assignable; + #endif + //********************************************* // is_trivially_constructible template ::value || etl::is_pointer::value> @@ -3087,6 +3285,57 @@ namespace etl }; #endif + #if ETL_USING_CPP11 + //********************************************* + // is_nothrow_constructible + template + struct is_nothrow_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_default_constructible + template + struct is_nothrow_default_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_copy_constructible + template + struct is_nothrow_copy_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_move_constructible + template + struct is_nothrow_move_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_assignable + template + struct is_nothrow_assignable : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_copy_assignable + template + struct is_nothrow_copy_assignable : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_nothrow_move_assignable + template + struct is_nothrow_move_assignable : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + #endif + //********************************************* // is_trivially_constructible template @@ -3180,6 +3429,27 @@ namespace etl template inline constexpr bool is_move_assignable_v = etl::is_move_assignable::value; + template + inline constexpr bool is_nothrow_constructible_v = etl::is_nothrow_constructible::value; + + template + inline constexpr bool is_nothrow_default_constructible_v = etl::is_nothrow_default_constructible::value; + + template + inline constexpr bool is_nothrow_copy_constructible_v = etl::is_nothrow_copy_constructible::value; + + template + inline constexpr bool is_nothrow_move_constructible_v = etl::is_nothrow_move_constructible::value; + + template + inline constexpr bool is_nothrow_assignable_v = etl::is_nothrow_assignable::value; + + template + inline constexpr bool is_nothrow_copy_assignable_v = etl::is_nothrow_copy_assignable::value; + + template + inline constexpr bool is_nothrow_move_assignable_v = etl::is_nothrow_move_assignable::value; + template inline constexpr bool is_trivially_constructible_v = etl::is_trivially_constructible::value; diff --git a/include/etl/vector.h b/include/etl/vector.h index ba10ac79..ec2b178e 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -1014,7 +1014,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - ivector& operator=(ivector&& rhs) + ivector& operator=(ivector&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) { if (&rhs != this) { @@ -1081,7 +1081,7 @@ namespace etl //********************************************************************* /// Constructor. //********************************************************************* - ivector(T* p_buffer_, size_t MAX_SIZE) + ivector(T* p_buffer_, size_t MAX_SIZE) ETL_NOEXCEPT : vector_base(MAX_SIZE) , p_buffer(p_buffer_) , p_end(p_buffer_) @@ -1284,7 +1284,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector() + vector() ETL_NOEXCEPT : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { this->initialise(); @@ -1363,7 +1363,7 @@ namespace etl //************************************************************************* /// Move constructor. //************************************************************************* - vector(vector&& other) + vector(vector&& other) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { if (this != &other) @@ -1384,7 +1384,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - vector& operator=(vector&& rhs) + vector& operator=(vector&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) { if (&rhs != this) { @@ -1409,7 +1409,7 @@ namespace etl #ifdef ETL_IVECTOR_REPAIR_ENABLE virtual #endif - ~vector() + ~vector() ETL_NOEXCEPT { this->clear(); } @@ -1466,7 +1466,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector_ext(void* buffer, size_t max_size) + vector_ext(void* buffer, size_t max_size) ETL_NOEXCEPT : etl::ivector(reinterpret_cast(buffer), max_size) { this->initialise(); @@ -1546,7 +1546,7 @@ namespace etl //************************************************************************* /// Move constructor. //************************************************************************* - vector_ext(vector_ext&& other, void* buffer, size_t max_size) + vector_ext(vector_ext&& other, void* buffer, size_t max_size) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) : etl::ivector(reinterpret_cast(buffer), max_size) { if (this != &other) @@ -1567,7 +1567,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - vector_ext& operator=(vector_ext&& rhs) + vector_ext& operator=(vector_ext&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible::value)) { if (&rhs != this) { @@ -1590,7 +1590,7 @@ namespace etl //************************************************************************* /// Destructor. //************************************************************************* - ~vector_ext() + ~vector_ext() ETL_NOEXCEPT { this->clear(); } @@ -1625,7 +1625,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector() + vector() ETL_NOEXCEPT : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { this->initialise(); @@ -1701,7 +1701,7 @@ namespace etl //************************************************************************* /// Move constructor. //************************************************************************* - vector(vector&& other) + vector(vector&& other) ETL_NOEXCEPT : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { (void)etl::ivector::operator=(etl::move(other)); @@ -1710,7 +1710,7 @@ namespace etl //************************************************************************* /// Move assignment operator. //************************************************************************* - vector& operator=(vector&& rhs) + vector& operator=(vector&& rhs) ETL_NOEXCEPT { (void)etl::ivector::operator=(etl::move(rhs)); @@ -1765,7 +1765,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - vector_ext(void* buffer, size_t max_size) + vector_ext(void* buffer, size_t max_size) ETL_NOEXCEPT : etl::ivector(reinterpret_cast(buffer), max_size) { this->initialise(); @@ -1872,7 +1872,7 @@ namespace etl //************************************************************************* /// Destructor. //************************************************************************* - ~vector_ext() + ~vector_ext() ETL_NOEXCEPT { this->clear(); } diff --git a/test/test_optional.cpp b/test/test_optional.cpp index a848b0cb..88242053 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include #include #include +#include #include #include "data.h" @@ -1176,5 +1177,164 @@ namespace CHECK_EQUAL(99, opt->_some); } #endif + + //************************************************************************* + // Tests for noexcept properties of etl::optional + // The noexcept specs only take effect when ETL_USING_EXCEPTIONS is enabled, + // because ETL_NOEXCEPT_IF expands to nothing otherwise. + // The etl::is_nothrow_* traits only work with STL or builtins. + //************************************************************************* +#if ETL_USING_CPP11 && ETL_USING_EXCEPTIONS && (defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS))) + struct NothrowCopyMove + { + NothrowCopyMove() noexcept {} + NothrowCopyMove(const NothrowCopyMove&) noexcept {} + NothrowCopyMove(NothrowCopyMove&&) noexcept {} + NothrowCopyMove& operator=(const NothrowCopyMove&) noexcept + { + return *this; + } + NothrowCopyMove& operator=(NothrowCopyMove&&) noexcept + { + return *this; + } + }; + + struct ThrowingCopy + { + ThrowingCopy() noexcept {} + ThrowingCopy(const ThrowingCopy&) {} // may throw + ThrowingCopy(ThrowingCopy&&) noexcept {} + ThrowingCopy& operator=(const ThrowingCopy&) + { + return *this; + } // may throw + ThrowingCopy& operator=(ThrowingCopy&&) noexcept + { + return *this; + } + }; + + struct ThrowingMove + { + ThrowingMove() noexcept {} + ThrowingMove(const ThrowingMove&) noexcept {} + ThrowingMove(ThrowingMove&&) {} // may throw + ThrowingMove& operator=(const ThrowingMove&) noexcept + { + return *this; + } + ThrowingMove& operator=(ThrowingMove&&) + { + return *this; + } // may throw + }; + + struct ThrowingBoth + { + ThrowingBoth() noexcept {} + ThrowingBoth(const ThrowingBoth&) {} // may throw + ThrowingBoth(ThrowingBoth&&) {} // may throw + ThrowingBoth& operator=(const ThrowingBoth&) + { + return *this; + } + ThrowingBoth& operator=(ThrowingBoth&&) + { + return *this; + } + }; + + TEST(test_optional_nothrow_copy_constructible) + { + // When T is nothrow copy constructible, optional should be too + static_assert(etl::is_nothrow_copy_constructible>::value, "optional should be nothrow copy constructible"); + static_assert(etl::is_nothrow_copy_constructible>::value, + "optional should be nothrow copy constructible"); + + // When T is NOT nothrow copy constructible, optional should not be either + static_assert(!etl::is_nothrow_copy_constructible>::value, + "optional should NOT be nothrow copy constructible"); + static_assert(!etl::is_nothrow_copy_constructible>::value, + "optional should NOT be nothrow copy constructible"); + + // ThrowingMove has nothrow copy but throwing move + static_assert(etl::is_nothrow_copy_constructible>::value, + "optional should be nothrow copy constructible"); + + CHECK(true); // Placeholder for the static_asserts above + } + + TEST(test_optional_nothrow_move_constructible) + { + // When T is nothrow move constructible, optional should be too + static_assert(etl::is_nothrow_move_constructible>::value, "optional should be nothrow move constructible"); + static_assert(etl::is_nothrow_move_constructible>::value, + "optional should be nothrow move constructible"); + + // When T is NOT nothrow move constructible, optional should not be either + static_assert(!etl::is_nothrow_move_constructible>::value, + "optional should NOT be nothrow move constructible"); + static_assert(!etl::is_nothrow_move_constructible>::value, + "optional should NOT be nothrow move constructible"); + + // ThrowingCopy has nothrow move but throwing copy + static_assert(etl::is_nothrow_move_constructible>::value, + "optional should be nothrow move constructible"); + + CHECK(true); // Placeholder for the static_asserts above + } + + TEST(test_optional_nothrow_default_constructible) + { + // Default construction of optional should always be noexcept + static_assert(etl::is_nothrow_default_constructible>::value, "optional should be nothrow default constructible"); + static_assert(etl::is_nothrow_default_constructible>::value, + "optional should be nothrow default constructible"); + static_assert(etl::is_nothrow_default_constructible>::value, + "optional should be nothrow default constructible"); + static_assert(etl::is_nothrow_default_constructible>::value, + "optional should be nothrow default constructible"); + + CHECK(true); + } + + TEST(test_optional_nothrow_constructible_from_value) + { + // optional(U&&) should be noexcept iff T is nothrow constructible from U&& + static_assert(etl::is_nothrow_constructible, int>::value, "optional should be nothrow constructible from int"); + static_assert(etl::is_nothrow_constructible, int&&>::value, "optional should be nothrow constructible from int&&"); + + CHECK(true); + } + + TEST(test_optional_nothrow_copy_assignable) + { + // Copy assignment should propagate noexcept from T + static_assert(etl::is_nothrow_copy_assignable>::value, "optional should be nothrow copy assignable"); + static_assert(etl::is_nothrow_copy_assignable>::value, + "optional should be nothrow copy assignable"); + + // ThrowingCopy has a throwing copy constructor, so copy assignment should not be noexcept + static_assert(!etl::is_nothrow_copy_assignable>::value, + "optional should NOT be nothrow copy assignable"); + + CHECK(true); + } + + TEST(test_optional_nothrow_move_assignable) + { + // Move assignment should propagate noexcept from T + static_assert(etl::is_nothrow_move_assignable>::value, "optional should be nothrow move assignable"); + static_assert(etl::is_nothrow_move_assignable>::value, + "optional should be nothrow move assignable"); + + // ThrowingMove has a throwing move constructor, so move assignment should not be noexcept + static_assert(!etl::is_nothrow_move_assignable>::value, + "optional should NOT be nothrow move assignable"); + + CHECK(true); + } +#endif } } // namespace diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index c49b2eda..7b2ab447 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -102,8 +102,8 @@ namespace return *this; } - Copyable(Copyable&&) = delete; - Copyable& operator=(Copyable&) = delete; + Copyable(Copyable&&) = delete; + Copyable& operator=(Copyable&&) = delete; }; //********************************************* @@ -146,8 +146,8 @@ namespace return *this; } - NotDefaultConstructible(NotDefaultConstructible&&) = delete; - NotDefaultConstructible& operator=(NotDefaultConstructible&) = delete; + NotDefaultConstructible(NotDefaultConstructible&&) = delete; + NotDefaultConstructible& operator=(NotDefaultConstructible&&) = delete; }; // A function to test etl::type_identity. @@ -344,7 +344,7 @@ using etl::is_move_constructible; //************************* template <> -struct etl::is_assignable : public etl::true_type +struct etl::is_assignable : public etl::false_type { }; @@ -364,7 +364,7 @@ struct etl::is_copy_assignable : public etl::true_type }; template <> -struct etl::is_move_assignable : public etl::true_type +struct etl::is_move_assignable : public etl::false_type { }; @@ -1490,6 +1490,155 @@ namespace #endif } + //************************************************************************* + TEST(test_is_nothrow_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_constructible::value) == true); + CHECK((etl::is_nothrow_constructible::value) == false); + CHECK((etl::is_nothrow_constructible::value) == false); + CHECK((etl::is_nothrow_constructible::value) == false); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + CHECK((etl::is_nothrow_constructible::value) == (std::is_nothrow_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + CHECK((etl::is_nothrow_constructible_v) == (std::is_nothrow_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_default_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_default_constructible::value) == true); + CHECK((etl::is_nothrow_default_constructible::value) == false); + CHECK((etl::is_nothrow_default_constructible::value) == false); + CHECK((etl::is_nothrow_default_constructible::value) == false); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + CHECK((etl::is_nothrow_default_constructible::value) == (std::is_nothrow_default_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + CHECK((etl::is_nothrow_default_constructible_v) == (std::is_nothrow_default_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_copy_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_copy_constructible::value) == true); + CHECK((etl::is_nothrow_copy_constructible::value) == true); + CHECK((etl::is_nothrow_copy_constructible::value) == false); + CHECK((etl::is_nothrow_copy_constructible::value) == false); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + CHECK((etl::is_nothrow_copy_constructible::value) == (std::is_nothrow_copy_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + CHECK((etl::is_nothrow_copy_constructible_v) == (std::is_nothrow_copy_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_move_constructible) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_move_constructible::value) == true); + CHECK((etl::is_nothrow_move_constructible::value) == false); + CHECK((etl::is_nothrow_move_constructible::value) == true); + CHECK((etl::is_nothrow_move_constructible::value) == true); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + CHECK((etl::is_nothrow_move_constructible::value) == (std::is_nothrow_move_constructible::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + CHECK((etl::is_nothrow_move_constructible_v) == (std::is_nothrow_move_constructible_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_assignable) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_assignable::value) == true); + CHECK((etl::is_nothrow_assignable::value) == false); + CHECK((etl::is_nothrow_assignable::value) == true); + CHECK((etl::is_nothrow_assignable::value) == true); + CHECK((etl::is_nothrow_assignable::value) == (std::is_nothrow_assignable::value)); + CHECK((etl::is_nothrow_assignable::value) == (std::is_nothrow_assignable::value)); + CHECK((etl::is_nothrow_assignable::value) == (std::is_nothrow_assignable::value)); + CHECK((etl::is_nothrow_assignable::value) + == (std::is_nothrow_assignable::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + CHECK((etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + CHECK((etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + CHECK( + (etl::is_nothrow_assignable_v) == (std::is_nothrow_assignable_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_copy_assignable) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_copy_assignable::value) == true); + CHECK((etl::is_nothrow_copy_assignable::value) == true); + CHECK((etl::is_nothrow_copy_assignable::value) == false); + CHECK((etl::is_nothrow_copy_assignable::value) == false); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + CHECK((etl::is_nothrow_copy_assignable::value) == (std::is_nothrow_copy_assignable::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + CHECK((etl::is_nothrow_copy_assignable_v) == (std::is_nothrow_copy_assignable_v)); + #endif +#endif + } + + //************************************************************************* + TEST(test_is_nothrow_move_assignable) + { +#if defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_nothrow_move_assignable::value) == true); + CHECK((etl::is_nothrow_move_assignable::value) == false); + CHECK((etl::is_nothrow_move_assignable::value) == true); + CHECK((etl::is_nothrow_move_assignable::value) == true); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + CHECK((etl::is_nothrow_move_assignable::value) == (std::is_nothrow_move_assignable::value)); + #if ETL_USING_CPP17 + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + CHECK((etl::is_nothrow_move_assignable_v) == (std::is_nothrow_move_assignable_v)); + #endif +#endif + } + //************************************************************************* TEST(test_is_trivially_constructible) { diff --git a/test/test_variant_variadic.cpp b/test/test_variant_variadic.cpp index f8b8fe5f..1a1410ba 100644 --- a/test/test_variant_variadic.cpp +++ b/test/test_variant_variadic.cpp @@ -2243,6 +2243,131 @@ namespace CHECK(etl::holds_alternative(v1)); CHECK(etl::get_if(&v1) != nullptr); } + + //************************************************************************* + // Tests for noexcept properties of etl::variant + // The noexcept specs only take effect when ETL_USING_EXCEPTIONS is enabled, + // because ETL_NOEXCEPT_IF expands to nothing otherwise. + // The etl::is_nothrow_* traits only work with STL or builtins. + //************************************************************************* + #if ETL_USING_EXCEPTIONS && (defined(ETL_USE_TYPE_TRAITS_BUILTINS) || (ETL_USING_STL && !defined(ETL_USER_DEFINED_TYPE_TRAITS))) + + struct VariantNothrowType + { + VariantNothrowType() noexcept {} + VariantNothrowType(const VariantNothrowType&) noexcept {} + VariantNothrowType(VariantNothrowType&&) noexcept {} + VariantNothrowType& operator=(const VariantNothrowType&) noexcept + { + return *this; + } + VariantNothrowType& operator=(VariantNothrowType&&) noexcept + { + return *this; + } + }; + + struct VariantThrowingCopy + { + VariantThrowingCopy() noexcept {} + VariantThrowingCopy(const VariantThrowingCopy&) {} // may throw + VariantThrowingCopy(VariantThrowingCopy&&) noexcept {} + VariantThrowingCopy& operator=(const VariantThrowingCopy&) + { + return *this; + } + VariantThrowingCopy& operator=(VariantThrowingCopy&&) noexcept + { + return *this; + } + }; + + struct VariantThrowingMove + { + VariantThrowingMove() noexcept {} + VariantThrowingMove(const VariantThrowingMove&) noexcept {} + VariantThrowingMove(VariantThrowingMove&&) {} // may throw + VariantThrowingMove& operator=(const VariantThrowingMove&) noexcept + { + return *this; + } + VariantThrowingMove& operator=(VariantThrowingMove&&) + { + return *this; + } + }; + + TEST(test_variant_nothrow_copy_constructible) + { + // variant is nothrow copy constructible only if all Ts are + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_copy_constructible::value, "variant should be nothrow copy constructible"); + + using HasThrowingCopy = etl::variant; + static_assert(!etl::is_nothrow_copy_constructible::value, + "variant should NOT be nothrow copy constructible"); + + using HasThrowingMove = etl::variant; + static_assert(etl::is_nothrow_copy_constructible::value, + "variant should be nothrow copy constructible (copy is nothrow)"); + + CHECK(true); + } + + TEST(test_variant_nothrow_move_constructible) + { + // variant is nothrow move constructible only if all Ts are + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_move_constructible::value, "variant should be nothrow move constructible"); + + using HasThrowingMove = etl::variant; + static_assert(!etl::is_nothrow_move_constructible::value, + "variant should NOT be nothrow move constructible"); + + using HasThrowingCopy = etl::variant; + static_assert(etl::is_nothrow_move_constructible::value, + "variant should be nothrow move constructible (move is nothrow)"); + + CHECK(true); + } + + TEST(test_variant_nothrow_default_constructible) + { + // variant default-constructs the first alternative + using NothrowFirst = etl::variant; + static_assert(etl::is_nothrow_default_constructible::value, + "variant should be nothrow default constructible (int is nothrow)"); + + using ThrowingFirst = etl::variant; + // VariantThrowingCopy has noexcept default ctor, so this should be nothrow + static_assert(etl::is_nothrow_default_constructible::value, + "variant should be nothrow default constructible (ThrowingCopy has noexcept default ctor)"); + + CHECK(true); + } + + TEST(test_variant_nothrow_copy_assignable) + { + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_copy_assignable::value, "variant should be nothrow copy assignable"); + + using HasThrowingCopy = etl::variant; + static_assert(!etl::is_nothrow_copy_assignable::value, "variant should NOT be nothrow copy assignable"); + + CHECK(true); + } + + TEST(test_variant_nothrow_move_assignable) + { + using AllNothrow = etl::variant; + static_assert(etl::is_nothrow_move_assignable::value, "variant should be nothrow move assignable"); + + using HasThrowingMove = etl::variant; + static_assert(!etl::is_nothrow_move_assignable::value, "variant should NOT be nothrow move assignable"); + + CHECK(true); + } + #endif } } // namespace