Make etl::variant and etl::vector methods noexcept (#1383)

* Print test names at test time (#1343)

* Fix operator| conflict with std::ranges (#1395)

* Make etl::optional, etl::variant and etl::vector methods noexcept

Adding type traits supporting the respective conditional noexcept

Fix missing etl::move() in etl::optional move constructors

---------

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
Roland Reichwein 2026-04-22 12:37:53 +02:00 committed by GitHub
parent 2b1dec0e79
commit a97817010e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 825 additions and 85 deletions

View File

@ -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<T>& other)
optional_impl(const optional_impl<T>& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
{
if (other.has_value())
{
@ -160,7 +160,7 @@ namespace etl
/// Move constructor.
//***************************************************************************
ETL_CONSTEXPR20_STL
optional_impl(optional_impl<T>&& other)
optional_impl(optional_impl<T>&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
{
if (other.has_value())
{
@ -177,7 +177,7 @@ namespace etl
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value
&& !etl::is_same<typename etl::decay<U>::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<T, U&&>::value))
{
storage.construct(etl::forward<U>(value_));
}
@ -186,7 +186,7 @@ namespace etl
/// Constructor from variadic args.
//***************************************************************************
template <typename... TArgs>
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<T, TArgs...>::value))
{
storage.construct(etl::forward<TArgs>(args)...);
}
@ -197,6 +197,7 @@ namespace etl
//*******************************************
template <typename U, typename... TArgs >
ETL_CONSTEXPR20_STL optional_impl(etl::in_place_t, std::initializer_list<U> ilist, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<U>, TArgs...>::value))
{
storage.construct(ilist, etl::forward<TArgs>(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<T>& other)
optional_impl& operator=(const optional_impl<T>& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::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<T>::value)
{
if (this != &other)
{
@ -277,7 +278,7 @@ namespace etl
template <typename U,
typename etl::enable_if< etl::is_constructible<T, U&&>::value && !etl::is_same<typename etl::decay<U>::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<T, U&&>::value))
{
storage.construct(etl::forward<U>(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<U>::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<T, U&&, URest...>::value))
{
storage.construct(etl::forward<U>(first), etl::forward<URest>(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<T>::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<T>& other)
ETL_CONSTEXPR14 optional_impl(const optional_impl<T>& 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 <typename... TArgs>
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<TArgs>(args)...);
}
@ -803,7 +804,7 @@ namespace etl
/// Construct from initializer_list and arguments.
//*******************************************
template <typename U, typename... TArgs >
ETL_CONSTEXPR14 optional_impl(etl::in_place_t, std::initializer_list<U> ilist, TArgs&&... args)
ETL_CONSTEXPR14 optional_impl(etl::in_place_t, std::initializer_list<U> ilist, TArgs&&... args) ETL_NOEXCEPT
{
storage.construct(ilist, etl::forward<TArgs>(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<T>& other)
ETL_CONSTEXPR14 optional_impl& operator=(const optional_impl<T>& 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 <typename... TArgs>
ETL_CONSTEXPR14 T& emplace(TArgs&&... args)
ETL_CONSTEXPR14 T& emplace(TArgs&&... args) ETL_NOEXCEPT
{
storage.construct(etl::forward<TArgs>(args)...);
@ -1286,7 +1287,7 @@ namespace etl
/// Constructor.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
ETL_CONSTEXPR14 optional()
ETL_CONSTEXPR14 optional() ETL_NOEXCEPT
: impl_t()
{
}
@ -1295,12 +1296,12 @@ namespace etl
/// Constructor.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
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 <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
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 <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
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 <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
ETL_CONSTEXPR14 optional(const optional& other)
ETL_CONSTEXPR14 optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
: impl_t(other)
{
}
@ -1349,7 +1350,7 @@ namespace etl
/// Copy constructor.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
ETL_CONSTEXPR20_STL optional(const optional& other)
ETL_CONSTEXPR20_STL optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
: impl_t(other)
{
}
@ -1369,8 +1370,8 @@ namespace etl
/// Move constructor.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
ETL_CONSTEXPR14 optional(optional&& other)
: impl_t(other)
ETL_CONSTEXPR14 optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
: impl_t(etl::move(other))
{
}
@ -1378,8 +1379,8 @@ namespace etl
/// Move constructor.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
ETL_CONSTEXPR20_STL optional(optional&& other)
: impl_t(other)
ETL_CONSTEXPR20_STL optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
: impl_t(etl::move(other))
{
}
#endif
@ -1396,7 +1397,7 @@ namespace etl
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
&& etl::is_pod<typename etl::remove_cv<T>::type>::value,
int>::type = 0>
ETL_CONSTEXPR14 optional(U&& value_)
ETL_CONSTEXPR14 optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
: impl_t(etl::forward<U>(value_))
{
}
@ -1410,7 +1411,7 @@ namespace etl
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
&& !etl::is_pod<typename etl::remove_cv<T>::type>::value,
int>::type = 0>
ETL_CONSTEXPR20_STL optional(U&& value_)
ETL_CONSTEXPR20_STL optional(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
: impl_t(etl::forward<U>(value_))
{
}
@ -1429,7 +1430,7 @@ namespace etl
/// Emplace construct from arguments.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14, typename... Args>
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<T, Args...>::value))
: impl_t(etl::in_place_t{}, etl::forward<Args>(args)...)
{
}
@ -1438,7 +1439,7 @@ namespace etl
/// Emplace construct from arguments.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL, typename... Args>
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<T, Args...>::value))
: impl_t(etl::in_place_t{}, etl::forward<Args>(args)...)
{
}
@ -1449,6 +1450,7 @@ namespace etl
//*******************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14, typename... TArgs>
ETL_CONSTEXPR14 explicit optional(etl::in_place_t, std::initializer_list<U> ilist, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<U>, TArgs...>::value))
: impl_t(etl::in_place_t{}, ilist, etl::forward<TArgs>(args)...)
{
}
@ -1458,6 +1460,7 @@ namespace etl
//*******************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL, typename... TArgs>
ETL_CONSTEXPR20_STL explicit optional(etl::in_place_t, std::initializer_list<U> ilist, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<U>, TArgs...>::value))
: impl_t(etl::in_place_t{}, ilist, etl::forward<TArgs>(args)...)
{
}
@ -1469,7 +1472,7 @@ namespace etl
/// Assignment operator from nullopt.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
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 <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
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 <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
ETL_CONSTEXPR14 optional& operator=(const optional& other)
ETL_CONSTEXPR14 optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
{
impl_t::operator=(other);
@ -1514,7 +1517,7 @@ namespace etl
/// Assignment operator from optional.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
ETL_CONSTEXPR20_STL optional& operator=(const optional& other)
ETL_CONSTEXPR20_STL optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
{
impl_t::operator=(other);
@ -1537,7 +1540,7 @@ namespace etl
/// Move assignment operator from optional.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
ETL_CONSTEXPR14 optional& operator=(optional&& other)
ETL_CONSTEXPR14 optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
{
impl_t::operator=(etl::move(other));
@ -1548,7 +1551,7 @@ namespace etl
/// Move assignment operator from optional.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
ETL_CONSTEXPR20_STL optional& operator=(optional&& other)
ETL_CONSTEXPR20_STL optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
{
impl_t::operator=(etl::move(other));
@ -1565,7 +1568,7 @@ namespace etl
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
&& etl::is_pod<typename etl::remove_cv<T>::type>::value,
int>::type = 0>
ETL_CONSTEXPR14 optional& operator=(U&& value_)
ETL_CONSTEXPR14 optional& operator=(U&& value_) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, U&&>::value))
{
impl_t::operator=(etl::forward<U>(value_));
@ -1580,7 +1583,7 @@ namespace etl
&& !etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value
&& !etl::is_pod<typename etl::remove_cv<T>::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<T, U&&>::value))
{
impl_t::operator=(etl::forward<U>(value_));

View File

@ -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<type_from_index<0U> >::value)
{
using type = type_from_index<0U>;
@ -501,7 +501,7 @@ namespace etl
//***************************************************************************
#include "diagnostic_uninitialized_push.h"
template <typename T, etl::enable_if_t< !etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
ETL_CONSTEXPR14 variant(T&& value)
ETL_CONSTEXPR14 variant(T&& value) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, T&&>::value))
: operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
, type_id(index_of_type<T>::value)
@ -518,6 +518,7 @@ namespace etl
#include "diagnostic_uninitialized_push.h"
template <typename T, typename... TArgs>
ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, TArgs...>::value))
: operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
, type_id(index_of_type<T>::value)
@ -534,6 +535,7 @@ namespace etl
#include "diagnostic_uninitialized_push.h"
template <size_t Index, typename... TArgs>
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, TArgs...>::value))
: type_id(Index)
{
using type = type_from_index<Index>;
@ -552,6 +554,7 @@ namespace etl
#include "diagnostic_uninitialized_push.h"
template <typename T, typename U, typename... TArgs >
ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, std::initializer_list<U> init, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, std::initializer_list<U>, TArgs...>::value))
: operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
, type_id(index_of_type<T>::value)
@ -568,6 +571,7 @@ namespace etl
#include "diagnostic_uninitialized_push.h"
template <size_t Index, typename U, typename... TArgs >
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, std::initializer_list<U>, TArgs...>::value))
: type_id(Index)
{
using type = type_from_index<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<etl::is_nothrow_copy_constructible<TTypes>...>::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<etl::is_nothrow_move_constructible<TTypes>...>::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 <typename T, typename... TArgs>
T& emplace(TArgs&&... args)
T& emplace(TArgs&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, TArgs...>::value))
{
static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
@ -664,6 +668,7 @@ namespace etl
//***************************************************************************
template <typename T, typename U, typename... TArgs>
T& emplace(std::initializer_list<U> il, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, std::initializer_list<U>, TArgs...>::value))
{
static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
@ -689,6 +694,7 @@ namespace etl
//***************************************************************************
template <size_t Index, typename... TArgs>
typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, TArgs...>::value))
{
static_assert(Index < sizeof...(TTypes), "Index out of range");
@ -714,6 +720,7 @@ namespace etl
//***************************************************************************
template <size_t Index, typename U, typename... TArgs>
typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(std::initializer_list<U> il, TArgs&&... args)
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, std::initializer_list<U>, TArgs...>::value))
{
static_assert(Index < sizeof...(TTypes), "Index out of range");
@ -739,7 +746,7 @@ namespace etl
///\param value The value to assign.
//***************************************************************************
template <typename T, etl::enable_if_t< !etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
variant& operator=(T&& value)
variant& operator=(T&& value) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, T&&>::value))
{
using type = etl::remove_cvref_t<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<etl::is_nothrow_copy_constructible<TTypes>...>::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<etl::is_nothrow_move_constructible<TTypes>...>::value))
{
if (this != &other)
{

View File

@ -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
@ -96,6 +104,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
@ -154,6 +170,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
@ -210,6 +234,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);

View File

@ -2635,6 +2635,41 @@ namespace etl
template <typename T>
using is_move_assignable = std::is_move_assignable<T>;
//*********************************************
// is_nothrow_constructible
template <typename T, typename... TArgs>
using is_nothrow_constructible = std::is_nothrow_constructible<T, TArgs...>;
//*********************************************
// is_nothrow_default_constructible
template <typename T>
using is_nothrow_default_constructible = std::is_nothrow_default_constructible<T>;
//*********************************************
// is_nothrow_copy_constructible
template <typename T>
using is_nothrow_copy_constructible = std::is_nothrow_copy_constructible<T>;
//*********************************************
// is_nothrow_move_constructible
template <typename T>
using is_nothrow_move_constructible = std::is_nothrow_move_constructible<T>;
//*********************************************
// is_nothrow_assignable
template <typename T, typename U>
using is_nothrow_assignable = std::is_nothrow_assignable<T, U>;
//*********************************************
// is_nothrow_copy_assignable
template <typename T>
using is_nothrow_copy_assignable = std::is_nothrow_copy_assignable<T>;
//*********************************************
// is_nothrow_move_assignable
template <typename T>
using is_nothrow_move_assignable = std::is_nothrow_move_assignable<T>;
//*********************************************
// is_trivially_constructible
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
@ -2795,6 +2830,71 @@ namespace etl
};
#endif
#if ETL_USING_CPP11
//*********************************************
// is_nothrow_constructible
template <typename T, typename... TArgs>
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<T>::value || etl::is_pointer<T>::value;
#endif
};
//*********************************************
// is_nothrow_default_constructible
template <typename T>
struct is_nothrow_default_constructible : public etl::is_nothrow_constructible<T>
{
};
//*********************************************
// is_nothrow_copy_constructible
template <typename T>
struct is_nothrow_copy_constructible : public etl::is_nothrow_constructible<T, typename etl::add_lvalue_reference<const T>::type>
{
};
//*********************************************
// is_nothrow_move_constructible
template <typename T>
struct is_nothrow_move_constructible : public etl::is_nothrow_constructible<T, typename etl::add_rvalue_reference<T>::type>
{
};
#endif
#if ETL_USING_CPP11
//*********************************************
// is_nothrow_assignable
template <typename T, typename U>
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<T>::value || etl::is_pointer<T>::value;
#endif
};
//*********************************************
// is_nothrow_copy_assignable
template <typename T>
struct is_nothrow_copy_assignable
: public etl::is_nothrow_assignable<typename etl::add_lvalue_reference<T>::type, typename etl::add_lvalue_reference<const T>::type>
{
};
//*********************************************
// is_nothrow_move_assignable
template <typename T>
struct is_nothrow_move_assignable
: public etl::is_nothrow_assignable<typename etl::add_lvalue_reference<T>::type, typename etl::add_rvalue_reference<T>::type>
{
};
#endif
#if ETL_USING_CPP11
//*********************************************
// is_trivially_constructible
@ -2989,6 +3089,104 @@ namespace etl
template <typename T>
struct is_move_assignable<T, false>;
#if ETL_USING_CPP11
//*********************************************
// is_nothrow_constructible
template <typename T, bool BValue, typename... TArgs>
struct is_nothrow_constructible_helper;
template <typename T, typename... TArgs>
struct is_nothrow_constructible_helper<T, true, TArgs...> : public etl::true_type
{
};
template <typename T, typename... TArgs>
struct is_nothrow_constructible_helper<T, false, TArgs...>;
template <typename T, typename... TArgs>
struct is_nothrow_constructible : public is_nothrow_constructible_helper<T, etl::is_arithmetic<T>::value || etl::is_pointer<T>::value, TArgs...>
{
};
//*********************************************
// is_nothrow_default_constructible
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_default_constructible;
template <typename T>
struct is_nothrow_default_constructible<T, true> : public etl::true_type
{
};
template <typename T>
struct is_nothrow_default_constructible<T, false>;
//*********************************************
// is_nothrow_copy_constructible
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_copy_constructible;
template <typename T>
struct is_nothrow_copy_constructible<T, true> : public etl::true_type
{
};
template <typename T>
struct is_nothrow_copy_constructible<T, false>;
//*********************************************
// is_nothrow_move_constructible
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_move_constructible;
template <typename T>
struct is_nothrow_move_constructible<T, true> : public etl::true_type
{
};
template <typename T>
struct is_nothrow_move_constructible<T, false>;
//*********************************************
// is_nothrow_assignable
template <typename T, typename U, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_assignable;
template <typename T, typename U>
struct is_nothrow_assignable<T, U, true> : public etl::true_type
{
};
template <typename T, typename U>
struct is_nothrow_assignable<T, U, false>;
//*********************************************
// is_nothrow_copy_assignable
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_copy_assignable;
template <typename T>
struct is_nothrow_copy_assignable<T, true> : public etl::true_type
{
};
template <typename T>
struct is_nothrow_copy_assignable<T, false>;
//*********************************************
// is_nothrow_move_assignable
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_move_assignable;
template <typename T>
struct is_nothrow_move_assignable<T, true> : public etl::true_type
{
};
template <typename T>
struct is_nothrow_move_assignable<T, false>;
#endif
//*********************************************
// is_trivially_constructible
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
@ -3209,6 +3407,57 @@ namespace etl
};
#endif
#if ETL_USING_CPP11
//*********************************************
// is_nothrow_constructible
template <typename T, typename... TArgs>
struct is_nothrow_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_nothrow_default_constructible
template <typename T>
struct is_nothrow_default_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_nothrow_copy_constructible
template <typename T>
struct is_nothrow_copy_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_nothrow_move_constructible
template <typename T>
struct is_nothrow_move_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_nothrow_assignable
template <typename T, typename U>
struct is_nothrow_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_nothrow_copy_assignable
template <typename T>
struct is_nothrow_copy_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_nothrow_move_assignable
template <typename T>
struct is_nothrow_move_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
#endif
//*********************************************
// is_trivially_constructible
template <typename T>
@ -3321,6 +3570,27 @@ namespace etl
template <typename T>
inline constexpr bool is_move_assignable_v = etl::is_move_assignable<T>::value;
template <typename T, typename... TArgs>
inline constexpr bool is_nothrow_constructible_v = etl::is_nothrow_constructible<T, TArgs...>::value;
template <typename T>
inline constexpr bool is_nothrow_default_constructible_v = etl::is_nothrow_default_constructible<T>::value;
template <typename T>
inline constexpr bool is_nothrow_copy_constructible_v = etl::is_nothrow_copy_constructible<T>::value;
template <typename T>
inline constexpr bool is_nothrow_move_constructible_v = etl::is_nothrow_move_constructible<T>::value;
template <typename T, typename U>
inline constexpr bool is_nothrow_assignable_v = etl::is_nothrow_assignable<T, U>::value;
template <typename T>
inline constexpr bool is_nothrow_copy_assignable_v = etl::is_nothrow_copy_assignable<T>::value;
template <typename T>
inline constexpr bool is_nothrow_move_assignable_v = etl::is_nothrow_move_assignable<T>::value;
template <typename T>
inline constexpr bool is_trivially_constructible_v = etl::is_trivially_constructible<T>::value;

View File

@ -1018,7 +1018,7 @@ namespace etl
//*************************************************************************
/// Move assignment operator.
//*************************************************************************
ivector& operator=(ivector&& rhs)
ivector& operator=(ivector&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible<T>::value))
{
if (&rhs != this)
{
@ -1085,7 +1085,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_)
@ -1288,7 +1288,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
vector()
vector() ETL_NOEXCEPT
: etl::ivector<T>(reinterpret_cast<T*>(&buffer), MAX_SIZE)
{
this->initialise();
@ -1367,7 +1367,7 @@ namespace etl
//*************************************************************************
/// Move constructor.
//*************************************************************************
vector(vector&& other)
vector(vector&& other) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible<T>::value))
: etl::ivector<T>(reinterpret_cast<T*>(&buffer), MAX_SIZE)
{
if (this != &other)
@ -1388,7 +1388,7 @@ namespace etl
//*************************************************************************
/// Move assignment operator.
//*************************************************************************
vector& operator=(vector&& rhs)
vector& operator=(vector&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible<T>::value))
{
if (&rhs != this)
{
@ -1413,7 +1413,7 @@ namespace etl
#ifdef ETL_IVECTOR_REPAIR_ENABLE
virtual
#endif
~vector()
~vector() ETL_NOEXCEPT
{
this->clear();
}
@ -1470,7 +1470,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
vector_ext(void* buffer, size_t max_size)
vector_ext(void* buffer, size_t max_size) ETL_NOEXCEPT
: etl::ivector<T>(reinterpret_cast<T*>(buffer), max_size)
{
this->initialise();
@ -1550,7 +1550,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<T>::value))
: etl::ivector<T>(reinterpret_cast<T*>(buffer), max_size)
{
if (this != &other)
@ -1571,7 +1571,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<T>::value))
{
if (&rhs != this)
{
@ -1594,7 +1594,7 @@ namespace etl
//*************************************************************************
/// Destructor.
//*************************************************************************
~vector_ext()
~vector_ext() ETL_NOEXCEPT
{
this->clear();
}
@ -1629,7 +1629,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
vector()
vector() ETL_NOEXCEPT
: etl::ivector<T*>(reinterpret_cast<T**>(&buffer), MAX_SIZE)
{
this->initialise();
@ -1705,7 +1705,7 @@ namespace etl
//*************************************************************************
/// Move constructor.
//*************************************************************************
vector(vector&& other)
vector(vector&& other) ETL_NOEXCEPT
: etl::ivector<T*>(reinterpret_cast<T**>(&buffer), MAX_SIZE)
{
(void)etl::ivector<T*>::operator=(etl::move(other));
@ -1714,7 +1714,7 @@ namespace etl
//*************************************************************************
/// Move assignment operator.
//*************************************************************************
vector& operator=(vector&& rhs)
vector& operator=(vector&& rhs) ETL_NOEXCEPT
{
(void)etl::ivector<T*>::operator=(etl::move(rhs));
@ -1769,7 +1769,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
vector_ext(void* buffer, size_t max_size)
vector_ext(void* buffer, size_t max_size) ETL_NOEXCEPT
: etl::ivector<T*>(reinterpret_cast<T**>(buffer), max_size)
{
this->initialise();
@ -1876,7 +1876,7 @@ namespace etl
//*************************************************************************
/// Destructor.
//*************************************************************************
~vector_ext()
~vector_ext() ETL_NOEXCEPT
{
this->clear();
}

View File

@ -31,6 +31,7 @@ SOFTWARE.
#include <cstdint>
#include <ostream>
#include <string>
#include <type_traits>
#include <vector>
#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<T> should be too
static_assert(etl::is_nothrow_copy_constructible<etl::optional<int>>::value, "optional<int> should be nothrow copy constructible");
static_assert(etl::is_nothrow_copy_constructible<etl::optional<NothrowCopyMove>>::value,
"optional<NothrowCopyMove> should be nothrow copy constructible");
// When T is NOT nothrow copy constructible, optional<T> should not be either
static_assert(!etl::is_nothrow_copy_constructible<etl::optional<ThrowingCopy>>::value,
"optional<ThrowingCopy> should NOT be nothrow copy constructible");
static_assert(!etl::is_nothrow_copy_constructible<etl::optional<ThrowingBoth>>::value,
"optional<ThrowingBoth> should NOT be nothrow copy constructible");
// ThrowingMove has nothrow copy but throwing move
static_assert(etl::is_nothrow_copy_constructible<etl::optional<ThrowingMove>>::value,
"optional<ThrowingMove> 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<T> should be too
static_assert(etl::is_nothrow_move_constructible<etl::optional<int>>::value, "optional<int> should be nothrow move constructible");
static_assert(etl::is_nothrow_move_constructible<etl::optional<NothrowCopyMove>>::value,
"optional<NothrowCopyMove> should be nothrow move constructible");
// When T is NOT nothrow move constructible, optional<T> should not be either
static_assert(!etl::is_nothrow_move_constructible<etl::optional<ThrowingMove>>::value,
"optional<ThrowingMove> should NOT be nothrow move constructible");
static_assert(!etl::is_nothrow_move_constructible<etl::optional<ThrowingBoth>>::value,
"optional<ThrowingBoth> should NOT be nothrow move constructible");
// ThrowingCopy has nothrow move but throwing copy
static_assert(etl::is_nothrow_move_constructible<etl::optional<ThrowingCopy>>::value,
"optional<ThrowingCopy> 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<etl::optional<int>>::value, "optional<int> should be nothrow default constructible");
static_assert(etl::is_nothrow_default_constructible<etl::optional<NothrowCopyMove>>::value,
"optional<NothrowCopyMove> should be nothrow default constructible");
static_assert(etl::is_nothrow_default_constructible<etl::optional<ThrowingCopy>>::value,
"optional<ThrowingCopy> should be nothrow default constructible");
static_assert(etl::is_nothrow_default_constructible<etl::optional<ThrowingBoth>>::value,
"optional<ThrowingBoth> should be nothrow default constructible");
CHECK(true);
}
TEST(test_optional_nothrow_constructible_from_value)
{
// optional<T>(U&&) should be noexcept iff T is nothrow constructible from U&&
static_assert(etl::is_nothrow_constructible<etl::optional<int>, int>::value, "optional<int> should be nothrow constructible from int");
static_assert(etl::is_nothrow_constructible<etl::optional<int>, int&&>::value, "optional<int> 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<etl::optional<int>>::value, "optional<int> should be nothrow copy assignable");
static_assert(etl::is_nothrow_copy_assignable<etl::optional<NothrowCopyMove>>::value,
"optional<NothrowCopyMove> 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<etl::optional<ThrowingCopy>>::value,
"optional<ThrowingCopy> 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<etl::optional<int>>::value, "optional<int> should be nothrow move assignable");
static_assert(etl::is_nothrow_move_assignable<etl::optional<NothrowCopyMove>>::value,
"optional<NothrowCopyMove> 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<etl::optional<ThrowingMove>>::value,
"optional<ThrowingMove> should NOT be nothrow move assignable");
CHECK(true);
}
#endif
}
} // namespace

View File

@ -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<Copyable, Copyable> : public etl::true_type
struct etl::is_assignable<Copyable, Copyable> : public etl::false_type
{
};
@ -364,7 +364,7 @@ struct etl::is_copy_assignable<Copyable> : public etl::true_type
};
template <>
struct etl::is_move_assignable<Copyable> : public etl::true_type
struct etl::is_move_assignable<Copyable> : public etl::false_type
{
};
@ -1548,6 +1548,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<int>::value) == true);
CHECK((etl::is_nothrow_constructible<Copyable>::value) == false);
CHECK((etl::is_nothrow_constructible<Moveable>::value) == false);
CHECK((etl::is_nothrow_constructible<MoveableCopyable>::value) == false);
CHECK((etl::is_nothrow_constructible<int>::value) == (std::is_nothrow_constructible<int>::value));
CHECK((etl::is_nothrow_constructible<Copyable>::value) == (std::is_nothrow_constructible<Copyable>::value));
CHECK((etl::is_nothrow_constructible<Moveable>::value) == (std::is_nothrow_constructible<Moveable>::value));
CHECK((etl::is_nothrow_constructible<MoveableCopyable>::value) == (std::is_nothrow_constructible<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_nothrow_constructible_v<int>) == (std::is_nothrow_constructible_v<int>));
CHECK((etl::is_nothrow_constructible_v<Copyable>) == (std::is_nothrow_constructible_v<Copyable>));
CHECK((etl::is_nothrow_constructible_v<Moveable>) == (std::is_nothrow_constructible_v<Moveable>));
CHECK((etl::is_nothrow_constructible_v<MoveableCopyable>) == (std::is_nothrow_constructible_v<MoveableCopyable>));
#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<int>::value) == true);
CHECK((etl::is_nothrow_default_constructible<Copyable>::value) == false);
CHECK((etl::is_nothrow_default_constructible<Moveable>::value) == false);
CHECK((etl::is_nothrow_default_constructible<MoveableCopyable>::value) == false);
CHECK((etl::is_nothrow_default_constructible<int>::value) == (std::is_nothrow_default_constructible<int>::value));
CHECK((etl::is_nothrow_default_constructible<Copyable>::value) == (std::is_nothrow_default_constructible<Copyable>::value));
CHECK((etl::is_nothrow_default_constructible<Moveable>::value) == (std::is_nothrow_default_constructible<Moveable>::value));
CHECK((etl::is_nothrow_default_constructible<MoveableCopyable>::value) == (std::is_nothrow_default_constructible<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_nothrow_default_constructible_v<int>) == (std::is_nothrow_default_constructible_v<int>));
CHECK((etl::is_nothrow_default_constructible_v<Copyable>) == (std::is_nothrow_default_constructible_v<Copyable>));
CHECK((etl::is_nothrow_default_constructible_v<Moveable>) == (std::is_nothrow_default_constructible_v<Moveable>));
CHECK((etl::is_nothrow_default_constructible_v<MoveableCopyable>) == (std::is_nothrow_default_constructible_v<MoveableCopyable>));
#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<int>::value) == true);
CHECK((etl::is_nothrow_copy_constructible<Copyable>::value) == true);
CHECK((etl::is_nothrow_copy_constructible<Moveable>::value) == false);
CHECK((etl::is_nothrow_copy_constructible<MoveableCopyable>::value) == false);
CHECK((etl::is_nothrow_copy_constructible<int>::value) == (std::is_nothrow_copy_constructible<int>::value));
CHECK((etl::is_nothrow_copy_constructible<Copyable>::value) == (std::is_nothrow_copy_constructible<Copyable>::value));
CHECK((etl::is_nothrow_copy_constructible<Moveable>::value) == (std::is_nothrow_copy_constructible<Moveable>::value));
CHECK((etl::is_nothrow_copy_constructible<MoveableCopyable>::value) == (std::is_nothrow_copy_constructible<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_nothrow_copy_constructible_v<int>) == (std::is_nothrow_copy_constructible_v<int>));
CHECK((etl::is_nothrow_copy_constructible_v<Copyable>) == (std::is_nothrow_copy_constructible_v<Copyable>));
CHECK((etl::is_nothrow_copy_constructible_v<Moveable>) == (std::is_nothrow_copy_constructible_v<Moveable>));
CHECK((etl::is_nothrow_copy_constructible_v<MoveableCopyable>) == (std::is_nothrow_copy_constructible_v<MoveableCopyable>));
#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<int>::value) == true);
CHECK((etl::is_nothrow_move_constructible<Copyable>::value) == false);
CHECK((etl::is_nothrow_move_constructible<Moveable>::value) == true);
CHECK((etl::is_nothrow_move_constructible<MoveableCopyable>::value) == true);
CHECK((etl::is_nothrow_move_constructible<int>::value) == (std::is_nothrow_move_constructible<int>::value));
CHECK((etl::is_nothrow_move_constructible<Copyable>::value) == (std::is_nothrow_move_constructible<Copyable>::value));
CHECK((etl::is_nothrow_move_constructible<Moveable>::value) == (std::is_nothrow_move_constructible<Moveable>::value));
CHECK((etl::is_nothrow_move_constructible<MoveableCopyable>::value) == (std::is_nothrow_move_constructible<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_nothrow_move_constructible_v<int>) == (std::is_nothrow_move_constructible_v<int>));
CHECK((etl::is_nothrow_move_constructible_v<Copyable>) == (std::is_nothrow_move_constructible_v<Copyable>));
CHECK((etl::is_nothrow_move_constructible_v<Moveable>) == (std::is_nothrow_move_constructible_v<Moveable>));
CHECK((etl::is_nothrow_move_constructible_v<MoveableCopyable>) == (std::is_nothrow_move_constructible_v<MoveableCopyable>));
#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<int&, int>::value) == true);
CHECK((etl::is_nothrow_assignable<Copyable&, Copyable>::value) == false);
CHECK((etl::is_nothrow_assignable<Moveable&, Moveable>::value) == true);
CHECK((etl::is_nothrow_assignable<MoveableCopyable&, MoveableCopyable>::value) == true);
CHECK((etl::is_nothrow_assignable<int&, int>::value) == (std::is_nothrow_assignable<int&, int>::value));
CHECK((etl::is_nothrow_assignable<Copyable&, Copyable>::value) == (std::is_nothrow_assignable<Copyable&, Copyable>::value));
CHECK((etl::is_nothrow_assignable<Moveable&, Moveable>::value) == (std::is_nothrow_assignable<Moveable&, Moveable>::value));
CHECK((etl::is_nothrow_assignable<MoveableCopyable&, MoveableCopyable>::value)
== (std::is_nothrow_assignable<MoveableCopyable&, MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_nothrow_assignable_v<int&, int>) == (std::is_nothrow_assignable_v<int&, int>));
CHECK((etl::is_nothrow_assignable_v<Copyable&, Copyable>) == (std::is_nothrow_assignable_v<Copyable&, Copyable>));
CHECK((etl::is_nothrow_assignable_v<Moveable&, Moveable>) == (std::is_nothrow_assignable_v<Moveable&, Moveable>));
CHECK(
(etl::is_nothrow_assignable_v<MoveableCopyable&, MoveableCopyable>) == (std::is_nothrow_assignable_v<MoveableCopyable&, MoveableCopyable>));
#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<int>::value) == true);
CHECK((etl::is_nothrow_copy_assignable<Copyable>::value) == true);
CHECK((etl::is_nothrow_copy_assignable<Moveable>::value) == false);
CHECK((etl::is_nothrow_copy_assignable<MoveableCopyable>::value) == false);
CHECK((etl::is_nothrow_copy_assignable<int>::value) == (std::is_nothrow_copy_assignable<int>::value));
CHECK((etl::is_nothrow_copy_assignable<Copyable>::value) == (std::is_nothrow_copy_assignable<Copyable>::value));
CHECK((etl::is_nothrow_copy_assignable<Moveable>::value) == (std::is_nothrow_copy_assignable<Moveable>::value));
CHECK((etl::is_nothrow_copy_assignable<MoveableCopyable>::value) == (std::is_nothrow_copy_assignable<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_nothrow_copy_assignable_v<int>) == (std::is_nothrow_copy_assignable_v<int>));
CHECK((etl::is_nothrow_copy_assignable_v<Copyable>) == (std::is_nothrow_copy_assignable_v<Copyable>));
CHECK((etl::is_nothrow_copy_assignable_v<Moveable>) == (std::is_nothrow_copy_assignable_v<Moveable>));
CHECK((etl::is_nothrow_copy_assignable_v<MoveableCopyable>) == (std::is_nothrow_copy_assignable_v<MoveableCopyable>));
#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<int>::value) == true);
CHECK((etl::is_nothrow_move_assignable<Copyable>::value) == false);
CHECK((etl::is_nothrow_move_assignable<Moveable>::value) == true);
CHECK((etl::is_nothrow_move_assignable<MoveableCopyable>::value) == true);
CHECK((etl::is_nothrow_move_assignable<int>::value) == (std::is_nothrow_move_assignable<int>::value));
CHECK((etl::is_nothrow_move_assignable<Copyable>::value) == (std::is_nothrow_move_assignable<Copyable>::value));
CHECK((etl::is_nothrow_move_assignable<Moveable>::value) == (std::is_nothrow_move_assignable<Moveable>::value));
CHECK((etl::is_nothrow_move_assignable<MoveableCopyable>::value) == (std::is_nothrow_move_assignable<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_nothrow_move_assignable_v<int>) == (std::is_nothrow_move_assignable_v<int>));
CHECK((etl::is_nothrow_move_assignable_v<Copyable>) == (std::is_nothrow_move_assignable_v<Copyable>));
CHECK((etl::is_nothrow_move_assignable_v<Moveable>) == (std::is_nothrow_move_assignable_v<Moveable>));
CHECK((etl::is_nothrow_move_assignable_v<MoveableCopyable>) == (std::is_nothrow_move_assignable_v<MoveableCopyable>));
#endif
#endif
}
//*************************************************************************
TEST(test_is_trivially_constructible)
{

View File

@ -2243,6 +2243,131 @@ namespace
CHECK(etl::holds_alternative<int>(v1));
CHECK(etl::get_if<int>(&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<Ts...> is nothrow copy constructible only if all Ts are
using AllNothrow = etl::variant<int, double, VariantNothrowType>;
static_assert(etl::is_nothrow_copy_constructible<AllNothrow>::value, "variant<int, double, NothrowType> should be nothrow copy constructible");
using HasThrowingCopy = etl::variant<int, VariantThrowingCopy>;
static_assert(!etl::is_nothrow_copy_constructible<HasThrowingCopy>::value,
"variant<int, ThrowingCopy> should NOT be nothrow copy constructible");
using HasThrowingMove = etl::variant<int, VariantThrowingMove>;
static_assert(etl::is_nothrow_copy_constructible<HasThrowingMove>::value,
"variant<int, ThrowingMove> should be nothrow copy constructible (copy is nothrow)");
CHECK(true);
}
TEST(test_variant_nothrow_move_constructible)
{
// variant<Ts...> is nothrow move constructible only if all Ts are
using AllNothrow = etl::variant<int, double, VariantNothrowType>;
static_assert(etl::is_nothrow_move_constructible<AllNothrow>::value, "variant<int, double, NothrowType> should be nothrow move constructible");
using HasThrowingMove = etl::variant<int, VariantThrowingMove>;
static_assert(!etl::is_nothrow_move_constructible<HasThrowingMove>::value,
"variant<int, ThrowingMove> should NOT be nothrow move constructible");
using HasThrowingCopy = etl::variant<int, VariantThrowingCopy>;
static_assert(etl::is_nothrow_move_constructible<HasThrowingCopy>::value,
"variant<int, ThrowingCopy> 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<int, VariantThrowingCopy>;
static_assert(etl::is_nothrow_default_constructible<NothrowFirst>::value,
"variant<int, ...> should be nothrow default constructible (int is nothrow)");
using ThrowingFirst = etl::variant<VariantThrowingCopy, int>;
// VariantThrowingCopy has noexcept default ctor, so this should be nothrow
static_assert(etl::is_nothrow_default_constructible<ThrowingFirst>::value,
"variant<ThrowingCopy, int> should be nothrow default constructible (ThrowingCopy has noexcept default ctor)");
CHECK(true);
}
TEST(test_variant_nothrow_copy_assignable)
{
using AllNothrow = etl::variant<int, double, VariantNothrowType>;
static_assert(etl::is_nothrow_copy_assignable<AllNothrow>::value, "variant<int, double, NothrowType> should be nothrow copy assignable");
using HasThrowingCopy = etl::variant<int, VariantThrowingCopy>;
static_assert(!etl::is_nothrow_copy_assignable<HasThrowingCopy>::value, "variant<int, ThrowingCopy> should NOT be nothrow copy assignable");
CHECK(true);
}
TEST(test_variant_nothrow_move_assignable)
{
using AllNothrow = etl::variant<int, double, VariantNothrowType>;
static_assert(etl::is_nothrow_move_assignable<AllNothrow>::value, "variant<int, double, NothrowType> should be nothrow move assignable");
using HasThrowingMove = etl::variant<int, VariantThrowingMove>;
static_assert(!etl::is_nothrow_move_assignable<HasThrowingMove>::value, "variant<int, ThrowingMove> should NOT be nothrow move assignable");
CHECK(true);
}
#endif
}
} // namespace